Merge pull request #1815 from dgarske/atecc508_fixes

Fixes for ATECC508A
This commit is contained in:
toddouska
2018-10-17 08:35:09 -07:00
committed by GitHub
8 changed files with 707 additions and 295 deletions

View File

@@ -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 <cryptoauthlib.h>]], [[ 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 <cryptoauthlib.h>]], [[ 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 <zlib.h>]], [[ deflateInit(0, 8); ]])],[ libz_linked=yes ],[ libz_linked=no ])

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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

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 */
@@ -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.

View File

@@ -25,14 +25,22 @@
#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>
#include <wolfssl/ssl.h>
#include <wolfssl/internal.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#ifdef WOLFSSL_ATMEL
/* remap name conflicts */
#define Aes Aes_Remap
#define Gmac Gmac_Remap
#include "asf.h"
@@ -42,27 +50,29 @@
#include <wolfssl/wolfcrypt/port/atmel/atmel.h>
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 */
#endif /* WOLFSSL_ATMEL || WOLFSSL_ATECC508A || WOLFSSL_ATECC_PKCB */

View File

@@ -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)

View File

@@ -1,4 +1,4 @@
/* atecc508.h
/* atmel.h
*
* Copyright (C) 2006-2018 wolfSSL Inc.
*
@@ -25,65 +25,107 @@
#include <stdint.h>
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/ssl.h>
#include <wolfssl/wolfcrypt/ecc.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>
#include <tls/atcatls.h>
#include <atcacert/atcacert_client.h>
#include <tls/atcatls_cfg.h>
#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 <wolfssl/wolfcrypt/ecc.h>
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_ */