diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 688602cdc0b..9c4d5dd28bb 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -734,6 +734,7 @@ THREADED_SNIFFTEST TIF_NEED_FPU_LOAD TIME_T_NOT_LONG TI_DUMMY_BUILD +TI_MCU_PLUS_SDK TLS13_RSA_PSS_SIGN_CB_NO_PREHASH TSIP_AES_128_CTR TSIP_AES_256_CTR @@ -1161,6 +1162,10 @@ WOLFSSL_STSAFE_TAKES_SLOT WOLFSSL_TELIT_M2MB WOLFSSL_TEMPLATE_EXAMPLE WOLFSSL_THREADED_CRYPT +WOLFSSL_TI_AM64X_R5 +WOLFSSL_TI_AM64X_RNG_CTR_DRBG +WOLFSSL_TI_AM64X_NO_AES +WOLFSSL_TI_AM64X_NO_SHA WOLFSSL_TICKET_DECRYPT_NO_CREATE WOLFSSL_TICKET_ENC_AES128_GCM WOLFSSL_TICKET_ENC_AES256_CBC diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index b9f3981aeb7..06b2cfdb16d 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -222,6 +222,10 @@ #endif #endif +#ifdef WOLFSSL_TI_AM64X_R5 + #include +#endif + #ifdef WOLFSSL_ASYNC_CRYPT #include #endif @@ -729,6 +733,10 @@ static WC_INLINE void bench_append_memory_info(char* buffer, size_t size, #define fprintf(fp, ...) \ __android_log_print(ANDROID_LOG_DEBUG, "[WOLFCRYPT]", __VA_ARGS__) +#elif defined(TI_MCU_PLUS_SDK) + #include "kernel/nortos/dpl/common/printf.h" + #define printf printf_ + #else #if defined(XMALLOC_USER) || defined(FREESCALE_MQX) /* MQX classic needs for EXIT_FAILURE */ @@ -2441,7 +2449,11 @@ static const char* bench_result_words2[][6] = { }; /* how many kB to test (en/de)cryption */ #define NUM_BLOCKS 25 - #define BENCH_SIZE (1024uL) + #ifdef BENCH_SIZE_EMBEDDED + # define BENCH_SIZE BENCH_SIZE_EMBEDDED + #else + # define BENCH_SIZE (1024uL) + #endif #else #ifndef BENCH_NTIMES #define BENCH_NTIMES 100 @@ -2592,7 +2604,11 @@ static void benchmark_static_init(int force) bench_pq_asym_algs = 0; bench_other_algs = 0; bench_pq_hash_sig_algs = 0; + #ifdef WOLFSSL_BENCHMARK_FIXED_CSV + csv_format = 1; + #else csv_format = 0; + #endif } } @@ -3205,13 +3221,13 @@ static void bench_stats_sym_finish(const char* desc, int useDeviceID, #else #ifdef HAVE_GET_CYCLES (void)XSNPRINTF(msg, sizeof(msg), - "sym,%s,%s,%lu," FLT_FMT "," FLT_FMT ",%lu,", desc, + "sym,%s,%s,%llu," FLT_FMT "," FLT_FMT ",%llu,", desc, BENCH_DEVID_GET_NAME(useDeviceID), bytes_processed, FLT_FMT_ARGS(total), FLT_FMT_ARGS(persec), total_cycles); #else (void)XSNPRINTF(msg, sizeof(msg), - "sym,%s,%s,%lu," FLT_FMT "," FLT_FMT ",", desc, + "sym,%s,%s,%llu," FLT_FMT "," FLT_FMT ",", desc, BENCH_DEVID_GET_NAME(useDeviceID), bytes_processed, FLT_FMT_ARGS(total), FLT_FMT_ARGS(persec)); @@ -8877,13 +8893,15 @@ void bench_sha256(int useDeviceID) printf("InitSha256_ex failed, ret = %d\n", ret); goto exit; } - #ifdef WOLFSSL_PIC32MZ_HASH - wc_Sha256SizeSet(hash[i], numBlocks * bench_size); - #endif } bench_stats_start(&count, &start); do { + #ifdef WOLFSSL_PIC32MZ_HASH + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha256SizeSet(hash[i], numBlocks * bench_size); + } + #endif for (times = 0; times < numBlocks || pending > 0; ) { bench_async_poll(&pending); @@ -19428,7 +19446,7 @@ int wolfcrypt_benchmark_main(int argc, char** argv) argc--; argv++; } -#endif /* MAIN_NO_ARGS */ +#endif /* !MAIN_NO_ARGS */ #if defined(WOLFSSL_BENCHMARK_FIXED_CSV) /* when defined, we'll always output CSV regardless of params. diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index f7aa53f9eb1..500c2d973a7 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -3572,9 +3572,6 @@ WC_ALL_ARGS_NOT_NULL static WARN_UNUSED_RESULT int wc_AesEncrypt( { #if defined(MAX3266X_AES) word32 keySize; -#endif -#if defined(MAX3266X_CB) - int ret_cb; #endif word32 r; @@ -3716,12 +3713,12 @@ WC_ALL_ARGS_NOT_NULL static WARN_UNUSED_RESULT int wc_AesEncrypt( outBlock, (unsigned int)keySize); } #endif -#if defined(MAX3266X_CB) && defined(HAVE_AES_ECB) /* Can do a basic ECB block */ +#if (defined(WOLFSSL_TI_AM64X_R5) || defined(MAX3266X_CB)) && defined(HAVE_AES_ECB) #ifndef WOLF_CRYPTO_CB_FIND if (aes->devId != INVALID_DEVID) #endif { - ret_cb = wc_CryptoCb_AesEcbEncrypt(aes, outBlock, inBlock, + int ret_cb = wc_CryptoCb_AesEcbEncrypt(aes, outBlock, inBlock, WC_AES_BLOCK_SIZE); if (ret_cb != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret_cb; @@ -4448,9 +4445,6 @@ WC_ALL_ARGS_NOT_NULL static WARN_UNUSED_RESULT int wc_AesDecrypt( { #if defined(MAX3266X_AES) word32 keySize; -#endif -#if defined(MAX3266X_CB) - int ret_cb; #endif word32 r; @@ -4566,12 +4560,12 @@ WC_ALL_ARGS_NOT_NULL static WARN_UNUSED_RESULT int wc_AesDecrypt( } #endif -#if defined(MAX3266X_CB) && defined(HAVE_AES_ECB) /* Can do a basic ECB block */ +#if (defined(WOLFSSL_TI_AM64X_R5) || defined(MAX3266X_CB)) && defined(HAVE_AES_ECB) #ifndef WOLF_CRYPTO_CB_FIND if (aes->devId != INVALID_DEVID) #endif { - ret_cb = wc_CryptoCb_AesEcbDecrypt(aes, outBlock, inBlock, + int ret_cb = wc_CryptoCb_AesEcbDecrypt(aes, outBlock, inBlock, WC_AES_BLOCK_SIZE); if (ret_cb != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret_cb; diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 0cc84908060..56a4dc71c74 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -4409,6 +4409,10 @@ int wc_ecc_get_curve_size_from_id(int curve_id) return ecc_sets[curve_idx].size; } +#ifdef TI_MCU_PLUS_SDK + #include +#endif + /* Returns the curve index that corresponds to a given curve name in * ecc_sets[] of ecc.c * diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 6bc3bb40cee..4b116a014cd 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -83,6 +83,7 @@ EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ wolfcrypt/src/port/ti/ti-ccm.c \ wolfcrypt/src/port/ti/ti-c2000-aes.c \ wolfcrypt/src/port/ti/ti-c2000-entropy.c \ + wolfcrypt/src/port/ti/ti-sa2ul_r5_port.c \ wolfcrypt/src/port/pic32/pic32mz-crypt.c \ wolfcrypt/src/port/nrf51.c \ wolfcrypt/src/port/aria/aria-crypt.c \ diff --git a/wolfcrypt/src/port/ti/README_sa2ul.md b/wolfcrypt/src/port/ti/README_sa2ul.md new file mode 100644 index 00000000000..03a8ea5f588 --- /dev/null +++ b/wolfcrypt/src/port/ti/README_sa2ul.md @@ -0,0 +1,43 @@ +# wolfSSL TI SA2UL Hardware Acceleration Port + +wolfSSL supports hardware acceleration on the TI AM6442 via the SA2UL peripheral. + +## SA2UL on the TI AM6442 + +The TI AM6442 is a multi-core SoC, with one dual-core Cortex-A53, two dual-core Cortex-R5F, +a Cortex-M4F, and a dedicated security core based on a Cortex-M3. This support has been +tested on the TMDS64EVM board (rev 101D). + +Basic hardware acceleration supported: +- TRNG (NRBG and CTR-DRBG SP800-90A) +- AES-ECB (128, 256) +- AES-CBC (128, 256) +- AES-GCM (128, 256) +- SHA256, SHA512 +- HMAC-SHA256, HMAC-SHA512 +- CMAC-AES (128, 256) + +Note: The wolfCrypt sa2ul support depends on the TI MCU Plus SDK. wolfBoot has +an example (ti-am64x.config) of how to compile with the MCU Plus SDK. + +### wolfSSL TI AM64x Hardware Acceleration Switches + +To enable all the above, with TRNG in NRBG mode, set the following build switch: + +**`WOLFSSL_TI_AM64X_R5`** + +To change the TRNG to CTR-DRBG mode, then also set this switch: + +**`WOLFSSL_TI_AM64X_RNG_CTR_DRBG`** + +In addition, parts of the hardware acceleration can be disabled (in favor of +wolfCrypt software algorithms), with the following switches: + +**`WOLFSSL_TI_AM64X_NO_AES`** + +**`WOLFSSL_TI_AM64X_NO_SHA`** + +## Support + +For questions please email support@wolfssl.com + diff --git a/wolfcrypt/src/port/ti/ti-sa2ul_r5_port.c b/wolfcrypt/src/port/ti/ti-sa2ul_r5_port.c new file mode 100644 index 00000000000..dae99409a0b --- /dev/null +++ b/wolfcrypt/src/port/ti/ti-sa2ul_r5_port.c @@ -0,0 +1,1242 @@ +/* ti-sa2ul_r5_port.c + * + * Copyright (C) 2006-2026 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 3 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 + */ + +#include + +#if defined(WOLFSSL_TI_AM64X_R5) + +#ifndef WOLF_CRYPTO_CB + #error WOLFSSL_TI_SA2UL support requires ./configure --enable-cryptocb or WOLF_CRYPTO_CB to be defined +#endif + +#include +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/* from ti mcu plus sdk... */ +#include "kernel/dpl/CacheP.h" +#include "kernel/dpl/ClockP.h" +#include "kernel/dpl/MutexArmP.h" +#include "security/security_common/drivers/crypto/crypto.h" +#include "security/security_common/drivers/crypto/rng/rng.h" +#include "security/security_common/drivers/crypto/sa2ul/sa2ul.h" +#include "drivers/sciclient.h" +#include "drivers/sciclient/include/tisci/security/tisci_soc_uid.h" + +static Crypto_Handle handle; +static XALIGNED(SA2UL_CACHELINE_ALIGNMENT) Crypto_Context cryptoCtx; +static uint32_t socUid[UID_LEN_WORDS]; +static int socUidAvail = 0; + +static uint32_t sa2ulHardwareMutex = MUTEX_ARM_UNLOCKED; +static XALIGNED(SA2UL_CACHELINE_ALIGNMENT) SA2UL_ContextParams scParams; +static XALIGNED(SA2UL_CACHELINE_ALIGNMENT) SA2UL_ContextObject scObj; + +static int ti_sa2ul_lock_mutex(void) +{ + if (try_lock_mutex(&sa2ulHardwareMutex) == MUTEX_ARM_LOCKED) + return CRYPTOCB_UNAVAILABLE; + + return 0; +} + +static void ti_sa2ul_unlock_mutex(void) +{ + unlock_mutex(&sa2ulHardwareMutex); +} + +static int _getSocUid(void) +{ + if (socUidAvail == 0) + { + struct tisci_msg_get_soc_uid_req req = {0}; + const Sciclient_ReqPrm_t reqPrm = + { + TISCI_MSG_GET_SOC_UID, + TISCI_MSG_FLAG_AOP, + (const uint8_t *)&req, + sizeof(req), + SystemP_WAIT_FOREVER + }; + struct tisci_msg_get_soc_uid_resp resp; + Sciclient_RespPrm_t respPrm = + { + 0, + (uint8_t *) &resp, + sizeof(resp) + }; + + if (Sciclient_service(&reqPrm, &respPrm) != SystemP_SUCCESS || + respPrm.flags != TISCI_MSG_FLAG_ACK) + { + return -1; + } + XMEMCPY(socUid, resp.soc_uid, sizeof(socUid)); + socUidAvail = 1; + } + return 0; +} + +#ifndef WC_NO_RNG +#define RNG_NUM_DWORDS (4u) +static RNG_Handle rngHandle = NULL; + +static int ti_sa2ul_trng_init_common(void) +{ + RNG_Handle handle = NULL; + if (gRngConfig[0].attrs->isOpen == 0) { + SA2UL_engineEnable(CSL_CP_ACE_CMD_STATUS_TRNG_EN_MASK); + handle = RNG_open(0); + if (handle != NULL) { + if (RNG_setup(handle) == RNG_RETURN_SUCCESS) { + rngHandle = handle; + } + else { + RNG_close(handle); + } + } + } + else { + /* already opened -- use existing handle */ + rngHandle = (RNG_Handle)&gRngConfig[0]; + } + return rngHandle == NULL; +} + +static int ti_sa2ul_trng_init_nrbg(void) +{ + gRngConfig[0].attrs->mode = RNG_DRBG_DISABLE_MODE; + return ti_sa2ul_trng_init_common(); +} + +static int ti_sa2ul_trng_get_nrbg(byte* output, word32 sz) +{ + int ret = 0; + uint32_t random[RNG_NUM_DWORDS]; + + if (output == NULL && sz != 0) + return BAD_FUNC_ARG; + + while (sz) { + uint8_t *ptr = (uint8_t *)random; + int copy_len; + if (RNG_read(rngHandle, random) != RNG_RETURN_SUCCESS) { + ret = WC_HW_E; + goto cleanup_out; + } + copy_len = RNG_NUM_DWORDS * 4; + if (sz < copy_len) + copy_len = sz; + XMEMCPY(output, ptr, copy_len); + output += copy_len; + sz -= copy_len; + } + +cleanup_out: + ForceZero(random, sizeof(random)); + return ret; +} + +#ifdef WOLFSSL_TI_AM64X_RNG_CTR_DRBG +static uint32_t initialSeed[RNG_DRBG_SEED_MAX_ARRY_SIZE_IN_DWORD]; + +static int ti_sa2ul_trng_init_drbg(void) +{ + if (_getSocUid() == 0) { + /* seed (384 bits) = 128-bit nonce + 256-bit uid */ + XMEMCPY(&initialSeed[4], socUid, sizeof(socUid)); + + RNG_close(rngHandle); + rngHandle = NULL; + gRngConfig[0].attrs->mode = RNG_DRBG_MODE; + gRngConfig[0].attrs->seedValue = initialSeed; + gRngConfig[0].attrs->seedSizeInDwords = + RNG_DRBG_SEED_MAX_ARRY_SIZE_IN_DWORD; + return ti_sa2ul_trng_init_common(); + } + return WC_HW_E; +} + +#define TRNG_TIMEOUT_US (100000ULL) /* 100 ms */ +static int ti_sa2ul_trng_get_drbg(byte* output, word32 sz) +{ + int ret = 0; + uint32_t random[RNG_NUM_DWORDS]; + CSL_Cp_aceTrngRegs *pTrngRegs = (CSL_Cp_aceTrngRegs *)gRngConfig[0].attrs->rngBaseAddr; + + if (output == NULL && sz != 0) + return BAD_FUNC_ARG; + + while (sz) { + uint32_t val; + uint8_t *ptr = (uint8_t *)random; + int copy_len; + uint64_t start_time; + + /* wait for READY==1 (random data ready) */ + start_time = ClockP_getTimeUsec(); + do { + if (ClockP_getTimeUsec() - start_time > TRNG_TIMEOUT_US) { + ret = WC_HW_E; + goto cleanup_out; + } + val = CSL_REG_RD(&pTrngRegs->TRNG_STATUS); + } while ((val & CSL_CP_ACE_TRNG_STATUS_READY_MASK) != + CSL_CP_ACE_TRNG_STATUS_READY_MASK); + + random[0] = CSL_REG_RD(&pTrngRegs->TRNG_INPUT_0); + random[1] = CSL_REG_RD(&pTrngRegs->TRNG_INPUT_1); + random[2] = CSL_REG_RD(&pTrngRegs->TRNG_INPUT_2); + random[3] = CSL_REG_RD(&pTrngRegs->TRNG_INPUT_3); + /* ack the data read */ + CSL_REG_WR(&pTrngRegs->TRNG_STATUS, CSL_CP_ACE_TRNG_INTACK_READY_ACK_MASK); + + /* kick off next generate request */ + val = CSL_REG_RD(&pTrngRegs->TRNG_CONTROL); + val |= CSL_CP_ACE_TRNG_CONTROL_DATA_BLOCKS_MASK; + val |= CSL_CP_ACE_TRNG_CONTROL_REQUEST_DATA_MASK; + CSL_REG_WR(&pTrngRegs->TRNG_CONTROL, val); + + copy_len = RNG_NUM_DWORDS * 4; + if (sz < copy_len) + copy_len = sz; + XMEMCPY(output, ptr, copy_len); + output += copy_len; + sz -= copy_len; + } + +cleanup_out: + ForceZero(random, sizeof(random)); + return ret; +} +#endif /* WOLFSSL_TI_AM64X_RNG_CTR_DRBG */ + +static int ti_sa2ul_trng_init(void) +{ + int ret; + + ret = ti_sa2ul_trng_init_nrbg(); + +#ifdef WOLFSSL_TI_AM64X_RNG_CTR_DRBG + /* use the nrbg to generate a 128-bit nonce for the drbg seed */ + if (ret == 0) { + ret = ti_sa2ul_trng_get_nrbg((byte*)&initialSeed[0], RNG_NUM_DWORDS * 4); + } + if (ret == 0) { + ret = ti_sa2ul_trng_init_drbg(); + } +#endif + + return ret; +} + +int ti_sa2ul_trng_get(byte* output, word32 sz) +{ +#ifdef WOLFSSL_TI_AM64X_RNG_CTR_DRBG + return ti_sa2ul_trng_get_drbg(output, sz); +#else + return ti_sa2ul_trng_get_nrbg(output, sz); +#endif +} +#endif /* !WC_NO_RNG */ + +static void _u8LeToU32(uint32_t *dest, uint8_t *src, uint32_t len) +{ + uint32_t i, t = 0; + + for (i=0; ikeylen) != 0) + return CRYPTOCB_UNAVAILABLE; + if (sz == 0) + return 0; + if ((sz % WC_AES_BLOCK_SIZE) != 0) + return BAD_FUNC_ARG; + + if (ti_sa2ul_lock_mutex() != 0) + return CRYPTOCB_UNAVAILABLE; + + SA2UL_ContextParams_init(&scParams); + + scParams.opType = SA2UL_OP_ENC; + scParams.encAlg = SA2UL_ENC_ALG_AES; + scParams.encMode = SA2UL_ENC_MODE_CBC; + scParams.encDirection = SA2UL_ENC_DIR_ENCRYPT; + if (aes->keylen == AES_128_KEY_SIZE) { + scParams.encKeySize = SA2UL_ENC_KEYSIZE_128; + } + else { + scParams.encKeySize = SA2UL_ENC_KEYSIZE_256; + } + XMEMCPY(&scParams.key[0], aes->devKey, aes->keylen); + XMEMCPY(&scParams.iv[0], aes->reg, AES_IV_SIZE); + scParams.inputLen = sz; + scObj.totalLengthInBytes = sz; + + if (SA2UL_contextAlloc(cryptoCtx.drvHandle, + &scObj, &scParams) != SystemP_SUCCESS) + { + ret = WC_HW_E; + } + + ForceZero(scParams.key, sizeof(scParams.key)); + + if (ret == 0) { + CacheP_wbInv((void *)in, sz, CacheP_TYPE_ALLD); + + if (SA2UL_contextProcess(&scObj, in, sz, out) != SystemP_SUCCESS) + ret = WC_HW_E; + else + XMEMCPY(aes->reg, out + sz - WC_AES_BLOCK_SIZE, WC_AES_BLOCK_SIZE); + } + + (void)SA2UL_contextFree(&scObj); + + ti_sa2ul_unlock_mutex(); + + return ret; +} + +#ifdef HAVE_AES_DECRYPT +static int ti_sa2ul_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + int ret = 0; + byte tmp_iv[WC_AES_BLOCK_SIZE]; + + if (aes == NULL) + return BAD_FUNC_ARG; + if (check_aes_keylength(aes->keylen) != 0) + return CRYPTOCB_UNAVAILABLE; + if (sz == 0) + return 0; + if ((sz % WC_AES_BLOCK_SIZE) != 0) + return BAD_FUNC_ARG; + + if (ti_sa2ul_lock_mutex() != 0) + return CRYPTOCB_UNAVAILABLE; + + SA2UL_ContextParams_init(&scParams); + + scParams.opType = SA2UL_OP_ENC; + scParams.encAlg = SA2UL_ENC_ALG_AES; + scParams.encMode = SA2UL_ENC_MODE_CBC; + scParams.encDirection = SA2UL_ENC_DIR_DECRYPT; + if (aes->keylen == AES_128_KEY_SIZE) { + scParams.encKeySize = SA2UL_ENC_KEYSIZE_128; + } + else { + scParams.encKeySize = SA2UL_ENC_KEYSIZE_256; + } + XMEMCPY(&scParams.key[0], aes->devKey, aes->keylen); + XMEMCPY(&scParams.iv[0], aes->reg, AES_IV_SIZE); + scParams.inputLen = sz; + scObj.totalLengthInBytes = sz; + + if (SA2UL_contextAlloc(cryptoCtx.drvHandle, + &scObj, &scParams) != SystemP_SUCCESS) + { + ret = WC_HW_E; + } + + ForceZero(scParams.key, sizeof(scParams.key)); + + if (ret == 0) { + XMEMCPY(tmp_iv, in + sz - WC_AES_BLOCK_SIZE, WC_AES_BLOCK_SIZE); + + CacheP_wbInv((void *)in, sz, CacheP_TYPE_ALLD); + + if (SA2UL_contextProcess(&scObj, in, sz, out) != SystemP_SUCCESS) + ret = WC_HW_E; + else + XMEMCPY(aes->reg, tmp_iv, WC_AES_BLOCK_SIZE); + } + + (void)SA2UL_contextFree(&scObj); + + ti_sa2ul_unlock_mutex(); + + return ret; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_CBC */ + +#ifdef HAVE_AES_ECB +static int ti_sa2ul_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + int ret = 0; + + if (aes == NULL) + return BAD_FUNC_ARG; + if (check_aes_keylength(aes->keylen) != 0) + return CRYPTOCB_UNAVAILABLE; + if (sz == 0) + return 0; + if ((sz % WC_AES_BLOCK_SIZE) != 0) + return BAD_FUNC_ARG; + + if (ti_sa2ul_lock_mutex() != 0) + return CRYPTOCB_UNAVAILABLE; + + SA2UL_ContextParams_init(&scParams); + + scParams.opType = SA2UL_OP_ENC; + scParams.encAlg = SA2UL_ENC_ALG_AES; + scParams.encMode = SA2UL_ENC_MODE_ECB; + scParams.encDirection = SA2UL_ENC_DIR_ENCRYPT; + if (aes->keylen == AES_128_KEY_SIZE) { + scParams.encKeySize = SA2UL_ENC_KEYSIZE_128; + } + else { + scParams.encKeySize = SA2UL_ENC_KEYSIZE_256; + } + XMEMCPY(&scParams.key[0], aes->devKey, aes->keylen); + XMEMCPY(&scParams.iv[0], aes->reg, AES_IV_SIZE); + scParams.inputLen = sz; + scObj.totalLengthInBytes = sz; + + if (SA2UL_contextAlloc(cryptoCtx.drvHandle, + &scObj, &scParams) != SystemP_SUCCESS) + { + ret = WC_HW_E; + } + + ForceZero(scParams.key, sizeof(scParams.key)); + + if (ret == 0) { + CacheP_wbInv((void *)in, sz, CacheP_TYPE_ALLD); + + if (SA2UL_contextProcess(&scObj, in, sz, out) != SystemP_SUCCESS) + ret = WC_HW_E; + } + + (void)SA2UL_contextFree(&scObj); + + ti_sa2ul_unlock_mutex(); + + return ret; +} + +#ifdef HAVE_AES_DECRYPT +static int ti_sa2ul_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + int ret = 0; + + if (aes == NULL) + return BAD_FUNC_ARG; + if (check_aes_keylength(aes->keylen) != 0) + return CRYPTOCB_UNAVAILABLE; + if (sz == 0) + return 0; + if ((sz % WC_AES_BLOCK_SIZE) != 0) + return BAD_FUNC_ARG; + + if (ti_sa2ul_lock_mutex() != 0) + return CRYPTOCB_UNAVAILABLE; + + SA2UL_ContextParams_init(&scParams); + + scParams.opType = SA2UL_OP_ENC; + scParams.encAlg = SA2UL_ENC_ALG_AES; + scParams.encMode = SA2UL_ENC_MODE_ECB; + scParams.encDirection = SA2UL_ENC_DIR_DECRYPT; + if (aes->keylen == AES_128_KEY_SIZE) { + scParams.encKeySize = SA2UL_ENC_KEYSIZE_128; + } + else { + scParams.encKeySize = SA2UL_ENC_KEYSIZE_256; + } + XMEMCPY(&scParams.key[0], aes->devKey, aes->keylen); + XMEMCPY(&scParams.iv[0], aes->reg, AES_IV_SIZE); + scParams.inputLen = sz; + scObj.totalLengthInBytes = sz; + + if (SA2UL_contextAlloc(cryptoCtx.drvHandle, + &scObj, &scParams) != SystemP_SUCCESS) + { + ret = WC_HW_E; + } + + ForceZero(scParams.key, sizeof(scParams.key)); + + if (ret == 0) { + CacheP_wbInv((void *)in, sz, CacheP_TYPE_ALLD); + + if (SA2UL_contextProcess(&scObj, in, sz, out) != SystemP_SUCCESS) + ret = WC_HW_E; + } + + (void)SA2UL_contextFree(&scObj); + + ti_sa2ul_unlock_mutex(); + + return ret; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_ECB */ + +#ifdef HAVE_AESGCM +static void _override_iv_with_ghash(Aes* aes, const byte* iv, word32 ivSz) +{ + SA2UL_SecCtx sc; + byte ivtmp[WC_AES_BLOCK_SIZE]; + + GHASH(&aes->gcm, NULL, 0, iv, ivSz, ivtmp, WC_AES_BLOCK_SIZE); + XMEMCPY(scObj.ctxPrms.iv, ivtmp, WC_AES_BLOCK_SIZE); + _64byteReverseWords((uint32_t*)&sc, (uint32_t*)&scObj.secCtx, sizeof(sc)); + _u8LeToU32(sc.u.enc.encAux3, ivtmp, WC_AES_BLOCK_SIZE); + _64byteReverseWords((uint32_t*)&scObj.secCtx, (uint32_t*)&sc, sizeof(sc)); + CacheP_wbInv(&scObj.secCtx, sizeof(sc), CacheP_TYPE_ALLD); + ForceZero(&sc, sizeof(sc)); +} + +static int ti_sa2ul_AesGcmEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = 0; + + if (aes == NULL) + return BAD_FUNC_ARG; + if (check_aes_keylength(aes->keylen) != 0) + return CRYPTOCB_UNAVAILABLE; + if (sz == 0 || (sz % WC_AES_BLOCK_SIZE) != 0) + return CRYPTOCB_UNAVAILABLE; + + if (ti_sa2ul_lock_mutex() != 0) + return CRYPTOCB_UNAVAILABLE; + + SA2UL_ContextParams_init(&scParams); + + scParams.opType = SA2UL_OP_ENC; + scParams.encAlg = SA2UL_ENC_ALG_AES; + scParams.encMode = SA2UL_ENC_MODE_GCM; + scParams.encDirection = SA2UL_ENC_DIR_ENCRYPT; + if (aes->keylen == AES_128_KEY_SIZE) { + scParams.encKeySize = SA2UL_ENC_KEYSIZE_128; + } + else { + scParams.encKeySize = SA2UL_ENC_KEYSIZE_256; + } + XMEMCPY(scParams.key, aes->devKey, aes->keylen); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(scParams.iv, iv, GCM_NONCE_MID_SZ); + } + XMEMCPY(scParams.ghash, aes->gcm.H, WC_AES_BLOCK_SIZE); + if (authInSz <= sizeof(scParams.aad)) { + XMEMCPY(scParams.aad, authIn, authInSz); + scParams.aadLen = authInSz; + } + else { + scParams.aadLen = 0; + } + scParams.inputLen = sz; + scObj.totalLengthInBytes = sz; + + if (SA2UL_contextAlloc(cryptoCtx.drvHandle, + &scObj, &scParams) != SystemP_SUCCESS) + { + ret = WC_HW_E; + } + + ForceZero(scParams.key, sizeof(scParams.key)); + + if (ret == 0) { + if (ivSz != GCM_NONCE_MID_SZ) { + _override_iv_with_ghash(aes, iv, ivSz); + } + + CacheP_wbInv((void *)in, sz, CacheP_TYPE_ALLD); + + if (SA2UL_contextProcess(&scObj, in, sz, out) != SystemP_SUCCESS) + ret = WC_HW_E; + } + + if (ret == 0 && authTag != NULL) { + if (authInSz <= sizeof(scParams.aad)) { + XMEMCPY(authTag, scObj.computedHash, authTagSz); + } + else { + ALIGN16 byte initialCounter[WC_AES_BLOCK_SIZE]; + ALIGN16 byte scratch[WC_AES_BLOCK_SIZE]; + GHASH(&aes->gcm, authIn, authInSz, out, sz, authTag, authTagSz); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(initialCounter, iv, ivSz); + initialCounter[WC_AES_BLOCK_SIZE-4] = 0; + initialCounter[WC_AES_BLOCK_SIZE-3] = 0; + initialCounter[WC_AES_BLOCK_SIZE-2] = 0; + initialCounter[WC_AES_BLOCK_SIZE-1] = 1; + } + else { + XMEMCPY(initialCounter, scObj.ctxPrms.iv, WC_AES_BLOCK_SIZE); + } + ret = wc_AesEncryptDirect(aes, scratch, initialCounter); + if (ret == 0) + xorbuf(authTag, scratch, authTagSz); + } + } + + (void)SA2UL_contextFree(&scObj); + + ti_sa2ul_unlock_mutex(); + + return ret; +} + +#ifdef HAVE_AES_DECRYPT +static int ti_sa2ul_AesGcmDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = 0; + + if (aes == NULL) + return BAD_FUNC_ARG; + if (check_aes_keylength(aes->keylen) != 0) + return CRYPTOCB_UNAVAILABLE; + if (sz == 0 || (sz % WC_AES_BLOCK_SIZE) != 0) + return CRYPTOCB_UNAVAILABLE; + + if (ti_sa2ul_lock_mutex() != 0) + return CRYPTOCB_UNAVAILABLE; + + SA2UL_ContextParams_init(&scParams); + + scParams.opType = SA2UL_OP_ENC; + scParams.encAlg = SA2UL_ENC_ALG_AES; + scParams.encMode = SA2UL_ENC_MODE_GCM; + scParams.encDirection = SA2UL_ENC_DIR_DECRYPT; + if (aes->keylen == AES_128_KEY_SIZE) { + scParams.encKeySize = SA2UL_ENC_KEYSIZE_128; + } + else { + scParams.encKeySize = SA2UL_ENC_KEYSIZE_256; + } + XMEMCPY(scParams.key, aes->devKey, aes->keylen); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(scParams.iv, iv, GCM_NONCE_MID_SZ); + } + XMEMCPY(scParams.ghash, aes->gcm.H, WC_AES_BLOCK_SIZE); + if (authInSz <= sizeof(scParams.aad)) { + XMEMCPY(scParams.aad, authIn, authInSz); + scParams.aadLen = authInSz; + } + else { + scParams.aadLen = 0; + } + scParams.inputLen = sz; + scObj.totalLengthInBytes = sz; + + if (SA2UL_contextAlloc(cryptoCtx.drvHandle, + &scObj, &scParams) != SystemP_SUCCESS) + { + ret = WC_HW_E; + } + + ForceZero(scParams.key, sizeof(scParams.key)); + + if (ret == 0) { + if (ivSz != GCM_NONCE_MID_SZ) { + _override_iv_with_ghash(aes, iv, ivSz); + } + } + + if (ret == 0 && authTag != NULL && authInSz > sizeof(scParams.aad)) { + ALIGN16 byte initialCounter[WC_AES_BLOCK_SIZE]; + ALIGN16 byte scratch[WC_AES_BLOCK_SIZE]; + ALIGN16 byte Tprime[WC_AES_BLOCK_SIZE]; + GHASH(&aes->gcm, authIn, authInSz, in, sz, Tprime, sizeof(Tprime)); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(initialCounter, iv, ivSz); + initialCounter[WC_AES_BLOCK_SIZE-4] = 0; + initialCounter[WC_AES_BLOCK_SIZE-3] = 0; + initialCounter[WC_AES_BLOCK_SIZE-2] = 0; + initialCounter[WC_AES_BLOCK_SIZE-1] = 1; + } + else { + XMEMCPY(initialCounter, scObj.ctxPrms.iv, WC_AES_BLOCK_SIZE); + } + ret = wc_AesEncryptDirect(aes, scratch, initialCounter); + if (ret == 0) { + xorbuf(Tprime, scratch, sizeof(Tprime)); + if (ConstantCompare(authTag, Tprime, authTagSz) != 0) { + ret = WC_NO_ERR_TRACE(AES_GCM_AUTH_E); + } + } + } + + if (ret == 0) { + CacheP_wbInv((void *)in, sz, CacheP_TYPE_ALLD); + if (SA2UL_contextProcess(&scObj, in, sz, out) != SystemP_SUCCESS) + ret = WC_HW_E; + } + + if (ret == 0 && authTag != NULL && authInSz <= sizeof(scParams.aad)) { + if (ConstantCompare(authTag, scObj.computedHash, authTagSz) != 0) { + ForceZero(out, sz); + ret = WC_NO_ERR_TRACE(AES_GCM_AUTH_E); + } + } + + (void)SA2UL_contextFree(&scObj); + + ti_sa2ul_unlock_mutex(); + + return ret; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AESGCM */ +#endif /* !NO_AES && !WOLFSSL_TI_AM64X_NO_AES */ + + +#if !defined(WOLFSSL_TI_AM64X_NO_SHA) && (!defined(NO_SHA256) || defined(WOLFSSL_SHA512)) +/* The ti mcu plus sdk sa2ul driver requires an output buffer of at least + * the size of the input buffer, and it will write data to it, though we don't + * use the data. So, we consider this a scratch buffer, but it also limits + * the amount of data we can hash at one time. */ +#define HASH_SCRATCH_SIZE 0x2000u +static XALIGNED(SA2UL_CACHELINE_ALIGNMENT) byte hash_scratch[HASH_SCRATCH_SIZE]; + +#ifndef NO_SHA256 +static int ti_sa2ul_InitSha256_ctx(wc_Sha256* sha256) +{ + if (ti_sa2ul_lock_mutex() != 0) { + /* mark as copy so we continue to fall back to software */ + sha256->flags |= WC_HASH_FLAG_ISCOPY; + return CRYPTOCB_UNAVAILABLE; + } + + SA2UL_ContextParams_init(&scParams); + + scParams.opType = SA2UL_OP_AUTH; + scParams.hashAlg = SA2UL_HASH_ALG_SHA2_256; + /* default length to all ff's, final will override when known */ + scParams.inputLen = 0xffffffffUL; + scObj.totalLengthInBytes = 0xffffffffUL; + + if (SA2UL_contextAlloc(cryptoCtx.drvHandle, + &scObj, &scParams) != SystemP_SUCCESS) + { + ti_sa2ul_unlock_mutex(); + return WC_HW_E; + } + + sha256->devCtx = (void *)&scObj; + + return 0; +} + +static void ti_sa2ul_Sha256Free_ctx(wc_Sha256* sha256) +{ + (void)SA2UL_contextFree(&scObj); + + sha256->devCtx = NULL; + + ti_sa2ul_unlock_mutex(); +} + +static void ti_sa2ul_Sha256Teardown(wc_Sha256* sha256) +{ + if (sha256 != NULL && sha256->devCtx == (void*)&scObj) { + /* hash will be finalized in sw via fallback, but we need the driver + * to tear down the context in hw. To do that, we update the context + * length and push some final arbitrary data. It will not affect + * the hash */ + byte buffer[WC_SHA256_DIGEST_SIZE]; + scObj.ctxPrms.inputLen = scObj.txBytesCnt + WC_SHA256_DIGEST_SIZE; + scObj.totalLengthInBytes = scObj.txBytesCnt + WC_SHA256_DIGEST_SIZE; + CacheP_wbInv((void *)buffer, WC_SHA256_DIGEST_SIZE, CacheP_TYPE_ALLD); + SA2UL_contextProcess(&scObj, buffer, + WC_SHA256_DIGEST_SIZE, hash_scratch); + ti_sa2ul_Sha256Free_ctx(sha256); + } +} + +static WC_INLINE void ti_sa2ul_Sha256AddLength(wc_Sha256* sha256, word32 len) +{ + word32 tmp = sha256->loLen; + if ((sha256->loLen += len) < tmp) { + sha256->hiLen++; + } +} + +static int ti_sa2ul_Sha256Hash(wc_Sha256* sha256, const byte* in, + word32 inSz, byte* digest) +{ + int ret = 0; + byte* buffer = (byte*)sha256->buffer; + word32 blocksLen; + word32 partialLen; + + if (in == NULL && digest == NULL) + return BAD_FUNC_ARG; + if ((sha256->flags & WC_HASH_FLAG_ISCOPY) != 0) + return CRYPTOCB_UNAVAILABLE; + + if (sha256->devCtx != (void*)&scObj && + inSz + sha256->buffLen >= WC_SHA256_BLOCK_SIZE) + { + ret = ti_sa2ul_InitSha256_ctx(sha256); + if (ret != 0) + return ret; + } + + if (in != NULL) { + /* update... */ + ti_sa2ul_Sha256AddLength(sha256, inSz); + + /* handle leftovers first */ + if (sha256->buffLen > 0) { + partialLen = min(inSz, WC_SHA256_BLOCK_SIZE - sha256->buffLen); + XMEMCPY(&buffer[sha256->buffLen], in, partialLen); + sha256->buffLen += partialLen; + in += partialLen; + inSz -= partialLen; + if (sha256->buffLen == WC_SHA256_BLOCK_SIZE) { + CacheP_wbInv((void *)buffer, WC_SHA256_BLOCK_SIZE, + CacheP_TYPE_ALLD); + if (SA2UL_contextProcess(&scObj, buffer, + WC_SHA256_BLOCK_SIZE, hash_scratch) != SystemP_SUCCESS) + { + return WC_HW_E; + } + XMEMCPY(sha256->digest, &scObj.computedHash, + WC_SHA256_DIGEST_SIZE); + /* final will fall back to sw, and sw needs bytes reversed */ + ByteReverseWords(sha256->digest, sha256->digest, + WC_SHA256_DIGEST_SIZE); + sha256->buffLen = 0; + } + } + /* chunks of full blocks */ + while (inSz >= WC_SHA256_BLOCK_SIZE) { + blocksLen = min(sizeof(hash_scratch), + inSz & ~((word32)WC_SHA256_BLOCK_SIZE-1)); + CacheP_wbInv((void *)in, blocksLen, CacheP_TYPE_ALLD); + if (SA2UL_contextProcess(&scObj, in, blocksLen, + hash_scratch) != SystemP_SUCCESS) { + return WC_HW_E; + } + XMEMCPY(sha256->digest, &scObj.computedHash, + WC_SHA256_DIGEST_SIZE); + ByteReverseWords(sha256->digest, sha256->digest, + WC_SHA256_DIGEST_SIZE); + in += blocksLen; + inSz -= blocksLen; + } + /* save leftovers */ + if (inSz > 0) { + XMEMCPY(&buffer[0], in, inSz); + sha256->buffLen = inSz; + } + } + else if (digest != NULL) { + /* final... */ + ti_sa2ul_Sha256Teardown(sha256); + /* hash will be finalized in sw via fallback */ + ret = CRYPTOCB_UNAVAILABLE; + } + + return ret; +} +#endif /* !NO_SHA256 */ + +#ifdef WOLFSSL_SHA512 +static int ti_sa2ul_InitSha512_ctx(wc_Sha512* sha512) +{ + if (ti_sa2ul_lock_mutex() != 0) { + /* mark as copy so we continue to fall back to software */ + sha512->flags |= WC_HASH_FLAG_ISCOPY; + return CRYPTOCB_UNAVAILABLE; + } + + SA2UL_ContextParams_init(&scParams); + + scParams.opType = SA2UL_OP_AUTH; + scParams.hashAlg = SA2UL_HASH_ALG_SHA2_512; + /* default length to all ff's, final will override when known */ + scParams.inputLen = 0xffffffffUL; + scObj.totalLengthInBytes = 0xffffffffUL; + + if (SA2UL_contextAlloc(cryptoCtx.drvHandle, + &scObj, &scParams) != SystemP_SUCCESS) + { + ti_sa2ul_unlock_mutex(); + return WC_HW_E; + } + + sha512->devCtx = (void *)&scObj; + + return 0; +} + +static void ti_sa2ul_Sha512Free_ctx(wc_Sha512* sha512) +{ + (void)SA2UL_contextFree(&scObj); + + sha512->devCtx = NULL; + + ti_sa2ul_unlock_mutex(); +} + +static void ti_sa2ul_Sha512Teardown(wc_Sha512* sha512) +{ + if (sha512 != NULL && sha512->devCtx == (void*)&scObj) { + /* hash will be finalized in sw via fallback, but we need the driver + * to tear down the context in hw. To do that, we update the context + * length and push some final arbitrary data. It will not affect + * the hash */ + byte buffer[WC_SHA512_DIGEST_SIZE]; + scObj.ctxPrms.inputLen = scObj.txBytesCnt + + WC_SHA512_DIGEST_SIZE; + scObj.totalLengthInBytes = scObj.txBytesCnt + + WC_SHA512_DIGEST_SIZE; + CacheP_wbInv((void *)buffer, WC_SHA512_DIGEST_SIZE, CacheP_TYPE_ALLD); + SA2UL_contextProcess(&scObj, buffer, + WC_SHA512_DIGEST_SIZE, hash_scratch); + ti_sa2ul_Sha512Free_ctx(sha512); + } +} + +static WC_INLINE void ti_sa2ul_Sha512AddLength(wc_Sha512* sha512, word32 len) +{ + word32 tmp = sha512->loLen; + if ((sha512->loLen += len) < tmp) { + sha512->hiLen++; + } +} + +static int ti_sa2ul_Sha512Hash(wc_Sha512* sha512, const byte* in, + word32 inSz, byte* digest) +{ + int ret = 0; + byte* buffer = (byte*)sha512->buffer; + word32 blocksLen; + word32 partialLen; + + if (in == NULL && digest == NULL) + return BAD_FUNC_ARG; + if (sha512->hashType != WC_HASH_TYPE_SHA512 || + (sha512->flags & WC_HASH_FLAG_ISCOPY) != 0) { + return CRYPTOCB_UNAVAILABLE; + } + + if (sha512->devCtx != (void*)&scObj && + inSz + sha512->buffLen >= WC_SHA512_BLOCK_SIZE) + { + ret = ti_sa2ul_InitSha512_ctx(sha512); + if (ret != 0) + return ret; + } + + if (in != NULL) { + /* update... */ + ti_sa2ul_Sha512AddLength(sha512, inSz); + + /* handle leftovers first */ + if (sha512->buffLen > 0) { + partialLen = min(inSz, WC_SHA512_BLOCK_SIZE - sha512->buffLen); + XMEMCPY(&buffer[sha512->buffLen], in, partialLen); + sha512->buffLen += partialLen; + in += partialLen; + inSz -= partialLen; + if (sha512->buffLen == WC_SHA512_BLOCK_SIZE) { + CacheP_wbInv((void *)buffer, WC_SHA512_BLOCK_SIZE, CacheP_TYPE_ALLD); + if (SA2UL_contextProcess(&scObj, buffer, + WC_SHA512_BLOCK_SIZE, hash_scratch) != SystemP_SUCCESS) + { + return WC_HW_E; + } + XMEMCPY(sha512->digest, &scObj.computedHash, + WC_SHA512_DIGEST_SIZE); + /* final will fall back to sw, and sw needs bytes reversed */ + ByteReverseWords64(sha512->digest, sha512->digest, + WC_SHA512_DIGEST_SIZE); + sha512->buffLen = 0; + } + } + /* chunks of full blocks */ + while (inSz >= WC_SHA512_BLOCK_SIZE) { + blocksLen = min(sizeof(hash_scratch), + inSz & ~((word32)WC_SHA512_BLOCK_SIZE-1)); + CacheP_wbInv((void *)in, blocksLen, CacheP_TYPE_ALLD); + if (SA2UL_contextProcess(&scObj, in, blocksLen, + hash_scratch) != SystemP_SUCCESS) { + return WC_HW_E; + } + XMEMCPY(sha512->digest, &scObj.computedHash, + WC_SHA512_DIGEST_SIZE); + ByteReverseWords64(sha512->digest, sha512->digest, + WC_SHA512_DIGEST_SIZE); + in += blocksLen; + inSz -= blocksLen; + } + /* save leftovers */ + if (inSz > 0) { + XMEMCPY(&buffer[0], in, inSz); + sha512->buffLen = inSz; + } + } + else if (digest != NULL) { + /* final... */ + ti_sa2ul_Sha512Teardown(sha512); + /* hash will be finalized in sw via fallback */ + ret = CRYPTOCB_UNAVAILABLE; + } + + return ret; +} +#endif /* WOLFSSL_SHA512 */ +#endif /* !WOLFSSL_TI_AM64X_NO_SHA && (!NO_SHA256 || WOLFSSL_SHA512) */ + +static int ti_sa2ul_CryptoDevCb(int devId, wc_CryptoInfo* info, void* devCtx) +{ + int ret = CRYPTOCB_UNAVAILABLE; + + WOLFSSL_ENTER("ti_sa2ul_CryptoDevCb"); + + (void)devCtx; + + if (info == NULL) + return BAD_FUNC_ARG; + if (devId == INVALID_DEVID) + return CRYPTOCB_UNAVAILABLE; + +#ifdef DEBUG_CRYPTOCB + wc_CryptoCb_InfoString(info); +#endif + + if (info->algo_type == WC_ALGO_TYPE_CIPHER) + { +#if !defined(NO_AES) && !defined(WOLFSSL_TI_AM64X_NO_AES) + if (0) { + /* nothing */ + } +# if defined(HAVE_AES_CBC) + else if (info->cipher.type == WC_CIPHER_AES_CBC) { + if (info->cipher.enc) { + ret = ti_sa2ul_AesCbcEncrypt(info->cipher.aescbc.aes, + info->cipher.aescbc.out, + info->cipher.aescbc.in, + info->cipher.aescbc.sz); + } +# ifdef HAVE_AES_DECRYPT + else { + ret = ti_sa2ul_AesCbcDecrypt(info->cipher.aescbc.aes, + info->cipher.aescbc.out, + info->cipher.aescbc.in, + info->cipher.aescbc.sz); + } +# endif /* HAVE_AES_DECRYPT */ + } +# endif /* HAVE_AES_CBC */ +# if defined(HAVE_AES_ECB) + else if (info->cipher.type == WC_CIPHER_AES_ECB) { + if (info->cipher.enc) { + ret = ti_sa2ul_AesEcbEncrypt(info->cipher.aesecb.aes, + info->cipher.aesecb.out, + info->cipher.aesecb.in, + info->cipher.aesecb.sz); + } +# ifdef HAVE_AES_DECRYPT + else { + ret = ti_sa2ul_AesEcbDecrypt(info->cipher.aesecb.aes, + info->cipher.aesecb.out, + info->cipher.aesecb.in, + info->cipher.aesecb.sz); + } +# endif /* HAVE_AES_DECRYPT */ + } +# endif /* HAVE_AES_ECB */ +# if defined(HAVE_AESGCM) + else if (info->cipher.type == WC_CIPHER_AES_GCM) { + if (info->cipher.enc) { + ret = ti_sa2ul_AesGcmEncrypt( + info->cipher.aesgcm_enc.aes, + info->cipher.aesgcm_enc.out, + info->cipher.aesgcm_enc.in, + info->cipher.aesgcm_enc.sz, + info->cipher.aesgcm_enc.iv, + info->cipher.aesgcm_enc.ivSz, + info->cipher.aesgcm_enc.authTag, + info->cipher.aesgcm_enc.authTagSz, + info->cipher.aesgcm_enc.authIn, + info->cipher.aesgcm_enc.authInSz); + } +# ifdef HAVE_AES_DECRYPT + else { + ret = ti_sa2ul_AesGcmDecrypt( + info->cipher.aesgcm_dec.aes, + info->cipher.aesgcm_dec.out, + info->cipher.aesgcm_dec.in, + info->cipher.aesgcm_dec.sz, + info->cipher.aesgcm_dec.iv, + info->cipher.aesgcm_dec.ivSz, + info->cipher.aesgcm_dec.authTag, + info->cipher.aesgcm_dec.authTagSz, + info->cipher.aesgcm_dec.authIn, + info->cipher.aesgcm_dec.authInSz); + } +# endif /* HAVE_AES_DECRYPT */ + } +# endif /* HAVE_AESGCM */ +#endif /* !NO_AES && !WOLFSSL_TI_AM64X_NO_AES */ + } + else if (info->algo_type == WC_ALGO_TYPE_HASH) + { +#if !defined(WOLFSSL_TI_AM64X_NO_SHA) && (!defined(NO_SHA256) || defined(WOLFSSL_SHA512)) + if (0) { + /* nothing */ + } +# ifndef NO_SHA256 + else if (info->hash.type == WC_HASH_TYPE_SHA256) { + ret = ti_sa2ul_Sha256Hash(info->hash.sha256, + info->hash.in, + info->hash.inSz, + info->hash.digest); + } +# endif /* !NO_SHA256 */ +# ifdef WOLFSSL_SHA512 + else if (info->hash.type == WC_HASH_TYPE_SHA512) { + ret = ti_sa2ul_Sha512Hash(info->hash.sha512, + info->hash.in, + info->hash.inSz, + info->hash.digest); + } +# endif /* WOLFSSL_SHA512 */ +#endif /* !WOLFSSL_TI_AM64X_NO_SHA && (!NO_SHA256 || WOLFSSL_SHA512) */ + } +#ifdef WOLF_CRYPTO_CB_FREE + else if (info->algo_type == WC_ALGO_TYPE_FREE) + { +# if !defined(WOLFSSL_TI_AM64X_NO_SHA) && (!defined(NO_SHA256) || defined(WOLFSSL_SHA512)) + if (info->free.algo == WC_ALGO_TYPE_HASH) { + if (0) { + /* nothing */ + } +# ifndef NO_SHA256 + else if (info->free.type == WC_HASH_TYPE_SHA256) { + wc_Sha256* sha256 = (wc_Sha256*)info->free.obj; + ti_sa2ul_Sha256Teardown(sha256); + /* ret still == CRYPTOCB_UNAVAILABLE for any malloc cleanup */ + } +# endif /* !NO_SHA256 */ +# ifdef WOLFSSL_SHA512 + else if (info->free.type == WC_HASH_TYPE_SHA512) { + wc_Sha512* sha512 = (wc_Sha512*)info->free.obj; + ti_sa2ul_Sha512Teardown(sha512); + /* ret still == CRYPTOCB_UNAVAILABLE for any malloc cleanup */ + } +# endif /* WOLFSSL_SHA512 */ + } +# endif /* !WOLFSSL_TI_AM64X_NO_SHA && (!NO_SHA256 || WOLFSSL_SHA512) */ + } +#endif /* WOLF_CRYPTO_CB_FREE */ + + return ret; +} + +void ti_sa2ul_soc_uid(byte* uid) +{ + if (_getSocUid() == 0) + XMEMCPY(uid, socUid, sizeof(socUid)); + else + XMEMSET(uid, 0xFFu, sizeof(socUid)); +} + +int ti_sa2ul_port_init(void) +{ + int ret = WC_HW_E; + +#ifndef WC_NO_RNG + if (ti_sa2ul_trng_init() != 0) + return ret; +#endif + + handle = Crypto_open(&cryptoCtx); + if (handle != NULL) { + ret = wc_CryptoCb_RegisterDevice(WOLFSSL_TI_SA2UL_DEVID, + ti_sa2ul_CryptoDevCb, NULL); + } + return ret; +} + +#endif /* WOLFSSL_TI_AM64X_R5 */ diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 55d23d2e6e5..b79f2c7a2c7 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -245,6 +245,10 @@ This library contains implementation for the random number generator. #endif #endif +#if defined(WOLFSSL_TI_AM64X_R5) + #include +#endif + #if defined(WOLFSSL_SILABS_SE_TYPES) #include #endif diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 5f0510f7c89..891d8708e3d 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -3596,6 +3596,10 @@ int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) } #endif +#if defined(WOLFSSL_TI_AM64X_R5) && !defined(WOLFSSL_TI_AM64X_NO_SHA) + dst->devCtx = NULL; +#endif + #ifdef WOLFSSL_HASH_FLAGS dst->flags |= WC_HASH_FLAG_ISCOPY; #endif diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index bac5fc9ef57..67bab807abb 100644 --- a/wolfcrypt/src/sha512.c +++ b/wolfcrypt/src/sha512.c @@ -959,6 +959,7 @@ static int InitSha512(wc_Sha512* sha512) #if defined(WOLFSSL_SHA512_HASHTYPE) sha512->hashType = WC_HASH_TYPE_SHA512; #endif /* WOLFSSL_SHA512_HASHTYPE */ + return 0; } @@ -3356,6 +3357,10 @@ int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst) #endif /* WOLFSSL_USE_ESP32_CRYPT_HASH_HW */ +#if defined(WOLFSSL_TI_AM64X_R5) && !defined(WOLFSSL_TI_AM64X_NO_SHA) + dst->devCtx = NULL; +#endif + #ifdef WOLFSSL_HASH_FLAGS dst->flags |= WC_HASH_FLAG_ISCOPY; #endif diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index 95527d195f8..2fffcbbffff 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -212,6 +212,10 @@ Threading/Mutex options: #include #endif +#ifdef WOLFSSL_TI_AM64X_R5 + #include +#endif + #ifdef WOLF_CRYPTO_CB #include #endif @@ -951,6 +955,14 @@ int wolfCrypt_Init(void) } #endif + #if defined(WOLFSSL_TI_AM64X_R5) + ret = ti_sa2ul_port_init(); + if (ret != 0) { + WOLFSSL_MSG("TI AM64x Init Failed"); + WOLFCRYPT_INIT_RAISE_BAD_STATE(); + } + #endif + #if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) || \ defined(WOLFSSL_ATECC608A) || defined(WOLFSSL_MICROCHIP_TA100) ret = atmel_init(); diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 260b6e94d22..7e16ca6bad0 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -355,6 +355,12 @@ static const byte const_byte_array[] = "A+Gd\0\0\0"; if ((_i & 7) != 0) WOLFSSL_DEBUG_PRINTF("\n"); \ } while(0) +#ifdef TI_MCU_PLUS_SDK +# include "kernel/nortos/dpl/common/printf.h" +# undef printf +# define printf printf_ +#endif + #include #include #include @@ -529,6 +535,10 @@ static const byte const_byte_array[] = "A+Gd\0\0\0"; #endif #endif +#ifdef WOLFSSL_TI_AM64X_R5 + #include +#endif + #ifdef _MSC_VER /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ #pragma warning(disable: 4996) diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index a24c448a6e7..8d19b2a3ad7 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -101,6 +101,7 @@ noinst_HEADERS+= \ wolfssl/wolfcrypt/port/ti/ti-ccm.h \ wolfssl/wolfcrypt/port/ti/ti-c2000.h \ wolfssl/wolfcrypt/port/ti/ti-c2000-entropy.h \ + wolfssl/wolfcrypt/port/ti/ti-sa2ul_r5_port.h \ wolfssl/wolfcrypt/port/nrf51.h \ wolfssl/wolfcrypt/port/nxp/ksdk_port.h \ wolfssl/wolfcrypt/port/nxp/dcp_port.h \ diff --git a/wolfssl/wolfcrypt/port/ti/ti-sa2ul_r5_port.h b/wolfssl/wolfcrypt/port/ti/ti-sa2ul_r5_port.h new file mode 100644 index 00000000000..1df2e5a9a56 --- /dev/null +++ b/wolfssl/wolfcrypt/port/ti/ti-sa2ul_r5_port.h @@ -0,0 +1,45 @@ +/* ti-sa2ul_r5_port.h + * + * Copyright (C) 2006-2026 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 3 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 + */ +#ifndef _TI_SA2UL_R5_PORT_H_ +#define _TI_SA2UL_R5_PORT_H_ + +#if defined(WOLFSSL_TI_AM64X_R5) + +#include +#include +#include "security/security_common/drivers/crypto/sa2ul/sa2ul.h" + +#define WOLFSSL_TI_SA2UL_DEVID 8888 +#define WC_USE_DEVID WOLFSSL_TI_SA2UL_DEVID + +#ifdef WOLFSSL_TI_AM64X_RNG_CTR_DRBG + #define CUSTOM_RAND_GENERATE_BLOCK ti_sa2ul_trng_get +#else + #define CUSTOM_RAND_GENERATE_SEED ti_sa2ul_trng_get +#endif + +int ti_sa2ul_port_init(void); +void ti_sa2ul_soc_uid(uint8_t *uid); +int ti_sa2ul_trng_get(byte* output, word32 sz); + +#endif /* WOLFSSL_TI_AM64X_R5 */ + +#endif /* _TI_SA2UL_R5_PORT_H_ */ diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 85f98891574..5b64dcc8ab1 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -2516,6 +2516,18 @@ #define NO_WOLFSSL_SHA256_INTERLEAVE #endif +#ifdef WOLFSSL_TI_AM64X_R5 + #define NO_DEV_RANDOM + #ifndef TI_MCU_PLUS_SDK + #define TI_MCU_PLUS_SDK + #endif + #define WOLFSSL_SHA512_HASHTYPE + #ifndef WOLF_CRYPTO_CB + #define WOLF_CRYPTO_CB + #endif + #define WOLF_CRYPTO_CB_FREE +#endif + #ifdef FREESCALE_LTC_TFM_RSA_4096_ENABLE #undef USE_CERT_BUFFERS_4096 #define USE_CERT_BUFFERS_4096 diff --git a/wolfssl/wolfcrypt/sha512.h b/wolfssl/wolfcrypt/sha512.h index 8de7266446c..b3323d17ccd 100644 --- a/wolfssl/wolfcrypt/sha512.h +++ b/wolfssl/wolfcrypt/sha512.h @@ -147,6 +147,7 @@ #if defined(WOLFSSL_MAX3266X) || defined(WOLFSSL_MAX3266X_OLD) #include "wolfssl/wolfcrypt/port/maxim/max3266x.h" #endif + /* wc_Sha512 digest */ struct wc_Sha512 { #if defined(PSOC6_HASH_SHA2) diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 7a177b34eb2..aab8483bbc8 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -2391,7 +2391,7 @@ WOLFSSL_API word32 CheckRunTimeSettings(void); #define PRAGMA_GCC_DIAG_POP /* null expansion */ #endif -#ifdef __clang__ +#if defined(__clang__) && !defined(__ti__) #define PRAGMA_CLANG_DIAG_PUSH _Pragma("clang diagnostic push") #define PRAGMA_CLANG(str) _Pragma(str) #define PRAGMA_CLANG_DIAG_POP _Pragma("clang diagnostic pop") @@ -2408,7 +2408,10 @@ WOLFSSL_API word32 CheckRunTimeSettings(void); #define PRAGMA_DIAG_PUSH /* null expansion */ #endif #ifndef PRAGMA +/* for ti, PRAGMA is defined in the mcu plus sdk... */ +# if !(defined(__ti__) && defined(TI_MCU_PLUS_SDK)) #define PRAGMA(str) /* null expansion */ +# endif #endif #ifndef PRAGMA_DIAG_POP #define PRAGMA_DIAG_POP /* null expansion */