diff --git a/CMakeLists.txt b/CMakeLists.txt index a21eb8d311..504ee8b882 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1652,6 +1652,8 @@ if(WOLFSSL_SHE STREQUAL "standard" OR WOLFSSL_SHE STREQUAL "extended") else() list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_SHE") + override_cache(WOLFSSL_CMAC "yes") + override_cache(WOLFSSL_AESCBC "yes") endif() endif() diff --git a/configure.ac b/configure.ac index 33daa4c968..94c61d5443 100644 --- a/configure.ac +++ b/configure.ac @@ -5957,6 +5957,10 @@ AC_ARG_ENABLE([she], if test "x$ENABLED_SHE" = "xstandard" || test "x$ENABLED_SHE" = "xextended" then + if test "$ENABLED_AESCBC" = "no" + then + AC_MSG_ERROR([SHE requires AES-CBC. Cannot use --disable-aescbc with --enable-she.]) + fi AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHE -DWOLFSSL_CMAC -DWOLFSSL_AES_DIRECT" ENABLED_CMAC=yes ENABLED_AESCBC=yes diff --git a/tests/api/test_she.c b/tests/api/test_she.c index ab29ec03c9..84e4dacf57 100644 --- a/tests/api/test_she.c +++ b/tests/api/test_she.c @@ -499,18 +499,32 @@ static int test_she_crypto_cb(int devIdArg, wc_CryptoInfo* info, void* ctx) info->she.op.generateM1M2M3.m3Sz); break; case WC_SHE_GENERATE_M4M5: - ret = wc_SHE_GenerateM4M5(she, - info->she.op.generateM4M5.uid, - info->she.op.generateM4M5.uidSz, - info->she.op.generateM4M5.authKeyId, - info->she.op.generateM4M5.targetKeyId, - info->she.op.generateM4M5.newKey, - info->she.op.generateM4M5.newKeySz, - info->she.op.generateM4M5.counter, - info->she.op.generateM4M5.m4, - info->she.op.generateM4M5.m4Sz, - info->she.op.generateM4M5.m5, - info->she.op.generateM4M5.m5Sz); + if (info->she.op.generateM4M5.uid == NULL && + she->generated) { + /* LoadKey flow: M1/M2/M3 already imported, simulate HSM + * returning M4/M5 from known test vectors. */ + if (info->she.op.generateM4M5.m4 != NULL) + XMEMCPY(info->she.op.generateM4M5.m4, + sheTestExpM4, WC_SHE_M4_SZ); + if (info->she.op.generateM4M5.m5 != NULL) + XMEMCPY(info->she.op.generateM4M5.m5, + sheTestExpM5, WC_SHE_M5_SZ); + ret = 0; + } + else { + ret = wc_SHE_GenerateM4M5(she, + info->she.op.generateM4M5.uid, + info->she.op.generateM4M5.uidSz, + info->she.op.generateM4M5.authKeyId, + info->she.op.generateM4M5.targetKeyId, + info->she.op.generateM4M5.newKey, + info->she.op.generateM4M5.newKeySz, + info->she.op.generateM4M5.counter, + info->she.op.generateM4M5.m4, + info->she.op.generateM4M5.m4Sz, + info->she.op.generateM4M5.m5, + info->she.op.generateM4M5.m5Sz); + } break; case WC_SHE_EXPORT_KEY: /* Simulate hardware export -- fill with test pattern */ @@ -635,4 +649,120 @@ int test_wc_SHE_CryptoCb(void) return EXPECT_RESULT(); } +#ifndef NO_WC_SHE_LOADKEY + +int test_wc_SHE_LoadKey(void) +{ + EXPECT_DECLS; + int sheTestDevId = 54322; + byte m1[WC_SHE_M1_SZ]; + byte m2[WC_SHE_M2_SZ]; + byte m3[WC_SHE_M3_SZ]; + byte m4[WC_SHE_M4_SZ]; + byte m5[WC_SHE_M5_SZ]; + + ExpectIntEQ(wc_CryptoCb_RegisterDevice(sheTestDevId, + test_she_crypto_cb, NULL), 0); + + /* Generate valid M1/M2/M3 from test vectors */ + { + wc_SHE she; + ExpectIntEQ(wc_SHE_Init(&she, NULL, INVALID_DEVID), 0); + ExpectIntEQ(wc_SHE_GenerateM1M2M3(&she, + sheTestUid, sizeof(sheTestUid), + WC_SHE_MASTER_ECU_KEY_ID, + sheTestAuthKey, sizeof(sheTestAuthKey), + 4, sheTestNewKey, sizeof(sheTestNewKey), 1, 0, + m1, WC_SHE_M1_SZ, m2, WC_SHE_M2_SZ, + m3, WC_SHE_M3_SZ), 0); + wc_SHE_Free(&she); + } + + /* Basic: LoadKey should import M1/M2/M3 and produce M4/M5 via callback */ + ExpectIntEQ(wc_SHE_LoadKey(NULL, sheTestDevId, + m1, WC_SHE_M1_SZ, m2, WC_SHE_M2_SZ, m3, WC_SHE_M3_SZ, + m4, WC_SHE_M4_SZ, m5, WC_SHE_M5_SZ), 0); + ExpectIntEQ(XMEMCMP(m4, sheTestExpM4, WC_SHE_M4_SZ), 0); + ExpectIntEQ(XMEMCMP(m5, sheTestExpM5, WC_SHE_M5_SZ), 0); + + /* Bad args: NULL m1 */ + ExpectIntEQ(wc_SHE_LoadKey(NULL, sheTestDevId, + NULL, WC_SHE_M1_SZ, m2, WC_SHE_M2_SZ, m3, WC_SHE_M3_SZ, + m4, WC_SHE_M4_SZ, m5, WC_SHE_M5_SZ), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + + /* Bad args: NULL m4 output */ + ExpectIntEQ(wc_SHE_LoadKey(NULL, sheTestDevId, + m1, WC_SHE_M1_SZ, m2, WC_SHE_M2_SZ, m3, WC_SHE_M3_SZ, + NULL, WC_SHE_M4_SZ, m5, WC_SHE_M5_SZ), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + + /* Bad args: INVALID_DEVID */ + ExpectIntEQ(wc_SHE_LoadKey(NULL, INVALID_DEVID, + m1, WC_SHE_M1_SZ, m2, WC_SHE_M2_SZ, m3, WC_SHE_M3_SZ, + m4, WC_SHE_M4_SZ, m5, WC_SHE_M5_SZ), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + + /* Bad args: wrong M1 size */ + ExpectIntEQ(wc_SHE_LoadKey(NULL, sheTestDevId, + m1, WC_SHE_M1_SZ - 1, m2, WC_SHE_M2_SZ, + m3, WC_SHE_M3_SZ, + m4, WC_SHE_M4_SZ, m5, WC_SHE_M5_SZ), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + + wc_CryptoCb_UnRegisterDevice(sheTestDevId); + return EXPECT_RESULT(); +} + +int test_wc_SHE_LoadKey_Verify(void) +{ + EXPECT_DECLS; + int sheTestDevId = 54323; + byte m1[WC_SHE_M1_SZ]; + byte m2[WC_SHE_M2_SZ]; + byte m3[WC_SHE_M3_SZ]; + byte m4[WC_SHE_M4_SZ]; + byte m5[WC_SHE_M5_SZ]; + byte badM4[WC_SHE_M4_SZ]; + + ExpectIntEQ(wc_CryptoCb_RegisterDevice(sheTestDevId, + test_she_crypto_cb, NULL), 0); + + /* Generate valid M1/M2/M3 from test vectors */ + { + wc_SHE she; + ExpectIntEQ(wc_SHE_Init(&she, NULL, INVALID_DEVID), 0); + ExpectIntEQ(wc_SHE_GenerateM1M2M3(&she, + sheTestUid, sizeof(sheTestUid), + WC_SHE_MASTER_ECU_KEY_ID, + sheTestAuthKey, sizeof(sheTestAuthKey), + 4, sheTestNewKey, sizeof(sheTestNewKey), 1, 0, + m1, WC_SHE_M1_SZ, m2, WC_SHE_M2_SZ, + m3, WC_SHE_M3_SZ), 0); + wc_SHE_Free(&she); + } + + /* Matching: expected M4/M5 match what the callback produces */ + ExpectIntEQ(wc_SHE_LoadKey_Verify(NULL, sheTestDevId, + m1, WC_SHE_M1_SZ, m2, WC_SHE_M2_SZ, m3, WC_SHE_M3_SZ, + m4, WC_SHE_M4_SZ, m5, WC_SHE_M5_SZ, + sheTestExpM4, WC_SHE_M4_SZ, + sheTestExpM5, WC_SHE_M5_SZ), 0); + + /* Mismatch: wrong expected M4 should fail with SIG_VERIFY_E */ + XMEMCPY(badM4, sheTestExpM4, WC_SHE_M4_SZ); + badM4[0] ^= 0xFF; + ExpectIntEQ(wc_SHE_LoadKey_Verify(NULL, sheTestDevId, + m1, WC_SHE_M1_SZ, m2, WC_SHE_M2_SZ, m3, WC_SHE_M3_SZ, + m4, WC_SHE_M4_SZ, m5, WC_SHE_M5_SZ, + badM4, WC_SHE_M4_SZ, + sheTestExpM5, WC_SHE_M5_SZ), + WC_NO_ERR_TRACE(SIG_VERIFY_E)); + + wc_CryptoCb_UnRegisterDevice(sheTestDevId); + return EXPECT_RESULT(); +} + +#endif /* !NO_WC_SHE_LOADKEY */ + #endif /* WOLF_CRYPTO_CB && WOLFSSL_SHE && !NO_AES */ diff --git a/tests/api/test_she.h b/tests/api/test_she.h index c1df2266d6..feccb10e3e 100644 --- a/tests/api/test_she.h +++ b/tests/api/test_she.h @@ -38,6 +38,10 @@ int test_wc_SHE_SetM2M4Header(void); #endif #if defined(WOLF_CRYPTO_CB) && defined(WOLFSSL_SHE) int test_wc_SHE_CryptoCb(void); +#ifndef NO_WC_SHE_LOADKEY +int test_wc_SHE_LoadKey(void); +int test_wc_SHE_LoadKey_Verify(void); +#endif #endif #define TEST_SHE_DECLS \ @@ -59,8 +63,15 @@ int test_wc_SHE_CryptoCb(void); #endif #if defined(WOLF_CRYPTO_CB) && defined(WOLFSSL_SHE) +#if !defined(NO_WC_SHE_LOADKEY) +#define TEST_SHE_CB_DECLS \ + TEST_DECL_GROUP("she", test_wc_SHE_CryptoCb), \ + TEST_DECL_GROUP("she", test_wc_SHE_LoadKey), \ + TEST_DECL_GROUP("she", test_wc_SHE_LoadKey_Verify) +#else #define TEST_SHE_CB_DECLS \ TEST_DECL_GROUP("she", test_wc_SHE_CryptoCb) +#endif #else #define TEST_SHE_CB_DECLS #endif diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index fe616e0e0e..dcdb5bf7b0 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -2121,7 +2121,7 @@ int wc_CryptoCb_Cmac(Cmac* cmac, const byte* key, word32 keySz, #endif /* WOLFSSL_CMAC */ #ifdef WOLFSSL_SHE -int wc_CryptoCb_SheGetUid(wc_SHE* she, const byte* uid, word32 uidSz, +int wc_CryptoCb_SheGetUid(wc_SHE* she, byte* uid, word32 uidSz, const void* ctx) { int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); diff --git a/wolfcrypt/src/wc_she.c b/wolfcrypt/src/wc_she.c index 74756c027b..a2a260383c 100644 --- a/wolfcrypt/src/wc_she.c +++ b/wolfcrypt/src/wc_she.c @@ -359,9 +359,6 @@ int wc_SHE_SetKdfConstants(wc_SHE* she, #endif /* WOLFSSL_SHE_EXTENDED */ -/* -------------------------------------------------------------------------- */ -/* GetUID */ - #if defined(WOLF_CRYPTO_CB) || !defined(NO_WC_SHE_IMPORT_M123) /* -------------------------------------------------------------------------- */ /* Import M1/M2/M3 */ @@ -933,6 +930,7 @@ int wc_SHE_LoadKey_Label( byte* m5, word32 m5Sz) { int ret; + word32 labelLen; WC_DECLARE_VAR(she, wc_SHE, 1, heap); if (label == NULL || m1 == NULL || m2 == NULL || m3 == NULL || @@ -944,7 +942,8 @@ int wc_SHE_LoadKey_Label( return BAD_FUNC_ARG; } - if (XSTRLEN(label) == 0 || XSTRLEN(label) > WC_SHE_MAX_LABEL_LEN) { + labelLen = (word32)XSTRLEN(label); + if (labelLen == 0 || labelLen > WC_SHE_MAX_LABEL_LEN) { return BAD_FUNC_ARG; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 19c8774873..1a6c4dff30 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -57061,6 +57061,35 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t she_test(void) goto exit_SHE_Test; } +#if !defined(NO_WC_SHE_LOADKEY) && \ + (defined(WOLF_CRYPTO_CB) || !defined(NO_WC_SHE_IMPORT_M123)) + /* ---- LoadKey_Verify ---- */ + XMEMSET(m4, 0, WC_SHE_M4_SZ); + XMEMSET(m5, 0, WC_SHE_M5_SZ); + ret = wc_SHE_LoadKey_Verify(HEAP_HINT, devId, + expM1, WC_SHE_M1_SZ, expM2, WC_SHE_M2_SZ, + expM3, WC_SHE_M3_SZ, + m4, WC_SHE_M4_SZ, m5, WC_SHE_M5_SZ, + expM4, WC_SHE_M4_SZ, expM5, WC_SHE_M5_SZ); + if (devId == INVALID_DEVID) { + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) { + ret = WC_TEST_RET_ENC_EC(ret); + goto exit_SHE_Test; + } + } + else { + if (ret != 0) { + goto exit_SHE_Test; + } + if (XMEMCMP(m4, expM4, WC_SHE_M4_SZ) != 0 || + XMEMCMP(m5, expM5, WC_SHE_M5_SZ) != 0) { + ret = WC_TEST_RET_ENC_NC; + goto exit_SHE_Test; + } + } + ret = 0; +#endif /* !NO_WC_SHE_LOADKEY */ + #if defined(WC_SHE_SW_DEFAULT) && defined(WOLF_CRYPTO_CB) && \ !defined(NO_WC_SHE_GETUID) && !defined(NO_WC_SHE_GETCOUNTER) ret = she_sw_default_test(); diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index 8cefd321bf..710b522b9e 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -488,7 +488,7 @@ typedef struct wc_CryptoInfo { const void* ctx; /* read-only caller context */ union { struct { - const byte* uid; + byte* uid; word32 uidSz; } getUid; struct { @@ -862,7 +862,7 @@ WOLFSSL_LOCAL int wc_CryptoCb_Cmac(Cmac* cmac, const byte* key, word32 keySz, #endif #ifdef WOLFSSL_SHE -WOLFSSL_LOCAL int wc_CryptoCb_SheGetUid(wc_SHE* she, const byte* uid, +WOLFSSL_LOCAL int wc_CryptoCb_SheGetUid(wc_SHE* she, byte* uid, word32 uidSz, const void* ctx); WOLFSSL_LOCAL int wc_CryptoCb_SheGetCounter(wc_SHE* she, word32* counter, const void* ctx);