Fix for checking the inLen when setting raw public key len for hardware. Finished the ATECC508A ECC functions to support native TLS with the WOLFSSL_ATECC508A option and SECP256R1. Added slot type for alloc/free. Added helper functions for setting the PK callbacks and custom content. Updated the README.md with build options. Added support for overriding the ATECC_MAX_SLOT. Added overridable define for encryption slot number ATECC_SLOT_I2C_ENC. Added new build option WOLFSSL_ATECC_PKCB for using just the reference PK callbacks.

This commit is contained in:
David Garske
2018-09-07 12:39:27 -07:00
parent 7074625048
commit 53c2264327
4 changed files with 149 additions and 94 deletions

View File

@@ -3381,12 +3381,20 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
}
#ifdef WOLFSSL_ATECC508A
err = atcatls_ecdh(private_key->slot, public_key->pubkey_raw, out);
if (err != ATCA_SUCCESS) {
err = BAD_COND_E;
/* For SECP256R1 use hardware */
if (private_key->dp->id == ECC_SECP256R1) {
err = atcatls_ecdh(private_key->slot, public_key->pubkey_raw, out);
if (err != ATCA_SUCCESS) {
err = BAD_COND_E;
}
*outlen = private_key->dp->size;
}
*outlen = private_key->dp->size;
else {
err = NOT_COMPILED_IN;
}
#else
err = wc_ecc_shared_secret_ex(private_key, &public_key->pubkey, out, outlen);
#endif /* WOLFSSL_ATECC508A */
@@ -3751,7 +3759,7 @@ static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn,
#endif
ecc_point* pub;
DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
#endif
#endif /* !WOLFSSL_ATECC508A */
if (key == NULL) {
return BAD_FUNC_ARG;
@@ -3851,9 +3859,7 @@ static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn,
/* free up local curve */
if (curveIn == NULL) {
wc_ecc_curve_free(curve);
#ifndef WOLFSSL_ATECC508A
FREE_CURVE_SPECS();
#endif
}
#else
@@ -3893,7 +3899,7 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id)
#ifndef WOLFSSL_SP_MATH
DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
#endif
#endif
#endif /* !WOLFSSL_ATECC508A */
if (key == NULL || rng == NULL) {
return BAD_FUNC_ARG;
@@ -3993,9 +3999,7 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id)
/* cleanup allocations */
wc_ecc_curve_free(curve);
#ifndef WOLFSSL_ATECC508A
FREE_CURVE_SPECS();
#endif
#endif /* WOLFSSL_SP_MATH */
}
@@ -4097,7 +4101,7 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId)
#endif
#ifdef WOLFSSL_ATECC508A
key->slot = atmel_ecc_alloc();
key->slot = atmel_ecc_alloc(ATMEL_SLOT_ANY);
if (key->slot == ATECC_INVALID_SLOT) {
return ECC_BAD_ARG_E;
}
@@ -5563,7 +5567,6 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx,
ecc_point* point)
{
int err = 0;
#ifndef WOLFSSL_ATECC508A
int compressed = 0;
int keysize;
byte pointType;
@@ -5613,11 +5616,6 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx,
/* calculate key size based on inLen / 2 */
keysize = inLen>>1;
#ifdef WOLFSSL_ATECC508A
/* populate key->pubkey_raw */
XMEMCPY(key->pubkey_raw, (byte*)in, sizeof(key->pubkey_raw));
#endif
/* read data */
if (err == MP_OKAY)
err = mp_read_unsigned_bin(point->x, (byte*)in, keysize);
@@ -5697,14 +5695,6 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx,
mp_clear(point->z);
}
#else
err = NOT_COMPILED_IN;
(void)in;
(void)inLen;
(void)curve_idx;
(void)point;
#endif /* !WOLFSSL_ATECC508A */
return err;
}
#endif /* HAVE_ECC_KEY_IMPORT */
@@ -5716,13 +5706,11 @@ int wc_ecc_export_point_der(const int curve_idx, ecc_point* point, byte* out,
{
int ret = MP_OKAY;
word32 numlen;
#ifndef WOLFSSL_ATECC508A
#ifdef WOLFSSL_SMALL_STACK
byte* buf;
#else
byte buf[ECC_BUFSIZE];
#endif
#endif /* !WOLFSSL_ATECC508A */
if ((curve_idx < 0) || (wc_ecc_is_valid_idx(curve_idx) == 0))
return ECC_BAD_ARG_E;
@@ -5744,12 +5732,6 @@ int wc_ecc_export_point_der(const int curve_idx, ecc_point* point, byte* out,
return BUFFER_E;
}
#ifdef WOLFSSL_ATECC508A
/* TODO: Implement equiv call to ATECC508A */
ret = BAD_COND_E;
#else
/* store byte point type */
out[0] = ECC_POINT_UNCOMP;
@@ -5781,7 +5763,6 @@ done:
#ifdef WOLFSSL_SMALL_STACK
XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER);
#endif
#endif /* WOLFSSL_ATECC508A */
return ret;
}
@@ -6080,8 +6061,8 @@ static int ecc_check_privkey_gen_helper(ecc_key* key)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_ATECC508A
/* TODO: Implement equiv call to ATECC508A */
err = BAD_COND_E;
/* Hardware based private key, so this operation is not supported */
err = MP_OKAY; /* just report success */
#else
ALLOC_CURVE_SPECS(2);
@@ -6173,7 +6154,7 @@ int wc_ecc_check_key(ecc_key* key)
if (key->slot == ATECC_INVALID_SLOT)
return ECC_BAD_ARG_E;
err = 0; /* consider key check success on ECC508A */
err = 0; /* consider key check success on ATECC508A */
#else
#ifdef USE_ECC_B_PARAM
@@ -6330,8 +6311,11 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key,
in += 1;
#ifdef WOLFSSL_ATECC508A
/* populate key->pubkey_raw */
XMEMCPY(key->pubkey_raw, (byte*)in, sizeof(key->pubkey_raw));
/* For SECP256R1 only save raw public key for hardware */
if (curve_id == ECC_SECP256R1 && !compressed &&
inLen <= sizeof(key->pubkey_raw)) {
XMEMCPY(key->pubkey_raw, (byte*)in, sizeof(key->pubkey_raw));
}
#endif
if (err == MP_OKAY) {
@@ -6471,7 +6455,7 @@ int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen,
#ifdef WOLFSSL_ATECC508A
/* Hardware cannot export private portion */
return BAD_COND_E;
return NOT_COMPILED_IN;
#else
err = wc_export_int(&key->k, d, dLen, keySz, encType);
if (err != MP_OKAY)
@@ -6572,8 +6556,8 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz,
return ret;
#ifdef WOLFSSL_ATECC508A
/* TODO: Implement equiv call to ATECC508A */
return BAD_COND_E;
/* Hardware does not support loading private keys */
return NOT_COMPILED_IN;
#else
@@ -6835,14 +6819,6 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx,
return err;
}
#ifdef WOLFSSL_ATECC508A
/* TODO: Implement equiv call to ATECC508A */
err = BAD_COND_E;
(void)d;
(void)encType;
#else
/* init key */
#ifdef ALT_ECC_SIZE
key->pubkey.x = (mp_int*)&key->pubkey.xyz[0];
@@ -6881,9 +6857,25 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx,
if (err == MP_OKAY)
err = mp_set(key->pubkey.z, 1);
#ifdef WOLFSSL_ATECC508A
/* For SECP256R1 only save raw public key for hardware */
if (err == MP_OKAY && curve_id == ECC_SECP256R1) {
word32 keySz = key->dp->size;
err = wc_export_int(key->pubkey.x, key->pubkey_raw,
&keySz, keySz, WC_TYPE_UNSIGNED_BIN);
if (err == MP_OKAY)
err = wc_export_int(key->pubkey.y, &key->pubkey_raw[keySz],
&keySz, keySz, WC_TYPE_UNSIGNED_BIN);
}
#endif
/* import private key */
if (err == MP_OKAY) {
if (d != NULL) {
#ifdef WOLFSSL_ATECC508A
/* Hardware doesn't support loading private key */
err = NOT_COMPILED_IN;
#else
key->type = ECC_PRIVATEKEY;
if (encType == WC_TYPE_HEX_STR)
@@ -6891,7 +6883,7 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx,
else
err = mp_read_unsigned_bin(&key->k, (const byte*)d,
key->dp->size);
#endif /* WOLFSSL_ATECC508A */
} else {
key->type = ECC_PUBLICKEY;
}
@@ -6908,7 +6900,6 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx,
mp_clear(key->pubkey.z);
mp_clear(&key->k);
}
#endif /* WOLFSSL_ATECC508A */
return err;
}
@@ -9403,12 +9394,6 @@ static int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen
return BUFFER_E;
}
#ifdef WOLFSSL_ATECC508A
/* TODO: Implement equiv call to ATECC508A */
ret = BAD_COND_E;
#else
/* store first byte */
out[0] = mp_isodd(key->pubkey.y) == MP_YES ? ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN;
@@ -9418,8 +9403,6 @@ static int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen
out+1 + (numlen - mp_unsigned_bin_size(key->pubkey.x)));
*outLen = 1 + numlen;
#endif /* WOLFSSL_ATECC508A */
return ret;
}

View File

@@ -1,17 +1,36 @@
# Atmel ATECC508A Port
# Microchip/Atmel ATECC508A/ATECC608A Support
* Adds wolfCrypt support for ECC Hardware acceleration using the ATECC508A
* The new defines added for this port are: `WOLFSSL_ATMEL` and `WOLFSSL_ATECC508A`.
* Adds new PK callback for Pre Master Secret.
Support for ATECC508A using these methods:
* TLS: Using the PK callbacks and reference ATECC508A callbacks. See Coding section below. Requires options `HAVE_PK_CALLBACKS` and `WOLFSSL_ATECC_PKCB or WOLFSSL_ATECC508A`
* wolfCrypt: Native wc_ecc_* API's using the `./configure CFLAGS="-DWOLFSSL_ATECC508A"` or `#define WOLFSSL_ATECC508A`.
## Dependency
Requires the Microchip CryptoAuthLib. The examples in `wolfcrypt/src/port/atmel/atmel.c` make calls to the `atcatls_*` API's.
## Building
`./configure --enable-pkcallbacks CFLAGS="-DWOLFSSL_ATECC508A"`
### Build Options
* `HAVE_PK_CALLBACKS`: Option for enabling wolfSSL's PK callback support for TLS.
* `WOLFSSL_ATECC508A`: Enables support for initializing the CryptoAuthLib and setting up the encryption key used for the I2C communication.
* `WOLFSSL_ATECC_PKCB`: Enables support for the reference PK callbacks without init.
* `WOLFSSL_ATMEL`: Enables ASF hooks seeding random data using the `atmel_get_random_number` function.
* `WOLFSSL_ATMEL_TIME`: Enables the built-in `atmel_get_curr_time_and_date` function get getting time from ASF RTC.
* `ATECC_GET_ENC_KEY`: Macro to define your own function for getting the encryption key.
* `ATECC_SLOT_I2C_ENC`: Macro for the default encryption key slot. Can also get via the slot callback with `ATMEL_SLOT_ENCKEY`.
* `ATECC_MAX_SLOT`: Macro for the maximum dynamically allocated slots.
### Build Command Examples
`./configure --enable-pkcallbacks CFLAGS="-DWOLFSSL_ATECC_PKCB"`
`#define HAVE_PK_CALLBACKS`
`#define WOLFSSL_ATECC_PKCB`
or
`#define HAVE_PK_CALLBACKS`
`./configure CFLAGS="-DWOLFSSL_ATECC508A"`
`#define WOLFSSL_ATECC508A`
@@ -31,7 +50,7 @@ wolfSSL_CTX_SetEccSharedSecretCb(ctx, atcatls_create_pms_cb);
The reference ATECC508A PK callback functions are located in the `wolfcrypt/src/port/atmel/atmel.c` file.
Adding a custom contex to the callbacks:
Adding a custom context to the callbacks:
```
/* Setup PK Callbacks context */
@@ -49,7 +68,7 @@ wolfSSL_SetEccSharedSecretCtx(ssl, myOwnCtx);
TLS Establishment Times:
* Hardware accelerated ATECC508A: 2.342 seconds avgerage
* Hardware accelerated ATECC508A: 2.342 seconds average
* Software only: 13.422 seconds average
The TLS connection establishment time is 5.73 times faster with the ATECC508A.

View File

@@ -25,7 +25,7 @@
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A)
#if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC_PKCB)
#include <wolfssl/wolfcrypt/memory.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
@@ -50,7 +50,7 @@
#include <wolfssl/wolfcrypt/port/atmel/atmel.h>
static bool mAtcaInitDone = 0;
static int mAtcaInitDone = 0;
#ifdef WOLFSSL_ATECC508A
@@ -59,6 +59,10 @@ static atmel_slot_alloc_cb mSlotAlloc;
static atmel_slot_dealloc_cb mSlotDealloc;
static int mSlotList[ATECC_MAX_SLOT+1];
#ifndef ATECC_SLOT_I2C_ENC
#define ATECC_SLOT_I2C_ENC 0x04 /* Slot holding symmetric encryption key */
#endif
/**
* \brief Structure to contain certificate information.
*/
@@ -112,12 +116,12 @@ int atmel_get_random_block(unsigned char* output, unsigned int sz)
}
#if defined(WOLFSSL_ATMEL) && defined(WOLFSSL_ATMEL_TIME)
extern struct rtc_module *_rtc_instance[RTC_INST_NUM];
#endif
extern struct rtc_module *_rtc_instance[RTC_INST_NUM];
long atmel_get_curr_time_and_date(long* tm)
{
long rt = 0;
#if defined(WOLFSSL_ATMEL) && defined(WOLFSSL_ATMEL_TIME)
/* Get current time */
struct rtc_calendar_time rtcTime;
const int monthDay[] = {0,31,59,90,120,151,181,212,243,273,304,334};
@@ -144,11 +148,11 @@ long atmel_get_curr_time_and_date(long* tm)
)
)
);
#endif /* WOLFSSL_ATMEL_TIME */
(void)tm;
return rt;
}
#endif
#ifdef WOLFSSL_ATECC508A
@@ -163,15 +167,20 @@ int atmel_set_slot_allocator(atmel_slot_alloc_cb alloc,
}
/* Function to allocate new slot number */
int atmel_ecc_alloc(void)
int atmel_ecc_alloc(int slotType)
{
int slot = ATECC_INVALID_SLOT;
if (mSlotAlloc) {
slot = mSlotAlloc();
slot = mSlotAlloc(slotType);
}
else {
int i;
if (slotType == ATMEL_SLOT_ENCKEY) {
return ATECC_SLOT_I2C_ENC;
}
for (i=0; i <= ATECC_MAX_SLOT; i++) {
/* Find free slot */
if (mSlotList[i] == ATECC_INVALID_SLOT) {
@@ -198,10 +207,11 @@ void atmel_ecc_free(int slot)
}
/* The macros ATCA_TLS_GET_ENC_KEY can be set to override the default
/* The macros ATECC_GET_ENC_KEY can be set to override the default
encryption key with your own at build-time */
#ifndef ATCA_TLS_GET_ENC_KEY
#define ATCA_TLS_GET_ENC_KEY atmel_get_enc_key
#ifndef ATECC_GET_ENC_KEY
#define ATECC_GET_ENC_KEY atmel_get_enc_key
/**
* \brief Callback function for getting the current encryption key
*/
@@ -224,17 +234,22 @@ static int atmel_init_enc_key(void)
{
uint8_t ret = 0;
uint8_t read_key[ATECC_KEY_SIZE];
int slot = atmel_ecc_alloc(ATMEL_SLOT_ENCKEY);
/* check for encryption key slot */
if (slot == ATECC_INVALID_SLOT)
return -1;
/* get encryption key */
ATCA_TLS_GET_ENC_KEY(read_key, sizeof(read_key));
ret = atcatls_set_enckey(read_key, TLS_SLOT_ENC_PARENT, 0);
ATECC_GET_ENC_KEY(read_key, sizeof(read_key));
ret = atcatls_set_enckey(read_key, slot, 0);
ForceZero(read_key, sizeof(read_key));
if (ret != ATCA_SUCCESS) {
WOLFSSL_MSG("Failed to write key");
return -1;
}
ret = atcatlsfn_set_get_enckey(ATCA_TLS_GET_ENC_KEY);
ret = atcatlsfn_set_get_enckey(ATECC_GET_ENC_KEY);
if (ret != ATCA_SUCCESS) {
WOLFSSL_MSG("Failed to set enckey cb");
return -1;
@@ -549,6 +564,25 @@ exit:
return ret;
}
int atcatls_set_callbacks(WOLFSSL_CTX* ctx)
{
wolfSSL_CTX_SetEccKeyGenCb(ctx, atcatls_create_key_cb);
wolfSSL_CTX_SetEccVerifyCb(ctx, atcatls_verify_signature_cb);
wolfSSL_CTX_SetEccSignCb(ctx, atcatls_sign_certificate_cb);
wolfSSL_CTX_SetEccSharedSecretCb(ctx, atcatls_create_pms_cb);
return 0;
}
int atcatls_set_callback_ctx(WOLFSSL* ssl, void* user_ctx)
{
wolfSSL_SetEccKeyGenCtx(ssl, user_ctx);
wolfSSL_SetEccVerifyCtx(ssl, user_ctx);
wolfSSL_SetEccSignCtx(ssl, user_ctx);
wolfSSL_SetEccSharedSecretCtx(ssl, user_ctx);
return 0;
}
#endif /* HAVE_PK_CALLBACKS */
#endif /* WOLFSSL_ATMEL || WOLFSSL_ATECC508A */
#endif /* WOLFSSL_ATMEL || WOLFSSL_ATECC508A || WOLFSSL_ATECC_PKCB */

View File

@@ -1,4 +1,4 @@
/* atecc508.h
/* atmel.h
*
* Copyright (C) 2006-2018 wolfSSL Inc.
*
@@ -25,10 +25,9 @@
#include <stdint.h>
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/ssl.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#ifdef WOLFSSL_ATECC508A
#if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC_PKCB)
#undef SHA_BLOCK_SIZE
#define SHA_BLOCK_SIZE SHA_BLOCK_SIZE_REMAP
#include <cryptoauthlib.h>
@@ -42,11 +41,18 @@
#define ATECC_KEY_SIZE (32)
#define ATECC_PUBKEY_SIZE (ATECC_KEY_SIZE*2) /* X and Y */
#define ATECC_SIG_SIZE (ATECC_KEY_SIZE*2) /* R and S */
#ifndef ATECC_MAX_SLOT
#define ATECC_MAX_SLOT (0x7) /* Only use 0-7 */
#endif
#define ATECC_INVALID_SLOT (-1)
/* ATECC_KEY_SIZE required for ecc.h */
#include <wolfssl/wolfcrypt/ecc.h>
struct WOLFSSL;
struct WOLFSSL_CTX;
struct WOLFSSL_X509_STORE_CTX;
struct ecc_key;
/* Cert Structure */
typedef struct t_atcert {
@@ -66,28 +72,41 @@ void atmel_finish(void);
int atmel_get_random_number(uint32_t count, uint8_t* rand_out);
long atmel_get_curr_time_and_date(long* tm);
int atmel_ecc_alloc(void);
#ifdef WOLFSSL_ATECC508A
enum atmelSlotType {
ATMEL_SLOT_ANY,
ATMEL_SLOT_ENCKEY,
ATMEL_SLOT_DEVICE,
ATMEL_SLOT_ECDHE,
ATMEL_SLOT_ECDHEPUB,
};
int atmel_ecc_alloc(int slotType);
void atmel_ecc_free(int slot);
typedef int (*atmel_slot_alloc_cb)(void);
typedef int (*atmel_slot_alloc_cb)(int);
typedef void (*atmel_slot_dealloc_cb)(int);
int atmel_set_slot_allocator(atmel_slot_alloc_cb alloc,
atmel_slot_dealloc_cb dealloc);
#include <wolfssl/wolfcrypt/ecc.h>
#endif /* WOLFSSL_ATECC508A */
#ifdef HAVE_PK_CALLBACKS
int atcatls_create_key_cb(WOLFSSL* ssl, ecc_key* key, word32 keySz,
int atcatls_create_key_cb(struct WOLFSSL* ssl, struct ecc_key* key, word32 keySz,
int ecc_curve, void* ctx);
int atcatls_create_pms_cb(WOLFSSL* ssl, ecc_key* otherKey,
int atcatls_create_pms_cb(struct WOLFSSL* ssl, struct ecc_key* otherKey,
unsigned char* pubKeyDer, unsigned int* pubKeySz,
unsigned char* out, unsigned int* outlen,
int side, void* ctx);
int atcatls_sign_certificate_cb(WOLFSSL* ssl, const byte* in, word32 inSz,
int atcatls_sign_certificate_cb(struct WOLFSSL* ssl, const byte* in, word32 inSz,
byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx);
int atcatls_verify_signature_cb(WOLFSSL* ssl, const byte* sig, word32 sigSz,
int atcatls_verify_signature_cb(struct WOLFSSL* ssl, const byte* sig, word32 sigSz,
const byte* hash, word32 hashSz, const byte* key, word32 keySz, int* result,
void* ctx);
int atcatls_set_callbacks(struct WOLFSSL_CTX* ctx);
int atcatls_set_callback_ctx(struct WOLFSSL* ssl, void* user_ctx);
#endif
#endif /* _ATECC508_H_ */