mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 09:10:53 +02:00
Merge pull request #10009 from night1rider/SHE-update
Add SHE (Secure Hardware Extension) support to wolfCrypt
This commit is contained in:
@@ -42,6 +42,15 @@ jobs:
|
||||
'--enable-dtls --enable-dtlscid --enable-dtls13 --enable-secure-renegotiation
|
||||
--enable-psk --enable-aesccm --enable-nullcipher
|
||||
CPPFLAGS=-DWOLFSSL_STATIC_RSA',
|
||||
'--enable-she=extended --enable-cryptocb --enable-cryptocbutils
|
||||
CPPFLAGS=''-DWC_SHE_SW_DEFAULT'' ',
|
||||
'--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-she=standard --enable-cmac --enable-cryptocb --enable-cryptocbutils
|
||||
CPPFLAGS=''-DWC_SHE_SW_DEFAULT'' ',
|
||||
'--enable-all CPPFLAGS=''-DNO_AES_192 -DNO_AES_256'' ',
|
||||
'--enable-sniffer --enable-curve25519 --enable-curve448 --enable-enckeys
|
||||
CPPFLAGS=-DWOLFSSL_DH_EXTRA',
|
||||
|
||||
@@ -446,6 +446,7 @@ NO_TKERNEL_MEM_POOL
|
||||
NO_TLSX_PSKKEM_PLAIN_ANNOUNCE
|
||||
NO_VERIFY_OID
|
||||
NO_WC_DHGENERATEPUBLIC
|
||||
NO_WC_SHE_LOADKEY
|
||||
NO_WC_SSIZE_TYPE
|
||||
NO_WOLFSSL_ALLOC_ALIGN
|
||||
NO_WOLFSSL_AUTOSAR_CRYIF
|
||||
|
||||
@@ -1640,6 +1640,30 @@ if(WOLFSSL_CMAC)
|
||||
endif()
|
||||
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 (standard|extended|no)"
|
||||
"no" "standard;extended;no")
|
||||
|
||||
if(WOLFSSL_SHE STREQUAL "standard" OR WOLFSSL_SHE STREQUAL "extended")
|
||||
if (NOT WOLFSSL_AES)
|
||||
message(FATAL_ERROR "Cannot use SHE without AES.")
|
||||
else()
|
||||
list(APPEND WOLFSSL_DEFINITIONS
|
||||
"-DWOLFSSL_SHE"
|
||||
"-DWOLFSSL_CMAC"
|
||||
"-DWOLFSSL_AES_DIRECT")
|
||||
override_cache(WOLFSSL_CMAC "yes")
|
||||
override_cache(WOLFSSL_AESCBC "yes")
|
||||
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
|
||||
@@ -2816,6 +2840,7 @@ if(WOLFSSL_EXAMPLES)
|
||||
tests/api/test_hash.c
|
||||
tests/api/test_hmac.c
|
||||
tests/api/test_cmac.c
|
||||
tests/api/test_she.c
|
||||
tests/api/test_des3.c
|
||||
tests/api/test_chacha.c
|
||||
tests/api/test_poly1305.c
|
||||
|
||||
@@ -345,6 +345,9 @@ function(generate_build_flags)
|
||||
if(WOLFSSL_HPKE OR WOLFSSL_USER_SETTINGS)
|
||||
set(BUILD_HPKE "yes" PARENT_SCOPE)
|
||||
endif()
|
||||
if(WOLFSSL_SHE AND NOT WOLFSSL_SHE STREQUAL "no")
|
||||
set(BUILD_SHE "yes" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
set(BUILD_FLAGS_GENERATED "yes" PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -1150,6 +1153,10 @@ function(generate_lib_src_list LIB_SOURCES)
|
||||
list(APPEND LIB_SOURCES wolfcrypt/src/cryptocb.c)
|
||||
endif()
|
||||
|
||||
if(BUILD_SHE)
|
||||
list(APPEND LIB_SOURCES wolfcrypt/src/wc_she.c)
|
||||
endif()
|
||||
|
||||
if(BUILD_PKCS11)
|
||||
list(APPEND LIB_SOURCES wolfcrypt/src/wc_pkcs11.c)
|
||||
endif()
|
||||
|
||||
@@ -5945,6 +5945,31 @@ fi
|
||||
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@<:@=standard|extended@:>@],
|
||||
[Enable SHE key update support (default: disabled)])],
|
||||
[ ENABLED_SHE=$enableval ],
|
||||
[ ENABLED_SHE=no ]
|
||||
)
|
||||
|
||||
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
|
||||
fi
|
||||
|
||||
if test "x$ENABLED_SHE" = "xextended"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHE_EXTENDED"
|
||||
fi
|
||||
|
||||
# AES-XTS
|
||||
AC_ARG_ENABLE([aesxts],
|
||||
@@ -11555,6 +11580,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" = "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"])
|
||||
|
||||
@@ -159,6 +159,10 @@ if BUILD_CMAC
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/cmac.c
|
||||
endif
|
||||
|
||||
if BUILD_SHE
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_she.c
|
||||
endif
|
||||
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fips.c \
|
||||
wolfcrypt/src/fips_test.c
|
||||
|
||||
@@ -424,6 +428,10 @@ if BUILD_CMAC
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/cmac.c
|
||||
endif
|
||||
|
||||
if BUILD_SHE
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_she.c
|
||||
endif
|
||||
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fips.c \
|
||||
wolfcrypt/src/fips_test.c
|
||||
|
||||
@@ -677,6 +685,10 @@ if BUILD_CMAC
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/cmac.c
|
||||
endif
|
||||
|
||||
if BUILD_SHE
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_she.c
|
||||
endif
|
||||
|
||||
if BUILD_CURVE448
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/curve448.c
|
||||
endif
|
||||
@@ -1009,6 +1021,10 @@ if !BUILD_FIPS_V2_PLUS
|
||||
if BUILD_CMAC
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/cmac.c
|
||||
endif
|
||||
|
||||
if BUILD_SHE
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_she.c
|
||||
endif
|
||||
endif !BUILD_FIPS_V2_PLUS
|
||||
|
||||
if !BUILD_FIPS_V2
|
||||
|
||||
@@ -202,6 +202,7 @@
|
||||
#include <tests/api/test_hash.h>
|
||||
#include <tests/api/test_hmac.h>
|
||||
#include <tests/api/test_cmac.h>
|
||||
#include <tests/api/test_she.h>
|
||||
#include <tests/api/test_des3.h>
|
||||
#include <tests/api/test_chacha.h>
|
||||
#include <tests/api/test_poly1305.h>
|
||||
@@ -35682,6 +35683,14 @@ TEST_CASE testCases[] = {
|
||||
TEST_HMAC_DECLS,
|
||||
/* CMAC */
|
||||
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
|
||||
|
||||
/* Cipher */
|
||||
/* Triple-DES */
|
||||
|
||||
@@ -18,6 +18,8 @@ tests_unit_test_SOURCES += tests/api/test_hash.c
|
||||
# MAC
|
||||
tests_unit_test_SOURCES += tests/api/test_hmac.c
|
||||
tests_unit_test_SOURCES += tests/api/test_cmac.c
|
||||
# SHE
|
||||
tests_unit_test_SOURCES += tests/api/test_she.c
|
||||
# Cipher
|
||||
tests_unit_test_SOURCES += tests/api/test_des3.c
|
||||
tests_unit_test_SOURCES += tests/api/test_chacha.c
|
||||
@@ -124,6 +126,7 @@ EXTRA_DIST += tests/api/test_digest.h
|
||||
EXTRA_DIST += tests/api/test_hash.h
|
||||
EXTRA_DIST += tests/api/test_hmac.h
|
||||
EXTRA_DIST += tests/api/test_cmac.h
|
||||
EXTRA_DIST += tests/api/test_she.h
|
||||
EXTRA_DIST += tests/api/test_des3.h
|
||||
EXTRA_DIST += tests/api/test_chacha.h
|
||||
EXTRA_DIST += tests/api/test_poly1305.h
|
||||
|
||||
@@ -0,0 +1,768 @@
|
||||
/* test_she.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 <tests/unit.h>
|
||||
|
||||
#ifdef NO_INLINE
|
||||
#include <wolfssl/wolfcrypt/misc.h>
|
||||
#else
|
||||
#define WOLFSSL_MISC_INCLUDED
|
||||
#include <wolfcrypt/src/misc.c>
|
||||
#endif
|
||||
|
||||
#include <wolfssl/wolfcrypt/wc_she.h>
|
||||
#include <wolfssl/wolfcrypt/types.h>
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
#include <wolfssl/wolfcrypt/cryptocb.h>
|
||||
#endif
|
||||
#include <tests/api/api.h>
|
||||
#include <tests/api/test_she.h>
|
||||
|
||||
/* Common test vector data */
|
||||
#if defined(WOLFSSL_SHE) && !defined(NO_AES)
|
||||
static const byte sheTestUid[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
|
||||
};
|
||||
static const byte sheTestAuthKey[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
|
||||
};
|
||||
static const byte sheTestNewKey[] = {
|
||||
0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
|
||||
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
|
||||
};
|
||||
static const byte sheTestExpM1[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41
|
||||
};
|
||||
static const byte sheTestExpM4[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41,
|
||||
0xb4, 0x72, 0xe8, 0xd8, 0x72, 0x7d, 0x70, 0xd5,
|
||||
0x72, 0x95, 0xe7, 0x48, 0x49, 0xa2, 0x79, 0x17
|
||||
};
|
||||
static const byte sheTestExpM5[] = {
|
||||
0x82, 0x0d, 0x8d, 0x95, 0xdc, 0x11, 0xb4, 0x66,
|
||||
0x88, 0x78, 0x16, 0x0c, 0xb2, 0xa4, 0xe2, 0x3e
|
||||
};
|
||||
#endif
|
||||
|
||||
int test_wc_SHE_Init(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_SHE) && !defined(NO_AES)
|
||||
wc_SHE she;
|
||||
|
||||
ExpectIntEQ(wc_SHE_Init(&she, NULL, INVALID_DEVID), 0);
|
||||
ExpectTrue(she.heap == NULL);
|
||||
ExpectIntEQ(she.devId, INVALID_DEVID);
|
||||
wc_SHE_Free(&she);
|
||||
|
||||
ExpectIntEQ(wc_SHE_Init(NULL, NULL, INVALID_DEVID),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_wc_SHE_Init_Id(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_SHE) && !defined(NO_AES) && defined(WOLF_PRIVATE_KEY_ID)
|
||||
wc_SHE she;
|
||||
unsigned char testId[] = {0x01, 0x02, 0x03, 0x04};
|
||||
|
||||
ExpectIntEQ(wc_SHE_Init_Id(&she, testId, (int)sizeof(testId),
|
||||
NULL, INVALID_DEVID), 0);
|
||||
ExpectIntEQ(she.idLen, (int)sizeof(testId));
|
||||
wc_SHE_Free(&she);
|
||||
|
||||
ExpectIntEQ(wc_SHE_Init_Id(NULL, testId, (int)sizeof(testId),
|
||||
NULL, INVALID_DEVID),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
ExpectIntEQ(wc_SHE_Init_Id(&she, testId, WC_SHE_MAX_ID_LEN + 1,
|
||||
NULL, INVALID_DEVID),
|
||||
WC_NO_ERR_TRACE(BUFFER_E));
|
||||
ExpectIntEQ(wc_SHE_Init_Id(&she, testId, -1, NULL, INVALID_DEVID),
|
||||
WC_NO_ERR_TRACE(BUFFER_E));
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_wc_SHE_Init_Label(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_SHE) && !defined(NO_AES) && defined(WOLF_PRIVATE_KEY_ID)
|
||||
wc_SHE she;
|
||||
|
||||
ExpectIntEQ(wc_SHE_Init_Label(&she, "test", NULL, INVALID_DEVID), 0);
|
||||
ExpectIntEQ(she.labelLen, 4);
|
||||
wc_SHE_Free(&she);
|
||||
|
||||
ExpectIntEQ(wc_SHE_Init_Label(NULL, "test", NULL, INVALID_DEVID),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
ExpectIntEQ(wc_SHE_Init_Label(&she, NULL, NULL, INVALID_DEVID),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
ExpectIntEQ(wc_SHE_Init_Label(&she, "", NULL, INVALID_DEVID),
|
||||
WC_NO_ERR_TRACE(BUFFER_E));
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_wc_SHE_Free(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_SHE) && !defined(NO_AES)
|
||||
wc_SHE she;
|
||||
|
||||
ExpectIntEQ(wc_SHE_Init(&she, NULL, INVALID_DEVID), 0);
|
||||
wc_SHE_Free(&she);
|
||||
ExpectIntEQ(she.devId, 0);
|
||||
|
||||
wc_SHE_Free(NULL);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_wc_SHE_ImportM1M2M3(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_SHE) && !defined(NO_AES) && \
|
||||
(defined(WOLF_CRYPTO_CB) && !defined(NO_WC_SHE_IMPORT_M123))
|
||||
wc_SHE she;
|
||||
byte m1[WC_SHE_M1_SZ] = {0};
|
||||
byte m2[WC_SHE_M2_SZ] = {0};
|
||||
byte m3[WC_SHE_M3_SZ] = {0};
|
||||
|
||||
ExpectIntEQ(wc_SHE_Init(&she, NULL, INVALID_DEVID), 0);
|
||||
ExpectIntEQ(wc_SHE_ImportM1M2M3(&she,
|
||||
m1, WC_SHE_M1_SZ, m2, WC_SHE_M2_SZ, m3, WC_SHE_M3_SZ), 0);
|
||||
ExpectIntEQ(she.generated, 1);
|
||||
|
||||
ExpectIntEQ(wc_SHE_ImportM1M2M3(NULL,
|
||||
m1, WC_SHE_M1_SZ, m2, WC_SHE_M2_SZ, m3, WC_SHE_M3_SZ),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
ExpectIntEQ(wc_SHE_ImportM1M2M3(&she,
|
||||
m1, WC_SHE_M1_SZ - 1, m2, WC_SHE_M2_SZ, m3, WC_SHE_M3_SZ),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
|
||||
wc_SHE_Free(&she);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_wc_SHE_AesMp16(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_SHE) && !defined(NO_AES)
|
||||
Aes aes;
|
||||
byte out[WC_SHE_KEY_SZ];
|
||||
byte input[WC_SHE_KEY_SZ * 2] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x01, 0x01, 0x53, 0x48, 0x45, 0x00, 0x80, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0
|
||||
};
|
||||
byte shortInput[17] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0xAA
|
||||
};
|
||||
|
||||
ExpectIntEQ(wc_AesInit(&aes, NULL, INVALID_DEVID), 0);
|
||||
ExpectIntEQ(wc_SHE_AesMp16(&aes, input, sizeof(input), out), 0);
|
||||
|
||||
ExpectIntEQ(wc_AesInit(&aes, NULL, INVALID_DEVID), 0);
|
||||
ExpectIntEQ(wc_SHE_AesMp16(&aes, shortInput, sizeof(shortInput), out), 0);
|
||||
|
||||
ExpectIntEQ(wc_SHE_AesMp16(NULL, input, sizeof(input), out),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
ExpectIntEQ(wc_SHE_AesMp16(&aes, NULL, sizeof(input), out),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
ExpectIntEQ(wc_SHE_AesMp16(&aes, input, 0, out),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
ExpectIntEQ(wc_SHE_AesMp16(&aes, input, sizeof(input), NULL),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
|
||||
wc_AesFree(&aes);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_wc_SHE_GenerateM1M2M3(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_SHE) && !defined(NO_AES)
|
||||
wc_SHE she;
|
||||
byte m1[WC_SHE_M1_SZ];
|
||||
byte m2[WC_SHE_M2_SZ];
|
||||
byte m3[WC_SHE_M3_SZ];
|
||||
|
||||
ExpectIntEQ(wc_SHE_Init(&she, NULL, INVALID_DEVID), 0);
|
||||
|
||||
/* Generate and verify M1 against test vector */
|
||||
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);
|
||||
ExpectIntEQ(XMEMCMP(m1, sheTestExpM1, WC_SHE_M1_SZ), 0);
|
||||
|
||||
/* Bad args */
|
||||
ExpectIntEQ(wc_SHE_GenerateM1M2M3(NULL,
|
||||
sheTestUid, sizeof(sheTestUid),
|
||||
1, sheTestAuthKey, sizeof(sheTestAuthKey),
|
||||
4, sheTestNewKey, sizeof(sheTestNewKey),
|
||||
1, 0,
|
||||
m1, WC_SHE_M1_SZ, m2, WC_SHE_M2_SZ, m3, WC_SHE_M3_SZ),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
|
||||
wc_SHE_Free(&she);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_wc_SHE_GenerateM4M5(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_SHE) && !defined(NO_AES)
|
||||
wc_SHE she;
|
||||
byte m4[WC_SHE_M4_SZ];
|
||||
byte m5[WC_SHE_M5_SZ];
|
||||
|
||||
ExpectIntEQ(wc_SHE_Init(&she, NULL, INVALID_DEVID), 0);
|
||||
|
||||
/* Generate and verify against test vector */
|
||||
ExpectIntEQ(wc_SHE_GenerateM4M5(&she,
|
||||
sheTestUid, sizeof(sheTestUid),
|
||||
WC_SHE_MASTER_ECU_KEY_ID, 4,
|
||||
sheTestNewKey, sizeof(sheTestNewKey), 1,
|
||||
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 */
|
||||
ExpectIntEQ(wc_SHE_GenerateM4M5(NULL,
|
||||
sheTestUid, sizeof(sheTestUid),
|
||||
1, 4, sheTestNewKey, sizeof(sheTestNewKey), 1,
|
||||
m4, WC_SHE_M4_SZ, m5, WC_SHE_M5_SZ),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
|
||||
wc_SHE_Free(&she);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_SHE_EXTENDED) && defined(WOLFSSL_SHE) && !defined(NO_AES)
|
||||
|
||||
int test_wc_SHE_SetKdfConstants(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
wc_SHE she;
|
||||
byte m1Def[WC_SHE_M1_SZ];
|
||||
byte m2Def[WC_SHE_M2_SZ];
|
||||
byte m3Def[WC_SHE_M3_SZ];
|
||||
byte m1Cust[WC_SHE_M1_SZ];
|
||||
byte m2Cust[WC_SHE_M2_SZ];
|
||||
byte m3Cust[WC_SHE_M3_SZ];
|
||||
byte m4[WC_SHE_M4_SZ];
|
||||
byte m5[WC_SHE_M5_SZ];
|
||||
byte customEncC[WC_SHE_KEY_SZ] = {0};
|
||||
byte customMacC[WC_SHE_KEY_SZ] = {0};
|
||||
|
||||
customEncC[0] = 0xFF;
|
||||
customMacC[0] = 0xFE;
|
||||
|
||||
/* Generate with defaults */
|
||||
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,
|
||||
m1Def, WC_SHE_M1_SZ, m2Def, WC_SHE_M2_SZ,
|
||||
m3Def, WC_SHE_M3_SZ), 0);
|
||||
wc_SHE_Free(&she);
|
||||
|
||||
/* Generate with custom KDF constants */
|
||||
ExpectIntEQ(wc_SHE_Init(&she, NULL, INVALID_DEVID), 0);
|
||||
ExpectIntEQ(wc_SHE_SetKdfConstants(&she,
|
||||
customEncC, WC_SHE_KEY_SZ,
|
||||
customMacC, WC_SHE_KEY_SZ), 0);
|
||||
ExpectIntEQ(she.kdfEncOverride, 1);
|
||||
ExpectIntEQ(she.kdfMacOverride, 1);
|
||||
|
||||
ExpectIntEQ(wc_SHE_GenerateM1M2M3(&she,
|
||||
sheTestUid, sizeof(sheTestUid),
|
||||
WC_SHE_MASTER_ECU_KEY_ID, sheTestAuthKey, sizeof(sheTestAuthKey),
|
||||
4, sheTestNewKey, sizeof(sheTestNewKey), 1, 0,
|
||||
m1Cust, WC_SHE_M1_SZ, m2Cust, WC_SHE_M2_SZ,
|
||||
m3Cust, WC_SHE_M3_SZ), 0);
|
||||
|
||||
/* M1 same, M2 should differ */
|
||||
ExpectIntEQ(XMEMCMP(m1Def, m1Cust, WC_SHE_M1_SZ), 0);
|
||||
ExpectIntNE(XMEMCMP(m2Def, m2Cust, WC_SHE_M2_SZ), 0);
|
||||
|
||||
/* Bad args */
|
||||
ExpectIntEQ(wc_SHE_SetKdfConstants(NULL,
|
||||
customEncC, WC_SHE_KEY_SZ, NULL, 0),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
ExpectIntEQ(wc_SHE_SetKdfConstants(&she,
|
||||
customEncC, WC_SHE_KEY_SZ - 1, NULL, 0),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
ExpectIntEQ(wc_SHE_SetKdfConstants(&she,
|
||||
NULL, 0, customMacC, WC_SHE_KEY_SZ - 1),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
|
||||
/* Test KDF override in M4M5 path */
|
||||
ExpectIntEQ(wc_SHE_GenerateM4M5(&she,
|
||||
sheTestUid, sizeof(sheTestUid),
|
||||
WC_SHE_MASTER_ECU_KEY_ID, 4,
|
||||
sheTestNewKey, sizeof(sheTestNewKey), 1,
|
||||
m4, WC_SHE_M4_SZ, m5, WC_SHE_M5_SZ), 0);
|
||||
|
||||
wc_SHE_Free(&she);
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_wc_SHE_SetM2M4Header(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
wc_SHE she;
|
||||
byte customHeader[WC_SHE_KEY_SZ] = {0};
|
||||
byte m1Def[WC_SHE_M1_SZ];
|
||||
byte m2Def[WC_SHE_M2_SZ];
|
||||
byte m3Def[WC_SHE_M3_SZ];
|
||||
byte m1Ovr[WC_SHE_M1_SZ];
|
||||
byte m2Ovr[WC_SHE_M2_SZ];
|
||||
byte m3Ovr[WC_SHE_M3_SZ];
|
||||
byte m4Def[WC_SHE_M4_SZ];
|
||||
byte m5Def[WC_SHE_M5_SZ];
|
||||
byte m4Ovr[WC_SHE_M4_SZ];
|
||||
byte m5Ovr[WC_SHE_M5_SZ];
|
||||
|
||||
/* Bad args */
|
||||
ExpectIntEQ(wc_SHE_SetM2Header(NULL, customHeader, WC_SHE_KEY_SZ),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
ExpectIntEQ(wc_SHE_SetM4Header(NULL, customHeader, WC_SHE_KEY_SZ),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
|
||||
ExpectIntEQ(wc_SHE_Init(&she, NULL, INVALID_DEVID), 0);
|
||||
|
||||
ExpectIntEQ(wc_SHE_SetM2Header(&she, NULL, WC_SHE_KEY_SZ),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
ExpectIntEQ(wc_SHE_SetM2Header(&she, customHeader, WC_SHE_KEY_SZ - 1),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
|
||||
/* Generate M1M2M3 with defaults */
|
||||
ExpectIntEQ(wc_SHE_GenerateM1M2M3(&she,
|
||||
sheTestUid, sizeof(sheTestUid),
|
||||
WC_SHE_MASTER_ECU_KEY_ID, sheTestAuthKey, sizeof(sheTestAuthKey),
|
||||
4, sheTestNewKey, sizeof(sheTestNewKey), 1, 0,
|
||||
m1Def, WC_SHE_M1_SZ, m2Def, WC_SHE_M2_SZ,
|
||||
m3Def, WC_SHE_M3_SZ), 0);
|
||||
wc_SHE_Free(&she);
|
||||
|
||||
/* Generate with overridden M2 header */
|
||||
ExpectIntEQ(wc_SHE_Init(&she, NULL, INVALID_DEVID), 0);
|
||||
customHeader[0] = 0xFF;
|
||||
ExpectIntEQ(wc_SHE_SetM2Header(&she, customHeader, WC_SHE_KEY_SZ), 0);
|
||||
ExpectIntEQ(she.m2pOverride, 1);
|
||||
|
||||
ExpectIntEQ(wc_SHE_GenerateM1M2M3(&she,
|
||||
sheTestUid, sizeof(sheTestUid),
|
||||
WC_SHE_MASTER_ECU_KEY_ID, sheTestAuthKey, sizeof(sheTestAuthKey),
|
||||
4, sheTestNewKey, sizeof(sheTestNewKey), 1, 0,
|
||||
m1Ovr, WC_SHE_M1_SZ, m2Ovr, WC_SHE_M2_SZ,
|
||||
m3Ovr, WC_SHE_M3_SZ), 0);
|
||||
|
||||
ExpectIntEQ(XMEMCMP(m1Def, m1Ovr, WC_SHE_M1_SZ), 0);
|
||||
ExpectIntNE(XMEMCMP(m2Def, m2Ovr, WC_SHE_M2_SZ), 0);
|
||||
wc_SHE_Free(&she);
|
||||
|
||||
/* Test M4 header override */
|
||||
ExpectIntEQ(wc_SHE_Init(&she, NULL, INVALID_DEVID), 0);
|
||||
ExpectIntEQ(wc_SHE_GenerateM4M5(&she,
|
||||
sheTestUid, sizeof(sheTestUid),
|
||||
WC_SHE_MASTER_ECU_KEY_ID, 4,
|
||||
sheTestNewKey, sizeof(sheTestNewKey), 1,
|
||||
m4Def, WC_SHE_M4_SZ, m5Def, WC_SHE_M5_SZ), 0);
|
||||
wc_SHE_Free(&she);
|
||||
|
||||
ExpectIntEQ(wc_SHE_Init(&she, NULL, INVALID_DEVID), 0);
|
||||
XMEMSET(customHeader, 0xBB, WC_SHE_KEY_SZ);
|
||||
ExpectIntEQ(wc_SHE_SetM4Header(&she, customHeader, WC_SHE_KEY_SZ), 0);
|
||||
ExpectIntEQ(she.m4pOverride, 1);
|
||||
|
||||
ExpectIntEQ(wc_SHE_GenerateM4M5(&she,
|
||||
sheTestUid, sizeof(sheTestUid),
|
||||
WC_SHE_MASTER_ECU_KEY_ID, 4,
|
||||
sheTestNewKey, sizeof(sheTestNewKey), 1,
|
||||
m4Ovr, WC_SHE_M4_SZ, m5Ovr, WC_SHE_M5_SZ), 0);
|
||||
|
||||
ExpectIntNE(XMEMCMP(m4Def, m4Ovr, WC_SHE_M4_SZ), 0);
|
||||
wc_SHE_Free(&she);
|
||||
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_SHE_EXTENDED && WOLFSSL_SHE && !NO_AES */
|
||||
|
||||
#if defined(WOLF_CRYPTO_CB) && defined(WOLFSSL_SHE) && !defined(NO_AES)
|
||||
|
||||
/* SHE callback -- re-calls with software devId */
|
||||
static int test_she_crypto_cb(int devIdArg, wc_CryptoInfo* info, void* ctx)
|
||||
{
|
||||
wc_SHE* she;
|
||||
int savedDevId;
|
||||
int ret;
|
||||
|
||||
(void)ctx;
|
||||
(void)devIdArg;
|
||||
|
||||
if (info == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB_FREE
|
||||
if (info->algo_type == WC_ALGO_TYPE_FREE) {
|
||||
if (info->free.algo == WC_ALGO_TYPE_SHE) {
|
||||
she = (wc_SHE*)info->free.obj;
|
||||
she->devId = INVALID_DEVID;
|
||||
wc_SHE_Free(she);
|
||||
return 0;
|
||||
}
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (info->algo_type != WC_ALGO_TYPE_SHE) {
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
|
||||
she = (wc_SHE*)info->she.she;
|
||||
if (she == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
savedDevId = she->devId;
|
||||
she->devId = INVALID_DEVID;
|
||||
|
||||
switch (info->she.type) {
|
||||
case WC_SHE_GET_UID:
|
||||
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:
|
||||
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:
|
||||
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 */
|
||||
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(CRYPTOCB_UNAVAILABLE);
|
||||
break;
|
||||
}
|
||||
|
||||
she->devId = savedDevId;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int test_wc_SHE_CryptoCb(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
wc_SHE she;
|
||||
int sheTestDevId = 54321;
|
||||
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);
|
||||
ExpectIntEQ(wc_SHE_Init(&she, NULL, sheTestDevId), 0);
|
||||
|
||||
/* Generate M1/M2/M3 via callback */
|
||||
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);
|
||||
ExpectIntEQ(XMEMCMP(m1, sheTestExpM1, WC_SHE_M1_SZ), 0);
|
||||
|
||||
/* Generate M4/M5 via callback */
|
||||
ExpectIntEQ(wc_SHE_GenerateM4M5(&she,
|
||||
sheTestUid, sizeof(sheTestUid),
|
||||
WC_SHE_MASTER_ECU_KEY_ID, 4,
|
||||
sheTestNewKey, sizeof(sheTestNewKey), 1,
|
||||
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);
|
||||
|
||||
/* ExportKey via callback -- simulated hardware */
|
||||
#if !defined(NO_WC_SHE_EXPORTKEY)
|
||||
{
|
||||
byte em1[WC_SHE_M1_SZ];
|
||||
byte em2[WC_SHE_M2_SZ];
|
||||
byte em3[WC_SHE_M3_SZ];
|
||||
byte em4[WC_SHE_M4_SZ];
|
||||
byte em5[WC_SHE_M5_SZ];
|
||||
byte pat[WC_SHE_M1_SZ];
|
||||
|
||||
ExpectIntEQ(wc_SHE_ExportKey(&she,
|
||||
em1, WC_SHE_M1_SZ, em2, WC_SHE_M2_SZ,
|
||||
em3, WC_SHE_M3_SZ, em4, WC_SHE_M4_SZ,
|
||||
em5, WC_SHE_M5_SZ, NULL), 0);
|
||||
|
||||
/* Verify callback filled with test pattern */
|
||||
XMEMSET(pat, 0x11, WC_SHE_M1_SZ);
|
||||
ExpectIntEQ(XMEMCMP(em1, pat, WC_SHE_M1_SZ), 0);
|
||||
|
||||
/* Bad args */
|
||||
ExpectIntEQ(wc_SHE_ExportKey(NULL,
|
||||
em1, WC_SHE_M1_SZ, em2, WC_SHE_M2_SZ,
|
||||
em3, WC_SHE_M3_SZ, em4, WC_SHE_M4_SZ,
|
||||
em5, WC_SHE_M5_SZ, NULL),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(NO_WC_SHE_GETUID)
|
||||
{
|
||||
byte cbUid[WC_SHE_UID_SZ];
|
||||
ExpectIntEQ(wc_SHE_GetUID(&she, cbUid, WC_SHE_UID_SZ, NULL), 0);
|
||||
ExpectIntEQ(wc_SHE_GetUID(NULL, cbUid, WC_SHE_UID_SZ, NULL),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
ExpectIntEQ(wc_SHE_GetUID(&she, NULL, WC_SHE_UID_SZ, NULL),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(NO_WC_SHE_GETCOUNTER)
|
||||
{
|
||||
word32 cnt1 = 0;
|
||||
word32 cnt2 = 0;
|
||||
|
||||
/* Callback should return incrementing counter */
|
||||
ExpectIntEQ(wc_SHE_GetCounter(&she, &cnt1, NULL), 0);
|
||||
ExpectIntEQ(wc_SHE_GetCounter(&she, &cnt2, NULL), 0);
|
||||
ExpectTrue(cnt2 > cnt1);
|
||||
|
||||
/* Bad args */
|
||||
ExpectIntEQ(wc_SHE_GetCounter(NULL, &cnt1, NULL),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
ExpectIntEQ(wc_SHE_GetCounter(&she, NULL, NULL),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
}
|
||||
#endif
|
||||
|
||||
wc_SHE_Free(&she);
|
||||
wc_CryptoCb_UnRegisterDevice(sheTestDevId);
|
||||
|
||||
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 */
|
||||
@@ -0,0 +1,79 @@
|
||||
/* test_she.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 WOLFCRYPT_TEST_SHE_H
|
||||
#define WOLFCRYPT_TEST_SHE_H
|
||||
|
||||
#include <tests/api/api_decl.h>
|
||||
|
||||
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_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);
|
||||
#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 \
|
||||
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)
|
||||
#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
|
||||
|
||||
#endif /* WOLFCRYPT_TEST_SHE_H */
|
||||
@@ -2120,6 +2120,187 @@ int wc_CryptoCb_Cmac(Cmac* cmac, const byte* key, word32 keySz,
|
||||
}
|
||||
#endif /* WOLFSSL_CMAC */
|
||||
|
||||
#ifdef WOLFSSL_SHE
|
||||
int wc_CryptoCb_SheGetUid(wc_SHE* she, byte* uid, word32 uidSz,
|
||||
const void* ctx)
|
||||
{
|
||||
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
|
||||
CryptoCb* dev;
|
||||
|
||||
if (she == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* locate registered callback */
|
||||
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_GET_UID;
|
||||
cryptoInfo.she.ctx = ctx;
|
||||
cryptoInfo.she.op.getUid.uid = uid;
|
||||
cryptoInfo.she.op.getUid.uidSz = uidSz;
|
||||
|
||||
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
|
||||
}
|
||||
|
||||
return wc_CryptoCb_TranslateErrorCode(ret);
|
||||
}
|
||||
|
||||
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 || counter == 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_GET_COUNTER;
|
||||
cryptoInfo.she.ctx = ctx;
|
||||
cryptoInfo.she.op.getCounter.counter = counter;
|
||||
|
||||
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
|
||||
}
|
||||
|
||||
return wc_CryptoCb_TranslateErrorCode(ret);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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_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);
|
||||
}
|
||||
|
||||
return wc_CryptoCb_TranslateErrorCode(ret);
|
||||
}
|
||||
|
||||
int wc_CryptoCb_SheExportKey(wc_SHE* she,
|
||||
byte* m1, word32 m1Sz,
|
||||
byte* m2, word32 m2Sz,
|
||||
byte* m3, word32 m3Sz,
|
||||
byte* m4, word32 m4Sz,
|
||||
byte* m5, word32 m5Sz,
|
||||
const void* ctx)
|
||||
{
|
||||
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_EXPORT_KEY;
|
||||
cryptoInfo.she.ctx = ctx;
|
||||
cryptoInfo.she.op.exportKey.m1 = m1;
|
||||
cryptoInfo.she.op.exportKey.m1Sz = m1Sz;
|
||||
cryptoInfo.she.op.exportKey.m2 = m2;
|
||||
cryptoInfo.she.op.exportKey.m2Sz = m2Sz;
|
||||
cryptoInfo.she.op.exportKey.m3 = m3;
|
||||
cryptoInfo.she.op.exportKey.m3Sz = m3Sz;
|
||||
cryptoInfo.she.op.exportKey.m4 = m4;
|
||||
cryptoInfo.she.op.exportKey.m4Sz = m4Sz;
|
||||
cryptoInfo.she.op.exportKey.m5 = m5;
|
||||
cryptoInfo.she.op.exportKey.m5Sz = m5Sz;
|
||||
|
||||
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
|
||||
}
|
||||
|
||||
return wc_CryptoCb_TranslateErrorCode(ret);
|
||||
}
|
||||
#endif /* WOLFSSL_SHE */
|
||||
|
||||
/* returns the default dev id for the current build */
|
||||
int wc_CryptoCb_DefaultDevID(void)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -348,6 +348,9 @@ static const byte const_byte_array[] = "A+Gd\0\0\0";
|
||||
#include <wolfssl/wolfcrypt/aes.h>
|
||||
#include <wolfssl/wolfcrypt/wc_encrypt.h>
|
||||
#include <wolfssl/wolfcrypt/cmac.h>
|
||||
#ifdef WOLFSSL_SHE
|
||||
#include <wolfssl/wolfcrypt/wc_she.h>
|
||||
#endif
|
||||
#include <wolfssl/wolfcrypt/siphash.h>
|
||||
#include <wolfssl/wolfcrypt/poly1305.h>
|
||||
#include <wolfssl/wolfcrypt/camellia.h>
|
||||
@@ -866,6 +869,9 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes192_test(void);
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes256_test(void);
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aesofb_test(void);
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cmac_test(void);
|
||||
#ifdef WOLFSSL_SHE
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t she_test(void);
|
||||
#endif
|
||||
#ifdef HAVE_ASCON
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ascon_hash256_test(void);
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ascon_aead128_test(void);
|
||||
@@ -3183,6 +3189,13 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\
|
||||
TEST_PASS("CMAC test passed!\n");
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_SHE) && !defined(NO_AES)
|
||||
if ( (ret = she_test()) != 0)
|
||||
TEST_FAIL("SHE test failed!\n", ret);
|
||||
else
|
||||
TEST_PASS("SHE test passed!\n");
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_SIPHASH)
|
||||
if ( (ret = siphash_test()) != 0)
|
||||
TEST_FAIL("SipHash test failed!\n", ret);
|
||||
@@ -56601,6 +56614,534 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cmac_test(void)
|
||||
|
||||
#endif /* !NO_AES && WOLFSSL_CMAC */
|
||||
|
||||
#if defined(WOLFSSL_SHE) && !defined(NO_AES)
|
||||
|
||||
#if defined(WC_SHE_SW_DEFAULT) && defined(WOLF_CRYPTO_CB) && \
|
||||
!defined(NO_WC_SHE_GETUID) && !defined(NO_WC_SHE_GETCOUNTER)
|
||||
|
||||
#ifndef WC_SHE_SW_TEST_AUTH_KEY
|
||||
#define WC_SHE_SW_TEST_AUTH_KEY { \
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WC_SHE_SW_TEST_NEW_KEY
|
||||
#define WC_SHE_SW_TEST_NEW_KEY { \
|
||||
0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, \
|
||||
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WC_SHE_SW_TEST_EXP_M1
|
||||
#define WC_SHE_SW_TEST_EXP_M1 { \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41 \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WC_SHE_SW_TEST_EXP_M2
|
||||
#define WC_SHE_SW_TEST_EXP_M2 { \
|
||||
0x2b, 0x11, 0x1e, 0x2d, 0x93, 0xf4, 0x86, 0x56, \
|
||||
0x6b, 0xcb, 0xba, 0x1d, 0x7f, 0x7a, 0x97, 0x97, \
|
||||
0xc9, 0x46, 0x43, 0xb0, 0x50, 0xfc, 0x5d, 0x4d, \
|
||||
0x7d, 0xe1, 0x4c, 0xff, 0x68, 0x22, 0x03, 0xc3 \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WC_SHE_SW_TEST_EXP_M3
|
||||
#define WC_SHE_SW_TEST_EXP_M3 { \
|
||||
0xb9, 0xd7, 0x45, 0xe5, 0xac, 0xe7, 0xd4, 0x18, \
|
||||
0x60, 0xbc, 0x63, 0xc2, 0xb9, 0xf5, 0xbb, 0x46 \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WC_SHE_SW_TEST_EXP_M4
|
||||
#define WC_SHE_SW_TEST_EXP_M4 { \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, \
|
||||
0xb4, 0x72, 0xe8, 0xd8, 0x72, 0x7d, 0x70, 0xd5, \
|
||||
0x72, 0x95, 0xe7, 0x48, 0x49, 0xa2, 0x79, 0x17 \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WC_SHE_SW_TEST_EXP_M5
|
||||
#define WC_SHE_SW_TEST_EXP_M5 { \
|
||||
0x82, 0x0d, 0x8d, 0x95, 0xdc, 0x11, 0xb4, 0x66, \
|
||||
0x88, 0x78, 0x16, 0x0c, 0xb2, 0xa4, 0xe2, 0x3e \
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Software-only SHE test using the full GetUID -> GetCounter -> GenerateM1M2M3
|
||||
* -> GenerateM4M5 API flow. This test allows someone to test a custom vector
|
||||
* by overriding the WC_SHE_SW_TEST_* and WC_SHE_DEFAULT_* macros, and
|
||||
* demonstrates the whole SHE API in a software-only configuration. */
|
||||
static wc_test_ret_t she_sw_default_test(void)
|
||||
{
|
||||
wc_test_ret_t ret = 0;
|
||||
byte uid[WC_SHE_UID_SZ];
|
||||
word32 counter;
|
||||
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];
|
||||
WC_DECLARE_VAR(she, wc_SHE, 1, HEAP_HINT);
|
||||
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte authKey[] = WC_SHE_SW_TEST_AUTH_KEY;
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte newKey[] = WC_SHE_SW_TEST_NEW_KEY;
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte expM1[] = WC_SHE_SW_TEST_EXP_M1;
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte expM2[] = WC_SHE_SW_TEST_EXP_M2;
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte expM3[] = WC_SHE_SW_TEST_EXP_M3;
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte expM4[] = WC_SHE_SW_TEST_EXP_M4;
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte expM5[] = WC_SHE_SW_TEST_EXP_M5;
|
||||
|
||||
WOLFSSL_ENTER("she_sw_default_test");
|
||||
|
||||
WC_ALLOC_VAR(she, wc_SHE, 1, HEAP_HINT);
|
||||
if (!WC_VAR_OK(she)) {
|
||||
return WC_TEST_RET_ENC_EC(MEMORY_E);
|
||||
}
|
||||
|
||||
/* Use INVALID_DEVID intentionally -- this test exercises the software-only
|
||||
* path and should not use any hardware callbacks. */
|
||||
ret = wc_SHE_Init(she, HEAP_HINT, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
WC_FREE_VAR(she, HEAP_HINT);
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
/* Get UID and counter from software defaults */
|
||||
ret = wc_SHE_GetUID(she, uid, WC_SHE_UID_SZ, NULL);
|
||||
if (ret != 0) {
|
||||
wc_SHE_Free(she);
|
||||
WC_FREE_VAR(she, HEAP_HINT);
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
ret = wc_SHE_GetCounter(she, &counter, NULL);
|
||||
if (ret != 0) {
|
||||
wc_SHE_Free(she);
|
||||
WC_FREE_VAR(she, HEAP_HINT);
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
/* Generate M1/M2/M3 using retrieved UID and counter */
|
||||
ret = wc_SHE_GenerateM1M2M3(she,
|
||||
uid, WC_SHE_UID_SZ,
|
||||
WC_SHE_MASTER_ECU_KEY_ID, authKey, sizeof(authKey),
|
||||
4, newKey, sizeof(newKey),
|
||||
counter, 0,
|
||||
m1, WC_SHE_M1_SZ,
|
||||
m2, WC_SHE_M2_SZ,
|
||||
m3, WC_SHE_M3_SZ);
|
||||
if (ret != 0) {
|
||||
wc_SHE_Free(she);
|
||||
WC_FREE_VAR(she, HEAP_HINT);
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
/* Verify M1/M2/M3 match expected values */
|
||||
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) {
|
||||
wc_SHE_Free(she);
|
||||
WC_FREE_VAR(she, HEAP_HINT);
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
}
|
||||
|
||||
/* Generate M4/M5 using same UID and counter */
|
||||
wc_SHE_Free(she);
|
||||
ret = wc_SHE_Init(she, HEAP_HINT, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
WC_FREE_VAR(she, HEAP_HINT);
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
ret = wc_SHE_GenerateM4M5(she,
|
||||
uid, WC_SHE_UID_SZ,
|
||||
WC_SHE_MASTER_ECU_KEY_ID, 4,
|
||||
newKey, sizeof(newKey),
|
||||
counter,
|
||||
m4, WC_SHE_M4_SZ,
|
||||
m5, WC_SHE_M5_SZ);
|
||||
if (ret != 0) {
|
||||
wc_SHE_Free(she);
|
||||
WC_FREE_VAR(she, HEAP_HINT);
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
/* Verify M4/M5 match expected values */
|
||||
if (XMEMCMP(m4, expM4, WC_SHE_M4_SZ) != 0 ||
|
||||
XMEMCMP(m5, expM5, WC_SHE_M5_SZ) != 0) {
|
||||
wc_SHE_Free(she);
|
||||
WC_FREE_VAR(she, HEAP_HINT);
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
}
|
||||
|
||||
wc_SHE_Free(she);
|
||||
WC_FREE_VAR(she, HEAP_HINT);
|
||||
return ret;
|
||||
}
|
||||
#endif /* WC_SHE_SW_DEFAULT && WOLF_CRYPTO_CB &&
|
||||
* !NO_WC_SHE_GETUID && !NO_WC_SHE_GETCOUNTER */
|
||||
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t she_test(void)
|
||||
{
|
||||
wc_test_ret_t ret = 0;
|
||||
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];
|
||||
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[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
|
||||
};
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte vectorAuthKey[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
|
||||
};
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte vectorNewKey[] = {
|
||||
0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
|
||||
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
|
||||
};
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte expM1[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41
|
||||
};
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte expM2[] = {
|
||||
0x2b, 0x11, 0x1e, 0x2d, 0x93, 0xf4, 0x86, 0x56,
|
||||
0x6b, 0xcb, 0xba, 0x1d, 0x7f, 0x7a, 0x97, 0x97,
|
||||
0xc9, 0x46, 0x43, 0xb0, 0x50, 0xfc, 0x5d, 0x4d,
|
||||
0x7d, 0xe1, 0x4c, 0xff, 0x68, 0x22, 0x03, 0xc3
|
||||
};
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte expM3[] = {
|
||||
0xb9, 0xd7, 0x45, 0xe5, 0xac, 0xe7, 0xd4, 0x18,
|
||||
0x60, 0xbc, 0x63, 0xc2, 0xb9, 0xf5, 0xbb, 0x46
|
||||
};
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte expM4[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41,
|
||||
0xb4, 0x72, 0xe8, 0xd8, 0x72, 0x7d, 0x70, 0xd5,
|
||||
0x72, 0x95, 0xe7, 0x48, 0x49, 0xa2, 0x79, 0x17
|
||||
};
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte expM5[] = {
|
||||
0x82, 0x0d, 0x8d, 0x95, 0xdc, 0x11, 0xb4, 0x66,
|
||||
0x88, 0x78, 0x16, 0x0c, 0xb2, 0xa4, 0xe2, 0x3e
|
||||
};
|
||||
|
||||
WOLFSSL_ENTER("she_test");
|
||||
|
||||
WC_ALLOC_VAR(she, wc_SHE, 1, HEAP_HINT);
|
||||
if (!WC_VAR_OK(she)) {
|
||||
return WC_TEST_RET_ENC_EC(MEMORY_E);
|
||||
}
|
||||
|
||||
/* ---- Init ---- */
|
||||
ret = wc_SHE_Init(she, HEAP_HINT, devId);
|
||||
if (ret != 0) {
|
||||
WC_FREE_VAR(she, HEAP_HINT);
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
/* ---- 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;
|
||||
}
|
||||
|
||||
/* ---- Check M1 ---- */
|
||||
if (XMEMCMP(m1, expM1, WC_SHE_M1_SZ) != 0) {
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* ---- Check M2 ---- */
|
||||
if (XMEMCMP(m2, expM2, WC_SHE_M2_SZ) != 0) {
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* ---- Check M3 ---- */
|
||||
if (XMEMCMP(m3, expM3, WC_SHE_M3_SZ) != 0) {
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* ---- Compute and export 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;
|
||||
}
|
||||
|
||||
/* ---- Check M4 ---- */
|
||||
if (XMEMCMP(m4, expM4, WC_SHE_M4_SZ) != 0) {
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* ---- Check M5 ---- */
|
||||
if (XMEMCMP(m5, expM5, WC_SHE_M5_SZ) != 0) {
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
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);
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
|
||||
/* Import M1/M2/M3, then generate M4/M5 */
|
||||
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;
|
||||
}
|
||||
#endif /* WOLF_CRYPTO_CB && !NO_WC_SHE_IMPORT_M123 */
|
||||
|
||||
/* ---- 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;
|
||||
}
|
||||
|
||||
#if !defined(NO_WC_SHE_LOADKEY) && !defined(NO_WC_SHE_LOADKEY_TEST) && \
|
||||
(defined(WOLF_CRYPTO_CB) && !defined(NO_WC_SHE_IMPORT_M123))
|
||||
/* ---- LoadKey_Verify ---- */
|
||||
/* Override WC_TEST_SHE_LOADKEY_VERIFY to use a platform-specific variant.
|
||||
* Platforms with hardware SHE (HSM/HSE) cannot use static test vectors
|
||||
* because the UID is device-specific. Options:
|
||||
*
|
||||
* Default (no override): calls wc_SHE_LoadKey_Verify (no id/label)
|
||||
*
|
||||
* WC_TEST_SHE_LOADKEY_ID: byte array for wc_SHE_LoadKey_Verify_Id
|
||||
* e.g. #define WC_TEST_SHE_LOADKEY_ID { 1, 0, 2, 0, 0, 0, 0 }
|
||||
*
|
||||
* WC_TEST_SHE_LOADKEY_LABEL: string for wc_SHE_LoadKey_Verify_Label
|
||||
* e.g. #define WC_TEST_SHE_LOADKEY_LABEL "she_key_1"
|
||||
*
|
||||
* Define NO_WC_SHE_LOADKEY_TEST to skip this sub-test entirely.
|
||||
*/
|
||||
XMEMSET(m4, 0, WC_SHE_M4_SZ);
|
||||
XMEMSET(m5, 0, WC_SHE_M5_SZ);
|
||||
#if defined(WOLF_PRIVATE_KEY_ID) && defined(WC_TEST_SHE_LOADKEY_ID)
|
||||
{
|
||||
unsigned char sheLoadkeyId[] = WC_TEST_SHE_LOADKEY_ID;
|
||||
ret = wc_SHE_LoadKey_Verify_Id(
|
||||
sheLoadkeyId, (int)sizeof(sheLoadkeyId),
|
||||
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);
|
||||
}
|
||||
#elif defined(WOLF_PRIVATE_KEY_ID) && defined(WC_TEST_SHE_LOADKEY_LABEL)
|
||||
ret = wc_SHE_LoadKey_Verify_Label(
|
||||
WC_TEST_SHE_LOADKEY_LABEL,
|
||||
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);
|
||||
#else
|
||||
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);
|
||||
#endif
|
||||
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 && !NO_WC_SHE_LOADKEY_TEST */
|
||||
|
||||
#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();
|
||||
if (ret != 0) {
|
||||
goto exit_SHE_Test;
|
||||
}
|
||||
#endif
|
||||
|
||||
exit_SHE_Test:
|
||||
wc_SHE_Free(she);
|
||||
WC_FREE_VAR(she, HEAP_HINT);
|
||||
WC_FREE_VAR(she2, HEAP_HINT);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_SHE && !NO_AES */
|
||||
|
||||
#if defined(WOLFSSL_SIPHASH)
|
||||
|
||||
#if WOLFSSL_SIPHASH_CROUNDS == 2 && WOLFSSL_SIPHASH_DROUNDS == 4
|
||||
@@ -66714,6 +67255,16 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (info->free.algo == WC_ALGO_TYPE_SHE) {
|
||||
#if defined(WOLFSSL_SHE) && !defined(NO_AES)
|
||||
wc_SHE* she = (wc_SHE*)info->free.obj;
|
||||
she->devId = INVALID_DEVID;
|
||||
wc_SHE_Free(she);
|
||||
ret = 0;
|
||||
#else
|
||||
ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN);
|
||||
}
|
||||
@@ -67153,7 +67704,101 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
|
||||
}
|
||||
#endif /* HAVE_CMAC_KDF */
|
||||
}
|
||||
#if defined(WOLFSSL_SHE) && !defined(NO_AES)
|
||||
else if (info->algo_type == WC_ALGO_TYPE_SHE) {
|
||||
wc_SHE* she = (wc_SHE*)info->she.she;
|
||||
int savedDevId;
|
||||
|
||||
if (she == NULL) {
|
||||
return NOT_COMPILED_IN;
|
||||
}
|
||||
|
||||
/* Save and override devId so re-call uses software path */
|
||||
savedDevId = she->devId;
|
||||
she->devId = INVALID_DEVID;
|
||||
|
||||
switch (info->she.type) {
|
||||
case WC_SHE_GET_UID:
|
||||
/* 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 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:
|
||||
/* 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);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Restore devId */
|
||||
she->devId = savedDevId;
|
||||
}
|
||||
#endif /* WOLFSSL_SHE && !NO_AES */
|
||||
|
||||
(void)devIdArg;
|
||||
(void)myCtx;
|
||||
|
||||
@@ -65,6 +65,9 @@
|
||||
#ifdef WOLFSSL_CMAC
|
||||
#include <wolfssl/wolfcrypt/cmac.h>
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHE
|
||||
#include <wolfssl/wolfcrypt/wc_she.h>
|
||||
#endif
|
||||
#ifdef HAVE_ED25519
|
||||
#include <wolfssl/wolfcrypt/ed25519.h>
|
||||
#endif
|
||||
@@ -478,6 +481,65 @@ typedef struct wc_CryptoInfo {
|
||||
int type;
|
||||
} cmac;
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHE
|
||||
struct {
|
||||
void* she; /* wc_SHE* context */
|
||||
int type; /* enum wc_SheType - discriminator */
|
||||
const void* ctx; /* read-only caller context */
|
||||
union {
|
||||
struct {
|
||||
byte* uid;
|
||||
word32 uidSz;
|
||||
} getUid;
|
||||
struct {
|
||||
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;
|
||||
word32 m2Sz;
|
||||
byte* m3;
|
||||
word32 m3Sz;
|
||||
} generateM1M2M3;
|
||||
struct {
|
||||
const byte* uid;
|
||||
word32 uidSz;
|
||||
byte authKeyId;
|
||||
byte targetKeyId;
|
||||
const byte* newKey;
|
||||
word32 newKeySz;
|
||||
word32 counter;
|
||||
byte* m4;
|
||||
word32 m4Sz;
|
||||
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;
|
||||
} she;
|
||||
#endif
|
||||
#ifndef NO_CERTS
|
||||
struct {
|
||||
const byte *id;
|
||||
@@ -799,6 +861,35 @@ WOLFSSL_LOCAL int wc_CryptoCb_Cmac(Cmac* cmac, const byte* key, word32 keySz,
|
||||
void* ctx);
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_SHE
|
||||
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);
|
||||
WOLFSSL_LOCAL 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);
|
||||
WOLFSSL_LOCAL 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);
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_SheExportKey(wc_SHE* she,
|
||||
byte* m1, word32 m1Sz,
|
||||
byte* m2, word32 m2Sz,
|
||||
byte* m3, word32 m3Sz,
|
||||
byte* m4, word32 m4Sz,
|
||||
byte* m5, word32 m5Sz,
|
||||
const void* ctx);
|
||||
#endif
|
||||
|
||||
#ifndef NO_CERTS
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_GetCert(int devId, const char *label,
|
||||
word32 labelLen, const byte *id, word32 idLen, byte** out,
|
||||
|
||||
@@ -10,6 +10,7 @@ nobase_include_HEADERS+= \
|
||||
wolfssl/wolfcrypt/poly1305.h \
|
||||
wolfssl/wolfcrypt/camellia.h \
|
||||
wolfssl/wolfcrypt/cmac.h \
|
||||
wolfssl/wolfcrypt/wc_she.h \
|
||||
wolfssl/wolfcrypt/coding.h \
|
||||
wolfssl/wolfcrypt/compress.h \
|
||||
wolfssl/wolfcrypt/des3.h \
|
||||
|
||||
@@ -1426,7 +1426,8 @@ enum wc_AlgoType {
|
||||
WC_ALGO_TYPE_FREE = 11,
|
||||
WC_ALGO_TYPE_SETKEY = 12,
|
||||
WC_ALGO_TYPE_EXPORT_KEY = 13,
|
||||
WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_EXPORT_KEY
|
||||
WC_ALGO_TYPE_SHE = 14,
|
||||
WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_SHE
|
||||
};
|
||||
|
||||
/* KDF types */
|
||||
|
||||
@@ -0,0 +1,418 @@
|
||||
/* wc_she.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 2 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 WOLF_CRYPT_SHE_H
|
||||
#define WOLF_CRYPT_SHE_H
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
|
||||
#ifdef WOLFSSL_SHE
|
||||
|
||||
#include <wolfssl/wolfcrypt/types.h>
|
||||
#include <wolfssl/wolfcrypt/aes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#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 /* 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 {
|
||||
WC_SHE_GET_UID = 1,
|
||||
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) */
|
||||
#define WC_SHE_MASTER_ECU_KEY_ID 1
|
||||
#define WC_SHE_FLAG_WRITE_PROTECT 0x01
|
||||
#define WC_SHE_FLAG_BOOT_PROTECT 0x02
|
||||
|
||||
/* internal field offsets and shifts for message construction */
|
||||
#define WC_SHE_M1_KID_OFFSET 15
|
||||
#define WC_SHE_M1_KID_SHIFT 4
|
||||
#define WC_SHE_M1_AID_SHIFT 0
|
||||
|
||||
#define WC_SHE_M2_COUNT_SHIFT 4
|
||||
#define WC_SHE_M2_FLAGS_SHIFT 0
|
||||
#define WC_SHE_M2_KEY_OFFSET 16
|
||||
|
||||
#define WC_SHE_M4_KID_OFFSET 15
|
||||
#define WC_SHE_M4_KID_SHIFT 4
|
||||
#define WC_SHE_M4_AID_SHIFT 0
|
||||
#define WC_SHE_M4_COUNT_OFFSET 16
|
||||
#define WC_SHE_M4_COUNT_SHIFT 4
|
||||
#define WC_SHE_M4_COUNT_PAD 0x8
|
||||
|
||||
/* SHE KDF constants (Miyaguchi-Preneel input) */
|
||||
#define WC_SHE_KEY_UPDATE_ENC_C { \
|
||||
0x01, 0x01, 0x53, 0x48, \
|
||||
0x45, 0x00, 0x80, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0xB0 \
|
||||
}
|
||||
|
||||
#define WC_SHE_KEY_UPDATE_MAC_C { \
|
||||
0x01, 0x02, 0x53, 0x48, \
|
||||
0x45, 0x00, 0x80, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0xB0 \
|
||||
}
|
||||
|
||||
enum {
|
||||
WC_SHE_MAX_ID_LEN = 32,
|
||||
WC_SHE_MAX_LABEL_LEN = 32
|
||||
};
|
||||
|
||||
typedef struct wc_SHE {
|
||||
#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 generated;
|
||||
#endif
|
||||
|
||||
void* heap;
|
||||
int devId;
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
void* devCtx;
|
||||
#endif
|
||||
#ifdef WOLF_PRIVATE_KEY_ID
|
||||
byte id[WC_SHE_MAX_ID_LEN];
|
||||
int idLen;
|
||||
char label[WC_SHE_MAX_LABEL_LEN];
|
||||
int labelLen;
|
||||
#endif
|
||||
} wc_SHE;
|
||||
|
||||
|
||||
/* 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.
|
||||
* 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.
|
||||
* 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 all data and zero the context. Safe to call on NULL. */
|
||||
WOLFSSL_API void wc_SHE_Free(wc_SHE* she);
|
||||
|
||||
/* Get UID from hardware.
|
||||
* she - initialized SHE context
|
||||
* uid - buffer to receive the 120-bit (15-byte) SHE UID
|
||||
* uidSz - size of uid buffer in bytes
|
||||
* ctx - read-only caller context (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 monotonic counter from hardware.
|
||||
* she - initialized SHE context
|
||||
* 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 */
|
||||
#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
|
||||
|
||||
/* 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 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 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 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 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,
|
||||
const byte* m2, word32 m2Sz,
|
||||
const byte* m3, word32 m3Sz);
|
||||
#endif
|
||||
|
||||
/* Generate M1/M2/M3 for the SHE key update protocol and write to
|
||||
* caller-provided buffers.
|
||||
*
|
||||
* 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).
|
||||
* authKeySz - must be WC_SHE_KEY_SZ (16)
|
||||
* 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.
|
||||
* newKeySz - must be WC_SHE_KEY_SZ (16)
|
||||
* 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,
|
||||
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 and write to caller-provided
|
||||
* buffers. Independent of M1/M2/M3, can be called on a separate context.
|
||||
*
|
||||
* 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).
|
||||
* newKeySz - must be WC_SHE_KEY_SZ (16)
|
||||
* 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,
|
||||
const byte* newKey, word32 newKeySz,
|
||||
word32 counter,
|
||||
byte* m4, word32 m4Sz,
|
||||
byte* m5, word32 m5Sz);
|
||||
|
||||
/* One-shot Load Key: Init, ImportM1M2M3, GenerateM4M5 (via callback), Free.
|
||||
* Requires a valid devId (not INVALID_DEVID) -- dispatches to a hardware
|
||||
* crypto callback that sends M1/M2/M3 to the HSM and returns M4/M5.
|
||||
* Define NO_WC_SHE_LOADKEY to compile out all LoadKey/Verify wrappers.
|
||||
* heap - heap hint for internal allocations, or NULL
|
||||
* devId - crypto callback device ID (must not be INVALID_DEVID)
|
||||
* m1-m3 - input: externally-provided SHE key update messages
|
||||
* m4,m5 - output: verification messages returned by the HSM */
|
||||
#ifndef NO_WC_SHE_LOADKEY
|
||||
#if defined(WOLF_CRYPTO_CB) && !defined(NO_WC_SHE_IMPORT_M123)
|
||||
WOLFSSL_API int wc_SHE_LoadKey(
|
||||
void* heap, int devId,
|
||||
const byte* m1, word32 m1Sz,
|
||||
const byte* m2, word32 m2Sz,
|
||||
const byte* m3, word32 m3Sz,
|
||||
byte* m4, word32 m4Sz,
|
||||
byte* m5, word32 m5Sz);
|
||||
|
||||
#ifdef WOLF_PRIVATE_KEY_ID
|
||||
/* One-shot Load Key with opaque hardware key identifier. */
|
||||
WOLFSSL_API int wc_SHE_LoadKey_Id(
|
||||
unsigned char* id, int idLen,
|
||||
void* heap, int devId,
|
||||
const byte* m1, word32 m1Sz,
|
||||
const byte* m2, word32 m2Sz,
|
||||
const byte* m3, word32 m3Sz,
|
||||
byte* m4, word32 m4Sz,
|
||||
byte* m5, word32 m5Sz);
|
||||
|
||||
/* One-shot Load Key with human-readable key label. */
|
||||
WOLFSSL_API int wc_SHE_LoadKey_Label(
|
||||
const char* label,
|
||||
void* heap, int devId,
|
||||
const byte* m1, word32 m1Sz,
|
||||
const byte* m2, word32 m2Sz,
|
||||
const byte* m3, word32 m3Sz,
|
||||
byte* m4, word32 m4Sz,
|
||||
byte* m5, word32 m5Sz);
|
||||
#endif /* WOLF_PRIVATE_KEY_ID */
|
||||
|
||||
/* One-shot Load Key with M4/M5 verification.
|
||||
* Same as wc_SHE_LoadKey but also compares the M4/M5 returned by the HSM
|
||||
* against caller-provided expected values. Returns SIG_VERIFY_E on mismatch.
|
||||
* The actual M4/M5 are still written to the output buffers on failure.
|
||||
* m4Expected, m5Expected - expected verification messages to compare against */
|
||||
WOLFSSL_API int wc_SHE_LoadKey_Verify(
|
||||
void* heap, int devId,
|
||||
const byte* m1, word32 m1Sz,
|
||||
const byte* m2, word32 m2Sz,
|
||||
const byte* m3, word32 m3Sz,
|
||||
byte* m4, word32 m4Sz,
|
||||
byte* m5, word32 m5Sz,
|
||||
const byte* m4Expected, word32 m4ExpectedSz,
|
||||
const byte* m5Expected, word32 m5ExpectedSz);
|
||||
|
||||
#ifdef WOLF_PRIVATE_KEY_ID
|
||||
WOLFSSL_API int wc_SHE_LoadKey_Verify_Id(
|
||||
unsigned char* id, int idLen,
|
||||
void* heap, int devId,
|
||||
const byte* m1, word32 m1Sz,
|
||||
const byte* m2, word32 m2Sz,
|
||||
const byte* m3, word32 m3Sz,
|
||||
byte* m4, word32 m4Sz,
|
||||
byte* m5, word32 m5Sz,
|
||||
const byte* m4Expected, word32 m4ExpectedSz,
|
||||
const byte* m5Expected, word32 m5ExpectedSz);
|
||||
|
||||
WOLFSSL_API int wc_SHE_LoadKey_Verify_Label(
|
||||
const char* label,
|
||||
void* heap, int devId,
|
||||
const byte* m1, word32 m1Sz,
|
||||
const byte* m2, word32 m2Sz,
|
||||
const byte* m3, word32 m3Sz,
|
||||
byte* m4, word32 m4Sz,
|
||||
byte* m5, word32 m5Sz,
|
||||
const byte* m4Expected, word32 m4ExpectedSz,
|
||||
const byte* m5Expected, word32 m5ExpectedSz);
|
||||
#endif /* WOLF_PRIVATE_KEY_ID */
|
||||
|
||||
#endif /* WOLF_CRYPTO_CB && !NO_WC_SHE_IMPORT_M123 */
|
||||
#endif /* !NO_WC_SHE_LOADKEY */
|
||||
|
||||
/* Export a key from hardware in SHE loadable format (M1-M5).
|
||||
* 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
|
||||
* 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,
|
||||
byte* m2, word32 m2Sz,
|
||||
byte* m3, word32 m3Sz,
|
||||
byte* m4, word32 m4Sz,
|
||||
byte* m5, word32 m5Sz,
|
||||
const void* ctx);
|
||||
#endif
|
||||
|
||||
/* 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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* WOLFSSL_SHE */
|
||||
#endif /* WOLF_CRYPT_SHE_H */
|
||||
Reference in New Issue
Block a user