mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-09 19:00:52 +02:00
SHE API: remove key storage from context, add direct output params
This commit is contained in:
@@ -42,8 +42,11 @@ jobs:
|
||||
'--enable-dtls --enable-dtlscid --enable-dtls13 --enable-secure-renegotiation
|
||||
--enable-psk --enable-aesccm --enable-nullcipher
|
||||
CPPFLAGS=-DWOLFSSL_STATIC_RSA',
|
||||
'--enable-she --enable-cmac',
|
||||
'--enable-she --enable-cmac --enable-cryptocb --enable-cryptocbutils',
|
||||
'--enable-she=standard --enable-cmac',
|
||||
'--enable-she=extended --enable-cmac --enable-cryptocb --enable-cryptocbutils',
|
||||
'--enable-she=standard --enable-cmac CPPFLAGS=''-DNO_WC_SHE_IMPORT_M123'' ',
|
||||
'--enable-she=extended --enable-cmac --enable-cryptocb --enable-cryptocbutils
|
||||
CPPFLAGS=''-DNO_WC_SHE_GETUID -DNO_WC_SHE_GETCOUNTER -DNO_WC_SHE_EXPORTKEY'' ',
|
||||
'--enable-all CPPFLAGS=''-DNO_AES_192 -DNO_AES_256'' ',
|
||||
'--enable-sniffer --enable-curve25519 --enable-curve448 --enable-enckeys
|
||||
CPPFLAGS=-DWOLFSSL_DH_EXTRA',
|
||||
|
||||
@@ -446,6 +446,10 @@ NO_TKERNEL_MEM_POOL
|
||||
NO_TLSX_PSKKEM_PLAIN_ANNOUNCE
|
||||
NO_VERIFY_OID
|
||||
NO_WC_DHGENERATEPUBLIC
|
||||
NO_WC_SHE_EXPORTKEY
|
||||
NO_WC_SHE_GETCOUNTER
|
||||
NO_WC_SHE_GETUID
|
||||
NO_WC_SHE_IMPORT_M123
|
||||
NO_WC_SSIZE_TYPE
|
||||
NO_WOLFSSL_ALLOC_ALIGN
|
||||
NO_WOLFSSL_AUTOSAR_CRYIF
|
||||
@@ -889,6 +893,7 @@ WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT
|
||||
WOLFSSL_SERVER_EXAMPLE
|
||||
WOLFSSL_SETTINGS_FILE
|
||||
WOLFSSL_SHE
|
||||
WOLFSSL_SHE_EXTENDED
|
||||
WOLFSSL_SH224
|
||||
WOLFSSL_SHA256_ALT_CH_MAJ
|
||||
WOLFSSL_SHA512_HASHTYPE
|
||||
|
||||
+9
-3
@@ -1641,11 +1641,12 @@ if(WOLFSSL_CMAC)
|
||||
endif()
|
||||
|
||||
# SHE (Secure Hardware Extension) key update message generation
|
||||
# standard: core SHE support, extended: adds custom KDF/header overrides
|
||||
add_option("WOLFSSL_SHE"
|
||||
"Enable SHE key update support (default: disabled)"
|
||||
"no" "yes;no")
|
||||
"Enable SHE key update support (standard|extended|no)"
|
||||
"no" "standard;extended;no")
|
||||
|
||||
if(WOLFSSL_SHE)
|
||||
if(WOLFSSL_SHE STREQUAL "standard" OR WOLFSSL_SHE STREQUAL "extended")
|
||||
if (NOT WOLFSSL_AES)
|
||||
message(FATAL_ERROR "Cannot use SHE without AES.")
|
||||
else()
|
||||
@@ -1654,6 +1655,11 @@ if(WOLFSSL_SHE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WOLFSSL_SHE STREQUAL "extended")
|
||||
list(APPEND WOLFSSL_DEFINITIONS
|
||||
"-DWOLFSSL_SHE_EXTENDED")
|
||||
endif()
|
||||
|
||||
# TODO: - RC2
|
||||
# - FIPS, again (there's more logic for FIPS in configure.ac)
|
||||
# - Selftest
|
||||
|
||||
+14
-4
@@ -5946,14 +5946,24 @@ AS_IF([test "x$ENABLED_CMAC" = "xyes"],
|
||||
[AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CMAC -DWOLFSSL_AES_DIRECT"])
|
||||
|
||||
# SHE (Secure Hardware Extension) key update message generation
|
||||
# --enable-she=standard: standard SHE support
|
||||
# --enable-she=extended: standard + extended overrides (custom KDF/headers)
|
||||
AC_ARG_ENABLE([she],
|
||||
[AS_HELP_STRING([--enable-she],[Enable SHE key update support (default: disabled)])],
|
||||
[AS_HELP_STRING([--enable-she@<:@=standard|extended@:>@],
|
||||
[Enable SHE key update support (default: disabled)])],
|
||||
[ ENABLED_SHE=$enableval ],
|
||||
[ ENABLED_SHE=no ]
|
||||
)
|
||||
|
||||
AS_IF([test "x$ENABLED_SHE" = "xyes"],
|
||||
[AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHE"])
|
||||
if test "x$ENABLED_SHE" = "xstandard" || test "x$ENABLED_SHE" = "xextended"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHE"
|
||||
fi
|
||||
|
||||
if test "x$ENABLED_SHE" = "xextended"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHE_EXTENDED"
|
||||
fi
|
||||
|
||||
# AES-XTS
|
||||
AC_ARG_ENABLE([aesxts],
|
||||
@@ -11564,7 +11574,7 @@ AM_CONDITIONAL([BUILD_FIPS_V6],[test $HAVE_FIPS_VERSION = 6])
|
||||
AM_CONDITIONAL([BUILD_FIPS_V6_PLUS],[test $HAVE_FIPS_VERSION -ge 6])
|
||||
AM_CONDITIONAL([BUILD_SIPHASH],[test "x$ENABLED_SIPHASH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_CMAC],[test "x$ENABLED_CMAC" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_SHE],[test "x$ENABLED_SHE" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_SHE],[test "x$ENABLED_SHE" = "xstandard" || test "x$ENABLED_SHE" = "xextended" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_SELFTEST],[test "x$ENABLED_SELFTEST" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_SHA224],[test "x$ENABLED_SHA224" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_SHA3],[test "x$ENABLED_SHA3" != "xno" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
|
||||
@@ -35638,6 +35638,9 @@ TEST_CASE testCases[] = {
|
||||
TEST_CMAC_DECLS,
|
||||
/* SHE */
|
||||
TEST_SHE_DECLS,
|
||||
#ifdef WOLFSSL_SHE_EXTENDED
|
||||
TEST_SHE_EXT_DECLS,
|
||||
#endif
|
||||
#if defined(WOLF_CRYPTO_CB) && defined(WOLFSSL_SHE)
|
||||
TEST_SHE_CB_DECLS,
|
||||
#endif
|
||||
|
||||
+376
-613
File diff suppressed because it is too large
Load Diff
+23
-25
@@ -28,37 +28,35 @@ int test_wc_SHE_Init(void);
|
||||
int test_wc_SHE_Init_Id(void);
|
||||
int test_wc_SHE_Init_Label(void);
|
||||
int test_wc_SHE_Free(void);
|
||||
int test_wc_SHE_SetUID(void);
|
||||
int test_wc_SHE_SetAuthKey(void);
|
||||
int test_wc_SHE_SetNewKey(void);
|
||||
int test_wc_SHE_SetCounter(void);
|
||||
int test_wc_SHE_SetFlags(void);
|
||||
int test_wc_SHE_ImportM1M2M3(void);
|
||||
int test_wc_She_AesMp16(void);
|
||||
int test_wc_SHE_GenerateM1M2M3(void);
|
||||
int test_wc_SHE_GenerateM4M5(void);
|
||||
#ifdef WOLFSSL_SHE_EXTENDED
|
||||
int test_wc_SHE_SetKdfConstants(void);
|
||||
int test_wc_SHE_SetM2M4Header(void);
|
||||
int test_wc_SHE_GenerateM1M2M3(void);
|
||||
int test_wc_She_AesMp16(void);
|
||||
int test_wc_SHE_GenerateM4M5(void);
|
||||
int test_wc_SHE_ExportKey(void);
|
||||
#endif
|
||||
#if defined(WOLF_CRYPTO_CB) && defined(WOLFSSL_SHE)
|
||||
int test_wc_SHE_CryptoCb(void);
|
||||
#endif
|
||||
|
||||
#define TEST_SHE_DECLS \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_Init), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_Init_Id), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_Init_Label), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_Free), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_SetUID), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_SetAuthKey), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_SetNewKey), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_SetCounter), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_SetFlags), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_SetKdfConstants), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_SetM2M4Header), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_GenerateM1M2M3), \
|
||||
TEST_DECL_GROUP("she", test_wc_She_AesMp16), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_GenerateM4M5), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_ExportKey)
|
||||
#define TEST_SHE_DECLS \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_Init), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_Init_Id), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_Init_Label), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_Free), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_ImportM1M2M3), \
|
||||
TEST_DECL_GROUP("she", test_wc_She_AesMp16), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_GenerateM1M2M3), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_GenerateM4M5)
|
||||
|
||||
#ifdef WOLFSSL_SHE_EXTENDED
|
||||
#define TEST_SHE_EXT_DECLS \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_SetKdfConstants), \
|
||||
TEST_DECL_GROUP("she", test_wc_SHE_SetM2M4Header)
|
||||
#else
|
||||
#define TEST_SHE_EXT_DECLS
|
||||
#endif
|
||||
|
||||
#if defined(WOLF_CRYPTO_CB) && defined(WOLFSSL_SHE)
|
||||
#define TEST_SHE_CB_DECLS \
|
||||
|
||||
+74
-11
@@ -2149,12 +2149,12 @@ int wc_CryptoCb_SheSetUid(wc_SHE* she, const byte* uid, word32 uidSz,
|
||||
return wc_CryptoCb_TranslateErrorCode(ret);
|
||||
}
|
||||
|
||||
int wc_CryptoCb_SheGenerateM1M2M3(wc_SHE* she, const void* ctx)
|
||||
int wc_CryptoCb_SheGetCounter(wc_SHE* she, word32* counter, const void* ctx)
|
||||
{
|
||||
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
|
||||
CryptoCb* dev;
|
||||
|
||||
if (she == NULL) {
|
||||
if (she == NULL || counter == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
@@ -2162,10 +2162,11 @@ int wc_CryptoCb_SheGenerateM1M2M3(wc_SHE* she, const void* ctx)
|
||||
if (dev && dev->cb) {
|
||||
wc_CryptoInfo cryptoInfo;
|
||||
XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
|
||||
cryptoInfo.algo_type = WC_ALGO_TYPE_SHE;
|
||||
cryptoInfo.she.she = she;
|
||||
cryptoInfo.she.type = WC_SHE_GENERATE_M1M2M3;
|
||||
cryptoInfo.she.ctx = ctx;
|
||||
cryptoInfo.algo_type = WC_ALGO_TYPE_SHE;
|
||||
cryptoInfo.she.she = she;
|
||||
cryptoInfo.she.type = WC_SHE_GET_COUNTER;
|
||||
cryptoInfo.she.ctx = ctx;
|
||||
cryptoInfo.she.op.getCounter.counter = counter;
|
||||
|
||||
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
|
||||
}
|
||||
@@ -2173,7 +2174,14 @@ int wc_CryptoCb_SheGenerateM1M2M3(wc_SHE* she, const void* ctx)
|
||||
return wc_CryptoCb_TranslateErrorCode(ret);
|
||||
}
|
||||
|
||||
int wc_CryptoCb_SheGenerateM4M5(wc_SHE* she, const void* ctx)
|
||||
int wc_CryptoCb_SheGenerateM1M2M3(wc_SHE* she,
|
||||
const byte* uid, word32 uidSz,
|
||||
byte authKeyId, const byte* authKey, word32 authKeySz,
|
||||
byte targetKeyId, const byte* newKey, word32 newKeySz,
|
||||
word32 counter, byte flags,
|
||||
byte* m1, word32 m1Sz,
|
||||
byte* m2, word32 m2Sz,
|
||||
byte* m3, word32 m3Sz)
|
||||
{
|
||||
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
|
||||
CryptoCb* dev;
|
||||
@@ -2186,10 +2194,65 @@ int wc_CryptoCb_SheGenerateM4M5(wc_SHE* she, const void* ctx)
|
||||
if (dev && dev->cb) {
|
||||
wc_CryptoInfo cryptoInfo;
|
||||
XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
|
||||
cryptoInfo.algo_type = WC_ALGO_TYPE_SHE;
|
||||
cryptoInfo.she.she = she;
|
||||
cryptoInfo.she.type = WC_SHE_GENERATE_M4M5;
|
||||
cryptoInfo.she.ctx = ctx;
|
||||
cryptoInfo.algo_type = WC_ALGO_TYPE_SHE;
|
||||
cryptoInfo.she.she = she;
|
||||
cryptoInfo.she.type = WC_SHE_GENERATE_M1M2M3;
|
||||
cryptoInfo.she.op.generateM1M2M3.uid = uid;
|
||||
cryptoInfo.she.op.generateM1M2M3.uidSz = uidSz;
|
||||
cryptoInfo.she.op.generateM1M2M3.authKeyId = authKeyId;
|
||||
cryptoInfo.she.op.generateM1M2M3.authKey = authKey;
|
||||
cryptoInfo.she.op.generateM1M2M3.authKeySz = authKeySz;
|
||||
cryptoInfo.she.op.generateM1M2M3.targetKeyId = targetKeyId;
|
||||
cryptoInfo.she.op.generateM1M2M3.newKey = newKey;
|
||||
cryptoInfo.she.op.generateM1M2M3.newKeySz = newKeySz;
|
||||
cryptoInfo.she.op.generateM1M2M3.counter = counter;
|
||||
cryptoInfo.she.op.generateM1M2M3.flags = flags;
|
||||
cryptoInfo.she.op.generateM1M2M3.m1 = m1;
|
||||
cryptoInfo.she.op.generateM1M2M3.m1Sz = m1Sz;
|
||||
cryptoInfo.she.op.generateM1M2M3.m2 = m2;
|
||||
cryptoInfo.she.op.generateM1M2M3.m2Sz = m2Sz;
|
||||
cryptoInfo.she.op.generateM1M2M3.m3 = m3;
|
||||
cryptoInfo.she.op.generateM1M2M3.m3Sz = m3Sz;
|
||||
|
||||
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
|
||||
}
|
||||
|
||||
return wc_CryptoCb_TranslateErrorCode(ret);
|
||||
}
|
||||
|
||||
int wc_CryptoCb_SheGenerateM4M5(wc_SHE* she,
|
||||
const byte* uid, word32 uidSz,
|
||||
byte authKeyId, byte targetKeyId,
|
||||
const byte* newKey, word32 newKeySz,
|
||||
word32 counter,
|
||||
byte* m4, word32 m4Sz,
|
||||
byte* m5, word32 m5Sz)
|
||||
{
|
||||
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
|
||||
CryptoCb* dev;
|
||||
|
||||
if (she == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
dev = wc_CryptoCb_FindDevice(she->devId, WC_ALGO_TYPE_SHE);
|
||||
if (dev && dev->cb) {
|
||||
wc_CryptoInfo cryptoInfo;
|
||||
XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
|
||||
cryptoInfo.algo_type = WC_ALGO_TYPE_SHE;
|
||||
cryptoInfo.she.she = she;
|
||||
cryptoInfo.she.type = WC_SHE_GENERATE_M4M5;
|
||||
cryptoInfo.she.op.generateM4M5.uid = uid;
|
||||
cryptoInfo.she.op.generateM4M5.uidSz = uidSz;
|
||||
cryptoInfo.she.op.generateM4M5.authKeyId = authKeyId;
|
||||
cryptoInfo.she.op.generateM4M5.targetKeyId = targetKeyId;
|
||||
cryptoInfo.she.op.generateM4M5.newKey = newKey;
|
||||
cryptoInfo.she.op.generateM4M5.newKeySz = newKeySz;
|
||||
cryptoInfo.she.op.generateM4M5.counter = counter;
|
||||
cryptoInfo.she.op.generateM4M5.m4 = m4;
|
||||
cryptoInfo.she.op.generateM4M5.m4Sz = m4Sz;
|
||||
cryptoInfo.she.op.generateM4M5.m5 = m5;
|
||||
cryptoInfo.she.op.generateM4M5.m5Sz = m5Sz;
|
||||
|
||||
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
|
||||
}
|
||||
|
||||
+213
-190
@@ -116,19 +116,14 @@ int wc_She_AesMp16(Aes* aes, const byte* in, word32 inSz, byte* out)
|
||||
/* -------------------------------------------------------------------------- */
|
||||
int wc_SHE_Init(wc_SHE* she, void* heap, int devId)
|
||||
{
|
||||
const byte encC[] = WC_SHE_KEY_UPDATE_ENC_C;
|
||||
const byte macC[] = WC_SHE_KEY_UPDATE_MAC_C;
|
||||
|
||||
if (she == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
XMEMSET(she, 0, sizeof(wc_SHE));
|
||||
ForceZero(she, sizeof(wc_SHE));
|
||||
she->heap = heap;
|
||||
she->devId = devId;
|
||||
XMEMCPY(she->kdfEncC, encC, WC_SHE_KEY_SZ);
|
||||
XMEMCPY(she->kdfMacC, macC, WC_SHE_KEY_SZ);
|
||||
/* m2pHeader/m4pHeader are zero from XMEMSET ΓÇö correct for counter=0 */
|
||||
/* kdfEncOverride/kdfMacOverride are zero from XMEMSET — defaults used */
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -227,85 +222,45 @@ void wc_SHE_Free(wc_SHE* she)
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Setter functions */
|
||||
/* GetUID — callback required */
|
||||
/* */
|
||||
/* Dispatches to callback to fetch UID from hardware. */
|
||||
/* Buffer size validation is the callback's responsibility. */
|
||||
/* Returns CRYPTOCB_UNAVAILABLE if no callback. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int wc_SHE_SetUID(wc_SHE* she, const byte* uid, word32 uidSz,
|
||||
#if defined(WOLF_CRYPTO_CB) && !defined(NO_WC_SHE_GETUID)
|
||||
int wc_SHE_GetUID(wc_SHE* she, byte* uid, word32 uidSz,
|
||||
const void* ctx)
|
||||
{
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
if (she == NULL) {
|
||||
if (she == NULL || uid == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* Try callback first if a device is registered */
|
||||
if (she->devId != INVALID_DEVID) {
|
||||
ret = wc_CryptoCb_SheSetUid(she, uid, uidSz, ctx);
|
||||
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
|
||||
return ret;
|
||||
}
|
||||
/* fall-through to software path */
|
||||
}
|
||||
#else
|
||||
(void)ctx;
|
||||
#endif
|
||||
|
||||
/* Software path: copy caller-provided UID */
|
||||
if (uid == NULL || uidSz != WC_SHE_UID_SZ) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
XMEMCPY(she->uid, uid, WC_SHE_UID_SZ);
|
||||
return 0;
|
||||
return wc_CryptoCb_SheSetUid(she, uid, uidSz, ctx);
|
||||
}
|
||||
#endif /* WOLF_CRYPTO_CB && !NO_WC_SHE_GETUID */
|
||||
|
||||
int wc_SHE_SetAuthKey(wc_SHE* she, byte authKeyId,
|
||||
const byte* authKey, word32 keySz)
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* GetCounter — callback required */
|
||||
/* */
|
||||
/* Dispatches to callback to read current counter from hardware. */
|
||||
/* Returns CRYPTOCB_UNAVAILABLE if no callback. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
#if defined(WOLF_CRYPTO_CB) && !defined(NO_WC_SHE_GETCOUNTER)
|
||||
int wc_SHE_GetCounter(wc_SHE* she, word32* counter, const void* ctx)
|
||||
{
|
||||
if (she == NULL || authKey == NULL || keySz != WC_SHE_KEY_SZ) {
|
||||
if (she == NULL || counter == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
she->authKeyId = authKeyId;
|
||||
XMEMCPY(she->authKey, authKey, WC_SHE_KEY_SZ);
|
||||
return 0;
|
||||
return wc_CryptoCb_SheGetCounter(she, counter, ctx);
|
||||
}
|
||||
#endif /* WOLF_CRYPTO_CB && !NO_WC_SHE_GETCOUNTER */
|
||||
|
||||
int wc_SHE_SetNewKey(wc_SHE* she, byte targetKeyId,
|
||||
const byte* newKey, word32 keySz)
|
||||
{
|
||||
if (she == NULL || newKey == NULL || keySz != WC_SHE_KEY_SZ) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
she->targetKeyId = targetKeyId;
|
||||
XMEMCPY(she->newKey, newKey, WC_SHE_KEY_SZ);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wc_SHE_SetCounter(wc_SHE* she, word32 counter)
|
||||
{
|
||||
if (she == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
she->counter = counter;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wc_SHE_SetFlags(wc_SHE* she, byte flags)
|
||||
{
|
||||
if (she == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
she->flags = flags;
|
||||
return 0;
|
||||
}
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Extended SHE overrides */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
#ifdef WOLFSSL_SHE_EXTENDED
|
||||
|
||||
int wc_SHE_SetKdfConstants(wc_SHE* she,
|
||||
const byte* encC, word32 encCSz,
|
||||
@@ -320,6 +275,7 @@ int wc_SHE_SetKdfConstants(wc_SHE* she,
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
XMEMCPY(she->kdfEncC, encC, WC_SHE_KEY_SZ);
|
||||
she->kdfEncOverride = 1;
|
||||
}
|
||||
|
||||
if (macC != NULL) {
|
||||
@@ -327,11 +283,44 @@ int wc_SHE_SetKdfConstants(wc_SHE* she,
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
XMEMCPY(she->kdfMacC, macC, WC_SHE_KEY_SZ);
|
||||
she->kdfMacOverride = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_SHE_EXTENDED */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* GetUID */
|
||||
|
||||
#if defined(WOLF_CRYPTO_CB) || !defined(NO_WC_SHE_IMPORT_M123)
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Import M1/M2/M3 */
|
||||
/* */
|
||||
/* Copy externally-provided M1/M2/M3 into context and set generated flag. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
int wc_SHE_ImportM1M2M3(wc_SHE* she,
|
||||
const byte* m1, word32 m1Sz,
|
||||
const byte* m2, word32 m2Sz,
|
||||
const byte* m3, word32 m3Sz)
|
||||
{
|
||||
if (she == NULL || m1 == NULL || m2 == NULL || m3 == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (m1Sz != WC_SHE_M1_SZ || m2Sz != WC_SHE_M2_SZ ||
|
||||
m3Sz != WC_SHE_M3_SZ) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
XMEMCPY(she->m1, m1, WC_SHE_M1_SZ);
|
||||
XMEMCPY(she->m2, m2, WC_SHE_M2_SZ);
|
||||
XMEMCPY(she->m3, m3, WC_SHE_M3_SZ);
|
||||
she->generated = 1;
|
||||
return 0;
|
||||
}
|
||||
#endif /* WOLF_CRYPTO_CB || !NO_WC_SHE_IMPORT_M123 */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Portable big-endian 32-bit store */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@@ -343,28 +332,45 @@ static WC_INLINE void she_store_be32(byte* dst, word32 val)
|
||||
dst[3] = (byte)(val);
|
||||
}
|
||||
|
||||
/* Build M2P/M4P headers from counter and flags using standard SHE packing.
|
||||
/* Build M2P and M4P headers from counter and flags using standard SHE packing.
|
||||
* M2P header: counter(28b) | flags(4b) | zeros(96b) = 16 bytes
|
||||
* M4P header: counter(28b) | 1(1b) | zeros(99b) = 16 bytes
|
||||
* Called internally by GenerateM1M2M3/GenerateM4M5 unless overridden. */
|
||||
static void she_build_headers(wc_SHE* she)
|
||||
* Writes to caller-provided buffers. Skipped if WOLFSSL_SHE_EXTENDED
|
||||
* override is active on the context. */
|
||||
static void she_build_headers(wc_SHE* she, word32 counter, byte flags,
|
||||
byte* m2pHeader, byte* m4pHeader)
|
||||
{
|
||||
word32 field;
|
||||
|
||||
if (!she->m2pOverride) {
|
||||
XMEMSET(she->m2pHeader, 0, WC_SHE_KEY_SZ);
|
||||
field = (she->counter << WC_SHE_M2_COUNT_SHIFT) |
|
||||
(she->flags << WC_SHE_M2_FLAGS_SHIFT);
|
||||
she_store_be32(she->m2pHeader, field);
|
||||
#ifdef WOLFSSL_SHE_EXTENDED
|
||||
if (she->m2pOverride) {
|
||||
XMEMCPY(m2pHeader, she->m2pHeader, WC_SHE_KEY_SZ);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
XMEMSET(m2pHeader, 0, WC_SHE_KEY_SZ);
|
||||
field = (counter << WC_SHE_M2_COUNT_SHIFT) |
|
||||
(flags << WC_SHE_M2_FLAGS_SHIFT);
|
||||
she_store_be32(m2pHeader, field);
|
||||
}
|
||||
|
||||
if (!she->m4pOverride) {
|
||||
XMEMSET(she->m4pHeader, 0, WC_SHE_KEY_SZ);
|
||||
field = (she->counter << WC_SHE_M4_COUNT_SHIFT) | WC_SHE_M4_COUNT_PAD;
|
||||
she_store_be32(she->m4pHeader, field);
|
||||
#ifdef WOLFSSL_SHE_EXTENDED
|
||||
if (she->m4pOverride) {
|
||||
XMEMCPY(m4pHeader, she->m4pHeader, WC_SHE_KEY_SZ);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
XMEMSET(m4pHeader, 0, WC_SHE_KEY_SZ);
|
||||
field = (counter << WC_SHE_M4_COUNT_SHIFT) | WC_SHE_M4_COUNT_PAD;
|
||||
she_store_be32(m4pHeader, field);
|
||||
}
|
||||
|
||||
(void)she;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_SHE_EXTENDED
|
||||
int wc_SHE_SetM2Header(wc_SHE* she, const byte* header, word32 headerSz)
|
||||
{
|
||||
if (she == NULL || header == NULL || headerSz != WC_SHE_KEY_SZ) {
|
||||
@@ -386,6 +392,7 @@ int wc_SHE_SetM4Header(wc_SHE* she, const byte* header, word32 headerSz)
|
||||
she->m4pOverride = 1;
|
||||
return 0;
|
||||
}
|
||||
#endif /* WOLFSSL_SHE_EXTENDED */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* M1/M2/M3 generation */
|
||||
@@ -397,31 +404,43 @@ int wc_SHE_SetM4Header(wc_SHE* she, const byte* header, word32 headerSz)
|
||||
/* */
|
||||
/* Ported from wolfHSM wh_She_GenerateLoadableKey() in wh_she_crypto.c. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
int wc_SHE_GenerateM1M2M3(wc_SHE* she)
|
||||
int wc_SHE_GenerateM1M2M3(wc_SHE* she,
|
||||
const byte* uid, word32 uidSz,
|
||||
byte authKeyId, const byte* authKey, word32 authKeySz,
|
||||
byte targetKeyId, const byte* newKey, word32 newKeySz,
|
||||
word32 counter, byte flags,
|
||||
byte* m1, word32 m1Sz,
|
||||
byte* m2, word32 m2Sz,
|
||||
byte* m3, word32 m3Sz)
|
||||
{
|
||||
int ret = 0;
|
||||
byte m2pHeader[WC_SHE_KEY_SZ];
|
||||
byte m4pHeader[WC_SHE_KEY_SZ];
|
||||
byte k1[WC_SHE_KEY_SZ];
|
||||
byte k2[WC_SHE_KEY_SZ];
|
||||
byte kdfInput[WC_SHE_KEY_SZ * 2];
|
||||
byte encC[] = WC_SHE_KEY_UPDATE_ENC_C;
|
||||
byte macC[] = WC_SHE_KEY_UPDATE_MAC_C;
|
||||
word32 cmacSz = AES_BLOCK_SIZE;
|
||||
WC_DECLARE_VAR(aes, Aes, 1, 0);
|
||||
WC_DECLARE_VAR(cmac, Cmac, 1, 0);
|
||||
|
||||
/* Validate SHE context first — required for both callback and software */
|
||||
if (she == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Build M2P/M4P headers from counter/flags (skipped if overridden) */
|
||||
she_build_headers(she);
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* Try callback first ΓÇö hardware may generate M1/M2/M3 directly */
|
||||
/* 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) {
|
||||
ret = wc_CryptoCb_SheGenerateM1M2M3(she, NULL);
|
||||
ret = wc_CryptoCb_SheGenerateM1M2M3(she, uid, uidSz,
|
||||
authKeyId, authKey, authKeySz,
|
||||
targetKeyId, newKey, newKeySz,
|
||||
counter, flags,
|
||||
m1, m1Sz, m2, m2Sz, m3, m3Sz);
|
||||
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
|
||||
if (ret == 0) {
|
||||
she->generated = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/* fall-through to software path */
|
||||
@@ -429,6 +448,29 @@ int wc_SHE_GenerateM1M2M3(wc_SHE* she)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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 ||
|
||||
m1 == NULL || m1Sz < WC_SHE_M1_SZ ||
|
||||
m2 == NULL || m2Sz < WC_SHE_M2_SZ ||
|
||||
m3 == NULL || m3Sz < WC_SHE_M3_SZ) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Override KDF constants if explicitly set */
|
||||
#ifdef WOLFSSL_SHE_EXTENDED
|
||||
if (she->kdfEncOverride) {
|
||||
XMEMCPY(encC, she->kdfEncC, WC_SHE_KEY_SZ);
|
||||
}
|
||||
if (she->kdfMacOverride) {
|
||||
XMEMCPY(macC, she->kdfMacC, WC_SHE_KEY_SZ);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Build M2P/M4P headers from counter/flags (skipped if overridden) */
|
||||
she_build_headers(she, counter, flags, m2pHeader, m4pHeader);
|
||||
|
||||
WC_ALLOC_VAR(aes, Aes, 1, she->heap);
|
||||
if (!WC_VAR_OK(aes)) {
|
||||
return MEMORY_E;
|
||||
@@ -449,34 +491,34 @@ int wc_SHE_GenerateM1M2M3(wc_SHE* she)
|
||||
}
|
||||
|
||||
/* ---- Derive K1 = AES-MP(AuthKey || CENC) ---- */
|
||||
XMEMCPY(kdfInput, she->authKey, WC_SHE_KEY_SZ);
|
||||
XMEMCPY(kdfInput + WC_SHE_KEY_SZ, she->kdfEncC, WC_SHE_KEY_SZ);
|
||||
XMEMCPY(kdfInput, authKey, WC_SHE_KEY_SZ);
|
||||
XMEMCPY(kdfInput + WC_SHE_KEY_SZ, encC, WC_SHE_KEY_SZ);
|
||||
ret = wc_She_AesMp16(aes, kdfInput, WC_SHE_KEY_SZ * 2, k1);
|
||||
|
||||
/* ---- Build M1: UID(15B) | TargetKeyID(4b) | AuthKeyID(4b) ---- */
|
||||
if (ret == 0) {
|
||||
XMEMCPY(she->m1, she->uid, WC_SHE_UID_SZ);
|
||||
she->m1[WC_SHE_M1_KID_OFFSET] =
|
||||
(byte)((she->targetKeyId << WC_SHE_M1_KID_SHIFT) |
|
||||
(she->authKeyId << WC_SHE_M1_AID_SHIFT));
|
||||
XMEMCPY(m1, uid, WC_SHE_UID_SZ);
|
||||
m1[WC_SHE_M1_KID_OFFSET] =
|
||||
(byte)((targetKeyId << WC_SHE_M1_KID_SHIFT) |
|
||||
(authKeyId << WC_SHE_M1_AID_SHIFT));
|
||||
}
|
||||
|
||||
/* ---- Build cleartext M2 and encrypt with K1 ---- */
|
||||
if (ret == 0) {
|
||||
/* M2P = m2pHeader(16B) | newKey(16B) */
|
||||
XMEMCPY(she->m2, she->m2pHeader, WC_SHE_KEY_SZ);
|
||||
XMEMCPY(she->m2 + WC_SHE_M2_KEY_OFFSET, she->newKey, WC_SHE_KEY_SZ);
|
||||
XMEMCPY(m2, m2pHeader, WC_SHE_KEY_SZ);
|
||||
XMEMCPY(m2 + WC_SHE_M2_KEY_OFFSET, newKey, WC_SHE_KEY_SZ);
|
||||
|
||||
/* Encrypt M2 in-place with AES-128-CBC, IV = 0 */
|
||||
ret = wc_AesSetKey(aes, k1, WC_SHE_KEY_SZ, NULL, AES_ENCRYPTION);
|
||||
if (ret == 0) {
|
||||
ret = wc_AesCbcEncrypt(aes, she->m2, she->m2, WC_SHE_M2_SZ);
|
||||
ret = wc_AesCbcEncrypt(aes, m2, m2, WC_SHE_M2_SZ);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- Derive K2 = AES-MP(AuthKey || CMAC) ---- */
|
||||
/* ---- Derive K2 = AES-MP(AuthKey || CMAC_C) ---- */
|
||||
if (ret == 0) {
|
||||
XMEMCPY(kdfInput + WC_SHE_KEY_SZ, she->kdfMacC, WC_SHE_KEY_SZ);
|
||||
XMEMCPY(kdfInput + WC_SHE_KEY_SZ, macC, WC_SHE_KEY_SZ);
|
||||
ret = wc_She_AesMp16(aes, kdfInput, WC_SHE_KEY_SZ * 2, k2);
|
||||
}
|
||||
|
||||
@@ -486,18 +528,14 @@ int wc_SHE_GenerateM1M2M3(wc_SHE* she)
|
||||
NULL, she->heap, she->devId);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_CmacUpdate(cmac, she->m1, WC_SHE_M1_SZ);
|
||||
ret = wc_CmacUpdate(cmac, m1, WC_SHE_M1_SZ);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_CmacUpdate(cmac, she->m2, WC_SHE_M2_SZ);
|
||||
ret = wc_CmacUpdate(cmac, m2, WC_SHE_M2_SZ);
|
||||
}
|
||||
if (ret == 0) {
|
||||
cmacSz = AES_BLOCK_SIZE;
|
||||
ret = wc_CmacFinal(cmac, she->m3, &cmacSz);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
she->generated = 1;
|
||||
ret = wc_CmacFinal(cmac, m3, &cmacSz);
|
||||
}
|
||||
|
||||
/* Scrub temporary key material */
|
||||
@@ -520,37 +558,68 @@ int wc_SHE_GenerateM1M2M3(wc_SHE* she)
|
||||
/* */
|
||||
/* These are the expected proof messages that SHE hardware should return. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
int wc_SHE_GenerateM4M5(wc_SHE* she)
|
||||
int wc_SHE_GenerateM4M5(wc_SHE* she,
|
||||
const byte* uid, word32 uidSz,
|
||||
byte authKeyId, byte targetKeyId,
|
||||
const byte* newKey, word32 newKeySz,
|
||||
word32 counter,
|
||||
byte* m4, word32 m4Sz,
|
||||
byte* m5, word32 m5Sz)
|
||||
{
|
||||
int ret = 0;
|
||||
byte m2pHeader[WC_SHE_KEY_SZ];
|
||||
byte m4pHeader[WC_SHE_KEY_SZ];
|
||||
byte k3[WC_SHE_KEY_SZ];
|
||||
byte k4[WC_SHE_KEY_SZ];
|
||||
byte kdfInput[WC_SHE_KEY_SZ * 2];
|
||||
byte encC[] = WC_SHE_KEY_UPDATE_ENC_C;
|
||||
byte macC[] = WC_SHE_KEY_UPDATE_MAC_C;
|
||||
word32 cmacSz;
|
||||
WC_DECLARE_VAR(aes, Aes, 1, 0);
|
||||
WC_DECLARE_VAR(cmac, Cmac, 1, 0);
|
||||
|
||||
/* Validate SHE context first */
|
||||
if (she == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (!she->generated) {
|
||||
return BAD_STATE_E;
|
||||
}
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* Try callback first — sends M1/M2/M3 to HW, receives M4/M5 */
|
||||
/* 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) {
|
||||
ret = wc_CryptoCb_SheGenerateM4M5(she, NULL);
|
||||
ret = wc_CryptoCb_SheGenerateM4M5(she, uid, uidSz,
|
||||
authKeyId, targetKeyId,
|
||||
newKey, newKeySz, counter,
|
||||
m4, m4Sz, m5, m5Sz);
|
||||
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
|
||||
if (ret == 0) {
|
||||
she->verified = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/* fall-through to software path */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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 ||
|
||||
m5 == NULL || m5Sz < WC_SHE_M5_SZ) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Override KDF constants if explicitly set */
|
||||
#ifdef WOLFSSL_SHE_EXTENDED
|
||||
if (she->kdfEncOverride) {
|
||||
XMEMCPY(encC, she->kdfEncC, WC_SHE_KEY_SZ);
|
||||
}
|
||||
if (she->kdfMacOverride) {
|
||||
XMEMCPY(macC, she->kdfMacC, WC_SHE_KEY_SZ);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Build headers from counter (skipped if overridden) */
|
||||
she_build_headers(she, counter, 0, m2pHeader, m4pHeader);
|
||||
|
||||
WC_ALLOC_VAR(aes, Aes, 1, she->heap);
|
||||
if (!WC_VAR_OK(aes)) {
|
||||
return MEMORY_E;
|
||||
@@ -571,50 +640,46 @@ int wc_SHE_GenerateM4M5(wc_SHE* she)
|
||||
}
|
||||
|
||||
/* ---- Derive K3 = AES-MP(NewKey || CENC) ---- */
|
||||
XMEMCPY(kdfInput, she->newKey, WC_SHE_KEY_SZ);
|
||||
XMEMCPY(kdfInput + WC_SHE_KEY_SZ, she->kdfEncC, WC_SHE_KEY_SZ);
|
||||
XMEMCPY(kdfInput, newKey, WC_SHE_KEY_SZ);
|
||||
XMEMCPY(kdfInput + WC_SHE_KEY_SZ, encC, WC_SHE_KEY_SZ);
|
||||
ret = wc_She_AesMp16(aes, kdfInput, WC_SHE_KEY_SZ * 2, k3);
|
||||
|
||||
/* ---- Build M4: UID|IDs header + AES-ECB(K3, m4pHeader) ---- */
|
||||
if (ret == 0) {
|
||||
XMEMSET(she->m4, 0, WC_SHE_M4_SZ);
|
||||
XMEMSET(m4, 0, WC_SHE_M4_SZ);
|
||||
|
||||
XMEMCPY(she->m4, she->uid, WC_SHE_UID_SZ);
|
||||
she->m4[WC_SHE_M4_KID_OFFSET] =
|
||||
(byte)((she->targetKeyId << WC_SHE_M4_KID_SHIFT) |
|
||||
(she->authKeyId << WC_SHE_M4_AID_SHIFT));
|
||||
XMEMCPY(m4, uid, WC_SHE_UID_SZ);
|
||||
m4[WC_SHE_M4_KID_OFFSET] =
|
||||
(byte)((targetKeyId << WC_SHE_M4_KID_SHIFT) |
|
||||
(authKeyId << WC_SHE_M4_AID_SHIFT));
|
||||
|
||||
/* Copy pre-built M4P header (counter|pad) into M4 counter block */
|
||||
XMEMCPY(she->m4 + WC_SHE_M4_COUNT_OFFSET, she->m4pHeader,
|
||||
XMEMCPY(m4 + WC_SHE_M4_COUNT_OFFSET, m4pHeader,
|
||||
WC_SHE_KEY_SZ);
|
||||
|
||||
/* Encrypt the 16-byte counter block in-place with AES-ECB */
|
||||
ret = wc_AesSetKey(aes, k3, WC_SHE_KEY_SZ, NULL, AES_ENCRYPTION);
|
||||
if (ret == 0) {
|
||||
ret = wc_AesEncryptDirect(aes,
|
||||
she->m4 + WC_SHE_M4_COUNT_OFFSET,
|
||||
she->m4 + WC_SHE_M4_COUNT_OFFSET);
|
||||
m4 + WC_SHE_M4_COUNT_OFFSET,
|
||||
m4 + WC_SHE_M4_COUNT_OFFSET);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- Derive K4 = AES-MP(NewKey || CMAC) ---- */
|
||||
/* ---- Derive K4 = AES-MP(NewKey || CMAC_C) ---- */
|
||||
if (ret == 0) {
|
||||
XMEMCPY(kdfInput + WC_SHE_KEY_SZ, she->kdfMacC, WC_SHE_KEY_SZ);
|
||||
XMEMCPY(kdfInput + WC_SHE_KEY_SZ, macC, WC_SHE_KEY_SZ);
|
||||
ret = wc_She_AesMp16(aes, kdfInput, WC_SHE_KEY_SZ * 2, k4);
|
||||
}
|
||||
|
||||
/* ---- Build M5 = AES-CMAC(K4, M4) ---- */
|
||||
if (ret == 0) {
|
||||
cmacSz = AES_BLOCK_SIZE;
|
||||
ret = wc_AesCmacGenerate_ex(cmac, she->m5, &cmacSz,
|
||||
she->m4, WC_SHE_M4_SZ, k4, WC_SHE_KEY_SZ,
|
||||
ret = wc_AesCmacGenerate_ex(cmac, m5, &cmacSz,
|
||||
m4, WC_SHE_M4_SZ, k4, WC_SHE_KEY_SZ,
|
||||
she->heap, she->devId);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
she->verified = 1;
|
||||
}
|
||||
|
||||
ForceZero(k3, sizeof(k3));
|
||||
ForceZero(k4, sizeof(k4));
|
||||
ForceZero(kdfInput, sizeof(kdfInput));
|
||||
@@ -633,6 +698,12 @@ int wc_SHE_GenerateM4M5(wc_SHE* she)
|
||||
/* M1/M2/M3 require generated state, M4/M5 require verified state. */
|
||||
/* Callback: asks hardware to export the key as M1-M5. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
#if defined(WOLF_CRYPTO_CB) && !defined(NO_WC_SHE_EXPORTKEY)
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Export Key — callback required */
|
||||
/* */
|
||||
/* Asks hardware to export a key slot as M1-M5 in SHE loadable format. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
int wc_SHE_ExportKey(wc_SHE* she,
|
||||
byte* m1, word32 m1Sz,
|
||||
byte* m2, word32 m2Sz,
|
||||
@@ -645,58 +716,10 @@ int wc_SHE_ExportKey(wc_SHE* she,
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Verify buffer sizes for any non-NULL pointers */
|
||||
if ((m1 != NULL && m1Sz < WC_SHE_M1_SZ) ||
|
||||
(m2 != NULL && m2Sz < WC_SHE_M2_SZ) ||
|
||||
(m3 != NULL && m3Sz < WC_SHE_M3_SZ) ||
|
||||
(m4 != NULL && m4Sz < WC_SHE_M4_SZ) ||
|
||||
(m5 != NULL && m5Sz < WC_SHE_M5_SZ)) {
|
||||
return BUFFER_E;
|
||||
}
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
if (she->devId != INVALID_DEVID) {
|
||||
int ret = wc_CryptoCb_SheExportKey(she,
|
||||
m1, m1Sz, m2, m2Sz, m3, m3Sz,
|
||||
m4, m4Sz, m5, m5Sz, ctx);
|
||||
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
|
||||
return ret;
|
||||
}
|
||||
/* fall-through to software path */
|
||||
}
|
||||
#endif
|
||||
(void)ctx;
|
||||
|
||||
/* Export M1/M2/M3 if requested */
|
||||
if (m1 != NULL || m2 != NULL || m3 != NULL) {
|
||||
if (!she->generated) {
|
||||
return BAD_STATE_E;
|
||||
}
|
||||
if (m1 != NULL) {
|
||||
XMEMCPY(m1, she->m1, WC_SHE_M1_SZ);
|
||||
}
|
||||
if (m2 != NULL) {
|
||||
XMEMCPY(m2, she->m2, WC_SHE_M2_SZ);
|
||||
}
|
||||
if (m3 != NULL) {
|
||||
XMEMCPY(m3, she->m3, WC_SHE_M3_SZ);
|
||||
}
|
||||
}
|
||||
|
||||
/* Export M4/M5 if requested */
|
||||
if (m4 != NULL || m5 != NULL) {
|
||||
if (!she->verified) {
|
||||
return BAD_STATE_E;
|
||||
}
|
||||
if (m4 != NULL) {
|
||||
XMEMCPY(m4, she->m4, WC_SHE_M4_SZ);
|
||||
}
|
||||
if (m5 != NULL) {
|
||||
XMEMCPY(m5, she->m5, WC_SHE_M5_SZ);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return wc_CryptoCb_SheExportKey(she,
|
||||
m1, m1Sz, m2, m2Sz, m3, m3Sz,
|
||||
m4, m4Sz, m5, m5Sz, ctx);
|
||||
}
|
||||
#endif /* WOLF_CRYPTO_CB && !NO_WC_SHE_EXPORTKEY */
|
||||
|
||||
#endif /* WOLFSSL_SHE */
|
||||
|
||||
+237
-70
@@ -56625,6 +56625,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t she_test(void)
|
||||
byte m4[WC_SHE_M4_SZ];
|
||||
byte m5[WC_SHE_M5_SZ];
|
||||
WC_DECLARE_VAR(she, wc_SHE, 1, HEAP_HINT);
|
||||
WC_DECLARE_VAR(she2, wc_SHE, 1, HEAP_HINT);
|
||||
|
||||
/* SHE specification test vector (from wolfHSM wh_test_she.c) */
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte sheUid[] = {
|
||||
@@ -56678,47 +56679,15 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t she_test(void)
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
/* ---- Set inputs from test vector ---- */
|
||||
ret = wc_SHE_SetUID(she, sheUid, sizeof(sheUid), NULL);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
ret = wc_SHE_SetAuthKey(she, WC_SHE_MASTER_ECU_KEY_ID,
|
||||
vectorAuthKey, sizeof(vectorAuthKey));
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
ret = wc_SHE_SetNewKey(she, 4, vectorNewKey, sizeof(vectorNewKey));
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
ret = wc_SHE_SetCounter(she, 1);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
ret = wc_SHE_SetFlags(she, 0);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* ---- Generate M1/M2/M3 ---- */
|
||||
ret = wc_SHE_GenerateM1M2M3(she);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* ---- Export M1/M2/M3 ---- */
|
||||
ret = wc_SHE_ExportKey(she,
|
||||
m1, WC_SHE_M1_SZ,
|
||||
m2, WC_SHE_M2_SZ,
|
||||
m3, WC_SHE_M3_SZ,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
NULL);
|
||||
/* ---- Generate M1/M2/M3 from test vector inputs ---- */
|
||||
ret = wc_SHE_GenerateM1M2M3(she,
|
||||
sheUid, sizeof(sheUid),
|
||||
WC_SHE_MASTER_ECU_KEY_ID, vectorAuthKey, sizeof(vectorAuthKey),
|
||||
4, vectorNewKey, sizeof(vectorNewKey),
|
||||
1, 0,
|
||||
m1, WC_SHE_M1_SZ,
|
||||
m2, WC_SHE_M2_SZ,
|
||||
m3, WC_SHE_M3_SZ);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
@@ -56741,20 +56710,19 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t she_test(void)
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* ---- Compute M4/M5 ---- */
|
||||
ret = wc_SHE_GenerateM4M5(she);
|
||||
/* ---- Compute and export M4/M5 ---- */
|
||||
wc_SHE_Free(she);
|
||||
ret = wc_SHE_Init(she, HEAP_HINT, devId);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* ---- Export M4/M5 ---- */
|
||||
ret = wc_SHE_ExportKey(she,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
m4, WC_SHE_M4_SZ,
|
||||
m5, WC_SHE_M5_SZ,
|
||||
NULL);
|
||||
ret = wc_SHE_GenerateM4M5(she,
|
||||
sheUid, sizeof(sheUid),
|
||||
WC_SHE_MASTER_ECU_KEY_ID, 4,
|
||||
vectorNewKey, sizeof(vectorNewKey),
|
||||
1,
|
||||
m4, WC_SHE_M4_SZ,
|
||||
m5, WC_SHE_M5_SZ);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
@@ -56771,9 +56739,160 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t she_test(void)
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* ---- Import M1/M2/M3 and generate M4/M5 (only NewKey needed) ---- */
|
||||
wc_SHE_Free(she);
|
||||
ret = wc_SHE_Init(she, HEAP_HINT, devId);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* Import M1/M2/M3, then generate M4/M5 via one-shot */
|
||||
ret = wc_SHE_ImportM1M2M3(she,
|
||||
expM1, WC_SHE_M1_SZ,
|
||||
expM2, WC_SHE_M2_SZ,
|
||||
expM3, WC_SHE_M3_SZ);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
ret = wc_SHE_GenerateM4M5(she,
|
||||
sheUid, sizeof(sheUid),
|
||||
WC_SHE_MASTER_ECU_KEY_ID, 4,
|
||||
vectorNewKey, sizeof(vectorNewKey),
|
||||
1,
|
||||
m4, WC_SHE_M4_SZ,
|
||||
m5, WC_SHE_M5_SZ);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
if (XMEMCMP(m4, expM4, WC_SHE_M4_SZ) != 0) {
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
if (XMEMCMP(m5, expM5, WC_SHE_M5_SZ) != 0) {
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* ---- One-shot M1/M2/M3 ---- */
|
||||
wc_SHE_Free(she);
|
||||
ret = wc_SHE_Init(she, HEAP_HINT, devId);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
ret = wc_SHE_GenerateM1M2M3(she,
|
||||
sheUid, sizeof(sheUid),
|
||||
WC_SHE_MASTER_ECU_KEY_ID, vectorAuthKey, sizeof(vectorAuthKey),
|
||||
4, vectorNewKey, sizeof(vectorNewKey),
|
||||
1, 0,
|
||||
m1, WC_SHE_M1_SZ,
|
||||
m2, WC_SHE_M2_SZ,
|
||||
m3, WC_SHE_M3_SZ);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
if (XMEMCMP(m1, expM1, WC_SHE_M1_SZ) != 0) {
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
if (XMEMCMP(m2, expM2, WC_SHE_M2_SZ) != 0) {
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
if (XMEMCMP(m3, expM3, WC_SHE_M3_SZ) != 0) {
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* ---- One-shot M4/M5 ---- */
|
||||
wc_SHE_Free(she);
|
||||
ret = wc_SHE_Init(she, HEAP_HINT, devId);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
ret = wc_SHE_GenerateM4M5(she,
|
||||
sheUid, sizeof(sheUid),
|
||||
WC_SHE_MASTER_ECU_KEY_ID, 4,
|
||||
vectorNewKey, sizeof(vectorNewKey),
|
||||
1,
|
||||
m4, WC_SHE_M4_SZ,
|
||||
m5, WC_SHE_M5_SZ);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
if (XMEMCMP(m4, expM4, WC_SHE_M4_SZ) != 0) {
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
if (XMEMCMP(m5, expM5, WC_SHE_M5_SZ) != 0) {
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* ---- Independence test: two separate contexts, M1M2M3 and M4M5 ---- */
|
||||
wc_SHE_Free(she);
|
||||
ret = wc_SHE_Init(she, HEAP_HINT, devId);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
WC_ALLOC_VAR(she2, wc_SHE, 1, HEAP_HINT);
|
||||
if (!WC_VAR_OK(she2)) {
|
||||
ret = WC_TEST_RET_ENC_EC(MEMORY_E);
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
ret = wc_SHE_Init(she2, HEAP_HINT, devId);
|
||||
if (ret != 0) {
|
||||
WC_FREE_VAR(she2, HEAP_HINT);
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* Generate M1/M2/M3 on first context */
|
||||
ret = wc_SHE_GenerateM1M2M3(she,
|
||||
sheUid, sizeof(sheUid),
|
||||
WC_SHE_MASTER_ECU_KEY_ID, vectorAuthKey, sizeof(vectorAuthKey),
|
||||
4, vectorNewKey, sizeof(vectorNewKey),
|
||||
1, 0,
|
||||
m1, WC_SHE_M1_SZ, m2, WC_SHE_M2_SZ, m3, WC_SHE_M3_SZ);
|
||||
if (ret != 0) {
|
||||
wc_SHE_Free(she2);
|
||||
WC_FREE_VAR(she2, HEAP_HINT);
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* Generate M4/M5 on second context — completely independent */
|
||||
ret = wc_SHE_GenerateM4M5(she2,
|
||||
sheUid, sizeof(sheUid),
|
||||
WC_SHE_MASTER_ECU_KEY_ID, 4,
|
||||
vectorNewKey, sizeof(vectorNewKey),
|
||||
1,
|
||||
m4, WC_SHE_M4_SZ, m5, WC_SHE_M5_SZ);
|
||||
|
||||
wc_SHE_Free(she2);
|
||||
WC_FREE_VAR(she2, HEAP_HINT);
|
||||
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* Verify both match the test vector */
|
||||
if (XMEMCMP(m1, expM1, WC_SHE_M1_SZ) != 0 ||
|
||||
XMEMCMP(m2, expM2, WC_SHE_M2_SZ) != 0 ||
|
||||
XMEMCMP(m3, expM3, WC_SHE_M3_SZ) != 0 ||
|
||||
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;
|
||||
}
|
||||
|
||||
exit_SHE_Test:
|
||||
wc_SHE_Free(she);
|
||||
WC_FREE_VAR(she, HEAP_HINT);
|
||||
WC_FREE_VAR(she2, HEAP_HINT);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -67356,28 +67475,76 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
|
||||
|
||||
switch (info->she.type) {
|
||||
case WC_SHE_SET_UID:
|
||||
ret = wc_SHE_SetUID(she, info->she.op.setUid.uid,
|
||||
info->she.op.setUid.uidSz,
|
||||
info->she.ctx);
|
||||
/* Test callback: just acknowledge, UID is in caller's buffer */
|
||||
ret = 0;
|
||||
break;
|
||||
case WC_SHE_GET_COUNTER:
|
||||
{
|
||||
static word32 simCounter = 0;
|
||||
if (info->she.op.getCounter.counter != NULL) {
|
||||
*info->she.op.getCounter.counter = ++simCounter;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
case WC_SHE_GENERATE_M1M2M3:
|
||||
/* Re-call with software devId using params from callback */
|
||||
ret = wc_SHE_GenerateM1M2M3(she,
|
||||
info->she.op.generateM1M2M3.uid,
|
||||
info->she.op.generateM1M2M3.uidSz,
|
||||
info->she.op.generateM1M2M3.authKeyId,
|
||||
info->she.op.generateM1M2M3.authKey,
|
||||
info->she.op.generateM1M2M3.authKeySz,
|
||||
info->she.op.generateM1M2M3.targetKeyId,
|
||||
info->she.op.generateM1M2M3.newKey,
|
||||
info->she.op.generateM1M2M3.newKeySz,
|
||||
info->she.op.generateM1M2M3.counter,
|
||||
info->she.op.generateM1M2M3.flags,
|
||||
info->she.op.generateM1M2M3.m1,
|
||||
info->she.op.generateM1M2M3.m1Sz,
|
||||
info->she.op.generateM1M2M3.m2,
|
||||
info->she.op.generateM1M2M3.m2Sz,
|
||||
info->she.op.generateM1M2M3.m3,
|
||||
info->she.op.generateM1M2M3.m3Sz);
|
||||
break;
|
||||
case WC_SHE_GENERATE_M4M5:
|
||||
/* Re-call with software devId — fills she->m4/m5 */
|
||||
ret = wc_SHE_GenerateM4M5(she);
|
||||
/* Re-call with software devId using params from callback */
|
||||
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:
|
||||
/* Fall back to software export */
|
||||
ret = wc_SHE_ExportKey(she,
|
||||
info->she.op.exportKey.m1,
|
||||
info->she.op.exportKey.m1Sz,
|
||||
info->she.op.exportKey.m2,
|
||||
info->she.op.exportKey.m2Sz,
|
||||
info->she.op.exportKey.m3,
|
||||
info->she.op.exportKey.m3Sz,
|
||||
info->she.op.exportKey.m4,
|
||||
info->she.op.exportKey.m4Sz,
|
||||
info->she.op.exportKey.m5,
|
||||
info->she.op.exportKey.m5Sz,
|
||||
info->she.ctx);
|
||||
/* 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);
|
||||
}
|
||||
if (info->she.op.exportKey.m2 != NULL) {
|
||||
XMEMSET(info->she.op.exportKey.m2, 0x22,
|
||||
WC_SHE_M2_SZ);
|
||||
}
|
||||
if (info->she.op.exportKey.m3 != NULL) {
|
||||
XMEMSET(info->she.op.exportKey.m3, 0x33,
|
||||
WC_SHE_M3_SZ);
|
||||
}
|
||||
if (info->she.op.exportKey.m4 != NULL) {
|
||||
XMEMSET(info->she.op.exportKey.m4, 0x44,
|
||||
WC_SHE_M4_SZ);
|
||||
}
|
||||
if (info->she.op.exportKey.m5 != NULL) {
|
||||
XMEMSET(info->she.op.exportKey.m5, 0x55,
|
||||
WC_SHE_M5_SZ);
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN);
|
||||
|
||||
@@ -488,19 +488,53 @@ typedef struct wc_CryptoInfo {
|
||||
const void* ctx; /* read-only caller context */
|
||||
union {
|
||||
struct {
|
||||
const byte* uid; /* caller-provided UID (may be NULL) */
|
||||
word32 uidSz; /* size of uid buffer */
|
||||
const byte* uid;
|
||||
word32 uidSz;
|
||||
} setUid;
|
||||
struct {
|
||||
byte* m1; /* output: M1 */
|
||||
word32* counter;
|
||||
} getCounter;
|
||||
struct {
|
||||
const byte* uid;
|
||||
word32 uidSz;
|
||||
byte authKeyId;
|
||||
const byte* authKey;
|
||||
word32 authKeySz;
|
||||
byte targetKeyId;
|
||||
const byte* newKey;
|
||||
word32 newKeySz;
|
||||
word32 counter;
|
||||
byte flags;
|
||||
byte* m1;
|
||||
word32 m1Sz;
|
||||
byte* m2; /* output: M2 */
|
||||
byte* m2;
|
||||
word32 m2Sz;
|
||||
byte* m3; /* output: M3 */
|
||||
byte* m3;
|
||||
word32 m3Sz;
|
||||
byte* m4; /* output: M4 */
|
||||
} generateM1M2M3;
|
||||
struct {
|
||||
const byte* uid;
|
||||
word32 uidSz;
|
||||
byte authKeyId;
|
||||
byte targetKeyId;
|
||||
const byte* newKey;
|
||||
word32 newKeySz;
|
||||
word32 counter;
|
||||
byte* m4;
|
||||
word32 m4Sz;
|
||||
byte* m5; /* output: M5 */
|
||||
byte* m5;
|
||||
word32 m5Sz;
|
||||
} generateM4M5;
|
||||
struct {
|
||||
byte* m1;
|
||||
word32 m1Sz;
|
||||
byte* m2;
|
||||
word32 m2Sz;
|
||||
byte* m3;
|
||||
word32 m3Sz;
|
||||
byte* m4;
|
||||
word32 m4Sz;
|
||||
byte* m5;
|
||||
word32 m5Sz;
|
||||
} exportKey;
|
||||
} op;
|
||||
@@ -830,10 +864,23 @@ WOLFSSL_LOCAL int wc_CryptoCb_Cmac(Cmac* cmac, const byte* key, word32 keySz,
|
||||
#ifdef WOLFSSL_SHE
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_SheSetUid(wc_SHE* she, const byte* uid,
|
||||
word32 uidSz, const void* ctx);
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_SheGetCounter(wc_SHE* she, word32* counter,
|
||||
const void* ctx);
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_SheGenerateM1M2M3(wc_SHE* she,
|
||||
const void* ctx);
|
||||
const byte* uid, word32 uidSz,
|
||||
byte authKeyId, const byte* authKey, word32 authKeySz,
|
||||
byte targetKeyId, const byte* newKey, word32 newKeySz,
|
||||
word32 counter, byte flags,
|
||||
byte* m1, word32 m1Sz,
|
||||
byte* m2, word32 m2Sz,
|
||||
byte* m3, word32 m3Sz);
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_SheGenerateM4M5(wc_SHE* she,
|
||||
const void* ctx);
|
||||
const byte* uid, word32 uidSz,
|
||||
byte authKeyId, byte targetKeyId,
|
||||
const byte* newKey, word32 newKeySz,
|
||||
word32 counter,
|
||||
byte* m4, word32 m4Sz,
|
||||
byte* m5, word32 m5Sz);
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_SheExportKey(wc_SHE* she,
|
||||
byte* m1, word32 m1Sz,
|
||||
byte* m2, word32 m2Sz,
|
||||
|
||||
+69
-51
@@ -46,9 +46,10 @@
|
||||
/* crypto callback sub-types for WC_ALGO_TYPE_SHE */
|
||||
enum wc_SheType {
|
||||
WC_SHE_SET_UID = 1,
|
||||
WC_SHE_GENERATE_M1M2M3 = 2,
|
||||
WC_SHE_GENERATE_M4M5 = 3,
|
||||
WC_SHE_EXPORT_KEY = 4
|
||||
WC_SHE_GET_COUNTER = 2,
|
||||
WC_SHE_GENERATE_M1M2M3 = 3,
|
||||
WC_SHE_GENERATE_M4M5 = 4,
|
||||
WC_SHE_EXPORT_KEY = 5
|
||||
};
|
||||
|
||||
/* test flags (only used for KATs) */
|
||||
@@ -93,29 +94,26 @@ enum {
|
||||
};
|
||||
|
||||
typedef struct wc_SHE {
|
||||
byte uid[WC_SHE_UID_SZ];
|
||||
byte authKeyId;
|
||||
byte targetKeyId;
|
||||
byte authKey[WC_SHE_KEY_SZ];
|
||||
byte newKey[WC_SHE_KEY_SZ];
|
||||
word32 counter;
|
||||
byte flags;
|
||||
|
||||
byte kdfEncC[WC_SHE_KEY_SZ]; /* KDF encryption constant (CENC) */
|
||||
byte kdfMacC[WC_SHE_KEY_SZ]; /* KDF authentication constant (CMAC) */
|
||||
byte m2pHeader[WC_SHE_KEY_SZ]; /* M2P cleartext header (counter|flags|pad) */
|
||||
byte m4pHeader[WC_SHE_KEY_SZ]; /* M4P cleartext header (counter|pad) */
|
||||
byte m2pOverride; /* set by SetM2Header to skip auto-build */
|
||||
byte m4pOverride; /* set by SetM4Header to skip auto-build */
|
||||
#ifdef WOLFSSL_SHE_EXTENDED
|
||||
/* Custom KDF constants and header overrides.
|
||||
* Useful for some HSMs that support multiple key groups with
|
||||
* different derivation constants. */
|
||||
byte kdfEncC[WC_SHE_KEY_SZ];
|
||||
byte kdfMacC[WC_SHE_KEY_SZ];
|
||||
byte m2pHeader[WC_SHE_KEY_SZ];
|
||||
byte m4pHeader[WC_SHE_KEY_SZ];
|
||||
byte kdfEncOverride;
|
||||
byte kdfMacOverride;
|
||||
byte m2pOverride;
|
||||
byte m4pOverride;
|
||||
#endif
|
||||
|
||||
#if defined(WOLF_CRYPTO_CB) || !defined(NO_WC_SHE_IMPORT_M123)
|
||||
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 generated;
|
||||
byte verified;
|
||||
#endif
|
||||
|
||||
void* heap;
|
||||
int devId;
|
||||
@@ -143,54 +141,69 @@ WOLFSSL_API int wc_SHE_Init_Label(wc_SHE* she, const char* label,
|
||||
void* heap, int devId);
|
||||
#endif
|
||||
|
||||
/* Scrub key material and zero the context */
|
||||
/* Scrub and zero the context */
|
||||
WOLFSSL_API void wc_SHE_Free(wc_SHE* she);
|
||||
|
||||
/* Set UID; callback optional (WC_SHE_SET_UID) */
|
||||
WOLFSSL_API int wc_SHE_SetUID(wc_SHE* she, const byte* uid, word32 uidSz,
|
||||
/* Get UID from hardware; callback required (WC_SHE_SET_UID) */
|
||||
#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
|
||||
|
||||
/* Set authorizing key slot ID and value */
|
||||
WOLFSSL_API int wc_SHE_SetAuthKey(wc_SHE* she, byte authKeyId,
|
||||
const byte* authKey, word32 keySz);
|
||||
/* Get counter from hardware; callback required */
|
||||
#if defined(WOLF_CRYPTO_CB) && !defined(NO_WC_SHE_GETCOUNTER)
|
||||
WOLFSSL_API int wc_SHE_GetCounter(wc_SHE* she, word32* counter,
|
||||
const void* ctx);
|
||||
#endif
|
||||
|
||||
/* Set target key slot ID and new key value */
|
||||
WOLFSSL_API int wc_SHE_SetNewKey(wc_SHE* she, byte targetKeyId,
|
||||
const byte* newKey, word32 keySz);
|
||||
|
||||
/* Set monotonic counter value for M2 */
|
||||
WOLFSSL_API int wc_SHE_SetCounter(wc_SHE* she, word32 counter);
|
||||
|
||||
/* Set flag byte for M2 */
|
||||
WOLFSSL_API int wc_SHE_SetFlags(wc_SHE* she, byte flags);
|
||||
|
||||
/* Set KDF constants (CENC/CMAC) used for key derivation.
|
||||
* Defaults are set by Init. Either pointer may be NULL to skip. */
|
||||
/* Custom KDF constants and header overrides.
|
||||
* 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. */
|
||||
WOLFSSL_API int wc_SHE_SetKdfConstants(wc_SHE* she,
|
||||
const byte* encC, word32 encCSz,
|
||||
const byte* macC, word32 macCSz);
|
||||
|
||||
/* Override M2P cleartext header (first 16 bytes before KID').
|
||||
* Skips auto-build from counter/flags in GenerateM1M2M3. */
|
||||
/* Override M2P cleartext header. Skips auto-build from counter/flags. */
|
||||
WOLFSSL_API int wc_SHE_SetM2Header(wc_SHE* she,
|
||||
const byte* header, word32 headerSz);
|
||||
|
||||
/* Override M4P cleartext header (16-byte counter block).
|
||||
* Skips auto-build from counter in GenerateM4M5. */
|
||||
/* Override M4P cleartext header. Skips auto-build from counter. */
|
||||
WOLFSSL_API int wc_SHE_SetM4Header(wc_SHE* she,
|
||||
const byte* header, word32 headerSz);
|
||||
#endif /* WOLFSSL_SHE_EXTENDED */
|
||||
|
||||
/* Generate M1/M2/M3 from the current context */
|
||||
WOLFSSL_API int wc_SHE_GenerateM1M2M3(wc_SHE* she);
|
||||
/* Import externally-provided M1/M2/M3 into context; sets generated flag */
|
||||
#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,
|
||||
const byte* m2, word32 m2Sz,
|
||||
const byte* m3, word32 m3Sz);
|
||||
#endif
|
||||
|
||||
/* Miyaguchi-Preneel AES-128 compression (internal, exposed for testing) */
|
||||
WOLFSSL_TEST_VIS int wc_She_AesMp16(Aes* aes, const byte* in, word32 inSz,
|
||||
byte* out);
|
||||
/* Generate M1/M2/M3 and write to caller buffers */
|
||||
WOLFSSL_API int wc_SHE_GenerateM1M2M3(wc_SHE* she,
|
||||
const byte* uid, word32 uidSz,
|
||||
byte authKeyId, const byte* authKey, word32 authKeySz,
|
||||
byte targetKeyId, const byte* newKey, word32 newKeySz,
|
||||
word32 counter, byte flags,
|
||||
byte* m1, word32 m1Sz,
|
||||
byte* m2, word32 m2Sz,
|
||||
byte* m3, word32 m3Sz);
|
||||
|
||||
/* Generate M4/M5 verification messages; callback optional (WC_SHE_GENERATE_M4M5) */
|
||||
WOLFSSL_API int wc_SHE_GenerateM4M5(wc_SHE* she);
|
||||
/* Generate M4/M5 and write to caller buffers */
|
||||
WOLFSSL_API int wc_SHE_GenerateM4M5(wc_SHE* she,
|
||||
const byte* uid, word32 uidSz,
|
||||
byte authKeyId, byte targetKeyId,
|
||||
const byte* newKey, word32 newKeySz,
|
||||
word32 counter,
|
||||
byte* m4, word32 m4Sz,
|
||||
byte* m5, word32 m5Sz);
|
||||
|
||||
/* Export M1-M5 into caller buffers; NULL to skip; callback optional (WC_SHE_EXPORT_KEY) */
|
||||
/* Export key from hardware as M1-M5; callback required.
|
||||
* Some HSMs allow exporting certain key slots (e.g. RAM key) in SHE format. */
|
||||
#if defined(WOLF_CRYPTO_CB) && !defined(NO_WC_SHE_EXPORTKEY)
|
||||
WOLFSSL_API int wc_SHE_ExportKey(wc_SHE* she,
|
||||
byte* m1, word32 m1Sz,
|
||||
byte* m2, word32 m2Sz,
|
||||
@@ -198,6 +211,11 @@ WOLFSSL_API int wc_SHE_ExportKey(wc_SHE* she,
|
||||
byte* m4, word32 m4Sz,
|
||||
byte* m5, word32 m5Sz,
|
||||
const void* ctx);
|
||||
#endif
|
||||
|
||||
/* Internal: Miyaguchi-Preneel AES-128 compression, exposed for testing */
|
||||
WOLFSSL_TEST_VIS int wc_She_AesMp16(Aes* aes, const byte* in, word32 inSz,
|
||||
byte* out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
Reference in New Issue
Block a user