mirror of https://github.com/wolfSSL/wolfssl.git
Add XMSS/XMSSMT wolfCrypt hooks.
parent
96205fc80d
commit
33d4b331fb
43
INSTALL
43
INSTALL
|
@ -371,7 +371,7 @@ We also have vcpkg ports for wolftpm, wolfmqtt and curl.
|
|||
resulting packages are placed in the root directory of the
|
||||
project.
|
||||
|
||||
18. Building for RHEL, Fedora, CentOS, SUSE, and openSUSE
|
||||
19. Building for RHEL, Fedora, CentOS, SUSE, and openSUSE
|
||||
|
||||
To generate a .rpm package, configure wolfSSL with the desired
|
||||
configuration. Then run `make rpm` to generate a .rpm package
|
||||
|
@ -380,3 +380,44 @@ We also have vcpkg ports for wolftpm, wolfmqtt and curl.
|
|||
resulting packages are placed in the root directory of the
|
||||
project.
|
||||
|
||||
20. Building with xmss-reference lib for XMSS/XMSS^MT support [EXPERIMENTAL]
|
||||
|
||||
Experimental support for XMSS/XMSS^MT has been achieved by integration
|
||||
with the xmss-reference implementation from RFC 8391 (XMSS: eXtended
|
||||
Merkle Signature Scheme). We support a patched version of xmss-reference
|
||||
based on this git commit:
|
||||
171ccbd26f098542a67eb5d2b128281c80bd71a6
|
||||
At the time of writing this, this is the HEAD of the master branch of
|
||||
the xmss-reference project.
|
||||
|
||||
How to get the xmss-reference library:
|
||||
$ mkdir ~/xmss
|
||||
$ cd ~/xmss
|
||||
$ git clone https://github.com/XMSS/xmss-reference.git src
|
||||
$ cd src
|
||||
$ git checkout 171ccbd26f098542a67eb5d2b128281c80bd71a6
|
||||
$ git apply <path to xmss reference patch>
|
||||
|
||||
The patch may be found in the wolfssl-examples repo here:
|
||||
pq/stateful_hash_sig/0001-Patch-to-support-xmss-reference-integration.patch
|
||||
|
||||
Note that this patch adds wolfCrypt SHA256 hashing to xmss-reference, and
|
||||
thus benefits from all the same asm speedups as wolfCrypt SHA hashing.
|
||||
Depending on architecture you may build with --enable-intelasm, or
|
||||
and --enable-armasm, and see 30-50% speedups in XMSS/XMSS^MT.
|
||||
|
||||
For full keygen, signing, verifying, and benchmarking support, build
|
||||
wolfSSL with:
|
||||
$ ./configure \
|
||||
--enable-xmss \
|
||||
--with-libxmss=<path to xmss src dir>
|
||||
$ make
|
||||
|
||||
Run the benchmark against XMSS/XMSS^MT with:
|
||||
$ ./wolfcrypt/benchmark/benchmark -xmss_xmssmt
|
||||
|
||||
For a leaner xmss verify-only build, build with
|
||||
$ ./configure \
|
||||
--enable-xmss=verify-only \
|
||||
--with-libxmss=<path to xmss src dir>
|
||||
$ make
|
||||
|
|
80
configure.ac
80
configure.ac
|
@ -1141,6 +1141,79 @@ then
|
|||
fi
|
||||
|
||||
|
||||
# XMSS
|
||||
AC_ARG_ENABLE([xmss],
|
||||
[AS_HELP_STRING([--enable-xmss],[Enable stateful XMSS/XMSS^MT signatures (default: disabled)])],
|
||||
[ ENABLED_XMSS=$enableval ],
|
||||
[ ENABLED_XMSS=no ]
|
||||
)
|
||||
|
||||
ENABLED_WC_XMSS=no
|
||||
for v in `echo $ENABLED_XMSS | tr "," " "`
|
||||
do
|
||||
case $v in
|
||||
yes)
|
||||
;;
|
||||
no)
|
||||
;;
|
||||
verify-only)
|
||||
XMSS_VERIFY_ONLY=yes
|
||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_XMSS_VERIFY_ONLY -DXMSS_VERIFY_ONLY"
|
||||
;;
|
||||
wolfssl)
|
||||
ENABLED_WC_XMSS=yes
|
||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_XMSS"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([Invalid choice for XMSS []: $ENABLED_XMSS.])
|
||||
break;;
|
||||
esac
|
||||
done
|
||||
|
||||
if test "$ENABLED_XMSS" != "no"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_XMSS"
|
||||
|
||||
if test "$ENABLED_WC_XMSS" = "no";
|
||||
then
|
||||
# Default is to use hash-sigs XMSS lib. Make sure it's enabled.
|
||||
if test "$ENABLED_LIBXMSS" = "no"; then
|
||||
AC_MSG_ERROR([The default implementation for XMSS is the xmss-reference lib.
|
||||
Please use --with-libxmss.])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# libxmss
|
||||
# Get the path to xmss-reference.
|
||||
ENABLED_LIBXMSS="no"
|
||||
trylibxmssdir=""
|
||||
AC_ARG_WITH([libxmss],
|
||||
[AS_HELP_STRING([--with-libxmss=PATH],[PATH to xmss-reference root dir. EXPERIMENTAL!])],
|
||||
[
|
||||
AC_MSG_CHECKING([for libxmss])
|
||||
|
||||
trylibxmssdir=$withval
|
||||
|
||||
if test -e $trylibxmssdir; then
|
||||
libxmss_linked=yes
|
||||
else
|
||||
AC_MSG_ERROR([libxmss isn't found.
|
||||
If it's already installed, specify its path using --with-libxmss=/dir/])
|
||||
fi
|
||||
|
||||
XMSS_ROOT=$trylibxmssdir
|
||||
|
||||
AC_MSG_RESULT([yes])
|
||||
|
||||
AM_CFLAGS="$AM_CFLAGS -DHAVE_LIBXMSS -I$trylibxmssdir"
|
||||
ENABLED_LIBXMSS="yes"
|
||||
AC_SUBST([XMSS_ROOT])
|
||||
],
|
||||
[XMSS_ROOT=""]
|
||||
)
|
||||
|
||||
|
||||
# LMS
|
||||
AC_ARG_ENABLE([lms],
|
||||
[AS_HELP_STRING([--enable-lms],[Enable stateful LMS/HSS signatures (default: disabled)])],
|
||||
|
@ -8999,6 +9072,7 @@ AM_CONDITIONAL([BUILD_CRL_MONITOR],[test "x$ENABLED_CRL_MONITOR" = "xyes"])
|
|||
AM_CONDITIONAL([BUILD_USER_RSA],[test "x$ENABLED_USER_RSA" = "xyes"] )
|
||||
AM_CONDITIONAL([BUILD_USER_CRYPTO],[test "x$ENABLED_USER_CRYPTO" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_LIBLMS],[test "x$ENABLED_LIBLMS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_LIBXMSS],[test "x$ENABLED_LIBXMSS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_LIBOQS],[test "x$ENABLED_LIBOQS" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_WNR],[test "x$ENABLED_WNR" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_SRP],[test "x$ENABLED_SRP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||
|
@ -9431,6 +9505,11 @@ echo " * ED448: $ENABLED_ED448"
|
|||
echo " * ED448 streaming: $ENABLED_ED448_STREAM"
|
||||
echo " * LMS: $ENABLED_LMS"
|
||||
echo " * LMS wolfSSL impl: $ENABLED_WC_LMS"
|
||||
echo " * XMSS: $ENABLED_XMSS"
|
||||
echo " * XMSS wolfSSL impl: $ENABLED_WC_XMSS"
|
||||
if test "$ENABLED_LIBXMSS" = "yes"; then
|
||||
echo " * XMSS_ROOT: $XMSS_ROOT"
|
||||
fi
|
||||
echo " * KYBER: $ENABLED_KYBER"
|
||||
echo " * KYBER wolfSSL impl: $ENABLED_WC_KYBER"
|
||||
echo " * ECCSI $ENABLED_ECCSI"
|
||||
|
@ -9486,6 +9565,7 @@ echo " * Persistent session cache: $ENABLED_SAVESESSION"
|
|||
echo " * Persistent cert cache: $ENABLED_SAVECERT"
|
||||
echo " * Atomic User Record Layer: $ENABLED_ATOMICUSER"
|
||||
echo " * Public Key Callbacks: $ENABLED_PKCALLBACKS"
|
||||
echo " * libxmss: $ENABLED_LIBXMSS"
|
||||
echo " * liblms: $ENABLED_LIBLMS"
|
||||
echo " * liboqs: $ENABLED_LIBOQS"
|
||||
echo " * Whitewood netRandom: $ENABLED_WNR"
|
||||
|
|
|
@ -807,6 +807,18 @@ if BUILD_LIBLMS
|
|||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ext_lms.c
|
||||
endif
|
||||
|
||||
if BUILD_LIBXMSS
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ext_xmss.c
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(XMSS_ROOT)/params.c
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(XMSS_ROOT)/thash.c
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(XMSS_ROOT)/hash_address.c
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(XMSS_ROOT)/wots.c
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(XMSS_ROOT)/xmss.c
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(XMSS_ROOT)/xmss_core_fast.c
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(XMSS_ROOT)/xmss_commons.c
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(XMSS_ROOT)/utils.c
|
||||
endif
|
||||
|
||||
if BUILD_LIBZ
|
||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/compress.c
|
||||
endif
|
||||
|
|
|
@ -150,18 +150,24 @@
|
|||
#endif
|
||||
#ifdef WOLFSSL_HAVE_KYBER
|
||||
#include <wolfssl/wolfcrypt/kyber.h>
|
||||
#ifdef WOLFSSL_WC_KYBER
|
||||
#include <wolfssl/wolfcrypt/wc_kyber.h>
|
||||
#endif
|
||||
#if defined(HAVE_LIBOQS) || defined(HAVE_PQM4)
|
||||
#include <wolfssl/wolfcrypt/ext_kyber.h>
|
||||
#endif
|
||||
#ifdef WOLFSSL_WC_KYBER
|
||||
#include <wolfssl/wolfcrypt/wc_kyber.h>
|
||||
#endif
|
||||
#if defined(HAVE_LIBOQS) || defined(HAVE_PQM4)
|
||||
#include <wolfssl/wolfcrypt/ext_kyber.h>
|
||||
#endif
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
|
||||
#include <wolfssl/wolfcrypt/lms.h>
|
||||
#ifdef HAVE_LIBLMS
|
||||
#include <wolfssl/wolfcrypt/ext_lms.h>
|
||||
#ifdef HAVE_LIBLMS
|
||||
#include <wolfssl/wolfcrypt/ext_lms.h>
|
||||
#endif
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_XMSS) && !defined(WOLFSSL_XMSS_VERIFY_ONLY)
|
||||
#include <wolfssl/wolfcrypt/xmss.h>
|
||||
#ifdef HAVE_LIBXMSS
|
||||
#include <wolfssl/wolfcrypt/ext_xmss.h>
|
||||
#endif
|
||||
#endif
|
||||
#ifdef WOLFCRYPT_HAVE_ECCSI
|
||||
#include <wolfssl/wolfcrypt/eccsi.h>
|
||||
|
@ -576,6 +582,7 @@
|
|||
|
||||
/* Post-Quantum Stateful Hash-Based sig algorithms. */
|
||||
#define BENCH_LMS_HSS 0x00000001
|
||||
#define BENCH_XMSS_XMSSMT 0x00000002
|
||||
|
||||
/* Other */
|
||||
#define BENCH_RNG 0x00000001
|
||||
|
@ -596,6 +603,11 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)) || \
|
||||
(defined(WOLFSSL_HAVE_XMSS) && !defined(WOLFSSL_XMSS_VERIFY_ONLY))
|
||||
#define BENCH_PQ_STATEFUL_HBS
|
||||
#endif
|
||||
|
||||
/* Benchmark all compiled in algorithms.
|
||||
* When 1, ignore other benchmark algorithm values.
|
||||
* 0, only benchmark algorithm values set.
|
||||
|
@ -870,7 +882,7 @@ static const bench_alg bench_other_opt[] = {
|
|||
|
||||
#endif /* !WOLFSSL_BENCHMARK_ALL && !NO_MAIN_DRIVER */
|
||||
|
||||
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
|
||||
#if defined(BENCH_PQ_STATEFUL_HBS)
|
||||
typedef struct bench_pq_hash_sig_alg {
|
||||
/* Command line option string. */
|
||||
const char* str;
|
||||
|
@ -880,10 +892,15 @@ typedef struct bench_pq_hash_sig_alg {
|
|||
|
||||
static const bench_pq_hash_sig_alg bench_pq_hash_sig_opt[] = {
|
||||
{ "-pq_hash_sig", 0xffffffff},
|
||||
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
|
||||
{ "-lms_hss", BENCH_LMS_HSS},
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_XMSS) && !defined(WOLFSSL_XMSS_VERIFY_ONLY)
|
||||
{ "-xmss_xmssmt", BENCH_XMSS_XMSSMT},
|
||||
#endif
|
||||
{ NULL, 0}
|
||||
};
|
||||
#endif /* if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) */
|
||||
#endif /* BENCH_PQ_STATEFUL_HBS */
|
||||
|
||||
#if defined(HAVE_PQC) && defined(HAVE_LIBOQS)
|
||||
/* The post-quantum-specific mapping of command line option to bit values and
|
||||
|
@ -2856,6 +2873,12 @@ static void* benchmarks_do(void* args)
|
|||
}
|
||||
#endif /* if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) */
|
||||
|
||||
#if defined(WOLFSSL_HAVE_XMSS) && !defined(WOLFSSL_XMSS_VERIFY_ONLY)
|
||||
if (bench_all || (bench_pq_hash_sig_algs & BENCH_XMSS_XMSSMT)) {
|
||||
bench_xmss();
|
||||
}
|
||||
#endif /* if defined(WOLFSSL_HAVE_XMSS) && !defined(WOLFSSL_XMSS_VERIFY_ONLY) */
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
if (bench_all || (bench_asym_algs & BENCH_ECC_MAKEKEY) ||
|
||||
(bench_asym_algs & BENCH_ECC) ||
|
||||
|
@ -8075,6 +8098,248 @@ void bench_lms(void)
|
|||
|
||||
#endif /* if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) */
|
||||
|
||||
#if defined(WOLFSSL_HAVE_XMSS) && !defined(WOLFSSL_XMSS_VERIFY_ONLY)
|
||||
|
||||
static int xmss_write_key_mem(const byte * priv, word32 privSz, void *context)
|
||||
{
|
||||
/* WARNING: THIS IS AN INSECURE WRITE CALLBACK THAT SHOULD ONLY
|
||||
* BE USED FOR TESTING PURPOSES! Production applications should
|
||||
* write only to non-volatile storage. */
|
||||
XMEMCPY(context, priv, privSz);
|
||||
return WC_XMSS_RC_SAVED_TO_NV_MEMORY;
|
||||
}
|
||||
|
||||
static int xmss_read_key_mem(byte * priv, word32 privSz, void *context)
|
||||
{
|
||||
/* WARNING: THIS IS AN INSECURE READ CALLBACK THAT SHOULD ONLY
|
||||
* BE USED FOR TESTING PURPOSES! */
|
||||
XMEMCPY(priv, context, privSz);
|
||||
return WC_XMSS_RC_READ_TO_MEMORY;
|
||||
}
|
||||
|
||||
static void bench_xmss_sign_verify(const char * params)
|
||||
{
|
||||
WC_RNG rng;
|
||||
XmssKey key;
|
||||
word32 pkSz = 0;
|
||||
word32 skSz = 0;
|
||||
int freeRng = 0;
|
||||
int freeKey = 0;
|
||||
unsigned char * sk = NULL;
|
||||
const char * msg = "XMSS post quantum signature test";
|
||||
word32 msgSz = (word32) XSTRLEN(msg);
|
||||
int ret = 0;
|
||||
byte * sig = NULL;
|
||||
word32 sigSz = 0;
|
||||
int times = 0;
|
||||
int count = 0;
|
||||
double start = 0.0F;
|
||||
|
||||
#ifndef HAVE_FIPS
|
||||
ret = wc_InitRng_ex(&rng, HEAP_HINT, INVALID_DEVID);
|
||||
#else
|
||||
ret = wc_InitRng(&rng);
|
||||
#endif
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "error: wc_InitRng failed: %d\n", ret);
|
||||
goto exit_xmss_sign_verify;
|
||||
}
|
||||
|
||||
freeRng = 1;
|
||||
|
||||
ret = wc_XmssKey_Init(&key, NULL, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "wc_XmssKey_Init failed: %d\n", ret);
|
||||
goto exit_xmss_sign_verify;
|
||||
}
|
||||
|
||||
ret = wc_XmssKey_SetParamStr(&key, params);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "wc_XmssKey_SetParamStr failed: %d\n", ret);
|
||||
goto exit_xmss_sign_verify;
|
||||
}
|
||||
|
||||
ret = wc_XmssKey_GetPubLen(&key, &pkSz);
|
||||
if (pkSz != XMSS_SHA256_PUBLEN) {
|
||||
fprintf(stderr, "error: xmss pub len: got %d, expected %d\n", pkSz,
|
||||
XMSS_SHA256_PUBLEN);
|
||||
goto exit_xmss_sign_verify;
|
||||
}
|
||||
|
||||
ret = wc_XmssKey_GetPrivLen(&key, &skSz);
|
||||
if (ret != 0 || skSz <= 0) {
|
||||
fprintf(stderr, "error: wc_XmssKey_GetPrivLen failed\n");
|
||||
goto exit_xmss_sign_verify;
|
||||
}
|
||||
|
||||
ret = wc_XmssKey_GetSigLen(&key, &sigSz);
|
||||
if (ret != 0 || sigSz <= 0) {
|
||||
fprintf(stderr, "error: wc_XmssKey_GetSigLen failed\n");
|
||||
goto exit_xmss_sign_verify;
|
||||
}
|
||||
|
||||
/* Allocate secret keys.*/
|
||||
sk = XMALLOC(skSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (sk == NULL) {
|
||||
fprintf(stderr, "error: allocate xmss sk failed\n");
|
||||
goto exit_xmss_sign_verify;
|
||||
}
|
||||
|
||||
/* Allocate signature array. */
|
||||
sig = XMALLOC(sigSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (sig == NULL) {
|
||||
fprintf(stderr, "error: allocate xmss sig failed\n");
|
||||
goto exit_xmss_sign_verify;
|
||||
}
|
||||
|
||||
ret = wc_XmssKey_SetWriteCb(&key, xmss_write_key_mem);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "error: wc_XmssKey_SetWriteCb failed: %d\n", ret);
|
||||
goto exit_xmss_sign_verify;
|
||||
}
|
||||
|
||||
ret = wc_XmssKey_SetReadCb(&key, xmss_read_key_mem);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "error: wc_XmssKey_SetReadCb failed: %d\n", ret);
|
||||
goto exit_xmss_sign_verify;
|
||||
}
|
||||
|
||||
ret = wc_XmssKey_SetContext(&key, (void *) sk);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "error: wc_XmssKey_SetContext failed: %d\n", ret);
|
||||
goto exit_xmss_sign_verify;
|
||||
}
|
||||
|
||||
#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_DEBUG_NONBLOCK)
|
||||
fprintf(stderr, "params: %s\n", params);
|
||||
fprintf(stderr, "pkSz: %d\n", pkSz);
|
||||
fprintf(stderr, "skSz: %d\n", skSz);
|
||||
fprintf(stderr, "sigSz: %d\n", sigSz);
|
||||
#endif
|
||||
|
||||
/* Making the private key is the bottleneck
|
||||
* for larger heights. Only print load time in debug builds. */
|
||||
#if defined(DEBUG_WOLFSSL)
|
||||
bench_stats_start(&count, &start);
|
||||
#endif /* if defined DEBUG_WOLFSSL*/
|
||||
|
||||
ret = wc_XmssKey_MakeKey(&key, &rng);
|
||||
if (ret != 0) {
|
||||
printf("wc_XmssKey_MakeKey failed: %d\n", ret);
|
||||
goto exit_xmss_sign_verify;
|
||||
}
|
||||
|
||||
count +=1;
|
||||
|
||||
#if defined(DEBUG_WOLFSSL)
|
||||
bench_stats_check(start);
|
||||
bench_stats_asym_finish(params, (int)skSz, "load", 0,
|
||||
count, start, ret);
|
||||
#endif /* if defined DEBUG_WOLFSSL*/
|
||||
|
||||
freeKey = 1;
|
||||
|
||||
count = 0;
|
||||
bench_stats_start(&count, &start);
|
||||
|
||||
do {
|
||||
/* XMSS is stateful. Async queuing not practical. */
|
||||
for (times = 0; times < ntimes; ++times) {
|
||||
|
||||
ret = wc_XmssKey_Sign(&key, sig, &sigSz, (byte *) msg, msgSz);
|
||||
if (ret) {
|
||||
printf("wc_XmssKey_Sign failed: %d\n", ret);
|
||||
goto exit_xmss_sign_verify;
|
||||
}
|
||||
}
|
||||
|
||||
count += times;
|
||||
} while (bench_stats_check(start));
|
||||
|
||||
bench_stats_asym_finish(params, (int)sigSz, "sign", 0,
|
||||
count, start, ret);
|
||||
|
||||
count = 0;
|
||||
bench_stats_start(&count, &start);
|
||||
|
||||
do {
|
||||
/* XMSS is stateful. Async queuing not practical. */
|
||||
for (times = 0; times < ntimes; ++times) {
|
||||
ret = wc_XmssKey_Verify(&key, sig, sigSz, (byte *) msg, msgSz);
|
||||
if (ret) {
|
||||
printf("wc_XmssKey_Verify failed: %d\n", ret);
|
||||
goto exit_xmss_sign_verify;
|
||||
}
|
||||
}
|
||||
|
||||
count += times;
|
||||
} while (bench_stats_check(start));
|
||||
|
||||
exit_xmss_sign_verify:
|
||||
bench_stats_asym_finish(params, (int)sigSz, "verify", 0,
|
||||
count, start, ret);
|
||||
|
||||
/* Cleanup everything. */
|
||||
if (sig != NULL) {
|
||||
XFREE(sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
sig = NULL;
|
||||
}
|
||||
|
||||
if (sk != NULL) {
|
||||
XFREE(sk, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
sk = NULL;
|
||||
}
|
||||
|
||||
if (freeRng) {
|
||||
wc_FreeRng(&rng);
|
||||
freeRng = 0;
|
||||
}
|
||||
|
||||
if (freeKey) {
|
||||
wc_XmssKey_Free(&key);
|
||||
freeKey = 0;
|
||||
}
|
||||
|
||||
if (sig != NULL) {
|
||||
XFREE(sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
sig = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void bench_xmss(void)
|
||||
{
|
||||
/* All NIST SP 800-208 approved SHA256 XMSS/XMSS^MT parameter
|
||||
* sets.
|
||||
*
|
||||
* note: not testing "XMSS-SHA2_16_256", "XMSS-SHA2_20_256",
|
||||
* and "XMSSMT-SHA2_60/3_256", because their keygen can be
|
||||
* very slow, their signatures and private keys quite large,
|
||||
* and xmss private keys are not portable across different
|
||||
* XMSS/XMSS^MT implementations.
|
||||
*
|
||||
* The bottleneck in key generation is the height of the first
|
||||
* level tree (or h/d).
|
||||
*
|
||||
* h is the total height of the hyper tree, and d the number of
|
||||
* trees.
|
||||
* */
|
||||
/* h/d h d */
|
||||
bench_xmss_sign_verify("XMSS-SHA2_10_256"); /* 10 10 1 */
|
||||
/* bench_xmss_sign_verify("XMSS-SHA2_16_256"); */ /* 16 16 1 */
|
||||
/* bench_xmss_sign_verify("XMSS-SHA2_20_256"); */ /* 20 20 1 */
|
||||
bench_xmss_sign_verify("XMSSMT-SHA2_20/2_256"); /* 10 20 2 */
|
||||
bench_xmss_sign_verify("XMSSMT-SHA2_20/4_256"); /* 5 20 4 */
|
||||
bench_xmss_sign_verify("XMSSMT-SHA2_40/4_256"); /* 10 40 4 */
|
||||
bench_xmss_sign_verify("XMSSMT-SHA2_40/8_256"); /* 5 40 8 */
|
||||
/* bench_xmss_sign_verify("XMSSMT-SHA2_60/3_256"); */ /* 20 60 3 */
|
||||
bench_xmss_sign_verify("XMSSMT-SHA2_60/6_256"); /* 10 60 6 */
|
||||
bench_xmss_sign_verify("XMSSMT-SHA2_60/12_256"); /* 5 60 12 */
|
||||
return;
|
||||
}
|
||||
#endif /* if defined(WOLFSSL_HAVE_XMSS) && !defined(WOLFSSL_XMSS_VERIFY_ONLY) */
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
|
||||
/* Maximum ECC name plus null terminator:
|
||||
|
@ -10410,10 +10675,10 @@ static void Usage(void)
|
|||
print_alg(bench_pq_asym_opt2[i].str, &line);
|
||||
#endif /* HAVE_LIBOQS && HAVE_SPHINCS */
|
||||
#endif /* HAVE_PQC */
|
||||
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
|
||||
#if defined(BENCH_PQ_STATEFUL_HBS)
|
||||
for (i=0; bench_pq_hash_sig_opt[i].str != NULL; i++)
|
||||
print_alg(bench_pq_hash_sig_opt[i].str, &line);
|
||||
#endif /* if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) */
|
||||
#endif /* BENCH_PQ_STATEFUL_HBS */
|
||||
printf("\n");
|
||||
#endif /* !WOLFSSL_BENCHMARK_ALL */
|
||||
e++;
|
||||
|
@ -10676,7 +10941,7 @@ int wolfcrypt_benchmark_main(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
|
||||
#if defined(BENCH_PQ_STATEFUL_HBS)
|
||||
/* post-quantum stateful hash-based signatures */
|
||||
for (i=0; !optMatched && bench_pq_hash_sig_opt[i].str != NULL; i++) {
|
||||
if (string_matches(argv[1], bench_pq_hash_sig_opt[i].str)) {
|
||||
|
@ -10685,7 +10950,7 @@ int wolfcrypt_benchmark_main(int argc, char** argv)
|
|||
optMatched = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* BENCH_PQ_STATEFUL_HBS */
|
||||
#endif
|
||||
if (!optMatched) {
|
||||
printf("Option not recognized: %s\n", argv[1]);
|
||||
|
|
|
@ -102,6 +102,7 @@ void bench_rsa_key(int useDeviceID, word32 keySz);
|
|||
void bench_dh(int useDeviceID);
|
||||
void bench_kyber(int type);
|
||||
void bench_lms(void);
|
||||
void bench_xmss(void);
|
||||
void bench_ecc_curve(int curveId);
|
||||
void bench_eccMakeKey(int useDeviceID, int curveId);
|
||||
void bench_ecc(int useDeviceID, int curveId);
|
||||
|
|
|
@ -0,0 +1,894 @@
|
|||
/* ext_xmss.c
|
||||
*
|
||||
* Copyright (C) 2006-2023 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
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
#include <wolfssl/wolfcrypt/logging.h>
|
||||
|
||||
#ifdef WOLFSSL_HAVE_XMSS
|
||||
#include <wolfssl/wolfcrypt/ext_xmss.h>
|
||||
|
||||
#ifdef NO_INLINE
|
||||
#include <wolfssl/wolfcrypt/misc.h>
|
||||
#else
|
||||
#define WOLFSSL_MISC_INCLUDED
|
||||
#include <wolfcrypt/src/misc.c>
|
||||
#endif
|
||||
|
||||
/* Init an Xmss key.
|
||||
*
|
||||
* Call this before setting the parms of an Xmss key.
|
||||
*
|
||||
* key [in] The Xmss key to init.
|
||||
* heap [in] Unused.
|
||||
* devId [in] Unused.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* */
|
||||
int wc_XmssKey_Init(XmssKey * key, void * heap, int devId)
|
||||
{
|
||||
if (key == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
(void) heap;
|
||||
(void) devId;
|
||||
|
||||
ForceZero(key, sizeof(XmssKey));
|
||||
|
||||
#ifndef WOLFSSL_XMSS_VERIFY_ONLY
|
||||
key->sk = NULL;
|
||||
key->write_private_key = NULL;
|
||||
key->read_private_key = NULL;
|
||||
key->context = NULL;
|
||||
#endif /* ifndef WOLFSSL_XMSS_VERIFY_ONLY */
|
||||
key->state = WC_XMSS_STATE_INITED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sets the Xmss key parameters, given an oid.
|
||||
*
|
||||
* Note: XMSS and XMSS^MT parameter sets do have overlapping
|
||||
* oids, therefore is_xmssmt is necessary to toggle.
|
||||
*
|
||||
* key [in] The Xmss key to set.
|
||||
* oid [in] The Xmss parameter set oid.
|
||||
* is_xmssmt [in] 1 The oid is assumed to be XMSS^MT.
|
||||
* 0 The oid is assumed to be XMSS.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* returns -1 on parse failure.
|
||||
* */
|
||||
static int wc_XmssKey_SetOid(XmssKey * key, uint32_t oid, int is_xmssmt)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (key == NULL || oid == 0) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Parse the oid and load the xmss params structure. */
|
||||
if (is_xmssmt) {
|
||||
ret = xmssmt_parse_oid(&key->params, oid);
|
||||
}
|
||||
else {
|
||||
ret = xmss_parse_oid(&key->params, oid);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
WOLFSSL_MSG("error: xmss parse oid failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Finally, sanity check that this is a supported parameter set.
|
||||
*
|
||||
* We are only supporting XMSS/XMSS^MT with SHA256 parameter sets
|
||||
* that NIST SP 800-208 has standardized. See patched xmss-reference
|
||||
* params.h for the defines. */
|
||||
if (key->params.func != XMSS_SHA2 ||
|
||||
key->params.n != XMSS_SHA256_N ||
|
||||
key->params.padding_len != XMSS_SHA256_PADDING_LEN ||
|
||||
key->params.wots_w != 16 ||
|
||||
key->params.wots_len != XMSS_SHA256_WOTS_LEN) {
|
||||
WOLFSSL_MSG("error: unsupported XMSS/XMSS^MT parameter set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
key->oid = oid;
|
||||
key->is_xmssmt = is_xmssmt;
|
||||
key->state = WC_XMSS_STATE_PARMSET;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the Xmss key parameter string.
|
||||
*
|
||||
* The input string must be one of the supported parm set names in
|
||||
* the "Name" section from the table in wolfssl/wolfcrypt/xmss.h,
|
||||
* e.g. "XMSS-SHA2_10_256" or "XMSSMT-SHA2_20/4_256".
|
||||
*
|
||||
* key [in] The Xmss key to set.
|
||||
* str [in] The XMSS/XMSS^MT parameter string.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* returns -1 on failure.
|
||||
* */
|
||||
int wc_XmssKey_SetParamStr(XmssKey * key, const char * str)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t oid = 0;
|
||||
int is_xmssmt = 0;
|
||||
|
||||
if (key == NULL || str == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (key->state != WC_XMSS_STATE_INITED) {
|
||||
WOLFSSL_MSG("error: xmss key needs init");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
switch(XSTRLEN(str)) {
|
||||
case XMSS_NAME_LEN:
|
||||
is_xmssmt = 0;
|
||||
break;
|
||||
case XMSSMT_NAME_MIN_LEN:
|
||||
case XMSSMT_NAME_MAX_LEN:
|
||||
is_xmssmt = 1;
|
||||
break;
|
||||
default:
|
||||
WOLFSSL_MSG("error: xmss param str invalid length");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Convert xmss param string to oid. */
|
||||
if (is_xmssmt) {
|
||||
ret = xmssmt_str_to_oid(&oid, str);
|
||||
}
|
||||
else {
|
||||
ret = xmss_str_to_oid(&oid, str);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
WOLFSSL_MSG("error: xmssmt_str_to_oid failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return wc_XmssKey_SetOid(key, oid, is_xmssmt);
|
||||
}
|
||||
|
||||
/* Force zeros and frees the Xmss key from memory.
|
||||
*
|
||||
* This does not touch the private key saved to non-volatile storage.
|
||||
*
|
||||
* This is the only function that frees the key->sk array.
|
||||
*
|
||||
* key [in] The Xmss key.
|
||||
*
|
||||
* returns void
|
||||
* */
|
||||
void wc_XmssKey_Free(XmssKey* key)
|
||||
{
|
||||
if (key == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef WOLFSSL_XMSS_VERIFY_ONLY
|
||||
if (key->sk != NULL) {
|
||||
ForceZero(key->sk, key->sk_len);
|
||||
XFREE(key->sk, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
key->sk = NULL;
|
||||
}
|
||||
#endif /* ifndef WOLFSSL_XMSS_VERIFY_ONLY */
|
||||
|
||||
ForceZero(key, sizeof(XmssKey));
|
||||
|
||||
key->state = WC_XMSS_STATE_FREED;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef WOLFSSL_XMSS_VERIFY_ONLY
|
||||
/* Sets the Xmss write private key callback.
|
||||
*
|
||||
* The callback must be able to write/update the private key to
|
||||
* non-volatile storage.
|
||||
*
|
||||
* key [in] The Xmss key.
|
||||
* write_cb [in] The write private key callback.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* returns -1 on failure.
|
||||
* */
|
||||
int wc_XmssKey_SetWriteCb(XmssKey * key, write_private_key_cb write_cb)
|
||||
{
|
||||
if (key == NULL || write_cb == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Changing the write callback of an already working key is forbidden. */
|
||||
if (key->state == WC_XMSS_STATE_OK) {
|
||||
WOLFSSL_MSG("error: wc_XmssKey_SetWriteCb: key in use");
|
||||
return -1;
|
||||
}
|
||||
|
||||
key->write_private_key = write_cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sets the Xmss read private key callback.
|
||||
*
|
||||
* The callback must be able to read the private key from
|
||||
* non-volatile storage.
|
||||
*
|
||||
* key [in] The Xmss key.
|
||||
* read_cb [in] The read private key callback.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* returns -1 on failure.
|
||||
* */
|
||||
int wc_XmssKey_SetReadCb(XmssKey * key, read_private_key_cb read_cb)
|
||||
{
|
||||
if (key == NULL || read_cb == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Changing the read callback of an already working key is forbidden. */
|
||||
if (key->state == WC_XMSS_STATE_OK) {
|
||||
WOLFSSL_MSG("error: wc_XmssKey_SetReadCb: key in use");
|
||||
return -1;
|
||||
}
|
||||
|
||||
key->read_private_key = read_cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sets the Xmss context to be used by write and read callbacks.
|
||||
*
|
||||
* E.g. this could be a filename if the callbacks write/read to file.
|
||||
*
|
||||
* key [in] The Xmss key.
|
||||
* context [in] The context pointer.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* returns -1 on failure.
|
||||
* */
|
||||
int wc_XmssKey_SetContext(XmssKey * key, void * context)
|
||||
{
|
||||
if (key == NULL || context == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Setting context of an already working key is forbidden. */
|
||||
if (key->state == WC_XMSS_STATE_OK) {
|
||||
WOLFSSL_MSG("error: wc_XmssKey_SetContext: key in use");
|
||||
return -1;
|
||||
}
|
||||
|
||||
key->context = context;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Allocates the Xmss secret key (sk) array.
|
||||
*
|
||||
* The XMSS/XMSS^MT secret key length is a function of the
|
||||
* parameters, and can't be allocated until the param string
|
||||
* has been set with SetParamStr.
|
||||
*
|
||||
* This is only called by MakeKey() and Reload().
|
||||
*
|
||||
* Note: the Xmss sk array is force zeroed after every use.
|
||||
*
|
||||
* key [in] The Xmss key.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* returns -1 on failure.
|
||||
* */
|
||||
static int wc_XmssKey_AllocSk(XmssKey* key)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (key == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (key->sk != NULL) {
|
||||
WOLFSSL_MSG("error: xmss secret key already exists");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The XMSS/XMSS^MT secret key length is a function of the
|
||||
* parameters. Therefore can't allocate this until param
|
||||
* string has been set. */
|
||||
ret = wc_XmssKey_GetPrivLen(key, &key->sk_len);
|
||||
|
||||
if (ret != 0 || key->sk_len <= 0) {
|
||||
WOLFSSL_MSG("error: wc_XmssKey_GetPrivLen failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
key->sk = XMALLOC(key->sk_len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
if (key->sk == NULL) {
|
||||
WOLFSSL_MSG("error: malloc Xmss key->sk failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ForceZero(key->sk, key->sk_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make the XMSS/XMSS^MT private/public key pair. The key must have its parameters
|
||||
* set before calling this.
|
||||
*
|
||||
* Write/read callbacks, and context data, must be set prior.
|
||||
* Key must have parameters set.
|
||||
*
|
||||
* This function and Reload() are the only functions that allocate
|
||||
* key->sk array. wc_XmssKey_FreeKey is the only function that
|
||||
* deallocates key->sk.
|
||||
*
|
||||
* key [in] The Xmss key to make.
|
||||
* rng [in] Initialized WC_RNG pointer.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* returns -1 on verify fail.
|
||||
* */
|
||||
int wc_XmssKey_MakeKey(XmssKey* key, WC_RNG * rng)
|
||||
{
|
||||
int ret = 0;
|
||||
enum wc_XmssRc cb_rc = WC_XMSS_RC_NONE;
|
||||
|
||||
if (key == NULL || rng == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (key->state != WC_XMSS_STATE_PARMSET) {
|
||||
WOLFSSL_MSG("error: XmssKey not ready for generation");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (key->write_private_key == NULL || key->read_private_key == NULL) {
|
||||
WOLFSSL_MSG("error: XmssKey write/read callbacks are not set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (key->context == NULL) {
|
||||
WOLFSSL_MSG("error: XmssKey context is not set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Allocate sk array. */
|
||||
ret = wc_XmssKey_AllocSk(key);
|
||||
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Finally make the secret public key pair. Immediately write it to NV
|
||||
* storage and then clear from memory. */
|
||||
if (key->is_xmssmt) {
|
||||
ret = xmssmt_keypair(key->pk, key->sk, key->oid, rng);
|
||||
}
|
||||
else {
|
||||
ret = xmss_keypair(key->pk, key->sk, key->oid, rng);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
cb_rc = key->write_private_key(key->sk, key->sk_len, key->context);
|
||||
}
|
||||
|
||||
ForceZero(key->sk, key->sk_len);
|
||||
|
||||
if (ret != 0) {
|
||||
WOLFSSL_MSG("error: xmss keypair failed");
|
||||
key->state = WC_XMSS_STATE_BAD;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cb_rc != WC_XMSS_RC_SAVED_TO_NV_MEMORY) {
|
||||
WOLFSSL_MSG("error: xmss write to NV storage failed");
|
||||
key->state = WC_XMSS_STATE_BAD;
|
||||
return -1;
|
||||
}
|
||||
|
||||
key->state = WC_XMSS_STATE_OK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function allocates the secret key buffer, and does a
|
||||
* quick sanity check to verify the secret key is readable
|
||||
* from NV storage, and then force zeros the key from memory.
|
||||
*
|
||||
* On success it sets the key state to OK.
|
||||
*
|
||||
* Use this function to resume signing with an already existing
|
||||
* xmss key pair.
|
||||
*
|
||||
* Write/read callbacks, and context data, must be set prior.
|
||||
* Key must have parameters set.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*
|
||||
* This function and MakeKey are the only functions that allocate
|
||||
* key->sk array. wc_XmssKey_FreeKey is the only function that
|
||||
* deallocates key->sk.
|
||||
*
|
||||
* key [in] Xmss key to load.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* returns -1 on load fail.
|
||||
* */
|
||||
int wc_XmssKey_Reload(XmssKey * key)
|
||||
{
|
||||
int ret = 0;
|
||||
enum wc_XmssRc cb_rc = WC_XMSS_RC_NONE;
|
||||
|
||||
if (key == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (key->state != WC_XMSS_STATE_PARMSET) {
|
||||
WOLFSSL_MSG("error: XmssKey not ready for reload");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (key->write_private_key == NULL || key->read_private_key == NULL) {
|
||||
WOLFSSL_MSG("error: XmssKey write/read callbacks are not set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (key->context == NULL) {
|
||||
WOLFSSL_MSG("error: XmssKey context is not set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Allocate sk array. */
|
||||
ret = wc_XmssKey_AllocSk(key);
|
||||
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read the current secret key from NV storage. Force clear it
|
||||
* immediately. This is just to sanity check the secret key
|
||||
* is readable from permanent storage. */
|
||||
cb_rc = key->read_private_key(key->sk, key->sk_len, key->context);
|
||||
ForceZero(key->sk, key->sk_len);
|
||||
|
||||
if (cb_rc != WC_XMSS_RC_READ_TO_MEMORY) {
|
||||
WOLFSSL_MSG("error: xmss read from NV storage failed");
|
||||
key->state = WC_XMSS_STATE_BAD;
|
||||
return -1;
|
||||
}
|
||||
|
||||
key->state = WC_XMSS_STATE_OK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Gets the XMSS/XMSS^MT private key length.
|
||||
*
|
||||
* Parameters must be set before calling this, as the key size (sk_bytes)
|
||||
* is a function of the parameters.
|
||||
*
|
||||
* Note: the XMSS/XMSS^MT private key format is implementation specific,
|
||||
* and not standardized. Interoperability of Xmss private keys should
|
||||
* not be expected.
|
||||
*
|
||||
* key [in] The Xmss key.
|
||||
* len [out] The length of the private key in bytes.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* returns -1 on sign fail.
|
||||
* */
|
||||
int wc_XmssKey_GetPrivLen(const XmssKey * key, word32 * len)
|
||||
{
|
||||
if (key == NULL || len == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (key->state != WC_XMSS_STATE_OK && key->state != WC_XMSS_STATE_PARMSET) {
|
||||
/* params.sk_bytes not set yet. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
*len = XMSS_OID_LEN + (word32) key->params.sk_bytes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Signs the message using the Xmss secret key, and
|
||||
* updates the secret key on NV storage.
|
||||
*
|
||||
* Both operations must succeed to be considered
|
||||
* successful.
|
||||
*
|
||||
* On success: sets key state to WC_XMSS_STATE_OK.
|
||||
* On failure: sets key state to WC_XMSS_STATE_BAD
|
||||
*
|
||||
* If no signatures are left, sets state to WC_XMSS_STATE_NOSIGS.
|
||||
*/
|
||||
static void wc_XmssKey_SignUpdate(XmssKey* key, byte * sig, word32 * sigLen,
|
||||
const byte * msg, int msgLen)
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned long long len = *sigLen;
|
||||
enum wc_XmssRc cb_rc = WC_XMSS_RC_NONE;
|
||||
|
||||
/* Set the key state to bad by default. State is presumed bad
|
||||
* unless a correct sign and update operation happen together. */
|
||||
key->state = WC_XMSS_STATE_BAD;
|
||||
*sigLen = 0;
|
||||
|
||||
/* Read the current secret key from NV storage.*/
|
||||
cb_rc = key->read_private_key(key->sk, key->sk_len, key->context);
|
||||
|
||||
if (cb_rc == WC_XMSS_RC_READ_TO_MEMORY) {
|
||||
/* Read was good. Now sign and update the secret key in memory. */
|
||||
if (key->is_xmssmt) {
|
||||
ret = xmssmt_sign(key->sk, sig, &len, msg, msgLen);
|
||||
}
|
||||
else {
|
||||
ret = xmss_sign(key->sk, sig, &len, msg, msgLen);
|
||||
}
|
||||
|
||||
if (ret == 0 && len == key->params.sig_bytes) {
|
||||
/* The signature succeeded. key->sk is now updated and must be
|
||||
* committed to NV storage. */
|
||||
cb_rc = key->write_private_key(key->sk, key->sk_len, key->context);
|
||||
|
||||
if (cb_rc == WC_XMSS_RC_SAVED_TO_NV_MEMORY) {
|
||||
/* key->sk was successfully committed to NV storage. Set the
|
||||
* key state to OK, and set the sigLen. */
|
||||
key->state = WC_XMSS_STATE_OK;
|
||||
*sigLen = (word32) len;
|
||||
}
|
||||
else {
|
||||
/* Write to NV storage failed. Erase the signature from
|
||||
* memory. */
|
||||
ForceZero(sig, key->params.sig_bytes);
|
||||
WOLFSSL_MSG("error: xmss write_private_key failed");
|
||||
}
|
||||
}
|
||||
else if (ret == -2) {
|
||||
/* Signature space exhausted. */
|
||||
key->state = WC_XMSS_STATE_NOSIGS;
|
||||
WOLFSSL_MSG("error: no xmss signatures remaining");
|
||||
}
|
||||
else {
|
||||
/* Something failed or inconsistent in signature. Erase the
|
||||
* signature just to be safe. */
|
||||
ForceZero(sig, key->params.sig_bytes);
|
||||
WOLFSSL_MSG("error: xmss sign failed");
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Read from NV storage failed. */
|
||||
WOLFSSL_MSG("error: xmss read_private_key failed");
|
||||
}
|
||||
|
||||
/* Force zero the secret key from memory always. */
|
||||
ForceZero(key->sk, key->sk_len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sign the message using the Xmss secret key.
|
||||
*
|
||||
* key [in] Xmss key to use to sign.
|
||||
* sig [in] Buffer to write signature into.
|
||||
* sigLen [in/out] On in, size of buffer.
|
||||
* On out, the length of the signature in bytes.
|
||||
* msg [in] Message to sign.
|
||||
* msgLen [in] Length of the message in bytes.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns -1 on sign fail.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* returns BUFFER_E when sigLen is too small.
|
||||
*/
|
||||
int wc_XmssKey_Sign(XmssKey* key, byte * sig, word32 * sigLen, const byte * msg,
|
||||
int msgLen)
|
||||
{
|
||||
if (key == NULL || sig == NULL || sigLen == NULL || msg == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (msgLen <= 0) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (*sigLen < key->params.sig_bytes) {
|
||||
/* Signature buffer too small. */
|
||||
WOLFSSL_MSG("error: xmss sig buffer too small");
|
||||
return BUFFER_E;
|
||||
}
|
||||
|
||||
if (key->state == WC_XMSS_STATE_NOSIGS) {
|
||||
WOLFSSL_MSG("error: xmss signatures exhausted");
|
||||
return -1;
|
||||
}
|
||||
else if (key->state != WC_XMSS_STATE_OK) {
|
||||
/* The key had an error the last time it was used, and we
|
||||
* can't guarantee its state. */
|
||||
WOLFSSL_MSG("error: can't sign, xmss key not in good state");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Finally, sign and update the secret key. */
|
||||
wc_XmssKey_SignUpdate(key, sig, sigLen, msg, msgLen);
|
||||
|
||||
return (key->state == WC_XMSS_STATE_OK) ? 0 : -1;
|
||||
}
|
||||
#endif /* ifndef WOLFSSL_XMSS_VERIFY_ONLY*/
|
||||
|
||||
/* Get the XMSS/XMSS^MT public key length. The public key
|
||||
* is static in size and does not depend on parameters,
|
||||
* other than the choice of SHA256 as hashing function.
|
||||
*
|
||||
* key [in] The Xmss key.
|
||||
* len [out] The length of the public key.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
*/
|
||||
int wc_XmssKey_GetPubLen(const XmssKey * key, word32 * len)
|
||||
{
|
||||
if (key == NULL || len == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
*len = XMSS_SHA256_PUBLEN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Export a generated public key and parameter set from one XmssKey
|
||||
* to another. Use this to prepare a signature verification XmssKey
|
||||
* that is pub only.
|
||||
*
|
||||
* keyDst [out] Destination key for copy.
|
||||
* keySrc [in] Source key for copy.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* */
|
||||
int wc_XmssKey_ExportPub(XmssKey * keyDst, const XmssKey * keySrc)
|
||||
{
|
||||
if (keyDst == NULL || keySrc == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
ForceZero(keyDst, sizeof(XmssKey));
|
||||
|
||||
XMEMCPY(keyDst->pk, keySrc->pk, sizeof(keySrc->pk));
|
||||
|
||||
keyDst->oid = keySrc->oid;
|
||||
keyDst->is_xmssmt = keySrc->is_xmssmt;
|
||||
|
||||
/* Mark keyDst as verify only, to prevent misuse. */
|
||||
keyDst->state = WC_XMSS_STATE_VERIFYONLY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Exports the raw XMSS public key buffer from key to out buffer.
|
||||
* The out buffer should be large enough to hold the public key, and
|
||||
* outLen should indicate the size of the buffer.
|
||||
*
|
||||
* key [in] Xmss key.
|
||||
* out [out] Array holding public key.
|
||||
* outLen [in/out] On in, size of buffer.
|
||||
* On out, the length of the public key.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns -1 on failure.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* returns BUFFER_E if array is too small.
|
||||
* */
|
||||
int wc_XmssKey_ExportPubRaw(const XmssKey * key, byte * out, word32 * outLen)
|
||||
{
|
||||
int ret = 0;
|
||||
word32 pubLen = 0;
|
||||
|
||||
if (key == NULL || out == NULL || outLen == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
ret = wc_XmssKey_GetPubLen(key, &pubLen);
|
||||
|
||||
if (ret != 0) {
|
||||
WOLFSSL_MSG("error: wc_XmssKey_GetPubLen failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*outLen < pubLen) {
|
||||
return BUFFER_E;
|
||||
}
|
||||
|
||||
XMEMCPY(out, key->pk, pubLen);
|
||||
*outLen = pubLen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Imports a raw public key buffer from in array to XmssKey key.
|
||||
*
|
||||
* The XMSS parameters must be set first with wc_XmssKey_SetParamStr,
|
||||
* and inLen must match the length returned by wc_XmssKey_GetPubLen.
|
||||
*
|
||||
* key [in] Xmss key.
|
||||
* in [in] Array holding public key.
|
||||
* inLen [in] Length of array in bytes.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* returns BUFFER_E if array is incorrect size.
|
||||
* returns -1 on failure.
|
||||
* */
|
||||
int wc_XmssKey_ImportPubRaw(XmssKey * key, const byte * in, word32 inLen)
|
||||
{
|
||||
int ret = 0;
|
||||
word32 pubLen = 0;
|
||||
|
||||
if (key == NULL || in == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (key->state != WC_XMSS_STATE_PARMSET) {
|
||||
/* Xmss key not ready for import. Param str must be set first. */
|
||||
WOLFSSL_MSG("error: xmss key not ready for import");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = wc_XmssKey_GetPubLen(key, &pubLen);
|
||||
|
||||
if (ret != 0) {
|
||||
WOLFSSL_MSG("error: wc_XmssKey_GetPubLen failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (inLen != pubLen) {
|
||||
/* Something inconsistent. Parameters weren't set, or input
|
||||
* pub key is wrong.*/
|
||||
return BUFFER_E;
|
||||
}
|
||||
|
||||
XMEMCPY(key->pk, in, pubLen);
|
||||
|
||||
key->state = WC_XMSS_STATE_VERIFYONLY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Gets the XMSS/XMSS^MT signature length.
|
||||
*
|
||||
* Parameters must be set before calling this, as the signature size
|
||||
* is a function of the parameters.
|
||||
*
|
||||
* Note: call this before wc_XmssKey_Sign or Verify so you know the
|
||||
* length of the required signature buffer.
|
||||
*
|
||||
* key [in] Xmss key to use to sign.
|
||||
* len [out] The length of the signature in bytes.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* returns -1 on sign fail.
|
||||
* */
|
||||
int wc_XmssKey_GetSigLen(const XmssKey * key, word32 * len)
|
||||
{
|
||||
if (key == NULL || len == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (key->state != WC_XMSS_STATE_OK && key->state != WC_XMSS_STATE_PARMSET) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*len = key->params.sig_bytes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Verify the signature using the Xmss public key.
|
||||
*
|
||||
* Requires that Xmss parameters have been set with
|
||||
* wc_XmssKey_SetParamStr, and that a public key is available
|
||||
* from importing or MakeKey().
|
||||
*
|
||||
* Call wc_XmssKey_GetSigLen() before this function to determine
|
||||
* length of the signature buffer.
|
||||
*
|
||||
* key [in] Xmss key to use to verify.
|
||||
* sig [in] Signature to verify.
|
||||
* sigLen [in] Size of signature in bytes.
|
||||
* msg [in] Message to verify.
|
||||
* msgLen [in] Length of the message in bytes.
|
||||
*
|
||||
* returns 0 on success.
|
||||
* returns -1 on verify fail.
|
||||
* returns BAD_FUNC_ARG when a parameter is NULL.
|
||||
* returns BUFFER_E when sigLen is too small.
|
||||
*/
|
||||
int wc_XmssKey_Verify(XmssKey * key, const byte * sig, word32 sigLen,
|
||||
const byte * msg, int msgLen)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long long msg_len = 0;
|
||||
|
||||
msg_len = msgLen;
|
||||
|
||||
if (key == NULL || sig == NULL || msg == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (sigLen < key->params.sig_bytes) {
|
||||
/* Signature buffer too small. */
|
||||
return BUFFER_E;
|
||||
}
|
||||
|
||||
if (key->state != WC_XMSS_STATE_OK &&
|
||||
key->state != WC_XMSS_STATE_VERIFYONLY) {
|
||||
/* Xmss key not ready for verification. Param str must be
|
||||
* set first, and Reload() called. */
|
||||
WOLFSSL_MSG("error: xmss key not ready for verification");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (key->is_xmssmt) {
|
||||
ret = xmssmt_sign_open(msg, &msg_len, sig, sigLen, key->pk);
|
||||
}
|
||||
else {
|
||||
ret = xmss_sign_open(msg, &msg_len, sig, sigLen, key->pk);
|
||||
}
|
||||
|
||||
if (ret != 0 || (int) msg_len != msgLen) {
|
||||
WOLFSSL_MSG("error: xmss verify failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_HAVE_XMSS */
|
|
@ -0,0 +1,26 @@
|
|||
/* wc_xmss.c
|
||||
*
|
||||
* Copyright (C) 2006-2023 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
|
||||
*/
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
|
||||
#ifdef WOLFSSL_HAVE_XMSS
|
||||
#error "Contact wolfSSL to get the implementation of this file"
|
||||
#endif
|
|
@ -293,6 +293,12 @@ const byte const_byte_array[] = "A+Gd\0\0\0";
|
|||
#include <wolfssl/wolfcrypt/ext_kyber.h>
|
||||
#endif
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_XMSS)
|
||||
#include <wolfssl/wolfcrypt/xmss.h>
|
||||
#ifdef HAVE_LIBXMSS
|
||||
#include <wolfssl/wolfcrypt/ext_xmss.h>
|
||||
#endif
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_LMS)
|
||||
#include <wolfssl/wolfcrypt/lms.h>
|
||||
#ifdef HAVE_LIBLMS
|
||||
|
@ -577,6 +583,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t scrypt_test(void);
|
|||
#ifdef WOLFSSL_HAVE_KYBER
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t kyber_test(void);
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_XMSS)
|
||||
#if !defined(WOLFSSL_XMSS_VERIFY_ONLY)
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test(void);
|
||||
#endif
|
||||
#if defined(WOLFSSL_XMSS_VERIFY_ONLY) && !defined(WOLFSSL_SMALL_STACK)
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test_verify_only(void);
|
||||
#endif
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_LMS)
|
||||
#if !defined(WOLFSSL_LMS_VERIFY_ONLY)
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void);
|
||||
|
@ -1623,6 +1637,22 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\
|
|||
TEST_PASS("KYBER test passed!\n");
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_HAVE_XMSS)
|
||||
#if !defined(WOLFSSL_XMSS_VERIFY_ONLY)
|
||||
if ( (ret = xmss_test()) != 0)
|
||||
TEST_FAIL("XMSS test failed!\n", ret);
|
||||
else
|
||||
TEST_PASS("XMSS test passed!\n");
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_XMSS_VERIFY_ONLY) && !defined(WOLFSSL_SMALL_STACK)
|
||||
if ( (ret = xmss_test_verify_only()) != 0)
|
||||
TEST_FAIL("XMSS test failed!\n", ret);
|
||||
else
|
||||
TEST_PASS("XMSS test passed!\n");
|
||||
#endif
|
||||
#endif /* if defined(WOLFSSL_HAVE_XMSS) */
|
||||
|
||||
#if defined(WOLFSSL_HAVE_LMS)
|
||||
#if !defined(WOLFSSL_LMS_VERIFY_ONLY)
|
||||
if ( (ret = lms_test()) != 0)
|
||||
|
@ -35091,6 +35121,616 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t kyber_test(void)
|
|||
}
|
||||
#endif /* WOLFSSL_HAVE_KYBER */
|
||||
|
||||
#if defined(WOLFSSL_HAVE_XMSS) && !defined(WOLFSSL_XMSS_VERIFY_ONLY)
|
||||
static int xmss_write_key_mem(const byte * priv, word32 privSz, void *context)
|
||||
{
|
||||
/* WARNING: THIS IS AN INSECURE WRITE CALLBACK THAT SHOULD ONLY
|
||||
* BE USED FOR TESTING PURPOSES! Production applications should
|
||||
* write only to non-volatile storage. */
|
||||
XMEMCPY(context, priv, privSz);
|
||||
return WC_XMSS_RC_SAVED_TO_NV_MEMORY;
|
||||
}
|
||||
|
||||
static int xmss_read_key_mem(byte * priv, word32 privSz, void *context)
|
||||
{
|
||||
/* WARNING: THIS IS AN INSECURE READ CALLBACK THAT SHOULD ONLY
|
||||
* BE USED FOR TESTING PURPOSES! */
|
||||
XMEMCPY(priv, context, privSz);
|
||||
return WC_XMSS_RC_READ_TO_MEMORY;
|
||||
}
|
||||
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test(void)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int ret = -1;
|
||||
int ret2 = -1;
|
||||
XmssKey signingKey;
|
||||
XmssKey verifyKey;
|
||||
WC_RNG rng;
|
||||
word32 pkSz = 0;
|
||||
word32 skSz = 0;
|
||||
word32 sigSz = 0;
|
||||
word32 bufSz = 0;
|
||||
unsigned char * sk = NULL;
|
||||
unsigned char * old_sk = NULL;
|
||||
const char * msg = "XMSS post quantum signature test";
|
||||
word32 msgSz = (word32) XSTRLEN(msg);
|
||||
const char * param = "XMSSMT-SHA2_20/4_256";
|
||||
byte * sig = NULL;
|
||||
|
||||
#ifndef HAVE_FIPS
|
||||
ret = wc_InitRng_ex(&rng, HEAP_HINT, INVALID_DEVID);
|
||||
#else
|
||||
ret = wc_InitRng(&rng);
|
||||
#endif
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
ret = wc_XmssKey_Init(&signingKey, NULL, INVALID_DEVID);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
ret = wc_XmssKey_Init(&verifyKey, NULL, INVALID_DEVID);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
/* Set the parameter string to the signing key, and
|
||||
* get sizes for secret key, pub key, and signature. */
|
||||
ret = wc_XmssKey_SetParamStr(&signingKey, param);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
ret = wc_XmssKey_GetPubLen(&signingKey, &pkSz);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
if (pkSz != XMSS_SHA256_PUBLEN) {
|
||||
return WC_TEST_RET_ENC_EC(pkSz);
|
||||
}
|
||||
|
||||
ret = wc_XmssKey_GetPrivLen(&signingKey, &skSz);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
ret = wc_XmssKey_GetSigLen(&signingKey, &sigSz);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
/* Allocate signature array. */
|
||||
sig = XMALLOC(sigSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (sig == NULL) { return WC_TEST_RET_ENC_ERRNO; }
|
||||
|
||||
bufSz = sigSz;
|
||||
|
||||
#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_DEBUG_NONBLOCK)
|
||||
fprintf(stderr, "param: %s\n", param);
|
||||
fprintf(stderr, "pkSz: %d\n", pkSz);
|
||||
fprintf(stderr, "skSz: %d\n", skSz);
|
||||
fprintf(stderr, "sigSz: %d\n", sigSz);
|
||||
#endif
|
||||
|
||||
/* Allocate current and old secret keys.*/
|
||||
sk = XMALLOC(skSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (sk == NULL) { return WC_TEST_RET_ENC_ERRNO; }
|
||||
|
||||
old_sk = XMALLOC(skSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (old_sk == NULL) { return WC_TEST_RET_ENC_ERRNO; }
|
||||
|
||||
XMEMSET(sk, 0, skSz);
|
||||
XMEMSET(old_sk, 0, skSz);
|
||||
XMEMSET(sig, 0, sigSz);
|
||||
|
||||
ret = wc_XmssKey_SetWriteCb(&signingKey, xmss_write_key_mem);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
ret = wc_XmssKey_SetReadCb(&signingKey, xmss_read_key_mem);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
ret = wc_XmssKey_SetContext(&signingKey, (void *) sk);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
ret = wc_XmssKey_MakeKey(&signingKey, &rng);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
/* Export the pub to a verify key. */
|
||||
ret = wc_XmssKey_ExportPub(&verifyKey, &signingKey);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
/* Repeat a few times to check that:
|
||||
* 1. The secret key is mutated on each sign.
|
||||
* 2. We can verify each new signature.
|
||||
* Only do a few times, because the full signature space
|
||||
* for this parameter set is huge. */
|
||||
for (i = 0; i < 10; ++i) {
|
||||
XMEMCPY(old_sk, sk, skSz);
|
||||
|
||||
ret = wc_XmssKey_Sign(&signingKey, sig, &sigSz, (byte *) msg, msgSz);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_I(i); }
|
||||
if (sigSz != bufSz) { return WC_TEST_RET_ENC_I(i); }
|
||||
|
||||
/* Old secret key and current secret key should not match. */
|
||||
ret = XMEMCMP(old_sk, sk, skSz);
|
||||
if (ret == 0) { return WC_TEST_RET_ENC_I(i); }
|
||||
|
||||
ret = wc_XmssKey_Verify(&verifyKey, sig, sigSz, (byte *) msg, msgSz);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_I(i); }
|
||||
|
||||
/* Flip bits in a few places throughout the signature, stepping in multiple
|
||||
* of hash size. These should all fail with -1. */
|
||||
for (j = 0; j < (int) sigSz; j+= 4 * 32) {
|
||||
sig[j] ^= 1;
|
||||
|
||||
ret2 = wc_XmssKey_Verify(&verifyKey, sig, sigSz, (byte *) msg,
|
||||
msgSz);
|
||||
if (ret2 != -1) {
|
||||
/* Verify passed when it should have failed. */
|
||||
return WC_TEST_RET_ENC_I(j);
|
||||
}
|
||||
|
||||
/* Flip this spot back. */
|
||||
sig[j] ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleanup everything. */
|
||||
if (sig != NULL) {
|
||||
XFREE(sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
sig = NULL;
|
||||
}
|
||||
|
||||
if (sk != NULL) {
|
||||
XFREE(sk, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
sk = NULL;
|
||||
}
|
||||
|
||||
if (old_sk != NULL) {
|
||||
XFREE(old_sk, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
old_sk = NULL;
|
||||
}
|
||||
|
||||
wc_XmssKey_Free(&signingKey);
|
||||
wc_FreeRng(&rng);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /*if defined(WOLFSSL_HAVE_XMSS) && !defined(WOLFSSL_XMSS_VERIFY_ONLY)*/
|
||||
|
||||
#if defined(WOLFSSL_HAVE_XMSS) && defined(WOLFSSL_XMSS_VERIFY_ONLY) && \
|
||||
!defined(WOLFSSL_SMALL_STACK)
|
||||
|
||||
/* A simple xmss verify only test using:
|
||||
* XMSS-SHA2_10_256
|
||||
* pub len: 68
|
||||
* msg len: 32
|
||||
* sig len: 2500
|
||||
*
|
||||
* These were generated with the test xmss_fast, from the unpatched
|
||||
* xmss-reference repository:
|
||||
* https://github.com/XMSS/xmss-reference
|
||||
* */
|
||||
|
||||
static byte xmss_pub[XMSS_SHA256_PUBLEN] =
|
||||
{
|
||||
0x00,0x00,0x00,0x01,0xA5,0x41,0x31,0x96,
|
||||
0x0A,0xF9,0xF3,0xB2,0x4B,0x2E,0x5B,0x3E,
|
||||
0xCA,0x74,0xAD,0x6C,0xA5,0x89,0xAD,0x2C,
|
||||
0x0E,0x96,0xB3,0x54,0xFB,0x5B,0x63,0x50,
|
||||
0x96,0x81,0xE2,0x59,0x72,0x10,0x09,0x54,
|
||||
0xBB,0x39,0xAC,0xEE,0x78,0xEF,0x95,0xEC,
|
||||
0x01,0x1D,0xF0,0x36,0x68,0xE2,0xC4,0xA5,
|
||||
0x2F,0x60,0x42,0x7E,0xD3,0x8E,0xAA,0x27,
|
||||
0xC9,0xB7,0x39,0x4E
|
||||
};
|
||||
|
||||
static byte xmss_msg[32] =
|
||||
{
|
||||
0x07,0x9F,0x80,0x86,0xDB,0x76,0x27,0xDF,
|
||||
0xED,0x5B,0x2A,0x81,0x60,0x60,0x7D,0xB4,
|
||||
0xE8,0x7A,0x69,0x45,0x20,0x6B,0xA2,0x96,
|
||||
0xC0,0x21,0xA5,0x46,0x29,0x63,0x9B,0x37
|
||||
};
|
||||
|
||||
/* This was actually the 5th signature produced from
|
||||
* xmss_fast test in xmss-reference. */
|
||||
static byte xmss_sig[2500] =
|
||||
{
|
||||
0x00,0x00,0x00,0x05,0xF0,0x15,0x34,0xBA,
|
||||
0x92,0x03,0x6A,0xB9,0xA5,0x23,0x86,0x11,
|
||||
0xAE,0x65,0x0A,0x5C,0x78,0x2C,0xC9,0xBE,
|
||||
0x7E,0xA6,0xDC,0xA2,0x8B,0xA9,0x9C,0x50,
|
||||
0xF6,0x61,0x8D,0x9D,0xD7,0xE9,0xC0,0xF8,
|
||||
0x67,0xCD,0x8A,0xC4,0x9B,0x74,0x96,0x07,
|
||||
0x5D,0xF2,0xC9,0xCC,0x28,0x05,0xB1,0xBE,
|
||||
0x5E,0xA4,0xBA,0xBE,0xAB,0xD8,0x21,0x6B,
|
||||
0x21,0x5F,0xAB,0xB7,0x6C,0xEC,0x2F,0xC8,
|
||||
0xC6,0x74,0x3E,0x97,0x1B,0xC3,0x45,0x57,
|
||||
0xAF,0xAA,0x1E,0xA8,0xF2,0x86,0xA8,0xAA,
|
||||
0x43,0x6D,0x66,0xE9,0x81,0x14,0xDE,0x09,
|
||||
0x39,0xD2,0xAF,0xD1,0x4C,0xE7,0x75,0x18,
|
||||
0x0D,0xAA,0x29,0xA1,0x92,0x53,0xCC,0xE9,
|
||||
0xF3,0x0B,0x1E,0x3B,0xE2,0xAE,0x80,0x0C,
|
||||
0xE7,0x7A,0x7C,0x13,0x8A,0x28,0xC6,0x5F,
|
||||
0x0A,0xA4,0xA3,0x73,0x0A,0x3A,0xC2,0xA6,
|
||||
0x3B,0xB4,0x30,0x67,0xC0,0x36,0x18,0xA1,
|
||||
0x58,0xCD,0xAD,0x54,0x36,0x64,0xCE,0xFD,
|
||||
0x52,0xFF,0x70,0x7E,0x09,0xFB,0x13,0xA2,
|
||||
0xEA,0xDF,0x67,0x8D,0x6C,0x42,0xB2,0x78,
|
||||
0xF5,0x7D,0x5C,0x4B,0xF7,0x8E,0xCF,0x3E,
|
||||
0xB7,0xC6,0xC1,0x23,0xFA,0x65,0xDE,0xD2,
|
||||
0xFA,0x40,0x51,0x97,0x0D,0x52,0x32,0x76,
|
||||
0x7E,0x82,0x8D,0xD0,0xB9,0x1E,0x62,0xD9,
|
||||
0x1E,0xC1,0xDB,0x40,0x43,0x37,0x4A,0x23,
|
||||
0x8A,0x1D,0x35,0xFA,0xF4,0x53,0x11,0x5A,
|
||||
0xB5,0x6D,0x1E,0x8B,0x22,0xC8,0x7D,0x2A,
|
||||
0xE4,0x94,0xAA,0x25,0x20,0x40,0x96,0xDB,
|
||||
0x82,0x62,0xBA,0x8F,0x8B,0x45,0xCB,0x4F,
|
||||
0x35,0x88,0x33,0xEB,0xEF,0xB3,0xBA,0xA7,
|
||||
0x09,0x72,0xB3,0x4C,0xEC,0xF2,0xC3,0xC7,
|
||||
0x5E,0x02,0x6C,0x41,0x93,0xCB,0x3C,0x89,
|
||||
0x12,0x09,0x68,0x54,0x8E,0xEC,0x6A,0x7E,
|
||||
0x20,0xE1,0x70,0x3D,0x8C,0xEB,0xB4,0x36,
|
||||
0xBE,0x91,0xBE,0x97,0xB5,0xA6,0x34,0x16,
|
||||
0x95,0x0F,0x10,0x26,0xA9,0x13,0x80,0x88,
|
||||
0x9C,0xAA,0x68,0xEC,0x34,0x70,0x4A,0x15,
|
||||
0x9B,0x5E,0x57,0x05,0x87,0x1C,0xF8,0x35,
|
||||
0x45,0x29,0xE9,0x6E,0xF2,0x70,0x13,0x42,
|
||||
0x89,0x4E,0x77,0xC0,0x18,0xC7,0x55,0x6D,
|
||||
0xE7,0xFA,0x0D,0x63,0x83,0x16,0x19,0x01,
|
||||
0x2D,0xFD,0x31,0x14,0x94,0xCA,0x3E,0x0E,
|
||||
0xD6,0x11,0x34,0x81,0x57,0x58,0xEC,0x24,
|
||||
0xA4,0x17,0x63,0xD3,0x25,0x00,0xBF,0x7D,
|
||||
0x78,0x5D,0xC5,0xD8,0xC6,0xC1,0xBD,0x8C,
|
||||
0xD0,0x94,0x0A,0xB1,0x33,0xA5,0x4B,0x31,
|
||||
0x25,0xF5,0xAF,0xE7,0x84,0x26,0xAA,0x05,
|
||||
0xBB,0xF3,0x9A,0xAF,0x58,0x36,0x40,0xEF,
|
||||
0x3D,0xA2,0xBD,0xCA,0xA1,0x8D,0x2F,0x6D,
|
||||
0x54,0xD2,0x62,0x33,0x09,0xAE,0xE6,0x73,
|
||||
0xD6,0x44,0xE8,0x7C,0x5C,0x39,0x2B,0x78,
|
||||
0x94,0x14,0xC7,0xC9,0xAF,0xEC,0x77,0x36,
|
||||
0xA1,0x61,0x61,0xF1,0xD0,0x09,0xA2,0xEE,
|
||||
0xE7,0x55,0xD7,0x35,0x89,0x89,0x9B,0xCF,
|
||||
0xFA,0xA6,0x09,0x1E,0x3B,0xBD,0x5D,0xD9,
|
||||
0x25,0xE7,0xED,0xDD,0x7C,0xF0,0x1C,0x57,
|
||||
0xE0,0x06,0xBB,0x08,0x39,0x59,0xDF,0xD7,
|
||||
0xAF,0x4B,0x88,0x0D,0x87,0x8F,0x4A,0xF3,
|
||||
0x1C,0xD4,0x4B,0xB3,0xE2,0xF3,0x1B,0x86,
|
||||
0x4F,0xCD,0x35,0x75,0xE2,0x03,0xF9,0x1D,
|
||||
0xBF,0x3E,0xD1,0x7B,0xC7,0x23,0x11,0x75,
|
||||
0x5F,0x92,0x0D,0x98,0xEE,0x14,0xE1,0xDA,
|
||||
0x7A,0x02,0x17,0x47,0x6B,0x41,0xEA,0x47,
|
||||
0xA1,0xAF,0x06,0x79,0x1A,0x52,0x6F,0x19,
|
||||
0x31,0x70,0x71,0xBD,0xC2,0x61,0x8D,0xB7,
|
||||
0xEE,0x6B,0x69,0x2A,0xE8,0x21,0x7A,0x95,
|
||||
0xBE,0x86,0x2A,0xA1,0xF4,0xE2,0x2F,0x17,
|
||||
0x02,0xFD,0xAD,0x17,0x9F,0x0A,0x0A,0x78,
|
||||
0xA9,0x92,0x30,0x21,0x72,0x2B,0x28,0xF8,
|
||||
0xF2,0x3E,0x05,0xD5,0xAC,0xC0,0x82,0xF8,
|
||||
0xD2,0xDA,0xD0,0xA3,0xBC,0x93,0xDB,0xA5,
|
||||
0x46,0xDE,0x14,0x1E,0xD4,0x3A,0x5D,0x79,
|
||||
0x3D,0x31,0x4B,0x06,0xCE,0x22,0x29,0x3C,
|
||||
0x98,0xB6,0x18,0x8A,0xAE,0xF7,0xBA,0x22,
|
||||
0x88,0xA1,0xEE,0xC0,0x14,0x4C,0x4A,0xA0,
|
||||
0x57,0x0A,0xD3,0x18,0xA2,0x3D,0xDD,0xC7,
|
||||
0x83,0x73,0xFC,0x38,0x9B,0x31,0xA3,0xE1,
|
||||
0x17,0x76,0xA1,0xA2,0x69,0xFC,0xAB,0x08,
|
||||
0x80,0x72,0x8D,0xF5,0xE4,0x14,0xB7,0x6B,
|
||||
0x03,0xFF,0xE8,0x11,0x4B,0x06,0x55,0x7E,
|
||||
0x36,0x21,0x2F,0xD7,0x54,0x82,0xC9,0x31,
|
||||
0xB4,0x85,0x68,0x41,0xEF,0x75,0xB0,0x3A,
|
||||
0xEA,0x4F,0xE0,0xEC,0x72,0xCC,0x33,0x96,
|
||||
0xCE,0x7D,0xAD,0xDD,0x0D,0x27,0x05,0x6E,
|
||||
0xA2,0xD4,0x11,0x07,0xD8,0x7D,0x27,0xD4,
|
||||
0x80,0x8F,0x00,0x22,0xE4,0xFC,0x2C,0x9D,
|
||||
0xD5,0xD8,0x18,0x7F,0x4E,0xF4,0xB9,0x7F,
|
||||
0xEF,0xD6,0x00,0x08,0x5C,0x05,0x04,0x1E,
|
||||
0x9A,0xC6,0x8D,0xCC,0x19,0xD9,0x0B,0x06,
|
||||
0xCC,0x6A,0x17,0xE2,0x03,0x23,0xDB,0x1C,
|
||||
0xBC,0xA2,0xB9,0xA2,0x95,0x3C,0x73,0xD8,
|
||||
0xFF,0xE6,0x0E,0xAE,0x04,0xB2,0xFC,0x91,
|
||||
0x4F,0xEF,0x8A,0x58,0xB7,0x31,0x68,0x4C,
|
||||
0x1E,0xD0,0x5B,0x85,0xCC,0x03,0xDC,0xF4,
|
||||
0xAC,0xDB,0x03,0x9B,0x35,0x33,0x08,0x71,
|
||||
0xD0,0x50,0x8D,0xDC,0xE3,0x3A,0x98,0x40,
|
||||
0x41,0x80,0xDD,0x35,0xE1,0xA2,0xAF,0x14,
|
||||
0x9A,0xDB,0xD3,0x68,0x14,0xE2,0x50,0x7A,
|
||||
0x76,0x3F,0xE4,0xA4,0x1B,0xAA,0xC1,0x06,
|
||||
0x87,0x9A,0x92,0xF9,0xBE,0x9E,0x86,0x8C,
|
||||
0x92,0x1D,0x74,0xB1,0x7F,0x27,0x43,0xC0,
|
||||
0xEE,0x2E,0xC2,0x6C,0x6D,0xAA,0x0C,0x0E,
|
||||
0x71,0xC9,0x56,0xD6,0x3A,0x56,0xCB,0x90,
|
||||
0xD1,0x7E,0x6E,0x1C,0x6A,0x00,0x2D,0x02,
|
||||
0x2C,0x96,0xF0,0x2A,0x37,0x37,0x18,0x07,
|
||||
0x0B,0xF4,0xB4,0x8C,0x30,0xF2,0xA4,0xAB,
|
||||
0x66,0xFB,0x8B,0x22,0xC0,0x00,0x7E,0x05,
|
||||
0xB6,0xF9,0x95,0x49,0x33,0xA1,0xDC,0x97,
|
||||
0x0C,0x5C,0x61,0x46,0xE2,0xD7,0x87,0x4B,
|
||||
0xC4,0xC7,0x5F,0x26,0x06,0x84,0xD7,0x47,
|
||||
0x05,0xF1,0x33,0xFF,0x85,0x85,0xB2,0xBD,
|
||||
0x1F,0x44,0xC6,0xC2,0x7D,0x51,0xBE,0x0E,
|
||||
0xB5,0xC4,0x44,0x2F,0xFE,0x73,0x5F,0xF4,
|
||||
0xA4,0xEF,0xE2,0xF1,0x73,0x0B,0xEF,0x3E,
|
||||
0x2B,0xD7,0xCC,0x9F,0xDA,0x1A,0x7E,0x92,
|
||||
0x39,0xA1,0x55,0xBF,0x60,0x0A,0xDB,0x23,
|
||||
0x74,0xFE,0xE7,0x05,0x63,0xA9,0x85,0x52,
|
||||
0x9F,0xCC,0xC3,0xFF,0xF6,0x6C,0x1B,0x4E,
|
||||
0x4F,0x01,0xBD,0xC3,0xEB,0x37,0xEC,0x29,
|
||||
0x21,0x3B,0x2C,0xC9,0x2E,0x93,0x20,0x3E,
|
||||
0x19,0xC0,0x8B,0xE8,0x33,0xCD,0xC6,0x6A,
|
||||
0x6E,0x72,0x13,0x15,0xA1,0x90,0x20,0x0C,
|
||||
0x14,0x66,0xED,0xCC,0xA4,0xDD,0x7F,0x58,
|
||||
0x53,0xBC,0x4A,0x68,0xFC,0x86,0x3E,0xAA,
|
||||
0xF1,0x17,0x0F,0x3E,0x20,0x54,0x93,0xF4,
|
||||
0x98,0xBF,0xB4,0x07,0x05,0xBD,0x70,0xE7,
|
||||
0xD7,0x34,0xFD,0xE3,0x69,0xDF,0xCD,0xF5,
|
||||
0x1A,0x73,0x6E,0xC9,0x2B,0x21,0xFB,0xB8,
|
||||
0x7E,0x44,0x10,0x83,0x56,0xCE,0xD5,0x15,
|
||||
0x9A,0x75,0xFC,0x91,0x8E,0x6B,0x9E,0x1A,
|
||||
0x3A,0x33,0x39,0x35,0xB4,0x0D,0x74,0xF4,
|
||||
0xFB,0x4C,0x0E,0x37,0xFE,0x82,0x95,0x46,
|
||||
0x6B,0xD2,0x6E,0xEE,0xCD,0x4D,0x38,0xAF,
|
||||
0x0A,0xAA,0xF1,0xD5,0xA4,0x7C,0x04,0xD8,
|
||||
0xB9,0xDB,0x11,0x68,0x88,0x35,0x41,0xDE,
|
||||
0x31,0x33,0x0C,0xDC,0x2D,0x4C,0xA8,0x20,
|
||||
0xCC,0x2C,0x4C,0x63,0xAB,0xBA,0xDF,0x48,
|
||||
0x84,0xD5,0x25,0xBC,0x70,0xE3,0x49,0xAA,
|
||||
0x43,0xCA,0x8B,0xE7,0x9F,0xDD,0x20,0x76,
|
||||
0x9B,0x38,0xF4,0xBA,0x4D,0x4E,0x34,0x4A,
|
||||
0xAF,0x81,0xE7,0x0B,0xEC,0xE9,0x59,0xC1,
|
||||
0x35,0x22,0x7F,0x69,0x46,0x62,0xD2,0x18,
|
||||
0x6E,0x1F,0x79,0xD1,0xAD,0xC3,0x84,0x95,
|
||||
0x96,0xB2,0x18,0x58,0x5E,0x7E,0x0C,0x25,
|
||||
0x0A,0x0F,0x69,0xA3,0x1D,0xEC,0x29,0xCB,
|
||||
0xDA,0xA2,0xD1,0x1A,0x10,0xA5,0x52,0xC3,
|
||||
0x62,0x1E,0xC5,0x83,0xFF,0xA3,0x56,0xC2,
|
||||
0xFD,0x87,0x3B,0x57,0x52,0x98,0x36,0x95,
|
||||
0x77,0x6B,0xE5,0x49,0x10,0x8E,0x39,0xDD,
|
||||
0xCA,0x4B,0xB3,0x9F,0x4C,0x0C,0x11,0x62,
|
||||
0xF3,0x22,0x78,0xDB,0x48,0xEB,0x68,0xFE,
|
||||
0xE4,0x2A,0xE9,0xAA,0x8F,0x7A,0x2F,0x69,
|
||||
0xA5,0xC5,0x03,0x2D,0xEF,0x62,0xA8,0x71,
|
||||
0x65,0x06,0x40,0x84,0x10,0x0F,0xF2,0xED,
|
||||
0xBC,0x70,0x71,0x69,0x24,0xA2,0xBF,0x83,
|
||||
0x39,0xDD,0xFA,0xA2,0x7B,0xE5,0xEC,0x3D,
|
||||
0xFE,0x3B,0x52,0x6E,0x3D,0x82,0xA6,0x2A,
|
||||
0x86,0x01,0x61,0x51,0x63,0xBF,0xF9,0x0A,
|
||||
0x06,0x72,0xF1,0xD5,0x39,0x0C,0xBA,0xC9,
|
||||
0x78,0xC6,0x77,0x22,0xE4,0x96,0x6E,0xB1,
|
||||
0x48,0x62,0x84,0x62,0x2D,0xEA,0x49,0x56,
|
||||
0x50,0x86,0x3F,0x90,0xC3,0x01,0x42,0x45,
|
||||
0xED,0xE6,0x9A,0x65,0x19,0x93,0x7F,0x48,
|
||||
0x16,0xF2,0x50,0xA7,0x70,0xB3,0xF5,0xDB,
|
||||
0x0E,0x5E,0x22,0x9E,0x64,0x04,0x26,0x69,
|
||||
0xC1,0x16,0xEE,0x65,0x08,0x82,0x27,0x65,
|
||||
0xEC,0x3D,0xDF,0x51,0x5E,0x2D,0xE8,0x76,
|
||||
0xF2,0xE3,0xE4,0x24,0x04,0x88,0x06,0x0F,
|
||||
0xB2,0x7B,0x9B,0x72,0x3D,0x4C,0x7D,0x6A,
|
||||
0x1F,0xB2,0xA2,0xD2,0x35,0xD6,0x40,0x25,
|
||||
0xC2,0x0B,0x25,0xF9,0xDF,0x26,0xE4,0xDC,
|
||||
0xFB,0xB1,0x84,0x84,0x77,0x1B,0x45,0x51,
|
||||
0x60,0xD5,0xF0,0xB6,0x09,0xE6,0xBC,0xE3,
|
||||
0x1C,0x70,0x96,0x2C,0xD3,0x9D,0x7D,0x7F,
|
||||
0xB1,0x70,0xDA,0x79,0xB8,0x74,0x99,0xBF,
|
||||
0x84,0x95,0xCC,0x93,0xD7,0x51,0xDD,0x66,
|
||||
0xD3,0x70,0x0C,0x75,0x86,0x09,0x06,0xFD,
|
||||
0x66,0x14,0x80,0xCD,0xF3,0x59,0xB4,0x92,
|
||||
0x5F,0xE4,0xEE,0x00,0xA8,0xB0,0x8B,0x5C,
|
||||
0x3E,0xDB,0x8A,0x9C,0x0B,0xB5,0x99,0xC2,
|
||||
0x0D,0x81,0x09,0x06,0x6C,0x28,0xC0,0x7E,
|
||||
0xA5,0x07,0x70,0x64,0xD7,0x41,0xF4,0xC3,
|
||||
0x66,0x61,0x1C,0xA8,0x51,0xF6,0x3C,0xBA,
|
||||
0xE0,0x94,0xA3,0x11,0x8C,0x2E,0xBA,0x13,
|
||||
0xB2,0x47,0x48,0x93,0xB4,0x1A,0x2C,0x9A,
|
||||
0x6E,0x8E,0x30,0x66,0x7B,0xD3,0xBB,0x3B,
|
||||
0x5D,0x97,0x0D,0xE4,0xEA,0x24,0x28,0x9E,
|
||||
0xB4,0x88,0xCE,0x1D,0x7D,0x6F,0x39,0xB3,
|
||||
0x87,0x21,0xE5,0x08,0x93,0xF0,0xD4,0x9D,
|
||||
0x2D,0x91,0xC9,0xFD,0x0C,0x74,0x34,0xB4,
|
||||
0x1F,0xFE,0xDA,0xDC,0x10,0x5B,0x8D,0x2B,
|
||||
0x87,0xD3,0x42,0xB4,0xAE,0x32,0x9C,0xAE,
|
||||
0x4C,0x99,0xD8,0xED,0x44,0x41,0x07,0xE0,
|
||||
0x8F,0xBD,0xA5,0x7C,0x5A,0xDF,0x91,0x29,
|
||||
0x00,0xB5,0x4B,0xC3,0x3A,0x40,0x6C,0x48,
|
||||
0xAB,0x2A,0xF3,0x02,0xCB,0xB3,0x69,0xDA,
|
||||
0x06,0x0C,0x4D,0x5C,0x45,0xC3,0x28,0xAC,
|
||||
0x7A,0x01,0xD4,0xF8,0xCB,0x07,0x63,0x89,
|
||||
0x09,0x34,0x78,0xA7,0x14,0x39,0xCF,0x2D,
|
||||
0x94,0x8D,0x7A,0x4E,0x4E,0xBD,0xC4,0x32,
|
||||
0xAB,0x21,0xC9,0xDA,0x3F,0x5F,0x04,0x6B,
|
||||
0x14,0x40,0x18,0x18,0x2F,0xF9,0x46,0x17,
|
||||
0x57,0x54,0x9B,0x28,0x7B,0xBD,0xF9,0xA2,
|
||||
0x13,0xAC,0x69,0x24,0xB1,0x31,0x39,0xBF,
|
||||
0x8D,0x75,0xC3,0xFD,0x03,0x54,0x5A,0xFD,
|
||||
0xD4,0x7A,0xB7,0x56,0x4F,0x66,0x43,0x57,
|
||||
0x1B,0xFB,0xF9,0x92,0x7A,0x83,0xE6,0xFF,
|
||||
0xB4,0xBA,0x83,0xD2,0x61,0x8E,0x4A,0x82,
|
||||
0x82,0xA8,0xF5,0x0C,0xD2,0x43,0x53,0xA8,
|
||||
0x85,0x0A,0xD4,0x69,0x7B,0x04,0x71,0x3B,
|
||||
0x80,0x49,0x27,0x47,0x12,0xB6,0xB0,0xEA,
|
||||
0x90,0x0A,0xFA,0xA8,0xC8,0x78,0x61,0xDE,
|
||||
0x30,0x12,0xBB,0xDC,0xA6,0x57,0x56,0x30,
|
||||
0x6E,0xF1,0xA8,0x3B,0xF6,0x09,0x07,0xEA,
|
||||
0x31,0xE2,0x08,0x23,0x31,0x0F,0xD4,0x34,
|
||||
0xE3,0x60,0xC2,0x2B,0xDB,0x5A,0x99,0xCF,
|
||||
0xD4,0x6B,0x4E,0x75,0x65,0x35,0xE8,0x8B,
|
||||
0x93,0x7D,0xCA,0x11,0x47,0xF0,0x3E,0x11,
|
||||
0x5C,0xD1,0xEE,0x4B,0x11,0xB4,0x65,0x2B,
|
||||
0x6B,0x79,0xC0,0x86,0x60,0xA4,0x4B,0x24,
|
||||
0xA0,0x5C,0x70,0x34,0xC3,0x7C,0xE7,0x4F,
|
||||
0x97,0x89,0x4D,0xFE,0x22,0x89,0x3A,0xE9,
|
||||
0x07,0xB9,0x1A,0x86,0xB8,0x7A,0x12,0x38,
|
||||
0xE1,0x24,0x46,0xBC,0x9B,0x21,0xCD,0xAC,
|
||||
0x30,0xAB,0x98,0x21,0x31,0xC5,0x17,0x3F,
|
||||
0x1E,0x56,0xC3,0x18,0xCE,0xF0,0xA1,0xCC,
|
||||
0xFF,0x9D,0xA8,0x53,0xAF,0x74,0x77,0x54,
|
||||
0x02,0x9A,0x8F,0xA4,0xD4,0xBD,0xB2,0x1A,
|
||||
0xBA,0x52,0x2E,0x19,0xBE,0x49,0x11,0x45,
|
||||
0x02,0x01,0x7A,0xBF,0x28,0xD6,0x18,0xED,
|
||||
0xBD,0xCE,0xE4,0xDE,0xB5,0xF1,0x53,0x5D,
|
||||
0x65,0xF9,0x5F,0x83,0x8F,0x2D,0xF2,0x82,
|
||||
0xA0,0x2D,0x28,0xD3,0x0A,0x9E,0x0F,0x7F,
|
||||
0xC7,0xC4,0x43,0x7F,0xC3,0x0E,0x06,0xEB,
|
||||
0x4E,0xB4,0x2D,0xFA,0xDD,0x48,0xAB,0xF4,
|
||||
0x7D,0x41,0x48,0x33,0x5A,0xE6,0x70,0x02,
|
||||
0xE7,0x71,0x8D,0xD9,0x6B,0x0C,0x5A,0x8F,
|
||||
0xA4,0xC1,0xB7,0x4E,0x96,0x83,0xD6,0xA7,
|
||||
0x1D,0xF1,0x88,0xB3,0x6E,0xF4,0x12,0xA9,
|
||||
0xF6,0x31,0x69,0x66,0xFE,0xFE,0x02,0xF2,
|
||||
0x86,0x6D,0xBB,0x57,0x51,0x8C,0x4C,0xE9,
|
||||
0x7C,0x92,0x3E,0x3A,0xD3,0x2D,0xA8,0x82,
|
||||
0x53,0x84,0x26,0x89,0xBB,0xCC,0x13,0x12,
|
||||
0x3D,0x94,0xBB,0xDF,0x3D,0x4C,0xDF,0x27,
|
||||
0x9B,0x1F,0xB8,0xB6,0xE4,0xEA,0xA2,0x07,
|
||||
0xF8,0x4D,0x42,0x8F,0x29,0x90,0xFE,0x21,
|
||||
0x20,0xE9,0x55,0x02,0xAD,0x90,0xA7,0x77,
|
||||
0x4E,0x29,0xB6,0xD9,0x14,0x94,0xB2,0x25,
|
||||
0xA4,0xB2,0x0E,0x96,0x31,0xAB,0x9E,0x93,
|
||||
0x49,0xAC,0xA9,0xCB,0x68,0x22,0xBA,0xB8,
|
||||
0x57,0x5C,0x9D,0x65,0xC1,0xF1,0xFC,0x99,
|
||||
0x7C,0x3C,0xE9,0xEA,0x4B,0x29,0x22,0x2F,
|
||||
0xDB,0x17,0x21,0x8D,0xB0,0x13,0xBF,0xEE,
|
||||
0x7D,0xE4,0x8B,0x6D,0x17,0xE0,0x53,0x92,
|
||||
0x0B,0x32,0x6B,0xB1,0x65,0x2E,0xA7,0x83,
|
||||
0xFD,0x62,0x62,0xE3,0xAA,0x81,0xE8,0xD6,
|
||||
0xF7,0xB1,0x30,0x65,0x80,0x9F,0x77,0x1E,
|
||||
0x4A,0xEA,0xE8,0x45,0x32,0x12,0x3A,0xFB,
|
||||
0x22,0xE9,0xA9,0xF6,0xCB,0xAB,0xA8,0x0C,
|
||||
0x20,0xA8,0x7C,0xF9,0xF7,0x53,0xC1,0xB4,
|
||||
0xC0,0x5D,0x06,0x45,0xDD,0x7E,0xA7,0x34,
|
||||
0xA1,0x21,0xC2,0x62,0xAB,0x22,0x45,0x3D,
|
||||
0x73,0x4C,0x26,0xD1,0x1A,0xB2,0xF0,0xB2,
|
||||
0x6D,0x11,0x70,0x58,0xAA,0xF5,0xA4,0xF5,
|
||||
0xF8,0x0B,0x3D,0xC1,0xF6,0x17,0x70,0x15,
|
||||
0xCD,0x72,0x02,0x7E,0x4E,0x94,0x96,0x0A,
|
||||
0x56,0xCC,0xA5,0xA3,0xB3,0x7E,0xDD,0x5A,
|
||||
0x72,0xD2,0xFB,0xAC,0x3D,0x0E,0x66,0x65,
|
||||
0xE9,0x08,0x6C,0xB0,0x1C,0xE2,0x1A,0x82,
|
||||
0xF6,0xF3,0x34,0x89,0x73,0x02,0x5B,0x42,
|
||||
0x6D,0x40,0x61,0xB6,0xE0,0xE6,0x53,0x32,
|
||||
0xA5,0x72,0x17,0x4F,0x3B,0x51,0x4F,0xBC,
|
||||
0x00,0xE0,0x69,0x26,0xA9,0xAE,0x83,0xE3,
|
||||
0x73,0x7F,0x71,0x97,0xE0,0xDC,0x7C,0x63,
|
||||
0x9C,0x85,0x5F,0xDF,0x7D,0xE4,0x6C,0xD8,
|
||||
0xA9,0x3A,0x6F,0x5E,0x4A,0x2E,0xB0,0xE7,
|
||||
0x8B,0x45,0xE2,0x90,0x05,0x37,0xE8,0xAB,
|
||||
0x49,0x48,0x4C,0xC0,0x59,0x1D,0x8C,0x46,
|
||||
0x5B,0x84,0xE0,0x83,0xCE,0xEA,0x4B,0xF9,
|
||||
0xD4,0xDC,0x63,0xDF,0x79,0xB7,0x5C,0x11,
|
||||
0x25,0x7F,0x90,0x2E,0x0A,0x38,0x03,0xEA,
|
||||
0xEA,0xA1,0x26,0x52,0x20,0x19,0xA3,0xBE,
|
||||
0xFC,0x9D,0xB7,0x6E,0xA6,0x58,0x8E,0x6D,
|
||||
0xC5,0x58,0xE9,0xED,0x2F,0x55,0x43,0x8B,
|
||||
0x03,0x8B,0xE6,0xA4,0xC2,0x25,0x4B,0x36,
|
||||
0xBA,0xD3,0x27,0x48,0x40,0x2E,0x87,0xA2,
|
||||
0xD4,0x12,0xC6,0x05,0x36,0x03,0x11,0x51,
|
||||
0xD1,0xF2,0xAC,0x71,0x2C,0xB6,0xC3,0xA5,
|
||||
0x57,0x0F,0xAF,0x4B,0xBD,0xCD,0x47,0x4C,
|
||||
0x3A,0x52,0x6F,0x47,0xE7,0x0B,0xB7,0xD5,
|
||||
0xF7,0xA6,0x39,0x63,0x82,0x08,0x4C,0x41,
|
||||
0x0E,0x2A,0x52,0x42,0x5A,0xEA,0x59,0xC7,
|
||||
0x94,0xFB,0xD0,0x88,0x47,0x27,0xF6,0x97,
|
||||
0x03,0x9E,0x29,0xB8,0x3A,0x67,0xE6,0xF3,
|
||||
0x95,0xA7,0x42,0xC1,0x96,0xD1,0x9A,0xA6,
|
||||
0xF0,0x09,0x0C,0xEA,0xE0,0xAB,0x0F,0x15,
|
||||
0xE9,0xC3,0xEB,0xA5,0x89,0x86,0x98,0x32,
|
||||
0x83,0xAB,0x30,0x33,0xAE,0x90,0x8D,0x2E,
|
||||
0xB3,0xAA,0x91,0xA6,0xD9,0xA4,0x4A,0x54,
|
||||
0xE0,0xD3,0x08,0xCC,0x79,0xCE,0xE4,0x15,
|
||||
0x31,0xA6,0xCE,0x61,0xCF,0x03,0x06,0xEE,
|
||||
0x8E,0xE2,0x64,0x29,0xD1,0x54,0x9B,0xD0,
|
||||
0x5F,0x09,0x2B,0x8B,0xD5,0xF8,0xD4,0x7D,
|
||||
0xF1,0x97,0x32,0xD9,0xEA,0x5A,0x0E,0x10,
|
||||
0x8C,0x4D,0xFB,0x55,0xE6,0x27,0x0C,0xBA,
|
||||
0xC1,0x73,0xC1,0x73,0xE3,0x1C,0x09,0xB3,
|
||||
0x6F,0xB4,0x12,0xFA,0xF3,0x29,0xDC,0x23,
|
||||
0x32,0xED,0x80,0x87,0x83,0xC2,0xF6,0x07,
|
||||
0xB5,0xA9,0x22,0xDE,0x66,0x1A,0xA7,0x4A,
|
||||
0x86,0xF1,0x39,0x9B,0xF4,0xE7,0x50,0x15,
|
||||
0x4A,0x55,0x3C,0x93,0xB9,0xF9,0xFD,0xDC,
|
||||
0xB3,0x5D,0x73,0x52
|
||||
};
|
||||
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test_verify_only(void)
|
||||
{
|
||||
int ret = -1;
|
||||
int ret2 = -1;
|
||||
int j = 0;
|
||||
XmssKey verifyKey;
|
||||
word32 pkSz = 0;
|
||||
word32 sigSz = 0;
|
||||
const char * param = "XMSS-SHA2_10_256";
|
||||
|
||||
ret = wc_XmssKey_Init(&verifyKey, NULL, INVALID_DEVID);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
ret = wc_XmssKey_SetParamStr(&verifyKey, param);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
ret = wc_XmssKey_GetPubLen(&verifyKey, &pkSz);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
if (pkSz != XMSS_SHA256_PUBLEN) {
|
||||
return WC_TEST_RET_ENC_EC(pkSz);
|
||||
}
|
||||
|
||||
ret = wc_XmssKey_GetSigLen(&verifyKey, &sigSz);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_DEBUG_NONBLOCK)
|
||||
fprintf(stderr, "param: %s\n", param);
|
||||
fprintf(stderr, "pkSz: %d\n", pkSz);
|
||||
fprintf(stderr, "sigSz: %d\n", sigSz);
|
||||
#endif
|
||||
|
||||
if (sigSz != sizeof(xmss_sig)) {
|
||||
return WC_TEST_RET_ENC_EC(sigSz);
|
||||
}
|
||||
|
||||
ret = wc_XmssKey_ImportPubRaw(&verifyKey, xmss_pub, XMSS_SHA256_PUBLEN);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
||||
ret = wc_XmssKey_Verify(&verifyKey, xmss_sig, sizeof(xmss_sig),
|
||||
(byte *) xmss_msg, sizeof(xmss_msg));
|
||||
if (ret != 0) {
|
||||
printf("error: wc_XmssKey_Verify returned %d, expected 0\n", ret);
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
/* Flip bits in message. This should fail. */
|
||||
xmss_msg[sizeof(xmss_msg) / 2] ^= 1;
|
||||
ret2 = wc_XmssKey_Verify(&verifyKey, xmss_sig, sizeof(xmss_sig),
|
||||
(byte *) xmss_msg, sizeof(xmss_msg));
|
||||
if (ret2 != -1) {
|
||||
printf("error: wc_XmssKey_Verify returned %d, expected -1\n", ret2);
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
/* Flip it back. This should pass again. */
|
||||
xmss_msg[sizeof(xmss_msg) / 2] ^= 1;
|
||||
ret = wc_XmssKey_Verify(&verifyKey, xmss_sig, sizeof(xmss_sig),
|
||||
(byte *) xmss_msg, sizeof(xmss_msg));
|
||||
if (ret != 0) {
|
||||
printf("error: wc_XmssKey_Verify returned %d, expected 0\n", ret);
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
/* Flip bits in a few places throughout the signature, stepping in multiple
|
||||
* of hash size. These should all fail with -1. */
|
||||
for (j = 0; j < (int) sizeof(xmss_sig); j+= 4 * 32) {
|
||||
xmss_sig[j] ^= 1;
|
||||
|
||||
ret2 = wc_XmssKey_Verify(&verifyKey, xmss_sig, sizeof(xmss_sig),
|
||||
(byte *) xmss_msg, sizeof(xmss_msg));
|
||||
if (ret2 != -1) {
|
||||
/* Verify passed when it should have failed. */
|
||||
return WC_TEST_RET_ENC_I(j);
|
||||
}
|
||||
|
||||
/* Flip this spot back. */
|
||||
xmss_sig[j] ^= 1;
|
||||
}
|
||||
|
||||
/* Cleanup everything. */
|
||||
wc_XmssKey_Free(&verifyKey);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* if defined(WOLFSSL_HAVE_XMSS) && defined(WOLFSSL_XMSS_VERIFY_ONLY) &&
|
||||
* !defined(WOLFSSL_SMALL_STACK) */
|
||||
|
||||
|
||||
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
|
||||
static int lms_write_key_mem(const byte * priv, word32 privSz, void *context)
|
||||
|
@ -35116,7 +35756,10 @@ static int lms_read_key_mem(byte * priv, word32 privSz, void *context)
|
|||
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
|
||||
{
|
||||
int ret;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int ret = -1;
|
||||
int ret2 = -1;
|
||||
int sigsLeft = 0;
|
||||
LmsKey signingKey;
|
||||
LmsKey verifyKey;
|
||||
|
@ -35138,6 +35781,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
|
|||
|
||||
XMEMSET(priv, 0, sizeof(priv));
|
||||
XMEMSET(old_priv, 0, sizeof(old_priv));
|
||||
XMEMSET(sig, 0, WC_TEST_LMS_SIG_LEN);
|
||||
|
||||
#ifndef HAVE_FIPS
|
||||
ret = wc_InitRng_ex(&rng, HEAP_HINT, INVALID_DEVID);
|
||||
|
@ -35190,7 +35834,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
|
|||
}
|
||||
|
||||
/* 2 ** 5 should be the max number of signatures */
|
||||
for (size_t i = 0; i < 32; ++i) {
|
||||
for (i = 0; i < 32; ++i) {
|
||||
/* We should have remaining signstures. */
|
||||
sigsLeft = wc_LmsKey_SigsLeft(&signingKey);
|
||||
if (sigsLeft == 0) {
|
||||
|
@ -35203,7 +35847,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
|
|||
|
||||
/* The updated private key should not match the old one. */
|
||||
if (XMEMCMP(old_priv, priv, sizeof(priv)) == 0) {
|
||||
printf("error: current priv key should not match old: %zu\n", i);
|
||||
printf("error: current priv key should not match old: %d\n", i);
|
||||
return WC_TEST_RET_ENC_I(i);
|
||||
}
|
||||
|
||||
|
@ -35211,6 +35855,22 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
|
|||
|
||||
ret = wc_LmsKey_Verify(&verifyKey, sig, sigSz, (byte *) msg, msgSz);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_I(i); }
|
||||
|
||||
/* Flip bits in a few places throughout the signature, stepping in multiple
|
||||
* of hash size. These should all fail with -1. */
|
||||
for (j = 0; j < (int) sigSz; j+= 4 * 32) {
|
||||
sig[j] ^= 1;
|
||||
|
||||
ret2 = wc_LmsKey_Verify(&verifyKey, sig, sigSz, (byte *) msg,
|
||||
msgSz);
|
||||
if (ret2 != -1) {
|
||||
/* Verify passed when it should have failed. */
|
||||
return WC_TEST_RET_ENC_I(j);
|
||||
}
|
||||
|
||||
/* Flip this spot back. */
|
||||
sig[j] ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* This should be the last signature. */
|
||||
|
@ -35243,6 +35903,15 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
|
|||
* signature length: 1456
|
||||
* */
|
||||
|
||||
/* "wolfSSL LMS example message!" without null terminator. */
|
||||
static byte lms_msg[28] =
|
||||
{
|
||||
0x77,0x6F,0x6C,0x66,0x53,0x53,0x4C,0x20,
|
||||
0x4C,0x4D,0x53,0x20,0x65,0x78,0x61,0x6D,
|
||||
0x70,0x6C,0x65,0x20,0x6D,0x65,0x73,0x73,
|
||||
0x61,0x67,0x65,0x21
|
||||
};
|
||||
|
||||
static byte lms_L1H10W8_pub[HSS_MAX_PUBLIC_KEY_LEN] =
|
||||
{
|
||||
0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,
|
||||
|
@ -35445,15 +36114,16 @@ static byte lms_L1H10W8_sig[LMS_L1H10W8_SIGLEN] =
|
|||
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test_verify_only(void)
|
||||
{
|
||||
int ret;
|
||||
LmsKey verifyKey;
|
||||
word32 sigSz = 0;
|
||||
const char * msg = "wolfSSL LMS example message!";
|
||||
word32 msgSz = (word32) XSTRLEN(msg);
|
||||
word32 pubLen = 0;
|
||||
int levels = 0;
|
||||
int height = 0;
|
||||
int winternitz = 0;
|
||||
int ret = -1;
|
||||
int ret2 = -1;
|
||||
int j = 0;
|
||||
LmsKey verifyKey;
|
||||
word32 sigSz = 0;
|
||||
word32 msgSz = sizeof(lms_msg);
|
||||
word32 pubLen = 0;
|
||||
int levels = 0;
|
||||
int height = 0;
|
||||
int winternitz = 0;
|
||||
|
||||
ret = wc_LmsKey_Init(&verifyKey, NULL, INVALID_DEVID);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
|
||||
|
@ -35492,12 +36162,47 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test_verify_only(void)
|
|||
}
|
||||
|
||||
ret = wc_LmsKey_Verify(&verifyKey, lms_L1H10W8_sig, LMS_L1H10W8_SIGLEN,
|
||||
(byte *) msg, msgSz);
|
||||
(byte *) lms_msg, msgSz);
|
||||
if (ret != 0) {
|
||||
printf("error: wc_LmsKey_Verify returned %d\n", ret);
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
/* Flip bits in message. This should fail. */
|
||||
lms_msg[msgSz / 2] ^= 1;
|
||||
ret2 = wc_LmsKey_Verify(&verifyKey, lms_L1H10W8_sig, LMS_L1H10W8_SIGLEN,
|
||||
(byte *) lms_msg, msgSz);
|
||||
if (ret2 != -1) {
|
||||
printf("error: wc_LmsKey_Verify returned %d, expected -1\n", ret2);
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
/* Flip it back. This should pass again. */
|
||||
lms_msg[msgSz / 2] ^= 1;
|
||||
ret = wc_LmsKey_Verify(&verifyKey, lms_L1H10W8_sig, LMS_L1H10W8_SIGLEN,
|
||||
(byte *) lms_msg, msgSz);
|
||||
if (ret != 0) {
|
||||
printf("error: wc_LmsKey_Verify returned %d, expected 0\n", ret);
|
||||
return WC_TEST_RET_ENC_EC(ret);
|
||||
}
|
||||
|
||||
/* Flip bits in a few places throughout the signature, stepping in multiple
|
||||
* of hash size. These should all fail with -1. */
|
||||
for (j = 0; j < (int) sigSz; j+= 4 * 32) {
|
||||
lms_L1H10W8_sig[j] ^= 1;
|
||||
|
||||
ret2 = wc_LmsKey_Verify(&verifyKey, lms_L1H10W8_sig,
|
||||
LMS_L1H10W8_SIGLEN,
|
||||
(byte *) lms_msg, msgSz);
|
||||
if (ret2 != -1) {
|
||||
/* Verify passed when it should have failed. */
|
||||
return WC_TEST_RET_ENC_I(j);
|
||||
}
|
||||
|
||||
/* Flip this spot back. */
|
||||
lms_L1H10W8_sig[j] ^= 1;
|
||||
}
|
||||
|
||||
wc_LmsKey_Free(&verifyKey);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/* ext_xmss.h
|
||||
*
|
||||
* Copyright (C) 2006-2023 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 EXT_XMSS_H
|
||||
#define EXT_XMSS_H
|
||||
|
||||
#ifdef WOLFSSL_HAVE_XMSS
|
||||
#include <wolfssl/wolfcrypt/xmss.h>
|
||||
|
||||
#if !defined(HAVE_LIBXMSS)
|
||||
#error "This code requires libxmss"
|
||||
#endif
|
||||
|
||||
#include <xmss.h>
|
||||
#include <params.h>
|
||||
|
||||
#if defined(WOLFSSL_WC_XMSS)
|
||||
#error "This code is incompatible with wolfCrypt's implementation of XMSS."
|
||||
#endif
|
||||
|
||||
struct XmssKey {
|
||||
unsigned char pk[XMSS_SHA256_PUBLEN];
|
||||
uint32_t oid;
|
||||
int is_xmssmt;
|
||||
xmss_params params;
|
||||
#ifndef WOLFSSL_XMSS_VERIFY_ONLY
|
||||
/* The secret key length is a function of xmss_params. */
|
||||
unsigned char * sk;
|
||||
word32 sk_len;
|
||||
write_private_key_cb write_private_key; /* Callback to write/update key. */
|
||||
read_private_key_cb read_private_key; /* Callback to read key. */
|
||||
void * context; /* Context arg passed to callbacks. */
|
||||
#endif /* ifndef WOLFSSL_XMSS_VERIFY_ONLY */
|
||||
enum wc_XmssState state;
|
||||
};
|
||||
|
||||
#endif /* WOLFSSL_HAVE_XMSS */
|
||||
#endif /* EXT_XMSS_H */
|
|
@ -81,7 +81,10 @@ nobase_include_HEADERS+= \
|
|||
wolfssl/wolfcrypt/sm4.h \
|
||||
wolfssl/wolfcrypt/lms.h \
|
||||
wolfssl/wolfcrypt/wc_lms.h \
|
||||
wolfssl/wolfcrypt/ext_lms.h
|
||||
wolfssl/wolfcrypt/ext_lms.h \
|
||||
wolfssl/wolfcrypt/xmss.h \
|
||||
wolfssl/wolfcrypt/wc_xmss.h \
|
||||
wolfssl/wolfcrypt/ext_xmss.h
|
||||
|
||||
noinst_HEADERS+= \
|
||||
wolfssl/wolfcrypt/port/aria/aria-crypt.h \
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/* wc_xmss.h
|
||||
*
|
||||
* Copyright (C) 2006-2023 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
|
||||
*/
|
||||
|
||||
#error "Contact wolfSSL to get the implementation of this file"
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
/* xmss.h
|
||||
*
|
||||
* Copyright (C) 2006-2023 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
|
||||
*/
|
||||
|
||||
/*!
|
||||
\file wolfssl/wolfcrypt/xmss.h
|
||||
*/
|
||||
|
||||
#ifndef WOLF_CRYPT_XMSS_H
|
||||
#define WOLF_CRYPT_XMSS_H
|
||||
|
||||
#include <wolfssl/wolfcrypt/types.h>
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
|
||||
#ifdef WOLFSSL_HAVE_XMSS
|
||||
|
||||
/* Note on XMSS/XMSS^MT pub/priv key sizes:
|
||||
* - The XMSS/XMSS^MT pub key has a defined format and size.
|
||||
* - The XMSS/XMSS^MT private key is implementation and parameter
|
||||
* specific. It does not have a standardized format or size.
|
||||
*
|
||||
* The XMSS/XMSS^MT public and secret key format and length is:
|
||||
* PK = OID || root || SEED;
|
||||
* PK_len = 4 + 2 * n
|
||||
*
|
||||
* SK = OID || (implementation defined)
|
||||
* SK_len = 4 + (implementation defined)
|
||||
*
|
||||
* where n is the number of bytes in the hash function, which is 32
|
||||
* in this SHA256 implementation.
|
||||
*
|
||||
* However the private key is implementation specific. For example,
|
||||
* in xmss-reference the private key size varies from 137 bytes to
|
||||
* 1377 bytes between slow and fast implementations with param name
|
||||
* "XMSSMT-SHA2_20/2_256".
|
||||
*
|
||||
* References:
|
||||
* - RFC 8391
|
||||
* - Table 2 of Kampanakis, Fluhrer, IACR, 2017.
|
||||
* */
|
||||
|
||||
#define XMSS_SHA256_PUBLEN (68)
|
||||
|
||||
/* Supported XMSS/XMSS^MT parameter set names:
|
||||
* We are supporting all SHA256 parameter sets with n=32 and
|
||||
* Winternitz=16, from RFC 8391 and NIST SP 800-208.
|
||||
*
|
||||
* ----------------------------------------------------------
|
||||
* | Name Oid n w len h d |
|
||||
* XMSS: | "XMSS-SHA2_10_256" 0x00000001 32 16 67 10 1 |
|
||||
* | "XMSS-SHA2_16_256" 0x00000002 32 16 67 16 1 |
|
||||
* | "XMSS-SHA2_20_256" 0x00000003 32 16 67 20 1 |
|
||||
* | |
|
||||
* XMSSMT: | "XMSSMT-SHA2_20/2_256" 0x00000001 32 16 67 20 2 |
|
||||
* | "XMSSMT-SHA2_20/4_256" 0x00000002 32 16 67 20 4 |
|
||||
* | "XMSSMT-SHA2_40/2_256" 0x00000003 32 16 67 40 2 |
|
||||
* | "XMSSMT-SHA2_40/4_256" 0x00000004 32 16 67 40 4 |
|
||||
* | "XMSSMT-SHA2_40/8_256" 0x00000005 32 16 67 40 8 |
|
||||
* | "XMSSMT-SHA2_60/3_256" 0x00000006 32 16 67 60 3 |
|
||||
* | "XMSSMT-SHA2_60/6_256" 0x00000007 32 16 67 60 6 |
|
||||
* | "XMSSMT-SHA2_60/12_256" 0x00000008 32 16 67 60 12 |
|
||||
* ----------------------------------------------------------
|
||||
*
|
||||
* Note that some XMSS and XMSSMT names do have overlapping Oids.
|
||||
*
|
||||
* References:
|
||||
* 1. NIST SP 800-208
|
||||
* 2. RFC 8391
|
||||
* */
|
||||
|
||||
#define XMSS_NAME_LEN (16) /* strlen("XMSS-SHA2_10_256") */
|
||||
#define XMSSMT_NAME_MIN_LEN (20) /* strlen("XMSSMT-SHA2_20/2_256") */
|
||||
#define XMSSMT_NAME_MAX_LEN (21) /* strlen("XMSSMT-SHA2_60/12_256") */
|
||||
|
||||
typedef struct XmssKey XmssKey;
|
||||
|
||||
/* Private key write and read callbacks. */
|
||||
typedef int (*write_private_key_cb)(const byte * priv, word32 privSz, void *context);
|
||||
typedef int (*read_private_key_cb)(byte * priv, word32 privSz, void *context);
|
||||
|
||||
/* Return codes returned by private key callbacks. */
|
||||
enum wc_XmssRc {
|
||||
WC_XMSS_RC_NONE,
|
||||
WC_XMSS_RC_BAD_ARG, /* Bad arg in read or write callback. */
|
||||
WC_XMSS_RC_WRITE_FAIL, /* Write or update private key failed. */
|
||||
WC_XMSS_RC_READ_FAIL, /* Read private key failed. */
|
||||
WC_XMSS_RC_SAVED_TO_NV_MEMORY, /* Wrote private key to nonvolatile storage. */
|
||||
WC_XMSS_RC_READ_TO_MEMORY /* Read private key from storage. */
|
||||
};
|
||||
|
||||
/* enum wc_XmssState is to help track the state of an XMSS Key. */
|
||||
enum wc_XmssState {
|
||||
WC_XMSS_STATE_FREED, /* Key has been freed from memory. */
|
||||
WC_XMSS_STATE_INITED, /* Key has been inited, ready to set parms.*/
|
||||
WC_XMSS_STATE_PARMSET, /* Parms are set, ready to MakeKey or Reload. */
|
||||
WC_XMSS_STATE_OK, /* Able to sign signatures and verify. */
|
||||
WC_XMSS_STATE_VERIFYONLY, /* A public only XmssKey. */
|
||||
WC_XMSS_STATE_BAD, /* Can't guarantee key's state. */
|
||||
WC_XMSS_STATE_NOSIGS /* Signatures exhausted. */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
WOLFSSL_API int wc_XmssKey_Init(XmssKey * key, void * heap, int devId);
|
||||
WOLFSSL_API int wc_XmssKey_SetParamStr(XmssKey * key, const char * str);
|
||||
#ifndef WOLFSSL_XMSS_VERIFY_ONLY
|
||||
WOLFSSL_API int wc_XmssKey_SetWriteCb(XmssKey * key,
|
||||
write_private_key_cb write_cb);
|
||||
WOLFSSL_API int wc_XmssKey_SetReadCb(XmssKey * key,
|
||||
read_private_key_cb read_cb);
|
||||
WOLFSSL_API int wc_XmssKey_SetContext(XmssKey * key, void * context);
|
||||
WOLFSSL_API int wc_XmssKey_MakeKey(XmssKey * key, WC_RNG * rng);
|
||||
WOLFSSL_API int wc_XmssKey_Reload(XmssKey * key);
|
||||
WOLFSSL_API int wc_XmssKey_GetPrivLen(const XmssKey * key, word32 * len);
|
||||
WOLFSSL_API int wc_XmssKey_Sign(XmssKey * key, byte * sig, word32 * sigSz,
|
||||
const byte * msg, int msgSz);
|
||||
WOLFSSL_API int wc_XmssKey_SigsLeft(XmssKey * key);
|
||||
#endif /* ifndef WOLFSSL_XMSS_VERIFY_ONLY */
|
||||
WOLFSSL_API void wc_XmssKey_Free(XmssKey * key);
|
||||
WOLFSSL_API int wc_XmssKey_GetSigLen(const XmssKey * key, word32 * len);
|
||||
WOLFSSL_API int wc_XmssKey_GetPubLen(const XmssKey * key, word32 * len);
|
||||
WOLFSSL_API int wc_XmssKey_ExportPub(XmssKey * keyDst, const XmssKey * keySrc);
|
||||
WOLFSSL_API int wc_XmssKey_ExportPubRaw(const XmssKey * key, byte * out,
|
||||
word32 * outLen);
|
||||
WOLFSSL_API int wc_XmssKey_ImportPubRaw(XmssKey * key, const byte * in,
|
||||
word32 inLen);
|
||||
WOLFSSL_API int wc_XmssKey_Verify(XmssKey * key, const byte * sig, word32 sigSz,
|
||||
const byte * msg, int msgSz);
|
||||
WOLFSSL_API const char * wc_XmssKey_RcToStr(enum wc_XmssRc lmsRc);
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* WOLFSSL_HAVE_XMSS */
|
||||
#endif /* WOLF_CRYPT_XMSS_H */
|
Loading…
Reference in New Issue