From 802c34018cd402d8a77c1a4027bdeade663474a3 Mon Sep 17 00:00:00 2001 From: night1rider Date: Fri, 20 Mar 2026 18:27:49 -0600 Subject: [PATCH] Add more in depth comments in header file for she.h --- .wolfssl_known_macro_extras | 2 +- tests/api/test_she.c | 6 +- wolfcrypt/src/she.c | 22 ++--- wolfcrypt/test/test.c | 8 +- wolfssl/wolfcrypt/she.h | 165 +++++++++++++++++++++++++++++++----- 5 files changed, 163 insertions(+), 40 deletions(-) diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 61327b9f47..5c5c717f34 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -892,9 +892,9 @@ WOLFSSL_SE050_NO_TRNG WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT WOLFSSL_SERVER_EXAMPLE WOLFSSL_SETTINGS_FILE +WOLFSSL_SH224 WOLFSSL_SHE WOLFSSL_SHE_EXTENDED -WOLFSSL_SH224 WOLFSSL_SHA256_ALT_CH_MAJ WOLFSSL_SHA512_HASHTYPE WOLFSSL_SHUTDOWNONCE diff --git a/tests/api/test_she.c b/tests/api/test_she.c index 2d98826646..2fc226111a 100644 --- a/tests/api/test_she.c +++ b/tests/api/test_she.c @@ -428,7 +428,7 @@ int test_wc_SHE_SetM2M4Header(void) #if defined(WOLF_CRYPTO_CB) && defined(WOLFSSL_SHE) && !defined(NO_AES) -/* SHE callback — re-calls with software devId */ +/* SHE callback -- re-calls with software devId */ static int test_she_crypto_cb(int devIdArg, wc_CryptoInfo* info, void* ctx) { wc_SHE* she; @@ -513,7 +513,7 @@ static int test_she_crypto_cb(int devIdArg, wc_CryptoInfo* info, void* ctx) info->she.op.generateM4M5.m5Sz); break; case WC_SHE_EXPORT_KEY: - /* Simulate hardware export — fill with test pattern */ + /* Simulate hardware export -- fill with test pattern */ if (info->she.op.exportKey.m1 != NULL) { XMEMSET(info->she.op.exportKey.m1, 0x11, WC_SHE_M1_SZ); } @@ -572,7 +572,7 @@ int test_wc_SHE_CryptoCb(void) ExpectIntEQ(XMEMCMP(m4, sheTestExpM4, WC_SHE_M4_SZ), 0); ExpectIntEQ(XMEMCMP(m5, sheTestExpM5, WC_SHE_M5_SZ), 0); - /* ExportKey via callback — simulated hardware */ + /* ExportKey via callback -- simulated hardware */ #if !defined(NO_WC_SHE_EXPORTKEY) { byte em1[WC_SHE_M1_SZ]; diff --git a/wolfcrypt/src/she.c b/wolfcrypt/src/she.c index 2539efa7f4..df44113bb4 100644 --- a/wolfcrypt/src/she.c +++ b/wolfcrypt/src/she.c @@ -123,7 +123,7 @@ int wc_SHE_Init(wc_SHE* she, void* heap, int devId) ForceZero(she, sizeof(wc_SHE)); she->heap = heap; she->devId = devId; - /* kdfEncOverride/kdfMacOverride are zero from XMEMSET — defaults used */ + /* kdfEncOverride/kdfMacOverride are zero from XMEMSET -- defaults used */ return 0; } @@ -222,7 +222,7 @@ void wc_SHE_Free(wc_SHE* she) } /* -------------------------------------------------------------------------- */ -/* GetUID — callback required */ +/* GetUID -- callback required */ /* */ /* Dispatches to callback to fetch UID from hardware. */ /* Buffer size validation is the callback's responsibility. */ @@ -241,7 +241,7 @@ int wc_SHE_GetUID(wc_SHE* she, byte* uid, word32 uidSz, #endif /* WOLF_CRYPTO_CB && !NO_WC_SHE_GETUID */ /* -------------------------------------------------------------------------- */ -/* GetCounter — callback required */ +/* GetCounter -- callback required */ /* */ /* Dispatches to callback to read current counter from hardware. */ /* Returns CRYPTOCB_UNAVAILABLE if no callback. */ @@ -425,13 +425,13 @@ int wc_SHE_GenerateM1M2M3(wc_SHE* she, WC_DECLARE_VAR(aes, Aes, 1, 0); WC_DECLARE_VAR(cmac, Cmac, 1, 0); - /* Validate SHE context first — required for both callback and software */ + /* Validate SHE context first -- required for both callback and software */ if (she == NULL) { return BAD_FUNC_ARG; } #ifdef WOLF_CRYPTO_CB - /* Try callback first — callback handles its own parameter validation. + /* Try callback first -- callback handles its own parameter validation. * This allows callers to pass NULL authKey/newKey when a secure element * holds the keys and the callback talks to it directly. */ if (she->devId != INVALID_DEVID) { @@ -448,7 +448,7 @@ int wc_SHE_GenerateM1M2M3(wc_SHE* she, } #endif - /* Software path — validate all parameters */ + /* Software path -- validate all parameters */ if (uid == NULL || uidSz != WC_SHE_UID_SZ || authKey == NULL || authKeySz != WC_SHE_KEY_SZ || newKey == NULL || newKeySz != WC_SHE_KEY_SZ || @@ -482,7 +482,7 @@ int wc_SHE_GenerateM1M2M3(wc_SHE* she, return MEMORY_E; } - /* Init AES once — used by both MP16 and CBC */ + /* Init AES once -- used by both MP16 and CBC */ ret = wc_AesInit(aes, she->heap, she->devId); if (ret != 0) { WC_FREE_VAR(aes, she->heap); @@ -584,7 +584,7 @@ int wc_SHE_GenerateM4M5(wc_SHE* she, } #ifdef WOLF_CRYPTO_CB - /* Try callback first — useful for uploading M1/M2/M3 to an HSM which + /* Try callback first -- useful for uploading M1/M2/M3 to an HSM which * loads the key and returns the correct M4/M5 proof values. The callback * handles its own parameter validation. */ if (she->devId != INVALID_DEVID) { @@ -599,7 +599,7 @@ int wc_SHE_GenerateM4M5(wc_SHE* she, } #endif - /* Software path — validate all parameters */ + /* Software path -- validate all parameters */ if (uid == NULL || uidSz != WC_SHE_UID_SZ || newKey == NULL || newKeySz != WC_SHE_KEY_SZ || m4 == NULL || m4Sz < WC_SHE_M4_SZ || @@ -631,7 +631,7 @@ int wc_SHE_GenerateM4M5(wc_SHE* she, return MEMORY_E; } - /* Init AES once — used by both MP16 and ECB */ + /* Init AES once -- used by both MP16 and ECB */ ret = wc_AesInit(aes, she->heap, she->devId); if (ret != 0) { WC_FREE_VAR(aes, she->heap); @@ -700,7 +700,7 @@ int wc_SHE_GenerateM4M5(wc_SHE* she, /* -------------------------------------------------------------------------- */ #if defined(WOLF_CRYPTO_CB) && !defined(NO_WC_SHE_EXPORTKEY) /* -------------------------------------------------------------------------- */ -/* Export Key — callback required */ +/* Export Key -- callback required */ /* */ /* Asks hardware to export a key slot as M1-M5 in SHE loadable format. */ /* -------------------------------------------------------------------------- */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index a0762a4614..fca7ea7e28 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -56739,6 +56739,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t she_test(void) goto exit_SHE_Test; } +#if defined(WOLF_CRYPTO_CB) || !defined(NO_WC_SHE_IMPORT_M123) /* ---- Import M1/M2/M3 and generate M4/M5 (only NewKey needed) ---- */ wc_SHE_Free(she); ret = wc_SHE_Init(she, HEAP_HINT, devId); @@ -56746,7 +56747,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t she_test(void) goto exit_SHE_Test; } - /* Import M1/M2/M3, then generate M4/M5 via one-shot */ + /* Import M1/M2/M3, then generate M4/M5 */ ret = wc_SHE_ImportM1M2M3(she, expM1, WC_SHE_M1_SZ, expM2, WC_SHE_M2_SZ, @@ -56773,6 +56774,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t she_test(void) ret = WC_TEST_RET_ENC_NC; goto exit_SHE_Test; } +#endif /* WOLF_CRYPTO_CB || !NO_WC_SHE_IMPORT_M123 */ /* ---- One-shot M1/M2/M3 ---- */ wc_SHE_Free(she); @@ -56864,7 +56866,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t she_test(void) goto exit_SHE_Test; } - /* Generate M4/M5 on second context — completely independent */ + /* Generate M4/M5 on second context -- completely independent */ ret = wc_SHE_GenerateM4M5(she2, sheUid, sizeof(sheUid), WC_SHE_MASTER_ECU_KEY_ID, 4, @@ -67523,7 +67525,7 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) info->she.op.generateM4M5.m5Sz); break; case WC_SHE_EXPORT_KEY: - /* Simulate hardware export — fill with test pattern */ + /* Simulate hardware export -- fill with test pattern */ if (info->she.op.exportKey.m1 != NULL) { XMEMSET(info->she.op.exportKey.m1, 0x11, WC_SHE_M1_SZ); diff --git a/wolfssl/wolfcrypt/she.h b/wolfssl/wolfcrypt/she.h index 2c7377d737..ac1b9c4e34 100644 --- a/wolfssl/wolfcrypt/she.h +++ b/wolfssl/wolfcrypt/she.h @@ -34,14 +34,14 @@ extern "C" { #endif -#define WC_SHE_KEY_SZ 16 -#define WC_SHE_UID_SZ 15 +#define WC_SHE_KEY_SZ 16 /* AES-128 key size (128 bits) */ +#define WC_SHE_UID_SZ 15 /* SHE UID size (120 bits) */ -#define WC_SHE_M1_SZ 16 -#define WC_SHE_M2_SZ 32 -#define WC_SHE_M3_SZ 16 -#define WC_SHE_M4_SZ 32 -#define WC_SHE_M5_SZ 16 +#define WC_SHE_M1_SZ 16 /* UID(15B) | KeyID(4b) | AuthID(4b) */ +#define WC_SHE_M2_SZ 32 /* AES-CBC(K1, counter|flags|pad|newkey) */ +#define WC_SHE_M3_SZ 16 /* AES-CMAC(K2, M1|M2) */ +#define WC_SHE_M4_SZ 32 /* UID|IDs + AES-ECB(K3, counter|pad) */ +#define WC_SHE_M5_SZ 16 /* AES-CMAC(K4, M4) */ /* crypto callback sub-types for WC_ALGO_TYPE_SHE */ enum wc_SheType { @@ -129,28 +129,55 @@ typedef struct wc_SHE { } wc_SHE; -/* Initialize SHE context, store heap hint and device ID */ +/* Initialize SHE context, store heap hint and device ID. + * she - pointer to wc_SHE structure to initialize + * heap - heap hint for internal allocations, or NULL + * devId - crypto callback device ID, or INVALID_DEVID for software */ WOLFSSL_API int wc_SHE_Init(wc_SHE* she, void* heap, int devId); #ifdef WOLF_PRIVATE_KEY_ID -/* Initialize with opaque hardware key identifier */ +/* Initialize with opaque hardware key identifier. + * Useful when using callbacks and additional info needs to be attached + * to the SHE context to determine slot or key group information. + * she - pointer to wc_SHE structure to initialize + * id - opaque key identifier bytes + * len - length of id in bytes (0 to WC_SHE_MAX_ID_LEN) + * heap - heap hint for internal allocations, or NULL + * devId - crypto callback device ID */ WOLFSSL_API int wc_SHE_Init_Id(wc_SHE* she, unsigned char* id, int len, void* heap, int devId); -/* Initialize with human-readable key label */ + +/* Initialize with human-readable key label. + * Useful when using callbacks and additional info needs to be attached + * to the SHE context to determine slot or key group information. + * she - pointer to wc_SHE structure to initialize + * label - NUL-terminated key label string + * heap - heap hint for internal allocations, or NULL + * devId - crypto callback device ID */ WOLFSSL_API int wc_SHE_Init_Label(wc_SHE* she, const char* label, void* heap, int devId); #endif -/* Scrub and zero the context */ +/* Scrub all data and zero the context. Safe to call on NULL. */ WOLFSSL_API void wc_SHE_Free(wc_SHE* she); -/* Get UID from hardware; callback required (WC_SHE_SET_UID) */ +/* Get UID from hardware via callback (WC_SHE_SET_UID). + * she - initialized SHE context with a registered callback + * uid - buffer to receive the 120-bit (15-byte) SHE UID + * uidSz - size of uid buffer in bytes + * ctx - read-only caller context passed to the callback + * (e.g. challenge buffer, HSM handle) */ #if defined(WOLF_CRYPTO_CB) && !defined(NO_WC_SHE_GETUID) WOLFSSL_API int wc_SHE_GetUID(wc_SHE* she, byte* uid, word32 uidSz, const void* ctx); #endif -/* Get counter from hardware; callback required */ +/* Get monotonic counter from hardware via callback (WC_SHE_GET_COUNTER). + * she - initialized SHE context with a registered callback + * counter - pointer to receive the current counter value. + * The SHE spec uses a 28-bit counter. The caller should + * increment this value before passing to GenerateM1M2M3/M4M5. + * ctx - read-only caller context passed to the callback */ #if defined(WOLF_CRYPTO_CB) && !defined(NO_WC_SHE_GETCOUNTER) WOLFSSL_API int wc_SHE_GetCounter(wc_SHE* she, word32* counter, const void* ctx); @@ -160,21 +187,47 @@ WOLFSSL_API int wc_SHE_GetCounter(wc_SHE* she, word32* counter, * Useful for some HSMs that support multiple key groups with * different derivation constants. */ #ifdef WOLFSSL_SHE_EXTENDED -/* Set KDF constants (CENC/CMAC). Defaults set by Init. NULL to skip. */ +/* Set KDF constants used in Miyaguchi-Preneel key derivation. + * Defaults are KEY_UPDATE_ENC_C and KEY_UPDATE_MAC_C from the SHE spec. + * Either pointer may be NULL to leave that constant unchanged. + * she - initialized SHE context + * encC - 16-byte encryption derivation constant (CENC), or NULL + * encCSz - must be WC_SHE_KEY_SZ (16) when encC is non-NULL + * macC - 16-byte MAC derivation constant (CMAC), or NULL + * macCSz - must be WC_SHE_KEY_SZ (16) when macC is non-NULL */ WOLFSSL_API int wc_SHE_SetKdfConstants(wc_SHE* she, const byte* encC, word32 encCSz, const byte* macC, word32 macCSz); -/* Override M2P cleartext header. Skips auto-build from counter/flags. */ +/* Override M2 cleartext header (first 16 bytes of M2 before encryption). + * When set, GenerateM1M2M3 uses this instead of auto-building from + * counter and flags. The header is: counter(28b)|flags(4b)|zeros(96b). + * she - initialized SHE context + * header - 16-byte cleartext header block + * headerSz - must be WC_SHE_KEY_SZ (16) */ WOLFSSL_API int wc_SHE_SetM2Header(wc_SHE* she, const byte* header, word32 headerSz); -/* Override M4P cleartext header. Skips auto-build from counter. */ +/* Override M4 cleartext counter block (16-byte block encrypted with K3). + * When set, GenerateM4M5 uses this instead of auto-building from counter. + * The block is: counter(28b)|1(1b)|zeros(99b). + * she - initialized SHE context + * header - 16-byte cleartext counter block + * headerSz - must be WC_SHE_KEY_SZ (16) */ WOLFSSL_API int wc_SHE_SetM4Header(wc_SHE* she, const byte* header, word32 headerSz); #endif /* WOLFSSL_SHE_EXTENDED */ -/* Import externally-provided M1/M2/M3 into context; sets generated flag */ +/* Import externally-provided M1/M2/M3 into context. + * Sets the generated flag so the callback for GenerateM4M5 can + * read M1/M2/M3 from the context to send to hardware. + * she - initialized SHE context + * m1 - 16-byte M1 message (UID | KeyID | AuthID) + * m1Sz - must be WC_SHE_M1_SZ (16) + * m2 - 32-byte M2 message (encrypted counter|flags|pad|newkey) + * m2Sz - must be WC_SHE_M2_SZ (32) + * m3 - 16-byte M3 message (CMAC over M1|M2) + * m3Sz - must be WC_SHE_M3_SZ (16) */ #if defined(WOLF_CRYPTO_CB) || !defined(NO_WC_SHE_IMPORT_M123) WOLFSSL_API int wc_SHE_ImportM1M2M3(wc_SHE* she, const byte* m1, word32 m1Sz, @@ -182,7 +235,36 @@ WOLFSSL_API int wc_SHE_ImportM1M2M3(wc_SHE* she, const byte* m3, word32 m3Sz); #endif -/* Generate M1/M2/M3 and write to caller buffers */ +/* Generate M1/M2/M3 for the SHE key update protocol and write to + * caller-provided buffers. Callback optional -- if a callback is + * registered it is tried first; if it returns CRYPTOCB_UNAVAILABLE + * the software path runs. This allows a secure element to generate + * M1/M2/M3 when it holds the auth key internally. + * + * she - initialized SHE context + * uid - 15-byte SHE UID (120-bit ECU/module identifier) + * uidSz - must be WC_SHE_UID_SZ (15) + * authKeyId - slot ID of the authorizing key (0-14, e.g. + * MASTER_ECU_KEY=1, KEY_1..KEY_10=4..13) + * authKey - 16-byte value of the authorizing key. Used to derive + * K1 (encryption) and K2 (MAC). May be NULL when the + * callback handles key access. + * authKeySz - must be WC_SHE_KEY_SZ (16) when authKey is non-NULL + * targetKeyId - slot ID of the key being loaded (1-14) + * newKey - 16-byte value of the new key to load. Placed in M2 + * cleartext and used to derive K3/K4 for M4/M5. + * May be NULL when the callback handles key access. + * newKeySz - must be WC_SHE_KEY_SZ (16) when newKey is non-NULL + * counter - 28-bit monotonic counter value. Must be strictly greater + * than the counter stored in the target slot on the SHE. + * flags - key protection flags (lower 4 bits of the counter|flags + * word in M2). + * m1 - output buffer for M1 (16 bytes) + * m1Sz - size of m1 buffer, must be >= WC_SHE_M1_SZ + * m2 - output buffer for M2 (32 bytes) + * m2Sz - size of m2 buffer, must be >= WC_SHE_M2_SZ + * m3 - output buffer for M3 (16 bytes) + * m3Sz - size of m3 buffer, must be >= WC_SHE_M3_SZ */ WOLFSSL_API int wc_SHE_GenerateM1M2M3(wc_SHE* she, const byte* uid, word32 uidSz, byte authKeyId, const byte* authKey, word32 authKeySz, @@ -192,7 +274,25 @@ WOLFSSL_API int wc_SHE_GenerateM1M2M3(wc_SHE* she, byte* m2, word32 m2Sz, byte* m3, word32 m3Sz); -/* Generate M4/M5 and write to caller buffers */ +/* Generate M4/M5 verification messages and write to caller-provided + * buffers. Independent of M1/M2/M3 -- can be called on a separate + * context. Callback optional -- useful for uploading M1/M2/M3 to an + * HSM which loads the key and returns M4/M5 as proof. + * + * she - initialized SHE context + * uid - 15-byte SHE UID (same UID used for M1) + * uidSz - must be WC_SHE_UID_SZ (15) + * authKeyId - slot ID of the authorizing key (same as in M1) + * targetKeyId - slot ID of the key being loaded (same as in M1) + * newKey - 16-byte value of the new key. Used to derive K3 + * (encryption for M4 counter block) and K4 (MAC for M5). + * May be NULL when the callback handles key access. + * newKeySz - must be WC_SHE_KEY_SZ (16) when newKey is non-NULL + * counter - 28-bit monotonic counter (same value as in M2) + * m4 - output buffer for M4 (32 bytes) + * m4Sz - size of m4 buffer, must be >= WC_SHE_M4_SZ + * m5 - output buffer for M5 (16 bytes) + * m5Sz - size of m5 buffer, must be >= WC_SHE_M5_SZ */ WOLFSSL_API int wc_SHE_GenerateM4M5(wc_SHE* she, const byte* uid, word32 uidSz, byte authKeyId, byte targetKeyId, @@ -201,8 +301,22 @@ WOLFSSL_API int wc_SHE_GenerateM4M5(wc_SHE* she, byte* m4, word32 m4Sz, byte* m5, word32 m5Sz); -/* Export key from hardware as M1-M5; callback required. - * Some HSMs allow exporting certain key slots (e.g. RAM key) in SHE format. */ +/* Export a key from hardware in SHE loadable format (M1-M5). + * Callback required -- dispatches to WC_SHE_EXPORT_KEY. + * Some HSMs allow exporting certain key slots (e.g. RAM key) so they + * can be re-loaded later via the SHE key update protocol. + * she - initialized SHE context with a registered callback + * m1 - output buffer for M1 (16 bytes), or NULL to skip + * m1Sz - size of m1 buffer + * m2 - output buffer for M2 (32 bytes), or NULL to skip + * m2Sz - size of m2 buffer + * m3 - output buffer for M3 (16 bytes), or NULL to skip + * m3Sz - size of m3 buffer + * m4 - output buffer for M4 (32 bytes), or NULL to skip + * m4Sz - size of m4 buffer + * m5 - output buffer for M5 (16 bytes), or NULL to skip + * m5Sz - size of m5 buffer + * ctx - read-only caller context passed to the callback */ #if defined(WOLF_CRYPTO_CB) && !defined(NO_WC_SHE_EXPORTKEY) WOLFSSL_API int wc_SHE_ExportKey(wc_SHE* she, byte* m1, word32 m1Sz, @@ -213,7 +327,14 @@ WOLFSSL_API int wc_SHE_ExportKey(wc_SHE* she, const void* ctx); #endif -/* Internal: Miyaguchi-Preneel AES-128 compression, exposed for testing */ +/* Internal: Miyaguchi-Preneel AES-128 one-way compression. + * H_0 = 0, H_i = E_{H_{i-1}}(M_i) XOR M_i XOR H_{i-1}. + * Only valid for AES-128 where key size equals block size. + * Exposed via WOLFSSL_TEST_VIS for testing. + * aes - caller-owned, already-initialized Aes structure + * in - input data (e.g. BaseKey || KDF_Constant, 32 bytes) + * inSz - length of input in bytes (zero-padded to block boundary) + * out - output buffer for 16-byte compressed result */ WOLFSSL_TEST_VIS int wc_She_AesMp16(Aes* aes, const byte* in, word32 inSz, byte* out);