diff --git a/src/internal.c b/src/internal.c index ef62d7dc0..83ce2f4a0 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2965,16 +2965,89 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, return ret; } +#ifdef HAVE_PK_CALLBACKS + /* Gets ECC key for shared secret callback testing + * Client side: returns peer key + * Server side: returns private key + */ + static int EccGetKey(WOLFSSL* ssl, ecc_key** otherKey) + { + int ret = NO_PEER_KEY; + ecc_key* tmpKey = NULL; + + if (ssl == NULL || otherKey == NULL) { + return BAD_FUNC_ARG; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ssl->specs.static_ecdh) { + if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent || + !ssl->peerEccDsaKey->dp) { + return NO_PEER_KEY; + } + tmpKey = (struct ecc_key*)ssl->peerEccDsaKey; + } + else { + if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || + !ssl->peerEccKey->dp) { + return NO_PEER_KEY; + } + tmpKey = (struct ecc_key*)ssl->peerEccKey; + } + } + else if (ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->specs.static_ecdh) { + if (ssl->sigKey == NULL) { + return NO_PRIVATE_KEY; + } + tmpKey = (struct ecc_key*)ssl->sigKey; + } + else { + if (!ssl->eccTempKeyPresent) { + return NO_PRIVATE_KEY; + } + tmpKey = (struct ecc_key*)ssl->eccTempKey; + } + } + + if (tmpKey) { + *otherKey = tmpKey; + ret = 0; + } + + return ret; + } +#endif /* HAVE_PK_CALLBACKS */ + int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key, - byte* out, word32* outSz) + byte* pubKeyDer, word32* pubKeySz, byte* out, word32* outlen, + int side, void* ctx) { int ret; (void)ssl; + (void)pubKeyDer; + (void)pubKeySz; + (void)side; + (void)ctx; WOLFSSL_ENTER("EccSharedSecret"); - ret = wc_ecc_shared_secret(priv_key, pub_key, out, outSz); +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->EccSharedSecretCb) { + ecc_key* otherKey = NULL; + + ret = EccGetKey(ssl, &otherKey); + if (ret == 0) { + ret = ssl->ctx->EccSharedSecretCb(ssl, otherKey, pubKeyDer, + pubKeySz, out, outlen, side, ctx); + } + } + else +#endif + { + ret = wc_ecc_shared_secret(priv_key, pub_key, out, outlen); + } /* Handle async pending response */ #if defined(WOLFSSL_ASYNC_CRYPT) @@ -15437,6 +15510,13 @@ int SendClientKeyExchange(WOLFSSL* ssl) ERROR_OUT(NO_PEER_KEY, exit_scke); } + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + /* create private key */ ssl->sigKey = XMALLOC(sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_ECC); @@ -15450,7 +15530,8 @@ int SendClientKeyExchange(WOLFSSL* ssl) if (ret != 0) { goto exit_scke; } - ret = EccMakeKey(ssl, (ecc_key*)ssl->sigKey, ssl->peerEccKey); + ret = EccMakeKey(ssl, (ecc_key*)ssl->sigKey, + ssl->peerEccKey); break; #endif /* HAVE_ECC && !NO_PSK */ #ifdef HAVE_NTRU @@ -15465,10 +15546,18 @@ int SendClientKeyExchange(WOLFSSL* ssl) { ecc_key* peerKey; + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + if (ssl->specs.static_ecdh) { /* TODO: EccDsa is really fixed Ecc change naming */ - if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent || - !ssl->peerEccDsaKey->dp) { + if (!ssl->peerEccDsaKey || + !ssl->peerEccDsaKeyPresent || + !ssl->peerEccDsaKey->dp) { ERROR_OUT(NO_PEER_KEY, exit_scke); } peerKey = ssl->peerEccDsaKey; @@ -15649,21 +15738,22 @@ int SendClientKeyExchange(WOLFSSL* ssl) output += esSz; encSz = esSz + OPAQUE16_LEN; - /* Place ECC key in output buffer, leaving room for size */ + /* length is used for public key size */ *length = MAX_ENCRYPT_SZ; + + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + + /* Place ECC key in buffer, leaving room for size */ ret = wc_ecc_export_x963((ecc_key*)ssl->sigKey, - output + 1, length); + output + OPAQUE8_LEN, length); if (ret != 0) { ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); } - - *output = (byte)*length; /* place size of key in output buffer */ - encSz += *length + 1; - - /* Create shared ECC key leaving room at the begining - of buffer for size of shared key. Note sizeof - preMasterSecret is ENCRYPT_LEN currently 512 */ - *length = sizeof(ssl->arrays->preMasterSecret) - OPAQUE16_LEN; break; } #endif /* HAVE_ECC && !NO_PSK */ @@ -15684,18 +15774,19 @@ int SendClientKeyExchange(WOLFSSL* ssl) #ifdef HAVE_ECC case ecc_diffie_hellman_kea: { - /* precede export with 1 byte length */ - *length = MAX_ENCRYPT_SZ; + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + + /* Place ECC key in buffer, leaving room for size */ ret = wc_ecc_export_x963((ecc_key*)ssl->sigKey, - encSecret + 1, length); + encSecret + OPAQUE8_LEN, &encSz); if (ret != 0) { ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); } - - encSecret[0] = (byte)*length; - encSz = *length + 1; - - *length = sizeof(ssl->arrays->preMasterSecret); break; } #endif /* HAVE_ECC */ @@ -15778,10 +15869,22 @@ int SendClientKeyExchange(WOLFSSL* ssl) #if defined(HAVE_ECC) && !defined(NO_PSK) case ecdhe_psk_kea: { - ret = EccSharedSecret(ssl, (ecc_key*)ssl->sigKey, - ssl->peerEccKey, + /* Create shared ECC key leaving room at the begining + of buffer for size of shared key. */ + ssl->arrays->preMasterSz = ENCRYPT_LEN - OPAQUE16_LEN; + + ret = EccSharedSecret(ssl, + (ecc_key*)ssl->sigKey, ssl->peerEccKey, + output + OPAQUE8_LEN, length, ssl->arrays->preMasterSecret + OPAQUE16_LEN, - length); + &ssl->arrays->preMasterSz, + WOLFSSL_CLIENT_END, + #ifdef HAVE_PK_CALLBACKS + ssl->EccSharedSecretCtx + #else + NULL + #endif + ); break; } #endif /* HAVE_ECC && !NO_PSK */ @@ -15815,8 +15918,20 @@ int SendClientKeyExchange(WOLFSSL* ssl) ecc_key* peerKey = (ssl->specs.static_ecdh) ? ssl->peerEccDsaKey : ssl->peerEccKey; - ret = EccSharedSecret(ssl, (ecc_key*)ssl->sigKey, peerKey, - ssl->arrays->preMasterSecret, length); + ssl->arrays->preMasterSz = ENCRYPT_LEN; + + ret = EccSharedSecret(ssl, + (ecc_key*)ssl->sigKey, peerKey, + encSecret + OPAQUE8_LEN, &encSz, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + WOLFSSL_CLIENT_END, + #ifdef HAVE_PK_CALLBACKS + ssl->EccSharedSecretCtx + #else + NULL + #endif + ); break; } #endif /* HAVE_ECC */ @@ -15861,6 +15976,11 @@ int SendClientKeyExchange(WOLFSSL* ssl) { byte* pms = ssl->arrays->preMasterSecret; + /* validate args */ + if (output == NULL || *length == 0) { + ERROR_OUT(BAD_FUNC_ARG, exit_scke); + } + c16toa((word16)*length, output); encSz += *length + OPAQUE16_LEN; c16toa((word16)ssl->arrays->preMasterSz, pms); @@ -15884,10 +16004,19 @@ int SendClientKeyExchange(WOLFSSL* ssl) { byte* pms = ssl->arrays->preMasterSecret; + /* validate args */ + if (output == NULL || *length > ENCRYPT_LEN) { + ERROR_OUT(BAD_FUNC_ARG, exit_scke); + } + + /* place size of public key in output buffer */ + *output = (byte)*length; + encSz += *length + OPAQUE8_LEN; + /* Create pre master secret is the concatination of eccSize + eccSharedKey + pskSize + pskKey */ - c16toa((word16)*length, pms); - ssl->arrays->preMasterSz += OPAQUE16_LEN + *length; + c16toa((word16)ssl->arrays->preMasterSz, pms); + ssl->arrays->preMasterSz += OPAQUE16_LEN; pms += ssl->arrays->preMasterSz; c16toa((word16)ssl->arrays->psk_keySz, pms); @@ -15910,7 +16039,9 @@ int SendClientKeyExchange(WOLFSSL* ssl) #ifdef HAVE_ECC case ecc_diffie_hellman_kea: { - ssl->arrays->preMasterSz = *length; + /* place size of public key in buffer */ + *encSecret = (byte)encSz; + encSz += OPAQUE8_LEN; break; } #endif /* HAVE_ECC */ @@ -19839,11 +19970,6 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_ECC case ecc_diffie_hellman_kea: { - if (!ssl->specs.static_ecdh && - ssl->eccTempKeyPresent == 0) { - WOLFSSL_MSG("Ecc ephemeral key not made correctly"); - ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); - } break; } #endif /* HAVE_ECC */ @@ -19872,11 +19998,6 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("No server PSK callback set"); ERROR_OUT(PSK_KEY_ERROR, exit_dcke); } - - if (ssl->eccTempKeyPresent == 0) { - WOLFSSL_MSG("Ecc ephemeral key not made correctly"); - ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); - } break; } #endif /* HAVE_ECC && !NO_PSK */ @@ -20093,10 +20214,23 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(BUFFER_ERROR, exit_dcke); } + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + + if (!ssl->specs.static_ecdh && + ssl->eccTempKeyPresent == 0) { + WOLFSSL_MSG("Ecc ephemeral key not made correctly"); + ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); + } + if (ssl->peerEccKey == NULL) { /* alloc/init on demand */ - ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); + ssl->peerEccKey = (ecc_key*)XMALLOC( + sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_ECC); if (ssl->peerEccKey == NULL) { WOLFSSL_MSG("PeerEccKey Memory error"); ERROR_OUT(MEMORY_E, exit_dcke); @@ -20116,19 +20250,12 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } } - if (wc_ecc_import_x963_ex(input + idx, length, ssl->peerEccKey, - private_key->dp->id)) { + if (wc_ecc_import_x963_ex(input + idx, length, + ssl->peerEccKey, private_key->dp->id)) { ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); } - idx += length; ssl->peerEccKeyPresent = 1; - - ssl->sigLen = sizeof(ssl->arrays->preMasterSecret); - - if (ret != 0) { - goto exit_dcke; - } break; } #endif /* HAVE_ECC */ @@ -20229,10 +20356,22 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(BUFFER_ERROR, exit_dcke); } + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + + if (ssl->eccTempKeyPresent == 0) { + WOLFSSL_MSG("Ecc ephemeral key not made correctly"); + ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); + } + if (ssl->peerEccKey == NULL) { /* alloc/init on demand */ - ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); + ssl->peerEccKey = (ecc_key*)XMALLOC( + sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_ECC); if (ssl->peerEccKey == NULL) { WOLFSSL_MSG("PeerEccKey Memory error"); ERROR_OUT(MEMORY_E, exit_dcke); @@ -20242,7 +20381,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ret != 0) { goto exit_dcke; } - } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ + } + else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ wc_ecc_free(ssl->peerEccKey); ssl->peerEccKeyPresent = 0; ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, @@ -20251,21 +20391,13 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto exit_dcke; } } + if (wc_ecc_import_x963_ex(input + idx, length, - ssl->peerEccKey, ssl->eccTempKey->dp->id)) { + ssl->peerEccKey, ssl->eccTempKey->dp->id)) { ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); } - idx += length; ssl->peerEccKeyPresent = 1; - - /* Note sizeof preMasterSecret is ENCRYPT_LEN currently 512 */ - ssl->sigLen = sizeof(ssl->arrays->preMasterSecret); - - if (ssl->eccTempKeyPresent == 0) { - WOLFSSL_MSG("Ecc ephemeral key not made correctly"); - ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); - } break; } #endif /* HAVE_ECC && !NO_PSK */ @@ -20325,9 +20457,21 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, private_key = (ecc_key*)ssl->sigKey; } + ssl->arrays->preMasterSz = ENCRYPT_LEN; + /* Generate shared secret */ - ret = EccSharedSecret(ssl, private_key, ssl->peerEccKey, - ssl->arrays->preMasterSecret, &ssl->sigLen); + ret = EccSharedSecret(ssl, + private_key, ssl->peerEccKey, + input + idx, &length, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + WOLFSSL_SERVER_END, + #ifdef HAVE_PK_CALLBACKS + ssl->EccSharedSecretCtx + #else + NULL + #endif + ); break; } #endif /* HAVE_ECC */ @@ -20377,12 +20521,21 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if defined(HAVE_ECC) && !defined(NO_PSK) case ecdhe_psk_kea: { + ssl->sigLen = ENCRYPT_LEN - OPAQUE16_LEN; + /* Generate shared secret */ ret = EccSharedSecret(ssl, - ssl->eccTempKey, - ssl->peerEccKey, + ssl->eccTempKey, ssl->peerEccKey, + input + idx, &length, ssl->arrays->preMasterSecret + OPAQUE16_LEN, - &ssl->sigLen); + &ssl->sigLen, + WOLFSSL_SERVER_END, + #ifdef HAVE_PK_CALLBACKS + ssl->EccSharedSecretCtx + #else + NULL + #endif + ); break; } #endif /* HAVE_ECC && !NO_PSK */ @@ -20436,7 +20589,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_ECC case ecc_diffie_hellman_kea: { - ssl->arrays->preMasterSz = ssl->sigLen; + /* skip past the imported peer key */ + idx += length; break; } #endif /* HAVE_ECC */ @@ -20483,6 +20637,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { byte* pms = ssl->arrays->preMasterSecret; + /* skip past the imported peer key */ + idx += length; + /* Add preMasterSecret */ c16toa((word16)ssl->sigLen, pms); ssl->arrays->preMasterSz += OPAQUE16_LEN + ssl->sigLen; diff --git a/src/io.c b/src/io.c index c861350d1..bbfd971af 100644 --- a/src/io.c +++ b/src/io.c @@ -80,6 +80,8 @@ #elif defined(WOLFSSL_VXWORKS) #include #include + #elif defined(WOLFSSL_ATMEL) + #include "socket/include/socket.h" #else #include #include diff --git a/src/ssl.c b/src/ssl.c index c02016ed9..a865bed42 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -958,6 +958,7 @@ int wolfSSL_SetMinEccKey_Sz(WOLFSSL* ssl, short keySz) ssl->options.minEccKeySz = keySz / 8; return SSL_SUCCESS; } + #endif /* !NO_RSA */ #ifndef NO_RSA @@ -18202,6 +18203,26 @@ void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl) return NULL; } +void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX* ctx, CallbackEccSharedSecret cb) +{ + if (ctx) + ctx->EccSharedSecretCb = cb; +} + +void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->EccSharedSecretCtx = ctx; +} + + +void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->EccSharedSecretCtx; + + return NULL; +} #endif /* HAVE_ECC */ #ifndef NO_RSA diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 87f92c720..07a488f58 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -2530,7 +2530,8 @@ void bench_ed25519KeySign(void) } #elif defined(WOLFSSL_IAR_ARM_TIME) || defined (WOLFSSL_MDK_ARM) || defined(WOLFSSL_USER_CURRTIME) - extern double current_time(int reset); + /* declared above at line 189 */ + /* extern double current_time(int reset); */ #elif defined FREERTOS diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c old mode 100644 new mode 100755 index 84b4d8813..28e3cb02a --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -149,10 +149,16 @@ ASN Options: #elif defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS) #include #ifndef XTIME - #define XTIME(t1) 0 + #define XTIME(t1) ksdk_time((t1)) #endif #define XGMTIME(c, t) gmtime((c)) +#elif defined(WOLFSSL_ATMEL) + #define XTIME(t1) atmel_get_curr_time_and_date((t1)) + #define WOLFSSL_GMTIME + #define USE_WOLF_TM + #define USE_WOLF_TIME_T + #elif defined(IDIRECT_DEV_TIME) /*Gets the timestamp from cloak software owned by VT iDirect in place of time() from */ @@ -224,6 +230,8 @@ ASN Options: #elif defined(TIME_OVERRIDES) extern time_t XTIME(time_t * timer); extern struct tm* XGMTIME(const time_t* timer, struct tm* tmp); +#elif defined(WOLFSSL_GMTIME) + struct tm* gmtime(const time_t* timer); #endif diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 4e53d8938..142f94e32 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -918,6 +918,12 @@ const ecc_set_type ecc_sets[] = { static oid_cache_t ecc_oid_cache[sizeof(ecc_sets)/sizeof(ecc_set_type)]; #endif +#ifdef HAVE_COMP_KEY +static int wc_ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen); +#endif + +#ifndef WOLFSSL_ATECC508A + int ecc_map(ecc_point*, mp_int*, mp_digit); int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, mp_int* a, mp_int* modulus, mp_digit mp); @@ -932,9 +938,7 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB, int mp_jacobi(mp_int* a, mp_int* n, int* c); int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret); -#ifdef HAVE_COMP_KEY -static int wc_ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen); -#endif +#endif /* WOLFSSL_ATECC508A */ static int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) @@ -972,6 +976,7 @@ static int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) return 0; } +#ifndef WOLFSSL_ATECC508A /* helper for either lib */ static int get_digit_count(mp_int* a) @@ -2263,6 +2268,9 @@ int wc_ecc_cmp_point(ecc_point* a, ecc_point *b) return MP_EQ; } +#endif /* !WOLFSSL_ATECC508A */ + + /** Returns whether an ECC idx is valid or not n The idx number to check return 1 if valid, 0 if not @@ -2295,11 +2303,13 @@ int wc_ecc_is_valid_idx(int n) int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, word32* outlen) { + int err = 0; +#ifndef WOLFSSL_ATECC508A word32 x = 0; ecc_point* result; mp_int prime; mp_int a; - int err; +#endif /* !WOLFSSL_ATECC508A */ if (private_key == NULL || public_key == NULL || out == NULL || outlen == NULL) { @@ -2340,6 +2350,15 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, } #endif +#ifdef WOLFSSL_ATECC508A + err = atcatls_ecdh(private_key->slot, public_key->pubkey, out); + if (err != ATCA_SUCCESS) { + err = BAD_COND_E; + } + *outlen = private_key->dp->size; + +#else + /* make new point */ result = wc_ecc_new_point_h(private_key->heap); if (result == NULL) { @@ -2379,9 +2398,13 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, #endif wc_ecc_del_point_h(result, private_key->heap); +#endif /* WOLFSSL_ATECC508A */ + return err; } +#ifndef WOLFSSL_ATECC508A + /** Create an ECC shared secret between private key and public point private_key The private ECC key (heap hint based on private key) @@ -2455,8 +2478,10 @@ int wc_ecc_shared_secret_ssh(ecc_key* private_key, ecc_point* point, return err; } +#endif /* !WOLFSSL_ATECC508A */ #endif /* HAVE_ECC_DHE */ +#ifndef WOLFSSL_ATECC508A /* return 1 if point is at infinity, 0 if not, < 0 on error */ int wc_ecc_point_is_at_infinity(ecc_point* p) { @@ -2469,10 +2494,13 @@ int wc_ecc_point_is_at_infinity(ecc_point* p) return 0; } +#endif /* WOLFSSL_ATECC508A */ + int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) { int err; +#ifndef WOLFSSL_ATECC508A ecc_point* base = NULL; mp_int prime; mp_int a; @@ -2482,6 +2510,7 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) #else byte buf[ECC_MAXSIZE_GEN]; #endif +#endif /* !WOLFSSL_ATECC508A */ if (key == NULL || rng == NULL) { return BAD_FUNC_ARG; @@ -2510,6 +2539,15 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) } #endif +#ifdef WOLFSSL_ATECC508A + key->type = ECC_PRIVATEKEY; + err = atcatls_create_key(key->slot, key->pubkey); + if (err != ATCA_SUCCESS) { + err = BAD_COND_E; + } + +#else + #ifdef WOLFSSL_SMALL_STACK buf = (byte*)XMALLOC(ECC_MAXSIZE_GEN, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (buf == NULL) @@ -2628,6 +2666,7 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) #ifdef WOLFSSL_SMALL_STACK XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif +#endif /* WOLFSSL_ATECC508A */ return err; } @@ -2721,6 +2760,13 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) key->dp = NULL; key->idx = 0; +#ifdef WOLFSSL_ATECC508A + key->slot = atmel_ecc_alloc(); + if (key->slot == ATECC_INVALID_SLOT) { + return ECC_BAD_ARG_E; + } +#else + #ifndef USE_FAST_MATH key->pubkey.x->dp = NULL; key->pubkey.y->dp = NULL; @@ -2742,6 +2788,8 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) alt_fp_init(key->pubkey.z); #endif +#endif /* WOLFSSL_ATECC508A */ + #ifdef WOLFSSL_HEAP_TEST key->heap = (void*)WOLFSSL_HEAP_TEST; #else @@ -2810,16 +2858,61 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, } #endif + /* is this a private key? */ + if (key->type != ECC_PRIVATEKEY) + return ECC_BAD_ARG_E; + + /* is the IDX valid ? */ + if (wc_ecc_is_valid_idx(key->idx) != 1) + return ECC_BAD_ARG_E; + if ((err = mp_init_multi(&r, &s, NULL, NULL, NULL, NULL)) != MP_OKAY) { return err; } - err = wc_ecc_sign_hash_ex(in, inlen, rng, key, &r, &s); - if (err == MP_OKAY) { - /* encoded with DSA header */ - err = StoreECC_DSA_Sig(out, outlen, &r, &s); +#ifdef WOLFSSL_ATECC508A + /* Check args */ + if (inlen != ATECC_KEY_SIZE || *outlen < SIGN_RSP_SIZE) { + err = ECC_BAD_ARG_E; + goto exit_sign; } + /* Sign: Result is 32-bytes of R then 32-bytes of S */ + err = atcatls_sign(key->slot, in, out); + if (err != ATCA_SUCCESS) { + err = BAD_COND_E; + goto exit_sign; + } + + /* Load R and S */ + err = mp_read_unsigned_bin(&r, &out[0], ATECC_KEY_SIZE); + if (err != MP_OKAY) { + goto exit_sign; + } + err = mp_read_unsigned_bin(&s, &out[ATECC_KEY_SIZE], ATECC_KEY_SIZE); + if (err != MP_OKAY) { + goto exit_sign; + } + + /* Check for zeros */ + if (mp_iszero(&r) || mp_iszero(&s)) { + err = MP_ZERO_E; + goto exit_sign; + } + +#else + + err = wc_ecc_sign_hash_ex(in, inlen, rng, key, &r, &s); + if (err != MP_OKAY) { + goto exit_sign; + } + + err = StoreECC_DSA_Sig(out, outlen, &r, &s); + +#endif /* WOLFSSL_ATECC508A */ + +exit_sign: + #ifndef USE_FAST_MATH mp_clear(&r); mp_clear(&s); @@ -2829,6 +2922,8 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, } #endif /* !NO_ASN */ +#ifndef WOLFSSL_ATECC508A + /** Sign a message digest in The message digest to sign @@ -2937,6 +3032,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, return err; } +#endif /* !WOLFSSL_ATECC508A */ #endif /* HAVE_ECC_SIGN */ /** @@ -2955,13 +3051,20 @@ void wc_ecc_free(ecc_key* key) } #endif +#ifdef WOLFSSL_ATECC508A + atmel_ecc_free(key->slot); + key->slot = -1; +#else + mp_clear(key->pubkey.x); mp_clear(key->pubkey.y); mp_clear(key->pubkey.z); mp_forcezero(&key->k); +#endif /* !WOLFSSL_ATECC508A */ } +#ifndef WOLFSSL_ATECC508A #ifdef ECC_SHAMIR /** Computes kA*A + kB*B = C using Shamir's Trick @@ -3187,8 +3290,8 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, return err; } - #endif /* ECC_SHAMIR */ +#endif /* !WOLFSSL_ATECC508A */ #ifdef HAVE_ECC_VERIFY @@ -3219,6 +3322,9 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, mp_int r; mp_int s; int err; +#ifdef WOLFSSL_ATECC508A + byte sigRS[ATECC_KEY_SIZE*2]; +#endif if (sig == NULL || hash == NULL || stat == NULL || key == NULL) { return ECC_BAD_ARG_E; @@ -3255,9 +3361,33 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, XMEMSET(&s, 0, sizeof(s)); err = DecodeECC_DSA_Sig(sig, siglen, &r, &s); + if (err != 0) { + goto exit_verify; + } - if (err == MP_OKAY) - err = wc_ecc_verify_hash_ex(&r, &s, hash, hashlen, stat, key); +#ifdef WOLFSSL_ATECC508A + /* Extract R and S */ + err = mp_to_unsigned_bin(&r, &sigRS[0]); + if (err != MP_OKAY) { + goto exit_verify; + } + err = mp_to_unsigned_bin(&s, &sigRS[ATECC_KEY_SIZE]); + if (err != MP_OKAY) { + goto exit_verify; + } + + err = atcatls_verify(hash, sigRS, key->pubkey, (bool*)stat); + if (err != ATCA_SUCCESS) { + err = BAD_COND_E; + } + +#else + + err = wc_ecc_verify_hash_ex(&r, &s, hash, hashlen, stat, key); + +#endif /* WOLFSSL_ATECC508A */ + +exit_verify: #ifndef USE_FAST_MATH mp_clear(&r); @@ -3268,6 +3398,9 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, } #endif /* !NO_ASN */ + +#ifndef WOLFSSL_ATECC508A + /** Verify an ECC signature r The signature R component to verify @@ -3442,9 +3575,11 @@ done: return err; } +#endif /* !WOLFSSL_ATECC508A */ #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_KEY_IMPORT +#ifndef WOLFSSL_ATECC508A /* import point from der */ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, ecc_point* point) @@ -3567,6 +3702,7 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, return err; } +#endif /* !WOLFSSL_ATECC508A */ #endif /* HAVE_ECC_KEY_IMPORT */ #ifdef HAVE_ECC_KEY_EXPORT @@ -3574,13 +3710,15 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, int wc_ecc_export_point_der(const int curve_idx, ecc_point* point, byte* out, word32* outLen) { + int ret = MP_OKAY; + word32 numlen; +#ifndef WOLFSSL_ATECC508A #ifdef WOLFSSL_SMALL_STACK byte* buf; #else byte buf[ECC_BUFSIZE]; #endif - word32 numlen; - int ret = MP_OKAY; +#endif /* !WOLFSSL_ATECC508A */ if ((curve_idx < 0) || (wc_ecc_is_valid_idx(curve_idx) == 0)) return ECC_BAD_ARG_E; @@ -3602,6 +3740,12 @@ 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 0x04 */ out[0] = 0x04; @@ -3633,6 +3777,7 @@ done: #ifdef WOLFSSL_SMALL_STACK XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif +#endif /* WOLFSSL_ATECC508A */ return ret; } @@ -3641,13 +3786,15 @@ done: /* export public ECC key in ANSI X9.63 format */ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) { + word32 numlen; + int ret = MP_OKAY; +#ifndef WOLFSSL_ATECC508A #ifdef WOLFSSL_SMALL_STACK byte* buf; #else byte buf[ECC_BUFSIZE]; #endif - word32 numlen; - int ret = MP_OKAY; +#endif /* return length needed only */ if (key != NULL && out == NULL && outLen != NULL) { @@ -3669,6 +3816,12 @@ int wc_ecc_export_x963(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 byte 0x04 */ out[0] = 0x04; @@ -3700,6 +3853,7 @@ done: #ifdef WOLFSSL_SMALL_STACK XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif +#endif /* WOLFSSL_ATECC508A */ return ret; } @@ -3722,6 +3876,8 @@ int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen, #endif /* HAVE_ECC_KEY_EXPORT */ +#ifndef WOLFSSL_ATECC508A + /* is ecc point on curve described by dp ? */ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) { @@ -3815,9 +3971,9 @@ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) /* validate privkey * generator == pubkey, 0 on success */ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) { + int err = MP_OKAY; ecc_point* base = NULL; ecc_point* res = NULL; - int err; if (key == NULL) return BAD_FUNC_ARG; @@ -3863,13 +4019,21 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) /* check privkey generator helper, creates prime needed */ static int ecc_check_privkey_gen_helper(ecc_key* key) { + int err = MP_OKAY; +#ifndef WOLFSSL_ATECC508A mp_int prime; mp_int a; - int err; +#endif /* !WOLFSSL_ATECC508A */ if (key == NULL) return BAD_FUNC_ARG; +#ifdef WOLFSSL_ATECC508A + /* TODO: Implement equiv call to ATECC508A */ + err = BAD_COND_E; + +#else + err = mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL); if (err != MP_OKAY) return err; @@ -3886,6 +4050,7 @@ static int ecc_check_privkey_gen_helper(ecc_key* key) mp_clear(&prime); mp_clear(&a); #endif +#endif /* WOLFSSL_ATECC508A */ return err; } @@ -3918,18 +4083,28 @@ static int ecc_check_pubkey_order(ecc_key* key, mp_int* a, mp_int* prime, return err; } +#endif /* !WOLFSSL_ATECC508A */ + /* perform sanity checks on ecc key validity, 0 on success */ int wc_ecc_check_key(ecc_key* key) { + int err = MP_OKAY; +#ifndef WOLFSSL_ATECC508A mp_int prime; /* used by multiple calls so let's cache */ mp_int a; mp_int order; /* other callers have, so let's gen here */ - int err; +#endif /* !WOLFSSL_ATECC508A */ if (key == NULL) return BAD_FUNC_ARG; +#ifdef WOLFSSL_ATECC508A + /* TODO: Implement equiv call to ATECC508A */ + err = BAD_COND_E; + +#else + /* pubkey point cannot be at infinity */ if (wc_ecc_point_is_at_infinity(&key->pubkey)) return ECC_INF_E; @@ -3963,6 +4138,7 @@ int wc_ecc_check_key(ecc_key* key) mp_clear(&a); mp_clear(&prime); #endif +#endif /* WOLFSSL_ATECC508A */ return err; } @@ -3972,8 +4148,10 @@ int wc_ecc_check_key(ecc_key* key) int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, int curve_id) { - int err; + int err = MP_OKAY; +#ifndef WOLFSSL_ATECC508A int compressed = 0; +#endif /* !WOLFSSL_ATECC508A */ if (in == NULL || key == NULL) return BAD_FUNC_ARG; @@ -3983,6 +4161,12 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, return ECC_BAD_ARG_E; } +#ifdef WOLFSSL_ATECC508A + /* TODO: Implement equiv call to ATECC508A */ + err = BAD_COND_E; + +#else + /* init key */ #ifdef ALT_ECC_SIZE key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; @@ -4107,6 +4291,7 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, mp_clear(key->pubkey.z); mp_clear(&key->k); } +#endif /* WOLFSSL_ATECC508A */ return err; } @@ -4140,8 +4325,15 @@ int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen) *outLen = numlen; XMEMSET(out, 0, *outLen); +#ifdef WOLFSSL_ATECC508A + /* TODO: Implement equiv call to ATECC508A */ + return BAD_COND_E; + +#else + return mp_to_unsigned_bin(&key->k, out + (numlen - mp_unsigned_bin_size(&key->k))); +#endif /* WOLFSSL_ATECC508A */ } #endif /* HAVE_ECC_KEY_EXPORT */ @@ -4155,8 +4347,16 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, const byte* pu key->type = ECC_PRIVATEKEY; +#ifdef WOLFSSL_ATECC508A + /* TODO: Implement equiv call to ATECC508A */ + return BAD_COND_E; + +#else + ret = mp_read_unsigned_bin(&key->k, priv, privSz); +#endif /* WOLFSSL_ATECC508A */ + #ifdef WOLFSSL_VALIDATE_ECC_IMPORT if (ret == MP_OKAY) ret = ecc_check_privkey_gen_helper(key); @@ -4222,7 +4422,7 @@ int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen) static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, const char* qy, const char* d, int curve_id) { - int err; + int err = MP_OKAY; if (key == NULL || qx == NULL || qy == NULL || d == NULL) { return BAD_FUNC_ARG; @@ -4234,6 +4434,12 @@ 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; + +#else + /* init key */ #ifdef ALT_ECC_SIZE key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; @@ -4278,6 +4484,7 @@ 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; } @@ -6373,6 +6580,7 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, #ifdef HAVE_COMP_KEY +#ifndef WOLFSSL_ATECC508A /* computes the jacobi c = (a | n) (or Legendre if n is prime) * HAC pp. 73 Algorithm 2.149 @@ -6664,6 +6872,7 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) return res; } +#endif /* !WOLFSSL_ATECC508A */ /* export public ECC key in ANSI X9.63 format compressed */ @@ -6685,6 +6894,12 @@ 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 ? 0x03 : 0x02; @@ -6693,6 +6908,9 @@ static int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen ret = mp_to_unsigned_bin(key->pubkey.x, out+1 + (numlen - mp_unsigned_bin_size(key->pubkey.x))); *outLen = 1 + numlen; + +#endif /* WOLFSSL_ATECC508A */ + return ret; } diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 5c76a03b6..9a3ce0a3b 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -47,7 +47,9 @@ EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ wolfcrypt/src/port/nrf51.c \ wolfcrypt/src/port/arm/armv8-aes.c \ wolfcrypt/src/port/arm/armv8-sha256.c \ - wolfssl/wolfcrypt/port/nxp/ksdk_port.c + wolfssl/wolfcrypt/port/nxp/ksdk_port.c \ + wolfcrypt/src/port/atmel/atmel.c \ + wolfcrypt/src/port/atmel/README.md if BUILD_CAVIUM src_libwolfssl_la_SOURCES += wolfcrypt/src/port/cavium/cavium_nitrox.c diff --git a/wolfcrypt/src/port/atmel/README.md b/wolfcrypt/src/port/atmel/README.md new file mode 100644 index 000000000..00f527507 --- /dev/null +++ b/wolfcrypt/src/port/atmel/README.md @@ -0,0 +1,8 @@ +# Atmel ATECC508A Port + +* 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. + + +For details see our [wolfSSL Atmel ATECC508A](wolfhttps://wolfssl.com/wolfSSL/wolfssl-atmel.html) page. diff --git a/wolfcrypt/src/port/atmel/atmel.c b/wolfcrypt/src/port/atmel/atmel.c new file mode 100755 index 000000000..4c5ed0dcc --- /dev/null +++ b/wolfcrypt/src/port/atmel/atmel.c @@ -0,0 +1,244 @@ +/* atmel.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_ATMEL + +#include +#include +#include +#include + +#define Aes Aes_Remap +#define Gmac Gmac_Remap +#include "asf.h" +#undef Aes +#undef Gmac + +#include + +static bool mAtcaInitDone = 0; + +#ifdef WOLFSSL_ATECC508A + +/* List of available key slots */ +static int mSlotList[ATECC_MAX_SLOT+1]; + +/** + * \brief Structure to contain certificate information. + */ +t_atcert atcert = { + .signer_ca_size = 512, + .signer_ca = { 0 }, + .signer_ca_pubkey = { 0 }, + .end_user_size = 512, + .end_user = { 0 }, + .end_user_pubkey = { 0 } +}; + +static int atmel_init_enc_key(void); + +#endif /* WOLFSSL_ATECC508A */ + + +/** + * \brief Generate random number to be used for hash. + */ +int atmel_get_random_number(uint32_t count, uint8_t* rand_out) +{ + int ret = 0; +#ifdef WOLFSSL_ATECC508A + uint8_t i = 0; + uint32_t copy_count = 0; + uint8_t rng_buffer[RANDOM_NUM_SIZE]; + + if (rand_out == NULL) { + return -1; + } + + while(i < count) { + + ret = atcatls_random(rng_buffer); + if (ret != 0) { + WOLFSSL_MSG("Failed to create random number!"); + return -1; + } + copy_count = (count - i > RANDOM_NUM_SIZE) ? RANDOM_NUM_SIZE : count - i; + XMEMCPY(&rand_out[i], rng_buffer, copy_count); + i += copy_count; + } + atcab_printbin_label((const uint8_t*)"\r\nRandom Number", rand_out, count); +#else + // TODO: Use on-board TRNG +#endif + return ret; +} + +int atmel_get_random_block(unsigned char* output, unsigned int sz) +{ + return atmel_get_random_number((uint32_t)sz, (uint8_t*)output); +} + +extern struct rtc_module *_rtc_instance[RTC_INST_NUM]; +long atmel_get_curr_time_and_date(long* tm) +{ + (void)tm; + + /* Get current time */ + //struct rtc_calendar_time rtcTime; + //rtc_calendar_get_time(_rtc_instance[0], &rtcTime); + + /* Convert rtc_calendar_time to seconds since UTC */ + + return 0; +} + + + +#ifdef WOLFSSL_ATECC508A + +/* Function to allocate new slot number */ +int atmel_ecc_alloc(void) +{ + int i, slot = -1; + for (i=0; i <= ATECC_MAX_SLOT; i++) { + /* Find free slot */ + if (mSlotList[i] == ATECC_INVALID_SLOT) { + mSlotList[i] = i; + slot = i; + break; + } + } + return slot; +} + + +/* Function to return slot number to avail list */ +void atmel_ecc_free(int slot) +{ + if (slot >= 0 && slot <= ATECC_MAX_SLOT) { + /* Mark slot of free */ + mSlotList[slot] = ATECC_INVALID_SLOT; + } +} + + +/** + * \brief Give enc key to read pms. + */ +static int atmel_set_enc_key(uint8_t* enckey, int16_t keysize) +{ + if (enckey == NULL || keysize != ATECC_KEY_SIZE) { + return -1; + } + + XMEMSET(enckey, 0xFF, keysize); // use default values + + return SSL_SUCCESS; +} + + +/** + * \brief Write enc key before. + */ +static int atmel_init_enc_key(void) +{ + uint8_t ret = 0; + uint8_t read_key[ATECC_KEY_SIZE] = { 0 }; + + XMEMSET(read_key, 0xFF, sizeof(read_key)); + ret = atcab_write_bytes_slot(0x04, 0, read_key, sizeof(read_key)); + if (ret != ATCA_SUCCESS) { + WOLFSSL_MSG("Failed to write key"); + return -1; + } + + ret = atcatlsfn_set_get_enckey(atmel_set_enc_key); + if (ret != ATCA_SUCCESS) { + WOLFSSL_MSG("Failed to set enckey"); + return -1; + } + + return ret; +} + +static void atmel_show_rev_info(void) +{ +#if 0 + uint32_t revision = 0; + atcab_info((uint8_t*)&revision); + printf("ATECC508A Revision: %x\n", (unsigned int)revision); +#endif +} + +#endif /* WOLFSSL_ATECC508A */ + + + +void atmel_init(void) +{ + if (!mAtcaInitDone) { +#ifdef WOLFSSL_ATECC508A + int i; + + /* Init the free slot list */ + for (i=0; i<=ATECC_MAX_SLOT; i++) { + if (i == 0 || i == 2 || i == 7) { + /* ECC Slots (mark avail) */ + mSlotList[i] = ATECC_INVALID_SLOT; + } + else { + mSlotList[i] = i; + } + } + + /* Initialize the CryptoAuthLib to communicate with ATECC508A */ + atcatls_init(&cfg_ateccx08a_i2c_default); + + /* Init the I2C pipe encryption key. */ + /* Value is generated/stored during pair for the ATECC508A and stored + on micro flash */ + /* For this example its a fixed value */ + if (atmel_init_enc_key() != ATCA_SUCCESS) { + WOLFSSL_MSG("Failed to initialize transport key"); + } + + /* show revision information */ + atmel_show_rev_info(); + + /* Configure the ECC508 for use with TLS API funcitons */ + #if 0 + atcatls_device_provision(); + #else + atcatls_config_default(); + #endif +#endif /* WOLFSSL_ATECC508A */ + + mAtcaInitDone = 1; + } +} + +#endif /* WOLFSSL_ATMEL */ diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c old mode 100644 new mode 100755 index b953e2dd7..df0512196 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -1619,6 +1619,23 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } +#elif defined(WOLFSSL_ATMEL) + #include + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret = 0; + + (void)os; + if (output == NULL) { + return BUFFER_E; + } + + ret = atmel_get_random_number(sz, output); + + return ret; + } + #elif defined(NO_DEV_RANDOM) #error "you need to write an os specific wc_GenerateSeed() here" diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index 5e3c32a49..669298cb6 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -39,6 +39,10 @@ #include #endif +#ifdef WOLFSSL_ATMEL + #include +#endif + #ifdef _MSC_VER /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ #pragma warning(disable: 4996) @@ -50,7 +54,7 @@ static volatile int initRefCount = 0; /* Used to initialize state for wolfcrypt return 0 on success */ -int wolfCrypt_Init() +int wolfCrypt_Init(void) { int ret = 0; @@ -77,6 +81,10 @@ int wolfCrypt_Init() ksdk_port_init(); #endif + #ifdef WOLFSSL_ATMEL + atmel_init(); + #endif + #ifdef WOLFSSL_ARMASM WOLFSSL_MSG("Using ARM hardware acceleration"); #endif diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 2ecbd06ce..3859c1534 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2036,6 +2036,7 @@ struct WOLFSSL_CTX { #ifdef HAVE_ECC CallbackEccSign EccSignCb; /* User EccSign Callback handler */ CallbackEccVerify EccVerifyCb; /* User EccVerify Callback handler */ + CallbackEccSharedSecret EccSharedSecretCb; /* User EccVerify Callback handler */ #endif /* HAVE_ECC */ #ifndef NO_RSA CallbackRsaSign RsaSignCb; /* User RsaSign Callback handler */ @@ -2850,6 +2851,7 @@ struct WOLFSSL { #ifdef HAVE_ECC void* EccSignCtx; /* Ecc Sign Callback Context */ void* EccVerifyCtx; /* Ecc Verify Callback Context */ + void* EccSharedSecretCtx; /* Ecc Pms Callback Context */ #endif /* HAVE_ECC */ #ifndef NO_RSA void* RsaSignCtx; /* Rsa Sign Callback Context */ @@ -3044,7 +3046,8 @@ WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); const byte* out, word32 outSz, ecc_key* key, byte* keyBuf, word32 keySz, void* ctx); WOLFSSL_LOCAL int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, - ecc_key* pub_key, byte* out, word32* outSz); + ecc_key* pub_key, byte* pubKeyDer, word32* pubKeySz, byte* out, + word32* outlen, int side, void* ctx); #endif /* HAVE_ECC */ #ifdef WOLFSSL_TRUST_PEER_CERT diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 839200393..64cfcbb3e 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1341,6 +1341,15 @@ WOLFSSL_API void wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX*, CallbackEccVerify); WOLFSSL_API void wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx); WOLFSSL_API void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl); +struct ecc_key; +typedef int (*CallbackEccSharedSecret)(WOLFSSL* ssl, struct ecc_key* otherKey, + unsigned char* pubKeyDer, unsigned int* pubKeySz, + unsigned char* out, unsigned int* outlen, + int side, void* ctx); /* side is WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */ +WOLFSSL_API void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX*, CallbackEccSharedSecret); +WOLFSSL_API void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl); + typedef int (*CallbackRsaSign)(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz, unsigned char* out, unsigned int* outSz, diff --git a/wolfssl/test.h b/wolfssl/test.h index a488418f1..e0a3c1a0e 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -1705,6 +1705,62 @@ static INLINE int myEccVerify(WOLFSSL* ssl, const byte* sig, word32 sigSz, return ret; } +static INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey, + unsigned char* pubKeyDer, unsigned int* pubKeySz, + unsigned char* out, unsigned int* outlen, + int side, void* ctx) +{ + int ret; + ecc_key* privKey = NULL; + ecc_key* pubKey = NULL; + ecc_key tmpKey; + + (void)ssl; + (void)ctx; + + ret = wc_ecc_init(&tmpKey); + if (ret != 0) { + return ret; + } + + /* for client: create and export public key */ + if (side == WOLFSSL_CLIENT_END) { + WC_RNG rng; + + privKey = &tmpKey; + pubKey = otherKey; + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_make_key_ex(&rng, 0, privKey, otherKey->dp->id); + if (ret == 0) + ret = wc_ecc_export_x963(privKey, pubKeyDer, pubKeySz); + wc_FreeRng(&rng); + } + } + + /* for server: import public key */ + else if (side == WOLFSSL_SERVER_END) { + privKey = otherKey; + pubKey = &tmpKey; + + ret = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, pubKey, + otherKey->dp->id); + } + else { + ret = BAD_FUNC_ARG; + } + + /* generate shared secret and return it */ + if (ret == 0) { + ret = wc_ecc_shared_secret(privKey, pubKey, out, outlen); + } + + wc_ecc_free(&tmpKey); + + return ret; +} + #endif /* HAVE_ECC */ #ifndef NO_RSA @@ -1834,6 +1890,7 @@ static INLINE void SetupPkCallbacks(WOLFSSL_CTX* ctx, WOLFSSL* ssl) #ifdef HAVE_ECC wolfSSL_CTX_SetEccSignCb(ctx, myEccSign); wolfSSL_CTX_SetEccVerifyCb(ctx, myEccVerify); + wolfSSL_CTX_SetEccSharedSecretCb(ctx, myEccSharedSecret); #endif /* HAVE_ECC */ #ifndef NO_RSA wolfSSL_CTX_SetRsaSignCb(ctx, myRsaSign); diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 7c25c13cf..2ae7d2a45 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -34,6 +34,11 @@ #include #endif +#ifdef WOLFSSL_ATECC508A + #include +#endif /* WOLFSSL_ATECC508A */ + + #ifdef __cplusplus extern "C" { #endif @@ -205,7 +210,7 @@ typedef struct alt_fp_int { int used, sign, size; fp_digit dp[FP_SIZE_ECC]; } alt_fp_int; -#endif +#endif /* ALT_ECC_SIZE */ /* A point on an ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpreted as affine */ @@ -224,16 +229,21 @@ typedef struct { /* An ECC Key */ -typedef struct { +typedef struct ecc_key { int type; /* Public or Private */ int idx; /* Index into the ecc_sets[] for the parameters of this curve if -1, this key is using user supplied curve in dp */ const ecc_set_type* dp; /* domain parameters, either points to NIST curves (idx >= 0) or user supplied */ + void* heap; /* heap hint */ +#ifdef WOLFSSL_ATECC508A + int slot; /* Key Slot Number (-1 unknown) */ + byte pubkey[PUB_KEY_SIZE]; +#else ecc_point pubkey; /* public key */ mp_int k; /* private key */ - void* heap; /* heap hint */ +#endif #ifdef WOLFSSL_ASYNC_CRYPT AsyncCryptDev asyncDev; @@ -257,9 +267,11 @@ int wc_ecc_check_key(ecc_key* key); WOLFSSL_API int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, word32* outlen); +#ifndef WOLFSSL_ATECC508A WOLFSSL_API int wc_ecc_shared_secret_ssh(ecc_key* private_key, ecc_point* point, byte* out, word32 *outlen); +#endif /* !WOLFSSL_ATECC508A */ #endif /* HAVE_ECC_DHE */ #ifdef HAVE_ECC_SIGN @@ -289,6 +301,11 @@ void wc_ecc_free(ecc_key* key); WOLFSSL_API void wc_ecc_fp_free(void); +WOLFSSL_API +int wc_ecc_is_valid_idx(int n); + +#ifndef WOLFSSL_ATECC508A + WOLFSSL_API ecc_point* wc_ecc_new_point(void); WOLFSSL_API @@ -304,14 +321,14 @@ int wc_ecc_cmp_point(ecc_point* a, ecc_point *b); WOLFSSL_API int wc_ecc_point_is_at_infinity(ecc_point *p); WOLFSSL_API -int wc_ecc_is_valid_idx(int n); -WOLFSSL_API int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, int map); - WOLFSSL_LOCAL int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, int map, void* heap); +#endif /* !WOLFSSL_ATECC508A */ + + #ifdef HAVE_ECC_KEY_EXPORT /* ASN key helpers */ WOLFSSL_API @@ -346,12 +363,16 @@ int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy, #ifdef HAVE_ECC_KEY_EXPORT WOLFSSL_API int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen); +#endif /* HAVE_ECC_KEY_EXPORT */ + +#ifdef HAVE_ECC_KEY_EXPORT WOLFSSL_API int wc_ecc_export_point_der(const int curve_idx, ecc_point* point, byte* out, word32* outLen); #endif /* HAVE_ECC_KEY_EXPORT */ + #ifdef HAVE_ECC_KEY_IMPORT WOLFSSL_API int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index 4dddbc687..7c9c0fb7f 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -65,7 +65,8 @@ noinst_HEADERS+= \ wolfssl/wolfcrypt/port/ti/ti-hash.h \ wolfssl/wolfcrypt/port/ti/ti-ccm.h \ wolfssl/wolfcrypt/port/nrf51.h \ - wolfssl/wolfcrypt/port/nxp/ksdk_port.h + wolfssl/wolfcrypt/port/nxp/ksdk_port.h \ + wolfssl/wolfcrypt/port/atmel/atmel.h if BUILD_CAVIUM noinst_HEADERS+= wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h diff --git a/wolfssl/wolfcrypt/port/atmel/atmel.h b/wolfssl/wolfcrypt/port/atmel/atmel.h new file mode 100755 index 000000000..99532dbad --- /dev/null +++ b/wolfssl/wolfcrypt/port/atmel/atmel.h @@ -0,0 +1,66 @@ +/* atecc508.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _ATECC508_H_ +#define _ATECC508_H_ + +#include + +#ifdef WOLFSSL_ATECC508A + #undef SHA_BLOCK_SIZE + #define SHA_BLOCK_SIZE SHA_BLOCK_SIZE_REMAP + #include + #include + #include + #include + #undef SHA_BLOCK_SIZE +#endif + +/* ATECC508A only supports ECC-256 */ +#define ATECC_KEY_SIZE (32) +#define ATECC_MAX_SLOT (0x7) /* Only use 0-7 */ +#define ATECC_INVALID_SLOT (-1) + +struct WOLFSSL; +struct WOLFSSL_X509_STORE_CTX; + +// Cert Structure +typedef struct t_atcert { + uint32_t signer_ca_size; + uint8_t signer_ca[512]; + uint8_t signer_ca_pubkey[64]; + uint32_t end_user_size; + uint8_t end_user[512]; + uint8_t end_user_pubkey[64]; +} t_atcert; + +extern t_atcert atcert; + + +/* Amtel port functions */ +void atmel_init(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); +void atmel_ecc_free(int slot); + +#endif /* _ATECC508_H_ */