diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index b7302b8376d..b03b8217da3 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -1089,6 +1089,7 @@ WOLFSSL_NUVOTON_NSC_IMPL WOLFSSL_NUVOTON_RNG_OFFLOAD WOLFSSL_NXP_CASPER_ECC_MUL2ADD WOLFSSL_NXP_CASPER_ECC_MULMOD +WOLFSSL_NXP_HWPUF WOLFSSL_NXP_LPC55S6X WOLFSSL_OCSP_SCREEN_RESPONDER WOLFSSL_OLDTLS_AEAD_CIPHERSUITES diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 5c294833b5d..e6fd6987bdc 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -6030,11 +6030,11 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))) || \ (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)) || \ defined(WOLFSSL_NXP_HASHCRYPT_AES) - #ifdef WOLF_CRYPTO_CB - #ifndef WOLF_CRYPTO_CB_FIND + /* HashCrypt always loads the key from devKey, regardless of devId */ + #if defined(WOLF_CRYPTO_CB) && !defined(WOLF_CRYPTO_CB_FIND) && \ + !defined(WOLFSSL_NXP_HASHCRYPT_AES) if (aes->devId != INVALID_DEVID) #endif - #endif { if (keylen > sizeof(aes->devKey)) { return BAD_FUNC_ARG; diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 82261393a4a..840c047781a 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -766,6 +766,24 @@ const char* wc_GetErrorString(int error) case UNEXPECTED_STATE_E: return "Object has unexpected state"; + case HWPUF_INIT_E: + return "HWPUF initialization failed"; + + case HWPUF_ENROLL_E: + return "HWPUF enrollment failed"; + + case HWPUF_START_E: + return "HWPUF start failed"; + + case HWPUF_GENERATE_KEY_E: + return "HWPUF generate key failed"; + + case HWPUF_GET_KEY_E: + return "HWPUF get key failed"; + + case HWPUF_ZEROIZE_E: + return "HWPUF zeroize failed"; + case MAX_CODE_E: case WC_SPAN1_MIN_CODE_E: case MIN_CODE_E: diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 088fa4a3e0f..a85a6cfa50b 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -103,6 +103,7 @@ EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ wolfcrypt/src/port/nxp/sec_qoriq_sim.c \ wolfcrypt/src/port/nxp/casper_port.c \ wolfcrypt/src/port/nxp/hashcrypt_port.c \ + wolfcrypt/src/port/nxp/hwpuf_port.c \ wolfcrypt/src/port/atmel/README.md \ wolfcrypt/src/port/xilinx/xil-sha3.c \ wolfcrypt/src/port/xilinx/xil-aesgcm.c \ diff --git a/wolfcrypt/src/port/nxp/README.md b/wolfcrypt/src/port/nxp/README.md index 25615b9f635..a079be04ee6 100644 --- a/wolfcrypt/src/port/nxp/README.md +++ b/wolfcrypt/src/port/nxp/README.md @@ -50,6 +50,30 @@ define the following symbol: NOTE: Both can be defined with no problem. +### LPC55S69 Hardware PUF + +To enable the hardware PUF (SRAM PUF) port, define the following symbol and +build `wolfcrypt/src/port/nxp/hwpuf_port.c` along with the MCUXpresso +`fsl_puf.c` driver: + +**`WOLFSSL_NXP_HWPUF`** + +This is not enabled by `WOLFSSL_NXP_LPC55S6X`. The API is declared in +`wolfssl/wolfcrypt/port/nxp/hwpuf_port.h`: + +- Provisioning (once per device): + `nxp_hwpuf_Init` -> `nxp_hwpuf_Enroll` (store the activation code) -> + `nxp_hwpuf_Deinit` -> `nxp_hwpuf_Init` -> `nxp_hwpuf_Start` -> + `nxp_hwpuf_GenerateKey` (store the key code(s)) +- Normal boot: + `nxp_hwpuf_Init` -> `nxp_hwpuf_Start` -> `nxp_hwpuf_GetKey` +- `nxp_hwpuf_Zeroize` wipes PUF state and deinitializes the PUF; call + `nxp_hwpuf_Init` before further use (no separate `nxp_hwpuf_Deinit` needed). + +Key index 0, which the PUF delivers only over the hardware bus to the AES +engine, is not supported: `nxp_hwpuf_GenerateKey()` and `nxp_hwpuf_GetKey()` +reject it. Use key indices 1 to 15. + ## NXP SE050 For details on wolfSSL integration with NXP SE050, diff --git a/wolfcrypt/src/port/nxp/hashcrypt_port.c b/wolfcrypt/src/port/nxp/hashcrypt_port.c index d1a21f47082..5c45ee140b5 100644 --- a/wolfcrypt/src/port/nxp/hashcrypt_port.c +++ b/wolfcrypt/src/port/nxp/hashcrypt_port.c @@ -536,6 +536,19 @@ int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) return ret; } + +int wc_AesCtrSetKey(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir) +{ + if (aes == NULL) { + return BAD_FUNC_ARG; + } + if (len > sizeof(aes->key)) { + return BAD_FUNC_ARG; + } + + return wc_AesSetKey(aes, key, len, iv, dir); +} #endif /* WOLFSSL_AES_COUNTER */ #endif /* !defined(NO_AES) && defined(WOLFSSL_NXP_HASHCRYPT_AES) */ diff --git a/wolfcrypt/src/port/nxp/hwpuf_port.c b/wolfcrypt/src/port/nxp/hwpuf_port.c new file mode 100644 index 00000000000..6fba755a747 --- /dev/null +++ b/wolfcrypt/src/port/nxp/hwpuf_port.c @@ -0,0 +1,261 @@ +/* hwpuf_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_NXP_HWPUF) + +#include +#include +#include "fsl_puf.h" + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/* PUF lifecycle: + * Provisioning (once per device): + * Init -> Enroll -> Deinit -> Init -> Start -> GenerateKey(s) + * Normal boot: + * Init -> Start -> GetKey(s) + * Enroll and Start are mutually exclusive within one Init session; the PUF + * must be re-initialized (Deinit/Init) after Enroll before Start, matching + * the NXP SDK PUF example flow. Zeroize wipes PUF state and deinitializes + * the PUF; only Init is needed before further use. + */ + +#define HWPUF_KEY_SIZE_IS_VALID(keysz) \ + ((keysz) == 16 || (keysz) == 24 || (keysz) == 32) + +typedef enum nxp_hwpuf_flag { + NXP_HWPUF_FLAG_NONE = 0, /* Deinit() clears all flags */ + NXP_HWPUF_FLAG_INITED = 0x01, /* Init() called successfully */ + NXP_HWPUF_FLAG_ENROLLED = 0x02, /* Enroll() called successfully */ + NXP_HWPUF_FLAG_READY = 0x04, /* Start() called successfully */ + WOLF_ENUM_DUMMY_LAST_ELEMENT(NXP_HWPUF_FLAG) +} nxp_hwpuf_flag; + +typedef enum nxp_hwpuf_keytype { + nxp_hwpuf_keytype_user = 0, + nxp_hwpuf_keytype_intrinsic = 1, + nxp_hwpuf_keytype_max = nxp_hwpuf_keytype_intrinsic +} nxp_hwpuf_keytype; + +typedef struct nxp_hwpuf_ctx { + word32 flags; +} nxp_hwpuf_ctx; + +static nxp_hwpuf_ctx ctx; +static puf_config_t conf; + +static int keyCodeCheck(const byte* keyCode, word32* keytype, + word32* keyidx, word32* keysize) +{ + *keytype = keyCode[0]; + *keyidx = keyCode[1]; + *keysize = keyCode[3] == 0 ? 512 : 8 * keyCode[3] ; + + if (*keytype > nxp_hwpuf_keytype_max) + return 1; + if (*keyidx > kPUF_KeyIndexMax) + return 2; + if ( !HWPUF_KEY_SIZE_IS_VALID(*keysize) ) + return 3; + + return 0; +} + +/* Validate PUF state and key code, return key index and key size */ +static int keyCodeParse(const byte* keyCode, word32 keyCodeSz, + word32* keyidx, word32* keysize) +{ + word32 keytype; + + if ((ctx.flags & NXP_HWPUF_FLAG_READY) == 0) + return HWPUF_START_E; + if (keyCode == NULL || keyCodeSz < PUF_MIN_KEY_CODE_SIZE) + return BAD_FUNC_ARG; + if (keyCodeCheck(keyCode, &keytype, keyidx, keysize) != 0) + return BAD_FUNC_ARG; + if (PUF_GET_KEY_CODE_SIZE_FOR_KEY_SIZE(*keysize) != keyCodeSz) + return BAD_FUNC_ARG; + + return 0; +} + +WOLFSSL_API int nxp_hwpuf_Init(void) +{ + WOLFSSL_ENTER("nxp_hwpuf_Init"); + + if ((ctx.flags & NXP_HWPUF_FLAG_INITED) != 0) + return 0; + + PUF_GetDefaultConfig(&conf); + if (PUF_Init(PUF, &conf) != kStatus_Success) { + PUF_Deinit(PUF, &conf); + return HWPUF_INIT_E; + } + ctx.flags |= NXP_HWPUF_FLAG_INITED; + return 0; +} + +WOLFSSL_API int nxp_hwpuf_Deinit(void) +{ + WOLFSSL_ENTER("nxp_hwpuf_Deinit"); + + PUF_Deinit(PUF, &conf); + + ctx.flags = 0; + + return 0; +} + +WOLFSSL_API int nxp_hwpuf_Enroll(byte* actCode, word32 actCodeSz) +{ + int ret; + + WOLFSSL_ENTER("nxp_hwpuf_Enroll"); + + if (actCode == NULL || actCodeSz != PUF_ACTIVATION_CODE_SIZE) + return BAD_FUNC_ARG; + if ((ctx.flags & NXP_HWPUF_FLAG_INITED) == 0) + return HWPUF_INIT_E; + if ((ctx.flags & NXP_HWPUF_FLAG_ENROLLED) != 0) + return HWPUF_ENROLL_E; + if ((ctx.flags & NXP_HWPUF_FLAG_READY) != 0) + return HWPUF_ENROLL_E; + + ret = PUF_Enroll(PUF, actCode, actCodeSz); + if (ret == kStatus_EnrollNotAllowed) { + /* power cycle and try again */ + (void)PUF_PowerCycle(PUF, &conf); + ret = PUF_Enroll(PUF, actCode, actCodeSz); + } + if (ret != kStatus_Success) { + return HWPUF_ENROLL_E; + } + + ctx.flags |= NXP_HWPUF_FLAG_ENROLLED; + + return 0; +} + +WOLFSSL_API int nxp_hwpuf_Start(byte* actCode, word32 actCodeSz) +{ + int ret; + + WOLFSSL_ENTER("nxp_hwpuf_Start"); + + if (actCode == NULL || actCodeSz != PUF_ACTIVATION_CODE_SIZE) + return BAD_FUNC_ARG; + if ((ctx.flags & NXP_HWPUF_FLAG_INITED) == 0) + return HWPUF_INIT_E; + if ((ctx.flags & NXP_HWPUF_FLAG_ENROLLED) != 0) + return HWPUF_START_E; + if ((ctx.flags & NXP_HWPUF_FLAG_READY) != 0) + return HWPUF_START_E; + + ret = PUF_Start(PUF, actCode, actCodeSz); + if (ret == kStatus_StartNotAllowed) { + /* power cycle and try again */ + (void)PUF_PowerCycle(PUF, &conf); + ret = PUF_Start(PUF, actCode, actCodeSz); + } + if (ret != kStatus_Success) { + return HWPUF_START_E; + } + + ctx.flags |= NXP_HWPUF_FLAG_READY; + + return 0; +} + +WOLFSSL_API int nxp_hwpuf_GenerateKey(byte keyIdx, word32 keySz, + byte* keyCode, word32 keyCodeSz) +{ + int ret; + word32 kcSz; + + WOLFSSL_ENTER("nxp_hwpuf_GenerateKey"); + + if ((ctx.flags & NXP_HWPUF_FLAG_READY) == 0) + return HWPUF_START_E; + /* keyidx 0 keys are only delivered over the hw bus, not supported */ + if (keyIdx == kPUF_KeyIndex_00 || keyIdx > kPUF_KeyIndexMax) + return BAD_FUNC_ARG; + if ( !HWPUF_KEY_SIZE_IS_VALID(keySz) ) + return BAD_FUNC_ARG; + kcSz = PUF_GET_KEY_CODE_SIZE_FOR_KEY_SIZE(keySz); + if (keyCode == NULL || kcSz != keyCodeSz) + return BAD_FUNC_ARG; + + ret = PUF_SetIntrinsicKey(PUF, (puf_key_index_register_t)keyIdx, keySz, + keyCode, keyCodeSz); + if (ret != kStatus_Success) + return HWPUF_GENERATE_KEY_E; + + return 0; +} + +WOLFSSL_API int nxp_hwpuf_GetKey(byte* keyCode, word32 keyCodeSz, + byte* key, word32 keySz) +{ + int ret; + word32 keyidx, keysize; + + WOLFSSL_ENTER("nxp_hwpuf_GetKey"); + + ret = keyCodeParse(keyCode, keyCodeSz, &keyidx, &keysize); + if (ret != 0) + return ret; + /* keyidx 0 keys are only delivered over the hw bus, not supported */ + if (keyidx == kPUF_KeyIndex_00 || key == NULL || keysize != keySz) + return BAD_FUNC_ARG; + + ret = PUF_GetKey(PUF, keyCode, keyCodeSz, key, keySz); + if (ret != kStatus_Success) { + ForceZero(key, keySz); + return HWPUF_GET_KEY_E; + } + return 0; +} + +WOLFSSL_API int nxp_hwpuf_Zeroize(void) +{ + int ret; + + WOLFSSL_ENTER("nxp_hwpuf_Zeroize"); + + ForceZero(&ctx, sizeof(ctx)); + + ret = PUF_Zeroize(PUF); + PUF_Deinit(PUF, &conf); + if (ret != kStatus_Success) { + return HWPUF_ZEROIZE_E; + } + return 0; +} + +#endif /* WOLFSSL_NXP_HWPUF */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 4fcc92f7805..c86b9568b97 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -5832,7 +5832,9 @@ static wc_test_ret_t sha_copy_test(wc_Sha* sha, wc_Sha* shaCopy) const char* a_input = ""; const char* a_output = "\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18" "\x90\xaf\xd8\x07\x09"; +#ifndef NO_WOLFSSL_SHA256_INTERLEAVE const char* b_input = "abc"; +#endif ret = wc_InitSha_ex(sha, HEAP_HINT, devId); if (ret != 0) @@ -6862,7 +6864,9 @@ static wc_test_ret_t sha256_copy_test(wc_Sha256* sha, wc_Sha256* shaCopy) const char* a_output = "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9" "\x24\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52" "\xb8\x55"; +#ifndef NO_WOLFSSL_SHA256_INTERLEAVE const char* b_input = "abc"; +#endif ret = wc_InitSha256_ex(sha, HEAP_HINT, devId); if (ret != 0) @@ -6895,6 +6899,7 @@ static wc_test_ret_t sha256_copy_test(wc_Sha256* sha, wc_Sha256* shaCopy) return ret; } +#ifndef NO_WOLFSSL_SHA256_INTERLEAVE /* Copy a context and then drive the original and the copy independently. * The message is longer than one block so that ports which buffer the whole * message before hashing (e.g. PIC32MZ) have to spill it to the heap. The @@ -7009,6 +7014,7 @@ static wc_test_ret_t sha256_copy_update_test(wc_Sha256* sha, return ret; } +#endif /* !NO_WOLFSSL_SHA256_INTERLEAVE */ #endif /* !HAVE_SELFTEST && (!HAVE_FIPS || FIPS_VERSION_GE(7, 0)) */ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sha256_test(void) @@ -7030,8 +7036,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sha256_test(void) #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7, 0)) if ((ret = sha256_copy_test(&sha, &shaCopy)) != 0) return ret; +# ifndef NO_WOLFSSL_SHA256_INTERLEAVE if ((ret = sha256_copy_update_test(&sha, &shaCopy)) != 0) return ret; +# endif #endif return 0; } diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index f0f57c492ff..fe37b05816e 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -357,8 +357,15 @@ enum wolfCrypt_ErrorCodes { NEEDS_RECOVERY_E = -1033, /* Object needs recovery before use */ UNEXPECTED_STATE_E = -1034, /* Object has unexpected state */ - WC_SPAN2_LAST_E = -1034, /* Update to indicate last used error code */ - WC_LAST_E = -1034, /* the last code used either here or in + HWPUF_INIT_E = -1035, /* HWPUF initialization failed */ + HWPUF_ENROLL_E = -1036, /* HWPUF enrollment failed */ + HWPUF_START_E = -1037, /* HWPUF start failed */ + HWPUF_GENERATE_KEY_E = -1038, /* HWPUF generate key failed */ + HWPUF_GET_KEY_E = -1039, /* HWPUF get key failed */ + HWPUF_ZEROIZE_E = -1040, /* HWPUF zeroize failed */ + + WC_SPAN2_LAST_E = -1040, /* Update to indicate last used error code */ + WC_LAST_E = -1040, /* the last code used either here or in * error-ssl.h */ WC_SPAN2_MIN_CODE_E = -1999, /* Last usable code in span 2 */ diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index d3c99ac7750..56c8b40075e 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -106,6 +106,7 @@ noinst_HEADERS+= \ wolfssl/wolfcrypt/port/nxp/dcp_port.h \ wolfssl/wolfcrypt/port/nxp/casper_port.h \ wolfssl/wolfcrypt/port/nxp/hashcrypt_port.h \ + wolfssl/wolfcrypt/port/nxp/hwpuf_port.h \ wolfssl/wolfcrypt/port/xilinx/xil-sha3.h \ wolfssl/wolfcrypt/port/xilinx/xil-versal-glue.h \ wolfssl/wolfcrypt/port/xilinx/xil-versal-trng.h \ diff --git a/wolfssl/wolfcrypt/port/nxp/hwpuf_port.h b/wolfssl/wolfcrypt/port/nxp/hwpuf_port.h new file mode 100644 index 00000000000..1547275b417 --- /dev/null +++ b/wolfssl/wolfcrypt/port/nxp/hwpuf_port.h @@ -0,0 +1,49 @@ +/* hwpuf_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 _NXP_HWPUF_PORT_H_ +#define _NXP_HWPUF_PORT_H_ + +#include +#include + +#if defined(WOLFSSL_NXP_HWPUF) + +#ifdef __cplusplus + extern "C" { +#endif + +WOLFSSL_API int nxp_hwpuf_Init(void); +WOLFSSL_API int nxp_hwpuf_Deinit(void); +WOLFSSL_API int nxp_hwpuf_Enroll(byte* actCode, word32 actCodeSz); +WOLFSSL_API int nxp_hwpuf_Start(byte* actCode, word32 actCodeSz); +WOLFSSL_API int nxp_hwpuf_GenerateKey(byte keyIdx, word32 keySz, + byte* keyCode, word32 keyCodeSz); +WOLFSSL_API int nxp_hwpuf_GetKey(byte* keyCode, word32 keyCodeSz, + byte* key, word32 keySz); +WOLFSSL_API int nxp_hwpuf_Zeroize(void); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_NXP_HWPUF */ + +#endif /* _NXP_HWPUF_PORT_H_ */ diff --git a/wolfssl/wolfcrypt/port/psa/psa.h b/wolfssl/wolfcrypt/port/psa/psa.h index f721ca6f8f6..fcda107fee5 100644 --- a/wolfssl/wolfcrypt/port/psa/psa.h +++ b/wolfssl/wolfcrypt/port/psa/psa.h @@ -81,10 +81,14 @@ int wc_psa_init(void); WOLFSSL_API int wc_psa_get_random(unsigned char *out, word32 sz); #ifndef HAVE_HASHDRBG +#ifndef CUSTOM_RAND_GENERATE_BLOCK #define CUSTOM_RAND_GENERATE_BLOCK wc_psa_get_random +#endif #else +#ifndef CUSTOM_RAND_GENERATE_SEED #define CUSTOM_RAND_GENERATE_SEED wc_psa_get_random #endif +#endif #endif /* WOLFSSL_HAVE_PSA_RNG */