/* atmel.c * * Copyright (C) 2006-2022 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 #if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) || \ defined(WOLFSSL_ATECC608A) || defined(WOLFSSL_ATECC_PKCB) #include #include #include #include #ifdef WOLFSSL_ATECC_TNGTLS #include "tng/tng_atcacert_client.h" #endif #ifdef WOLFSSL_ATECC_TFLXTLS #include "atcacert/atcacert_client.h" #include "tng/cust_def_device.h" #include "tng/cust_def_signer.h" #endif #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" #undef Aes #undef Gmac #endif /* WOLFSSL_ATMEL */ #include #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A) #ifdef WOLFSSL_ATECC508A_TLS extern ATCA_STATUS device_init_default(void); #endif static int mAtcaInitDone = 0; /* 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 #ifdef WOLFSSL_ATECC_TNGTLS #define ATECC_I2C_ADDR 0x6A #else #define ATECC_I2C_ADDR 0xC0 #endif #endif #ifndef ATECC_I2C_BUS #define ATECC_I2C_BUS 1 #endif #ifndef ATECC_DEV_TYPE #ifdef WOLFSSL_ATECC508A #define ATECC_DEV_TYPE ATECC508A #else #define ATECC_DEV_TYPE ATECC608A #endif #endif static int ateccx08a_cfg_initialized = 0; static ATCAIfaceCfg cfg_ateccx08a_i2c_pi; #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; #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A) 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 = atcab_random(rng_buffer); if (ret != ATCA_SUCCESS) { 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; } #ifdef ATCAPRINTF atcab_printbin_label((const char*)"\r\nRandom Number", rand_out, count); #endif #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); } #if defined(WOLFSSL_ATMEL) && defined(WOLFSSL_ATMEL_TIME) #include "asf.h" #include "rtc_calendar.h" extern struct rtc_module *_rtc_instance[RTC_INST_NUM]; long atmel_get_curr_time_and_date(long* tm) { long rt = 0; /* 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; rtc_calendar_get_time(_rtc_instance[0], &rtcTime); /* Convert rtc_calendar_time to seconds since UTC */ 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 ) ) ); (void)tm; return rt; } #endif #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A) /* Set the ATECC configuration for wolfSSL to use. * * Return 0 on success, negative upon error */ int wolfCrypt_ATECC_SetConfig(ATCAIfaceCfg* cfg) { WOLFSSL_MSG("Setting ATECC ATCAIfaceCfg configuration"); if (cfg == NULL) { return -1; } /* copy configuration into our local struct */ XMEMSET(&cfg_ateccx08a_i2c_pi, 0, sizeof(cfg_ateccx08a_i2c_pi)); cfg_ateccx08a_i2c_pi.iface_type = cfg->iface_type; cfg_ateccx08a_i2c_pi.devtype = cfg->devtype; #ifdef ATCA_ENABLE_DEPRECATED cfg_ateccx08a_i2c_pi.atcai2c.slave_address = cfg->atcai2c.slave_address; #else cfg_ateccx08a_i2c_pi.atcai2c.address = cfg->atcai2c.address; #endif cfg_ateccx08a_i2c_pi.atcai2c.bus = cfg->atcai2c.bus; cfg_ateccx08a_i2c_pi.atcai2c.baud = cfg->atcai2c.baud; cfg_ateccx08a_i2c_pi.wake_delay = cfg->wake_delay; cfg_ateccx08a_i2c_pi.rx_retries = cfg->rx_retries; cfg_ateccx08a_i2c_pi.cfg_data = cfg->cfg_data; ateccx08a_cfg_initialized = 1; return 0; } int atmel_ecc_translate_err(int status) { 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_ATECC_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; #ifdef WOLFSSL_ATECC_TNGTLS /* not reserved in mSlotList, so return */ goto exit; #else break; #endif case ATMEL_SLOT_ECDHE_ENC: slotId = ATECC_SLOT_ENC_PARENT; #ifdef WOLFSSL_ATECC_TNGTLS /* not reserved in mSlotList, so return */ goto exit; #else break; #endif 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; } } exit: #ifndef SINGLE_THREADED wc_UnLockMutex(&mSlotMutex); #endif return slotId; } /* Function to return slotId number to available list */ void atmel_ecc_free(int slotId) { #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 #ifdef WOLFSSL_ATECC_TNGTLS && slotId != ATMEL_SLOT_ECDHE_ENC #endif ) { /* Mark slotId free */ mSlotList[slotId] = ATECC_INVALID_SLOT; } } #ifndef SINGLE_THREADED wc_UnLockMutex(&mSlotMutex); #endif } /** * \brief Callback function for getting the current encryption key */ int atmel_get_enc_key_default(byte* enckey, word16 keysize) { if (enckey == NULL || keysize != ATECC_KEY_SIZE) { return BAD_FUNC_ARG; } XMEMSET(enckey, 0xFF, keysize); /* use default value */ return 0; } /** * \brief Write enc key before. */ #if defined(WOLFSSL_ATECC_ECDH_ENC) || defined(WOLFSSL_ATECC_ECDH_IOENC) static int atmel_init_enc_key(void) { int ret; uint8_t read_key[ATECC_KEY_SIZE]; uint8_t writeBlock = 0; uint8_t writeOffset = 0; int slotId; bool isLocked = false; slotId = atmel_ecc_alloc(ATMEL_SLOT_ENCKEY); /* check for encryption key slotId */ if (slotId == ATECC_INVALID_SLOT) return BAD_FUNC_ARG; /* skip if slot has already been locked */ ret = atcab_is_slot_locked(slotId, &isLocked); if (ret != ATCA_SUCCESS) { return atmel_ecc_translate_err(ret); } else if (isLocked) { return 0; } /* 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; } #endif int atmel_get_rev_info(word32* 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_ATECC_DEBUG word32 revision = 0; atmel_get_rev_info(&revision); printf("ATECC608 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]; #ifdef WOLFSSL_ATECC_ECDH_ENC int slotIdEnc; slotIdEnc = atmel_ecc_alloc(ATMEL_SLOT_ECDHE_ENC); if (slotIdEnc == ATECC_INVALID_SLOT) return BAD_FUNC_ARG; #endif /* get encryption key */ ATECC_GET_ENC_KEY(read_key, sizeof(read_key)); #ifdef WOLFSSL_ATECC_ECDH_ENC /* send the encrypted version of the ECDH command */ ret = atcab_ecdh_enc(slotId, peerKey, pms, read_key, slotIdEnc); #elif defined(WOLFSSL_ATECC_ECDH_IOENC) /* encrypted ECDH command, using I/O protection key */ ret = atcab_ecdh_ioenc(slotId, peerKey, pms, read_key); #else ret = atcab_ecdh(slotId, peerKey, pms); #endif ret = atmel_ecc_translate_err(ret); ForceZero(read_key, sizeof(read_key)); #ifdef WOLFSSL_ATECC_ECDH_ENC /* free the ECDHE slot */ atmel_ecc_free(slotIdEnc); #endif return ret; } int atmel_ecc_create_key(int slotId, byte* peerKey) { int ret; /* verify provided slotId */ if (slotId == ATECC_INVALID_SLOT) { return WC_HW_WAIT_E; } /* 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* pVerified) { int ret; bool verified = false; ret = atcab_verify_extern(message, signature, pubkey, &verified); ret = atmel_ecc_translate_err(ret); if (pVerified) *pVerified = (int)verified; return ret; } #endif /* WOLFSSL_ATECC508A */ int atmel_init(void) { int ret = 0; #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A) #if defined(WOLFSSL_ATECC608A) /*Harmony3 will generate configuration based on user inputs*/ #ifdef MICROCHIP_MPLAB_HARMONY_3 extern ATCAIfaceCfg atecc608_0_init_data; #endif #endif if (!mAtcaInitDone) { ATCA_STATUS status; int i; #ifndef SINGLE_THREADED wc_InitMutex(&mSlotMutex); #endif /* Init the free slotId list */ for (i=0; islot = slotId; } else { atmel_ecc_free(slotId); #ifdef WOLFSSL_ATECC_DEBUG printf("atcatls_create_key_cb: ret %d\n", ret); #endif } } 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 */ } 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, word32* pubKeySz, unsigned char* out, word32* outlen, int side, void* ctx) { int ret; ecc_key tmpKey; uint8_t peerKeyBuf[ATECC_PUBKEY_SIZE]; uint8_t* peerKey = peerKeyBuf; uint8_t* qx = &peerKey[0]; uint8_t* qy = &peerKey[ATECC_PUBKEY_SIZE/2]; word32 qxLen = ATECC_PUBKEY_SIZE/2, qyLen = ATECC_PUBKEY_SIZE/2; if (pubKeyDer == NULL || pubKeySz == NULL || out == NULL || outlen == NULL) { return BAD_FUNC_ARG; } (void)ssl; (void)ctx; (void)otherKey; ret = wc_ecc_init(&tmpKey); if (ret != 0) { return ret; } /* 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) { 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); } } /* for server: import public key */ else if (side == WOLFSSL_SERVER_END) { tmpKey.slot = otherKey->slot; /* 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_KEY_SIZE; #ifndef WOLFSSL_ATECC508A_NOIDLE /* put chip into idle to prevent watchdog situation on chip */ atcab_idle(); #endif (void)qxLen; (void)qyLen; } else { #ifndef WOLFSSL_ATECC508A_NOSOFTECC /* use software for non P-256 cases */ ecc_key* privKey = NULL; ecc_key* pubKey = NULL; /* 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); } #else ret = NOT_COMPILED_IN; #endif /* !WOLFSSL_ATECC508A_NOSOFTECC */ } exit: wc_ecc_free(&tmpKey); #ifdef WOLFSSL_ATECC_DEBUG if (ret != 0) { printf("atcab_ecdh_enc: ret %d\n", ret); } #endif return ret; } /** * \brief Sign received digest using private key on device */ int atcatls_sign_certificate_cb(WOLFSSL* ssl, const byte* in, unsigned int inSz, byte* out, word32* outSz, const byte* key, unsigned int keySz, void* ctx) { int ret; byte sigRs[ATECC_SIG_SIZE]; int slotId; (void)ssl; (void)inSz; (void)key; (void)keySz; (void)ctx; if (in == NULL || out == NULL || outSz == NULL) { return BAD_FUNC_ARG; } 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/2, &sigRs[ATECC_SIG_SIZE/2], ATECC_SIG_SIZE/2, out, outSz); if (ret != 0) { goto exit; } exit: atmel_ecc_free(slotId); #ifdef WOLFSSL_ATECC_DEBUG if (ret != 0) { printf("atcatls_sign_certificate_cb: ret %d\n", ret); } #endif return ret; } /** * \brief Verify signature received from peers to prove peer's private key. */ int atcatls_verify_signature_cb(WOLFSSL* ssl, const byte* sig, unsigned int sigSz, const byte* hash, unsigned int hashSz, const byte* key, unsigned int keySz, int* result, void* ctx) { int ret; ecc_key tmpKey; word32 idx = 0; uint8_t peerKey[ATECC_PUBKEY_SIZE]; uint8_t* qx = &peerKey[0]; uint8_t* qy = &peerKey[ATECC_PUBKEY_SIZE/2]; word32 qxLen = ATECC_PUBKEY_SIZE/2, qyLen = ATECC_PUBKEY_SIZE/2; byte sigRs[ATECC_SIG_SIZE]; word32 rSz = ATECC_SIG_SIZE/2; word32 sSz = ATECC_SIG_SIZE/2; (void)sigSz; (void)hashSz; (void)ctx; if (ssl == NULL || key == NULL || sig == NULL || hash == NULL || result == NULL) { return BAD_FUNC_ARG; } /* import public key */ ret = wc_ecc_init(&tmpKey); if (ret == 0) { ret = wc_EccPublicKeyDecode(key, &idx, &tmpKey, keySz); } 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); if (ret != 0) { goto exit; } /* decode the ECDSA signature */ ret = wc_ecc_sig_to_rs(sig, sigSz, &sigRs[0], &rSz, &sigRs[ATECC_SIG_SIZE/2], &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 } 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 */ } (void)rSz; (void)sSz; (void)qxLen; (void)qyLen; ret = 0; /* success */ exit: #ifdef WOLFSSL_ATECC_DEBUG if (ret != 0) { printf("atcatls_verify_signature_cb: ret %d\n", ret); } #endif return ret; } static int atcatls_set_certificates(WOLFSSL_CTX *ctx) { #ifndef ATCATLS_SIGNER_CERT_MAX_SIZE #define ATCATLS_SIGNER_CERT_MAX_SIZE 0x250 #endif #ifndef ATCATLS_DEVICE_CERT_MAX_SIZE #define ATCATLS_DEVICE_CERT_MAX_SIZE 0x250 #endif #ifndef ATCATLS_CERT_BUFF_MAX_SIZE #define ATCATLS_CERT_BUFF_MAX_SIZE (ATCATLS_SIGNER_CERT_MAX_SIZE +\ ATCATLS_DEVICE_CERT_MAX_SIZE) #endif #ifndef ATCATLS_PUBKEY_BUFF_MAX_SIZE #define ATCATLS_PUBKEY_BUFF_MAX_SIZE 65 #endif int ret = 0; ATCA_STATUS status; size_t signerCertSize = ATCATLS_SIGNER_CERT_MAX_SIZE; size_t deviceCertSize = ATCATLS_DEVICE_CERT_MAX_SIZE; uint8_t certBuffer[ATCATLS_CERT_BUFF_MAX_SIZE]; uint8_t signerBuffer[ATCATLS_SIGNER_CERT_MAX_SIZE]; #ifdef WOLFSSL_ATECC_TFLXTLS uint8_t signerPubKeyBuffer[ATCATLS_PUBKEY_BUFF_MAX_SIZE]; #endif #ifdef WOLFSSL_ATECC_TNGTLS ret = tng_atcacert_max_signer_cert_size(&signerCertSize); if (ret != ATCACERT_E_SUCCESS) { #ifdef WOLFSSL_ATECC_DEBUG printf("Failed to get max signer cert size\r\n"); #endif return ret; } else if (signerCertSize > ATCATLS_SIGNER_CERT_MAX_SIZE) { #ifdef WOLFSSL_ATECC_DEBUG printf("Signer CA cert buffer too small, need to increase at least" " to %d\r\n", signerCertSize); #endif return -1; } /* Read TNGTLS signer cert */ status = tng_atcacert_read_signer_cert(signerBuffer, &signerCertSize); if (ATCA_SUCCESS != status) { ret = atmel_ecc_translate_err(status); return ret; } /* Read device cert signed by the signer above */ status = tng_atcacert_read_device_cert(certBuffer, &deviceCertSize, signerBuffer); if (ATCA_SUCCESS != status) { ret = atmel_ecc_translate_err(status); return ret; } else if (deviceCertSize > ATCATLS_DEVICE_CERT_MAX_SIZE) { #ifdef WOLFSSL_ATECC_DEBUG printf("Device cert buffer too small, need to increase at least" " to %d\r\n", deviceCertSize); #endif return -1; } #endif #ifdef WOLFSSL_ATECC_TFLXTLS /* MAKE SURE TO COPY YOUR CUSTOM CERTIFICATE FILES UNDER CAL/tng * Verify variable names, here below the code uses typical tflxtls * proto example. * * g_cert_def_1_signer * g_cert_ca_public_key_1_signer * g_cert_def_3_device */ status = atcacert_read_cert(&g_cert_def_1_signer, (const uint8_t*)g_cert_ca_public_key_1_signer, signerBuffer, &signerCertSize); if (status != ATCA_SUCCESS) { #ifdef WOLFSSL_ATECC_DEBUG printf("Failed to read TFLXTLS signer cert!\r\n"); #endif return (int)status; } else if (signerCertSize > ATCATLS_SIGNER_CERT_MAX_SIZE) { #ifdef WOLFSSL_ATECC_DEBUG printf("Signer TFLXTLS CA cert buffer too small, need to increase" " at least to %d\r\n", signerCertSize); #endif return -1; } status = atcacert_get_subj_public_key(&g_cert_def_1_signer, signerBuffer, signerCertSize, signerPubKeyBuffer); if (status != ATCA_SUCCESS) { #ifdef WOLFSSL_ATECC_DEBUG printf("Failed to read TFLXTLS signer public key!\r\n"); #endif return (int)status; } status = atcacert_read_cert(&g_cert_def_3_device, signerPubKeyBuffer, certBuffer, &deviceCertSize); if (status != ATCA_SUCCESS) { #ifdef WOLFSSL_ATECC_DEBUG printf("Failed to read device cert!\r\n"); #endif return (int)status; } #endif /* Prepare the full buffer adding the signer certificate */ XMEMCPY(&certBuffer[deviceCertSize], signerBuffer, signerCertSize); ret = wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, (const unsigned char*)certBuffer, (signerCertSize + deviceCertSize), WOLFSSL_FILETYPE_ASN1); if (ret != WOLFSSL_SUCCESS) { #ifdef WOLFSSL_ATECC_DEBUG printf("Error registering certificate chain\r\n"); #endif ret = -1; } else { ret = 0; } return ret; } int atcatls_set_callbacks(WOLFSSL_CTX* ctx) { int ret = 0; 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); #if defined(WOLFSSL_ATECC_TNGTLS) || defined(WOLFSSL_ATECC_TFLXTLS) ret = atcatls_set_certificates(ctx); if (ret != 0) { #ifdef WOLFSSL_ATECC_DEBUG printf("atcatls_set_certificates failed. (%d)\r\n", ret); #endif } #endif return ret; } 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 || WOLFSSL_ATECC_PKCB */