diff --git a/configure.ac b/configure.ac index a544cd7e8..3c4e91373 100644 --- a/configure.ac +++ b/configure.ac @@ -788,6 +788,50 @@ fi AM_CONDITIONAL([BUILD_PKCALLBACKS], [ test "x$ENABLED_PKCALLBACKS" = "xyes" ]) +# Microchip/Atmel CryptoAuthLib +ENABLED_CRYPTOAUTHLIB="no" +trylibatcadir="" +AC_ARG_WITH([cryptoauthlib], + [AS_HELP_STRING([--with-cryptoauthlib=PATH],[PATH to CryptoAuthLib install (default /usr/)])], + [ + AC_MSG_CHECKING([for cryptoauthlib]) + CPPFLAGS="$CPPFLAGS -DWOLFSSL_ATECC508A" + LIBS="$LIBS -lcryptoauth" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ atcab_init(0); ]])],[ libatca_linked=yes ],[ libatca_linked=no ]) + + if test "x$libatca_linked" == "xno" ; then + if test "x$withval" != "xno" ; then + trylibatcadir=$withval + fi + if test "x$withval" == "xyes" ; then + trylibatcadir="/usr" + fi + + LDFLAGS="$LDFLAGS -L$trylibatcadir/lib" + CPPFLAGS="$CPPFLAGS -I$trylibatcadir/lib" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ atcab_init(0); ]])],[ libatca_linked=yes ],[ libatca_linked=no ]) + + if test "x$libatca_linked" == "xno" ; then + AC_MSG_ERROR([cryptoauthlib isn't found. + If it's already installed, specify its path using --with-cryptoauthlib=/dir/]) + fi + + AM_LDFLAGS="$AM_LDFLAGS -L$trylibatcadir/lib" + AM_CFLAGS="$AM_CFLAGS -I$trylibatcadir/lib" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([yes]) + fi + + ENABLED_CRYPTOAUTHLIB="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ATECC508A" + ] +) +AM_CONDITIONAL([BUILD_CRYPTOAUTHLIB], [test "x$ENABLED_CRYPTOAUTHLIB" = "xyes"]) + + # sniffer doesn't work in maxstrength mode if test "$ENABLED_SNIFFER" = "yes" && test "$ENABLED_MAXSTRENGTH" = "yes" then @@ -3528,7 +3572,7 @@ AC_ARG_WITH([libz], trylibzdir="/usr" fi - AM_LDFLAGS="$AM_LDFLAGS -L$trylibzdir/lib" + LDFLAGS="$LDFLAGS -L$trylibzdir/lib" CPPFLAGS="$CPPFLAGS -I$trylibzdir/include" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ deflateInit(0, 8); ]])],[ libz_linked=yes ],[ libz_linked=no ]) diff --git a/tests/api.c b/tests/api.c index c565bdda6..4d13402a1 100644 --- a/tests/api.c +++ b/tests/api.c @@ -14266,7 +14266,8 @@ static int test_wc_ecc_pointFns (void) { int ret = 0; -#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && \ + !defined(WC_NO_RNG) && !defined(WOLFSSL_ATECC508A) ecc_key key; WC_RNG rng; ecc_point* point = NULL; @@ -14440,7 +14441,8 @@ static int test_wc_ecc_shared_secret_ssh (void) { int ret = 0; -#if defined(HAVE_ECC) && defined(HAVE_ECC_DHE) && !defined(WC_NO_RNG) +#if defined(HAVE_ECC) && defined(HAVE_ECC_DHE) && \ + !defined(WC_NO_RNG) && !defined(WOLFSSL_ATECC508A) ecc_key key, key2; WC_RNG rng; int keySz = KEY32; diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 00637c288..e9f83b14c 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -3381,12 +3381,17 @@ 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 = atmel_ecc_create_pms(private_key->slot, public_key->pubkey_raw, out); + *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 */ @@ -3757,7 +3762,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; @@ -3857,9 +3862,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 @@ -3899,7 +3902,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; @@ -3942,10 +3945,7 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) #ifdef WOLFSSL_ATECC508A key->type = ECC_PRIVATEKEY; - err = atcatls_create_key(key->slot, key->pubkey_raw); - if (err != ATCA_SUCCESS) { - err = BAD_COND_E; - } + err = atmel_ecc_create_key(key->slot, key->pubkey_raw); /* populate key->pubkey */ err = mp_read_unsigned_bin(key->pubkey.x, key->pubkey_raw, @@ -3999,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 */ } @@ -4103,10 +4101,7 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) #endif #ifdef WOLFSSL_ATECC508A - key->slot = atmel_ecc_alloc(); - if (key->slot == ATECC_INVALID_SLOT) { - return ECC_BAD_ARG_E; - } + key->slot = -1; #else #ifdef ALT_ECC_SIZE key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; @@ -4201,10 +4196,15 @@ static int wc_ecc_sign_hash_hw(const byte* in, word32 inlen, } #if defined(WOLFSSL_ATECC508A) + key->slot = atmel_ecc_alloc(ATMEL_SLOT_DEVICE); + if (key->slot == ATECC_INVALID_SLOT) { + return ECC_BAD_ARG_E; + } + /* Sign: Result is 32-bytes of R then 32-bytes of S */ - err = atcatls_sign(key->slot, in, out); - if (err != ATCA_SUCCESS) { - return BAD_COND_E; + err = atmel_ecc_sign(key->slot, in, out); + if (err != 0) { + return err; } #elif defined(PLUTON_CRYPTO_ECC) { @@ -5282,9 +5282,9 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, return err; } - err = atcatls_verify(hash, sigRS, key->pubkey_raw, (bool*)res); - if (err != ATCA_SUCCESS) { - return BAD_COND_E; + err = atmel_ecc_verify(hash, sigRS, key->pubkey_raw, res); + if (err != 0) { + return err; } (void)hashlen; @@ -5569,7 +5569,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; @@ -5619,11 +5618,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); @@ -5703,14 +5697,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 */ @@ -5722,13 +5708,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; @@ -5750,12 +5734,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; @@ -5787,7 +5765,6 @@ done: #ifdef WOLFSSL_SMALL_STACK XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER); #endif -#endif /* WOLFSSL_ATECC508A */ return ret; } @@ -6086,8 +6063,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); @@ -6176,10 +6153,7 @@ int wc_ecc_check_key(ecc_key* key) #ifdef WOLFSSL_ATECC508A - 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 @@ -6335,6 +6309,14 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, inLen -= 1; in += 1; +#ifdef WOLFSSL_ATECC508A + /* 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, inLen); + } +#endif + if (err == MP_OKAY) { #ifdef HAVE_COMP_KEY /* adjust inLen if compressed */ @@ -6472,7 +6454,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) @@ -6573,8 +6555,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 @@ -6836,14 +6818,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]; @@ -6882,9 +6856,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) @@ -6892,7 +6882,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; } @@ -6909,7 +6899,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; } @@ -9404,12 +9393,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; @@ -9419,8 +9402,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; } diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index a68dae838..83a1b7b90 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -52,7 +52,6 @@ EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ wolfcrypt/src/port/arm/armv8-aes.c \ wolfcrypt/src/port/arm/armv8-sha256.c \ wolfcrypt/src/port/nxp/ksdk_port.c \ - wolfcrypt/src/port/atmel/atmel.c \ wolfcrypt/src/port/atmel/README.md \ wolfcrypt/src/port/xilinx/xil-sha3.c \ wolfcrypt/src/port/xilinx/xil-aesgcm.c \ @@ -96,3 +95,7 @@ src_libwolfssl_la_SOURCES += wolfcrypt/src/port/intel/quickassist_mem.c EXTRA_DIST += wolfcrypt/src/port/intel/README.md endif + +if BUILD_CRYPTOAUTHLIB +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/atmel/atmel.c +endif diff --git a/wolfcrypt/src/port/atmel/README.md b/wolfcrypt/src/port/atmel/README.md index f67b29be9..50352fcd2 100644 --- a/wolfcrypt/src/port/atmel/README.md +++ b/wolfcrypt/src/port/atmel/README.md @@ -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 */ @@ -45,11 +64,13 @@ wolfSSL_SetEccSharedSecretCtx(ssl, myOwnCtx); ## Benchmarks +Supports ECC SECP256R1 (NIST P-256) + ### TLS 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. @@ -58,16 +79,16 @@ The TLS connection establishment time is 5.73 times faster with the ATECC508A. Software only implementation (SAMD21 48Mhz Cortex-M0, Fast Math TFM-ASM): -`ECC 256 key generation 3123.000 milliseconds, avg over 5 iterations` -`EC-DHE key agreement 3117.000 milliseconds, avg over 5 iterations` -`EC-DSA sign time 1997.000 milliseconds, avg over 5 iterations` -`EC-DSA verify time 5057.000 milliseconds, avg over 5 iterations` +`EC-DHE key generation 3123.000 milliseconds, avg over 5 iterations, 1.601 ops/sec` +`EC-DHE key agreement 3117.000 milliseconds, avg over 5 iterations, 1.604 ops/sec` +`EC-DSA sign time 1997.000 milliseconds, avg over 5 iterations, 2.504 ops/sec` +`EC-DSA verify time 5057.000 milliseconds, avg over 5 iterations, 0.988 ops/sec` ATECC508A HW accelerated implementation: -`ECC 256 key generation 144.400 milliseconds, avg over 5 iterations` -`EC-DHE key agreement 134.200 milliseconds, avg over 5 iterations` -`EC-DSA sign time 293.400 milliseconds, avg over 5 iterations` -`EC-DSA verify time 208.400 milliseconds, avg over 5 iterations` +`EC-DHE key generation 144.400 milliseconds, avg over 5 iterations, 34.722 ops/sec` +`EC-DHE key agreement 134.200 milliseconds, avg over 5 iterations, 37.313 ops/sec` +`EC-DSA sign time 293.400 milliseconds, avg over 5 iterations, 17.065 ops/sec` +`EC-DSA verify time 208.400 milliseconds, avg over 5 iterations, 24.038 ops/sec` For details see our [wolfSSL Atmel ATECC508A](https://wolfssl.com/wolfSSL/wolfssl-atmel.html) page. diff --git a/wolfcrypt/src/port/atmel/atmel.c b/wolfcrypt/src/port/atmel/atmel.c index c5e5d95af..fcfc121a6 100644 --- a/wolfcrypt/src/port/atmel/atmel.c +++ b/wolfcrypt/src/port/atmel/atmel.c @@ -25,14 +25,22 @@ #include -#if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) +#if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC_PKCB) #include #include #include #include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + #ifdef WOLFSSL_ATMEL +/* remap name conflicts */ #define Aes Aes_Remap #define Gmac Gmac_Remap #include "asf.h" @@ -42,27 +50,29 @@ #include -static bool mAtcaInitDone = 0; - #ifdef WOLFSSL_ATECC508A -/* List of available key slots */ -static int mSlotList[ATECC_MAX_SLOT+1]; +static int mAtcaInitDone = 0; -/** - * \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); +/* ATECC slotId handling */ +static atmel_slot_alloc_cb mSlotAlloc; +static atmel_slot_dealloc_cb mSlotDealloc; +static byte mSlotList[ATECC_MAX_SLOT]; +#ifndef SINGLE_THREADED +static wolfSSL_Mutex mSlotMutex; +#endif +/* Raspberry Pi uses /dev/i2c-1 */ +#ifndef ATECC_I2C_ADDR +#define ATECC_I2C_ADDR 0xC0 +#endif +#ifndef ATECC_I2C_BUS +#define ATECC_I2C_BUS 1 +#endif +#ifndef ATECC_DEV_TYPE +#define ATECC_DEV_TYPE ATECC508A +#endif +static ATCAIfaceCfg cfg_ateccx08a_i2c_pi; #endif /* WOLFSSL_ATECC508A */ @@ -81,10 +91,9 @@ int atmel_get_random_number(uint32_t count, uint8_t* rand_out) return -1; } - while(i < count) { - - ret = atcatls_random(rng_buffer); - if (ret != 0) { + while (i < count) { + ret = atcab_random(rng_buffer); + if (ret != ATCA_SUCCESS) { WOLFSSL_MSG("Failed to create random number!"); return -1; } @@ -92,9 +101,9 @@ int atmel_get_random_number(uint32_t count, uint8_t* rand_out) XMEMCPY(&rand_out[i], rng_buffer, copy_count); i += copy_count; } - atcab_printbin_label((const uint8_t*)"\r\nRandom Number", rand_out, count); + atcab_printbin_label((const char*)"\r\nRandom Number", rand_out, count); #else - // TODO: Use on-board TRNG + /* TODO: Use on-board TRNG */ #endif return ret; } @@ -104,164 +113,351 @@ int atmel_get_random_block(unsigned char* output, unsigned int sz) return atmel_get_random_number((uint32_t)sz, (uint8_t*)output); } -#ifdef WOLFSSL_ATMEL_TIME +#if defined(WOLFSSL_ATMEL) && defined(WOLFSSL_ATMEL_TIME) extern struct rtc_module *_rtc_instance[RTC_INST_NUM]; -#endif + long atmel_get_curr_time_and_date(long* tm) { - (void)tm; + long rt = 0; -#ifdef 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}; + int month, year, yearLeap; - //struct rtc_calendar_time rtcTime; - //rtc_calendar_get_time(_rtc_instance[0], &rtcTime); + rtc_calendar_get_time(_rtc_instance[0], &rtcTime); /* Convert rtc_calendar_time to seconds since UTC */ -#endif + month = rtcTime.month % 12; + year = rtcTime.year + rtcTime.month / 12; + if (month < 0) { + month += 12; + year--; + } + yearLeap = (month > 1) ? year + 1 : year; + rt = rtcTime.second + + 60 * (rtcTime.minute + + 60 * (rtcTime.hour + + 24 * (monthDay[month] + rtcTime.day - 1 + + 365 * (year - 70) + + (yearLeap - 69) / 4 + - (yearLeap - 1) / 100 + + (yearLeap + 299) / 400 + ) + ) + ); - return 0; + (void)tm; + return rt; } - +#endif #ifdef WOLFSSL_ATECC508A -/* Function to allocate new slot number */ -int atmel_ecc_alloc(void) +int atmel_ecc_translate_err(int status) { - 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; + switch (status) { + case ATCA_SUCCESS: + return 0; + case ATCA_BAD_PARAM: + return BAD_FUNC_ARG; + case ATCA_ALLOC_FAILURE: + return MEMORY_E; + default: + #ifdef WOLFSSL_ATECC508A_DEBUG + printf("ATECC Failure: %x\n", (word32)status); + #endif break; + } + return WC_HW_E; +} + +/* Function to set the slotId allocator and deallocator */ +int atmel_set_slot_allocator(atmel_slot_alloc_cb alloc, + atmel_slot_dealloc_cb dealloc) +{ +#ifndef SINGLE_THREADED + wc_LockMutex(&mSlotMutex); +#endif + mSlotAlloc = alloc; + mSlotDealloc = dealloc; +#ifndef SINGLE_THREADED + wc_UnLockMutex(&mSlotMutex); +#endif + return 0; +} + +/* Function to allocate new slotId number */ +int atmel_ecc_alloc(int slotType) +{ + int slotId = ATECC_INVALID_SLOT, i; + +#ifndef SINGLE_THREADED + wc_LockMutex(&mSlotMutex); +#endif + + if (mSlotAlloc) { + slotId = mSlotAlloc(slotType); + } + else { + switch (slotType) { + case ATMEL_SLOT_ENCKEY: + /* not reserved in mSlotList, so return */ + slotId = ATECC_SLOT_I2C_ENC; + goto exit; + case ATMEL_SLOT_DEVICE: + /* not reserved in mSlotList, so return */ + slotId = ATECC_SLOT_AUTH_PRIV; + goto exit; + case ATMEL_SLOT_ECDHE: + slotId = ATECC_SLOT_ECDHE_PRIV; + break; + case ATMEL_SLOT_ECDHE_ENC: + slotId = ATECC_SLOT_ENC_PARENT; + break; + case ATMEL_SLOT_ANY: + for (i=0; i < ATECC_MAX_SLOT; i++) { + /* Find free slotId */ + if (mSlotList[i] == ATECC_INVALID_SLOT) { + slotId = i; + break; + } + } + break; + } + + /* is slot available */ + if (mSlotList[slotId] != ATECC_INVALID_SLOT) { + slotId = ATECC_INVALID_SLOT; + } + else { + mSlotList[slotId] = slotId; } } - return slot; + +exit: +#ifndef SINGLE_THREADED + wc_UnLockMutex(&mSlotMutex); +#endif + + return slotId; } -/* Function to return slot number to avail list */ -void atmel_ecc_free(int slot) +/* Function to return slotId number to available list */ +void atmel_ecc_free(int slotId) { - if (slot >= 0 && slot <= ATECC_MAX_SLOT) { - /* Mark slot of free */ - mSlotList[slot] = ATECC_INVALID_SLOT; +#ifndef SINGLE_THREADED + wc_LockMutex(&mSlotMutex); +#endif + if (mSlotDealloc) { + mSlotDealloc(slotId); } + else if (slotId >= 0 && slotId < ATECC_MAX_SLOT) { + if (slotId != ATECC_SLOT_AUTH_PRIV && slotId != ATECC_SLOT_I2C_ENC) { + /* Mark slotId free */ + mSlotList[slotId] = ATECC_INVALID_SLOT; + } + } +#ifndef SINGLE_THREADED + wc_UnLockMutex(&mSlotMutex); +#endif } /** - * \brief Give enc key to read pms. + * \brief Callback function for getting the current encryption key */ -static int atmel_set_enc_key(uint8_t* enckey, int16_t keysize) +int atmel_get_enc_key_default(byte* enckey, word16 keysize) { if (enckey == NULL || keysize != ATECC_KEY_SIZE) { - return -1; + return BAD_FUNC_ARG; } - XMEMSET(enckey, 0xFF, keysize); // use default values + XMEMSET(enckey, 0xFF, keysize); /* use default value */ - return SSL_SUCCESS; + return 0; } - /** * \brief Write enc key before. */ static int atmel_init_enc_key(void) { - uint8_t ret = 0; - uint8_t read_key[ATECC_KEY_SIZE] = { 0 }; + int ret; + uint8_t read_key[ATECC_KEY_SIZE]; + uint8_t writeBlock = 0; + uint8_t writeOffset = 0; + int slotId; - XMEMSET(read_key, 0xFF, sizeof(read_key)); - ret = atcab_write_bytes_slot(TLS_SLOT_ENC_PARENT, 0, read_key, sizeof(read_key)); - if (ret != ATCA_SUCCESS) { - WOLFSSL_MSG("Failed to write key"); - return -1; - } + slotId = atmel_ecc_alloc(ATMEL_SLOT_ENCKEY); - ret = atcatlsfn_set_get_enckey(atmel_set_enc_key); - if (ret != ATCA_SUCCESS) { - WOLFSSL_MSG("Failed to set enckey"); - return -1; - } + /* check for encryption key slotId */ + if (slotId == ATECC_INVALID_SLOT) + return BAD_FUNC_ARG; + + /* get encryption key */ + ATECC_GET_ENC_KEY(read_key, sizeof(read_key)); + + ret = atcab_write_zone(ATCA_ZONE_DATA, slotId, writeBlock, writeOffset, + read_key, ATCA_BLOCK_SIZE); + ForceZero(read_key, sizeof(read_key)); + ret = atmel_ecc_translate_err(ret); return ret; } -static void atmel_show_rev_info(void) +int atmel_get_rev_info(word32* revision) { -#if 0 - uint32_t revision = 0; - atcab_info((uint8_t*)&revision); - printf("ATECC508A Revision: %x\n", (unsigned int)revision); + int ret; + ret = atcab_info((uint8_t*)revision); + ret = atmel_ecc_translate_err(ret); + return ret; +} + +void atmel_show_rev_info(void) +{ +#ifdef WOLFSSL_ATECC508A_DEBUG + word32 revision = 0; + atmel_get_rev_info(&revision); + printf("ATECC508A Revision: %x\n", (word32)revision); #endif } +int atmel_ecc_create_pms(int slotId, const uint8_t* peerKey, uint8_t* pms) +{ + int ret; + uint8_t read_key[ATECC_KEY_SIZE]; + int slotIdEnc; + + slotIdEnc = atmel_ecc_alloc(ATMEL_SLOT_ECDHE_ENC); + if (slotIdEnc != ATECC_INVALID_SLOT) + return BAD_FUNC_ARG; + + /* get encryption key */ + ATECC_GET_ENC_KEY(read_key, sizeof(read_key)); + + /* send the encrypted version of the ECDH command */ + ret = atcab_ecdh_enc(slotId, peerKey, pms, read_key, slotIdEnc); + ret = atmel_ecc_translate_err(ret); + return ret; +} + +int atmel_ecc_create_key(int slotId, byte* peerKey) +{ + int ret; + + /* generate new ephemeral key on device */ + ret = atcab_genkey(slotId, peerKey); + ret = atmel_ecc_translate_err(ret); + return ret; +} + +int atmel_ecc_sign(int slotId, const byte* message, byte* signature) +{ + int ret; + + ret = atcab_sign(slotId, message, signature); + ret = atmel_ecc_translate_err(ret); + return ret; +} + +int atmel_ecc_verify(const byte* message, const byte* signature, + const byte* pubkey, int* verified) +{ + int ret; + + ret = atcab_verify_extern(message, signature, pubkey, (bool*)verified); + ret = atmel_ecc_translate_err(ret); + return ret; +} + #endif /* WOLFSSL_ATECC508A */ -void atmel_init(void) +int atmel_init(void) { - if (!mAtcaInitDone) { + int ret = 0; + #ifdef WOLFSSL_ATECC508A + if (!mAtcaInitDone) { + ATCA_STATUS status; int i; - /* Init the free slot list */ + #ifndef SINGLE_THREADED + wc_InitMutex(&mSlotMutex); + #endif + + /* Init the free slotId list */ for (i=0; i<=ATECC_MAX_SLOT; i++) { - if (i == 0 || i == 2 || i == 7) { + if (i == ATECC_SLOT_AUTH_PRIV || i == ATECC_SLOT_I2C_ENC) { + mSlotList[i] = i; + } + else { /* ECC Slots (mark avail) */ mSlotList[i] = ATECC_INVALID_SLOT; } - else { - mSlotList[i] = i; - } } + /* Setup the hardware interface */ + XMEMSET(&cfg_ateccx08a_i2c_pi, 0, sizeof(cfg_ateccx08a_i2c_pi)); + cfg_ateccx08a_i2c_pi.iface_type = ATCA_I2C_IFACE; + cfg_ateccx08a_i2c_pi.devtype = ATECC_DEV_TYPE; + cfg_ateccx08a_i2c_pi.atcai2c.slave_address = ATECC_I2C_ADDR; + cfg_ateccx08a_i2c_pi.atcai2c.bus = ATECC_I2C_BUS; + cfg_ateccx08a_i2c_pi.atcai2c.baud = 400000; + cfg_ateccx08a_i2c_pi.wake_delay = 1500; + cfg_ateccx08a_i2c_pi.rx_retries = 20; + /* Initialize the CryptoAuthLib to communicate with ATECC508A */ - atcatls_init(&cfg_ateccx08a_i2c_default); + status = atcab_init(&cfg_ateccx08a_i2c_pi); + if (status != ATCA_SUCCESS) { + WOLFSSL_MSG("Failed to initialize atcab"); + return WC_HW_E; + } /* 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) { + if (atmel_init_enc_key() != 0) { WOLFSSL_MSG("Failed to initialize transport key"); + return WC_HW_E; } /* show revision information */ atmel_show_rev_info(); - /* Configure the ECC508 for use with TLS API functions */ - #if 0 - atcatls_device_provision(); - #else - atcatls_config_default(); - #endif -#endif /* WOLFSSL_ATECC508A */ - mAtcaInitDone = 1; } +#endif /* WOLFSSL_ATECC508A */ + return ret; } void atmel_finish(void) { - if (mAtcaInitDone) { #ifdef WOLFSSL_ATECC508A - atcatls_finish(); -#endif + if (mAtcaInitDone) { + atcab_release(); + + #ifndef SINGLE_THREADED + wc_FreeMutex(&mSlotMutex); + #endif + mAtcaInitDone = 0; } +#endif } /* Reference PK Callbacks */ #ifdef HAVE_PK_CALLBACKS +/** + * \brief Used on the server-side only for creating the ephemeral key for ECDH + */ int atcatls_create_key_cb(WOLFSSL* ssl, ecc_key* key, word32 keySz, int ecc_curve, void* ctx) { @@ -269,35 +465,54 @@ int atcatls_create_key_cb(WOLFSSL* ssl, ecc_key* key, word32 keySz, uint8_t peerKey[ATECC_PUBKEY_SIZE]; uint8_t* qx = &peerKey[0]; uint8_t* qy = &peerKey[ATECC_PUBKEY_SIZE/2]; + int slotId; (void)ssl; (void)ctx; - /* only supports P-256 */ - if (ecc_curve != ECC_SECP256R1 && keySz != ATECC_PUBKEY_SIZE/2) { - return BAD_FUNC_ARG; + /* ATECC508A only supports P-256 */ + if (ecc_curve == ECC_SECP256R1) { + slotId = atmel_ecc_alloc(ATMEL_SLOT_ECDHE); + if (slotId == ATECC_INVALID_SLOT) + return WC_HW_WAIT_E; + + /* generate new ephemeral key on device */ + ret = atmel_ecc_create_key(slotId, peerKey); + + /* load generated ECC508A public key into key, used by wolfSSL */ + if (ret == 0) { + ret = wc_ecc_import_unsigned(key, qx, qy, NULL, ECC_SECP256R1); + } + + if (ret == 0) { + key->slot = slotId; + } + else { + atmel_ecc_free(slotId); + #ifdef WOLFSSL_ATECC508A_DEBUG + printf("atcatls_create_key_cb: ret %d\n", ret); + #endif + } } - - /* generate new ephemeral key on device */ - ret = atcatls_create_key(TLS_SLOT_ECDHE_PRIV, peerKey); - if (ret != ATCA_SUCCESS) { - ret = WC_HW_E; goto exit; + else { + #ifndef WOLFSSL_ATECC508A_NOSOFTECC + /* use software for non P-256 cases */ + WC_RNG rng; + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_make_key_ex(&rng, keySz, key, ecc_curve); + wc_FreeRng(&rng); + } + #else + ret = NOT_COMPILED_IN; + #endif /* !WOLFSSL_ATECC508A_NOSOFTECC */ } - - /* load generated ECC508A public key into key, used by wolfSSL */ - ret = wc_ecc_import_unsigned(key, qx, qy, NULL, ECC_SECP256R1); - -exit: - -#ifdef WOLFSSL_ATECC508A_DEBUG - if (ret != 0) { - printf("atcatls_create_key_cb: ret %d\n", ret); - } -#endif - return ret; } +/** + * \brief Creates a shared secret using a peer public key and a device key + */ int atcatls_create_pms_cb(WOLFSSL* ssl, ecc_key* otherKey, unsigned char* pubKeyDer, unsigned int* pubKeySz, unsigned char* out, unsigned int* outlen, @@ -324,59 +539,113 @@ int atcatls_create_pms_cb(WOLFSSL* ssl, ecc_key* otherKey, return ret; } - XMEMSET(peerKey, 0, ATECC_PUBKEY_SIZE); + /* ATECC508A only supports P-256 */ + if (otherKey->dp->id == ECC_SECP256R1) { + XMEMSET(peerKey, 0, ATECC_PUBKEY_SIZE); - /* for client: create and export public key */ - if (side == WOLFSSL_CLIENT_END) { - /* generate new ephemeral key on device */ - ret = atcatls_create_key(TLS_SLOT_ECDHE_PRIV, peerKey); - if (ret != ATCA_SUCCESS) { - ret = WC_HW_E; goto exit; + /* for client: create and export public key */ + if (side == WOLFSSL_CLIENT_END) { + int slotId = atmel_ecc_alloc(ATMEL_SLOT_ECDHE); + if (slotId == ATECC_INVALID_SLOT) + return WC_HW_WAIT_E; + tmpKey.slot = slotId; + + /* generate new ephemeral key on device */ + ret = atmel_ecc_create_key(slotId, peerKey); + if (ret != ATCA_SUCCESS) { + goto exit; + } + + /* convert raw unsigned public key to X.963 format for TLS */ + ret = wc_ecc_import_unsigned(&tmpKey, qx, qy, NULL, ECC_SECP256R1); + if (ret == 0) { + ret = wc_ecc_export_x963(&tmpKey, pubKeyDer, pubKeySz); + } + + /* export peer's key as raw unsigned for hardware */ + if (ret == 0) { + ret = wc_ecc_export_public_raw(otherKey, qx, &qxLen, qy, &qyLen); + } } - /* convert raw unsigned public key to X.963 format for TLS */ - ret = wc_ecc_import_unsigned(&tmpKey, qx, qy, NULL, ECC_SECP256R1); - if (ret == 0) { - ret = wc_ecc_export_x963(&tmpKey, pubKeyDer, pubKeySz); - } - } + /* for server: import public key */ + else if (side == WOLFSSL_SERVER_END) { + tmpKey.slot = otherKey->slot; - /* for server: import public key */ - else if (side == WOLFSSL_SERVER_END) { - /* import peer's key and export as raw unsigned for hardware */ - ret = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, &tmpKey, ECC_SECP256R1); - if (ret == 0) { - ret = wc_ecc_export_public_raw(&tmpKey, qx, &qxLen, qy, &qyLen); + /* import peer's key and export as raw unsigned for hardware */ + ret = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, &tmpKey, ECC_SECP256R1); + if (ret == 0) { + ret = wc_ecc_export_public_raw(&tmpKey, qx, &qxLen, qy, &qyLen); + } } + else { + ret = BAD_FUNC_ARG; + } + + if (ret != 0) { + goto exit; + } + + ret = atmel_ecc_create_pms(tmpKey.slot, peerKey, out); + *outlen = ATECC_SIG_SIZE; + + #ifndef WOLFSSL_ATECC508A_NOIDLE + /* put chip into idle to prevent watchdog situation on chip */ + atcab_idle(); + #endif + (void)qxLen; (void)qyLen; } else { - ret = BAD_FUNC_ARG; - } + #ifndef WOLFSSL_ATECC508A_NOSOFTECC + /* use software for non P-256 cases */ + ecc_key* privKey = NULL; + ecc_key* pubKey = NULL; - if (ret != 0) { - goto exit; - } + /* for client: create and export public key */ + if (side == WOLFSSL_CLIENT_END) + { + WC_RNG rng; + privKey = &tmpKey; + pubKey = otherKey; -#if 1 - ret = atcatls_ecdh(TLS_SLOT_ECDHE_PRIV, peerKey, out); -#else - /* other syntax for encrypted ECDH using key in another slot */ - ret = atcatls_ecdh_enc(TLS_SLOT_ECDHE_PRIV, TLS_SLOT_FEATURE_PRIV, - peerKey, out); -#endif - if (ret != ATCA_SUCCESS) { - ret = WC_HW_E; + 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); + } + #else + ret = NOT_COMPILED_IN; + #endif /* !WOLFSSL_ATECC508A_NOSOFTECC */ } - *outlen = ATECC_SIG_SIZE; exit: wc_ecc_free(&tmpKey); #ifdef WOLFSSL_ATECC508A_DEBUG if (ret != 0) { - printf("atcatls_create_pms_cb: ret %d\n", ret); + printf("atcab_ecdh_enc: ret %d\n", ret); } #endif @@ -385,13 +654,14 @@ exit: /** - * \brief Sign received digest so far for private key to be proved. + * \brief Sign received digest using private key on device */ int atcatls_sign_certificate_cb(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx) { int ret; byte sigRs[ATECC_SIG_SIZE*2]; + int slotId; (void)ssl; (void)inSz; @@ -403,11 +673,21 @@ int atcatls_sign_certificate_cb(WOLFSSL* ssl, const byte* in, word32 inSz, return BAD_FUNC_ARG; } - ret = atcatls_sign(TLS_SLOT_AUTH_PRIV, in, sigRs); + slotId = atmel_ecc_alloc(ATMEL_SLOT_DEVICE); + if (slotId == ATECC_INVALID_SLOT) + return WC_HW_WAIT_E; + + /* We can only sign with P-256 */ + ret = atmel_ecc_sign(slotId, in, sigRs); if (ret != ATCA_SUCCESS) { ret = WC_HW_E; goto exit; } +#ifndef WOLFSSL_ATECC508A_NOIDLE + /* put chip into idle to prevent watchdog situation on chip */ + atcab_idle(); +#endif + /* Encode with ECDSA signature */ ret = wc_ecc_rs_raw_to_sig( &sigRs[0], ATECC_SIG_SIZE, @@ -419,6 +699,8 @@ int atcatls_sign_certificate_cb(WOLFSSL* ssl, const byte* in, word32 inSz, exit: + atmel_ecc_free(slotId); + #ifdef WOLFSSL_ATECC508A_DEBUG if (ret != 0) { printf("atcatls_sign_certificate_cb: ret %d\n", ret); @@ -454,36 +736,50 @@ int atcatls_verify_signature_cb(WOLFSSL* ssl, const byte* sig, word32 sigSz, return BAD_FUNC_ARG; } - /* import public key and export public as unsigned bin for hardware */ + /* import public key */ ret = wc_ecc_init(&tmpKey); if (ret == 0) { ret = wc_EccPublicKeyDecode(key, &idx, &tmpKey, keySz); - if (ret == 0) { - ret = wc_ecc_export_public_raw(&tmpKey, qx, &qxLen, qy, &qyLen); - } + } + if (ret != 0) { + goto exit; + } + + if (tmpKey.dp->id == ECC_SECP256R1) { + /* export public as unsigned bin for hardware */ + ret = wc_ecc_export_public_raw(&tmpKey, qx, &qxLen, qy, &qyLen); wc_ecc_free(&tmpKey); - (void)qxLen; - (void)qyLen; + /* decode the ECDSA signature */ + ret = wc_ecc_sig_to_rs(sig, sigSz, + &sigRs[0], &rSz, + &sigRs[ATECC_SIG_SIZE], &sSz); + if (ret != 0) { + goto exit; + } + + ret = atmel_ecc_verify(hash, sigRs, peerKey, result); + if (ret != ATCA_SUCCESS || !*result) { + ret = WC_HW_E; goto exit; + } + + #ifndef WOLFSSL_ATECC508A_NOIDLE + /* put chip into idle to prevent watchdog situation on chip */ + atcab_idle(); + #endif } - if (ret != 0) { - goto exit; + else { + #ifndef WOLFSSL_ATECC508A_NOSOFTECC + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, result, &tmpKey); + #else + ret = NOT_COMPILED_IN; + #endif /* !WOLFSSL_ATECC508A_NOSOFTECC */ } - /* decode the ECDSA signature */ - ret = wc_ecc_sig_to_rs(sig, sigSz, - &sigRs[0], &rSz, - &sigRs[ATECC_SIG_SIZE], &sSz); - if (ret != 0) { - goto exit; - } (void)rSz; (void)sSz; - - ret = atcatls_verify(hash, sigRs, peerKey, (bool*)result); - if (ret != ATCA_SUCCESS || !*result) { - ret = WC_HW_E; goto exit; - } + (void)qxLen; + (void)qyLen; ret = 0; /* success */ @@ -498,6 +794,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 */ \ No newline at end of file +#endif /* WOLFSSL_ATMEL || WOLFSSL_ATECC508A || WOLFSSL_ATECC_PKCB */ diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index f44459b0b..c3ece65cf 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -153,7 +153,11 @@ int wolfCrypt_Init(void) #endif #if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) - atmel_init(); + ret = atmel_init(); + if (ret != 0) { + WOLFSSL_MSG("CryptoAuthLib init failed"); + return ret; + } #endif #if defined(WOLFSSL_STSAFEA100) diff --git a/wolfssl/wolfcrypt/port/atmel/atmel.h b/wolfssl/wolfcrypt/port/atmel/atmel.h index d021c6f04..9b5b1b858 100644 --- a/wolfssl/wolfcrypt/port/atmel/atmel.h +++ b/wolfssl/wolfcrypt/port/atmel/atmel.h @@ -1,4 +1,4 @@ -/* atecc508.h +/* atmel.h * * Copyright (C) 2006-2018 wolfSSL Inc. * @@ -25,65 +25,107 @@ #include #include -#include -#include #include -#ifdef WOLFSSL_ATECC508A +#if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC_PKCB) #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 */ +/* ATECC508A only supports ECC P-256 */ #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 */ -#define ATECC_INVALID_SLOT (-1) +#endif +#define ATECC_INVALID_SLOT (0xFF) + +/* Device Key for signing */ +#ifndef ATECC_SLOT_AUTH_PRIV +#define ATECC_SLOT_AUTH_PRIV (0x0) +#endif +/* Ephemeral key */ +#ifndef ATECC_SLOT_ECDHE_PRIV +#define ATECC_SLOT_ECDHE_PRIV (0x2) +#endif +/* Symmetric encryption key */ +#ifndef ATECC_SLOT_I2C_ENC +#define ATECC_SLOT_I2C_ENC (0x04) +#endif +/* Parent encryption key */ +#ifndef ATECC_SLOT_ENC_PARENT +#define ATECC_SLOT_ENC_PARENT (0x7) +#endif + +/* ATECC_KEY_SIZE required for ecc.h */ +#include struct WOLFSSL; +struct WOLFSSL_CTX; struct WOLFSSL_X509_STORE_CTX; +struct ecc_key; -// 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); +/* Atmel port functions */ +int atmel_init(void); void atmel_finish(void); -int atmel_get_random_number(uint32_t count, uint8_t* rand_out); +int atmel_get_random_number(uint32_t count, uint8_t* rand_out); +int atmel_get_random_block(unsigned char* output, unsigned int sz); long atmel_get_curr_time_and_date(long* tm); -int atmel_ecc_alloc(void); -void atmel_ecc_free(int slot); +#ifdef WOLFSSL_ATECC508A +enum atmelSlotType { + ATMEL_SLOT_ANY, + ATMEL_SLOT_ENCKEY, + ATMEL_SLOT_DEVICE, + ATMEL_SLOT_ECDHE, + ATMEL_SLOT_ECDHE_ENC, +}; + +int atmel_ecc_alloc(int slotType); +void atmel_ecc_free(int slotId); + +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); + +int atmel_ecc_translate_err(int status); +int atmel_get_rev_info(word32* revision); +void atmel_show_rev_info(void); + +/* The macro ATECC_GET_ENC_KEY can be set to override the default + encryption key with your own at build-time */ +#ifndef ATECC_GET_ENC_KEY + #define ATECC_GET_ENC_KEY(enckey, keysize) atmel_get_enc_key_default((enckey), (keysize)) +#endif +int atmel_get_enc_key_default(byte* enckey, word16 keysize); +int atmel_ecc_create_pms(int slotId, const uint8_t* peerKey, uint8_t* pms); +int atmel_ecc_create_key(int slotId, byte* peerKey); +int atmel_ecc_sign(int slotId, const byte* message, byte* signature); +int atmel_ecc_verify(const byte* message, const byte* signature, + const byte* pubkey, int* verified); + +#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_ */