Merge pull request #6738 from philljj/wolfcrypt_lms_verify_only

Wolfcrypt LMS verify-only support
This commit is contained in:
JacobBarthelmeh
2023-09-01 13:25:31 -06:00
committed by GitHub
7 changed files with 647 additions and 181 deletions

23
INSTALL
View File

@ -264,20 +264,20 @@ We also have vcpkg ports for wolftpm, wolfmqtt and curl.
branch of the hash-sigs project. branch of the hash-sigs project.
Currently the hash-sigs project only builds static libraries: Currently the hash-sigs project only builds static libraries:
- hss_verify.a: a single-threaded verify-only static lib.
- hss_lib.a: a single-threaded static lib. - hss_lib.a: a single-threaded static lib.
- hss_lib_thread.a: a multi-threaded static lib. - hss_lib_thread.a: a multi-threaded static lib.
The multi-threaded version will mainly have speedups for key The multi-threaded version will mainly have speedups for key
generation and signing. generation and signing.
Additionally, the hash-sigs project can be modified to build The default LMS build (--enable-lms) will look for
and install a shared library in /usr/local with either single hss_lib.a first, and hss_lib_thread.a second, in a specified
or multi-threaded versions. If the shared version has been hash-sigs dir.
built, libhss.so is the assumed name.
wolfSSL supports either option, and by default will look for The LMS verify-only build (--enable-lms=verify-only) will look
hss_lib.a first, and hss_lib_thread.a second, and libhss.so for hss_verify.a only, which is a slimmer library that includes
lastly, in a specified hash-sigs dir. only the minimal functions necessary for signature verification.
How to get and build the hash-sigs library: How to get and build the hash-sigs library:
$ mkdir ~/hash_sigs $ mkdir ~/hash_sigs
@ -299,12 +299,17 @@ We also have vcpkg ports for wolftpm, wolfmqtt and curl.
$ ls *.a $ ls *.a
hss_lib_thread.a hss_lib_thread.a
To build verify-only:
$ make hss_verify.a
$ ls *.a
hss_verify.a
Build wolfSSL with Build wolfSSL with
$ ./configure \ $ ./configure \
--enable-static \ --enable-static \
--disable-shared \ --disable-shared \
--enable-lms=yes \ --enable-lms \
--with-liblms=<path to dir containing hss_lib_thread.a> --with-liblms=<path to dir containing hss_lib.a or hss_lib_thread.a>
$ make $ make
Run the benchmark against LMS/HSS with: Run the benchmark against LMS/HSS with:

View File

@ -1141,69 +1141,6 @@ then
fi fi
# liblms
# Get the path to the hash-sigs LMS HSS lib.
ENABLED_LIBLMS="no"
tryliblmsdir=""
AC_ARG_WITH([liblms],
[AS_HELP_STRING([--with-liblms=PATH],[PATH to hash-sigs LMS/HSS install (default /usr/local) EXPERIMENTAL!])],
[
AC_MSG_CHECKING([for liblms])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <hss.h>]], [[ param_set_t lm_type; param_set_t lm_ots_type; hss_get_public_key_len(4, &lm_type, &lm_ots_type); ]])], [ liblms_linked=yes ],[ liblms_linked=no ])
if test "x$liblms_linked" = "xno" ; then
if test "x$withval" != "xno" ; then
tryliblmsdir=$withval
fi
if test "x$withval" = "xyes" ; then
tryliblmsdir="/usr/local"
fi
# 1. By default use the hash-sigs single-threaded static library.
# 2. If 1 not found, then use the multi-threaded static lib.
# 3. If 2 not found, then use the multi-threaded dynamic lib.
if test -e $tryliblmsdir/hss_lib.a; then
CPPFLAGS="$AM_CPPFLAGS -DHAVE_LIBLMS -I$tryliblmsdir"
LIB_STATIC_ADD="$LIB_STATIC_ADD $tryliblmsdir/hss_lib.a"
enable_shared=no
enable_static=yes
liblms_linked=yes
elif test -e $tryliblmsdir/hss_lib_thread.a; then
CPPFLAGS="$AM_CPPFLAGS -DHAVE_LIBLMS -I$tryliblmsdir"
LIB_STATIC_ADD="$LIB_STATIC_ADD $tryliblmsdir/hss_lib_thread.a"
enable_shared=no
enable_static=yes
liblms_linked=yes
elif test -e $tryliblmsdir/lib/libhss.so; then
LIBS="$LIBS -lhss"
CPPFLAGS="$AM_CPPFLAGS -DHAVE_LIBLMS -I$tryliblmsdir/include/hss"
LDFLAGS="$AM_LDFLAGS $LDFLAGS -L$tryliblmsdir/lib"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <hss.h>]], [[ param_set_t lm_type; param_set_t lm_ots_type; hss_get_public_key_len(4, &lm_type, &lm_ots_type); ]])], [ liblms_linked=yes ],[ liblms_linked=no ])
else
AC_MSG_ERROR([liblms isn't found.
If it's already installed, specify its path using --with-liblms=/dir/])
fi
if test "x$liblms_linked" = "xno" ; then
AC_MSG_ERROR([liblms isn't found.
If it's already installed, specify its path using --with-liblms=/dir/])
fi
AC_MSG_RESULT([yes])
AM_CPPFLAGS="$CPPFLAGS"
AM_LDFLAGS="$LDFLAGS"
else
AC_MSG_RESULT([yes])
fi
AM_CFLAGS="$AM_CFLAGS -DHAVE_LIBLMS"
ENABLED_LIBLMS="yes"
]
)
# LMS # LMS
AC_ARG_ENABLE([lms], AC_ARG_ENABLE([lms],
[AS_HELP_STRING([--enable-lms],[Enable stateful LMS/HSS signatures (default: disabled)])], [AS_HELP_STRING([--enable-lms],[Enable stateful LMS/HSS signatures (default: disabled)])],
@ -1219,6 +1156,10 @@ do
;; ;;
no) no)
;; ;;
verify-only)
LMS_VERIFY_ONLY=yes
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_LMS_VERIFY_ONLY"
;;
wolfssl) wolfssl)
ENABLED_WC_LMS=yes ENABLED_WC_LMS=yes
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_LMS" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_LMS"
@ -1243,6 +1184,72 @@ then
fi fi
fi fi
# liblms
# Get the path to the hash-sigs LMS HSS lib.
ENABLED_LIBLMS="no"
tryliblmsdir=""
AC_ARG_WITH([liblms],
[AS_HELP_STRING([--with-liblms=PATH],[PATH to hash-sigs LMS/HSS install (default /usr/local) EXPERIMENTAL!])],
[
AC_MSG_CHECKING([for liblms])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <hss.h>]], [[ param_set_t lm_type; param_set_t lm_ots_type; hss_get_public_key_len(4, &lm_type, &lm_ots_type); ]])], [ liblms_linked=yes ],[ liblms_linked=no ])
if test "x$liblms_linked" = "xno" ; then
if test "x$withval" != "xno" ; then
tryliblmsdir=$withval
fi
if test "x$withval" = "xyes" ; then
tryliblmsdir="/usr/local"
fi
# 1. If verify only build, use hss_verify.a
# 2. If normal build, by default use single-threaded hss_lib.a
# 3. If 2 not found, then use the multi-threaded hss_lib_thread.a
if test "$LMS_VERIFY_ONLY" = "yes"; then
if test -e $tryliblmsdir/hss_verify.a; then
CPPFLAGS="$AM_CPPFLAGS -DHAVE_LIBLMS -I$tryliblmsdir"
LIB_STATIC_ADD="$LIB_STATIC_ADD $tryliblmsdir/hss_verify.a"
enable_shared=no
enable_static=yes
liblms_linked=yes
else
AC_MSG_ERROR([hss_verify.a isn't found.
If it's already installed, specify its path using --with-liblms=/dir/])
fi
elif test -e $tryliblmsdir/hss_lib.a; then
CPPFLAGS="$AM_CPPFLAGS -DHAVE_LIBLMS -I$tryliblmsdir"
LIB_STATIC_ADD="$LIB_STATIC_ADD $tryliblmsdir/hss_lib.a"
enable_shared=no
enable_static=yes
liblms_linked=yes
elif test -e $tryliblmsdir/hss_lib_thread.a; then
CPPFLAGS="$AM_CPPFLAGS -DHAVE_LIBLMS -I$tryliblmsdir"
LIB_STATIC_ADD="$LIB_STATIC_ADD $tryliblmsdir/hss_lib_thread.a"
enable_shared=no
enable_static=yes
liblms_linked=yes
else
AC_MSG_ERROR([liblms isn't found.
If it's already installed, specify its path using --with-liblms=/dir/])
fi
if test "x$liblms_linked" = "xno" ; then
AC_MSG_ERROR([liblms isn't found.
If it's already installed, specify its path using --with-liblms=/dir/])
fi
AC_MSG_RESULT([yes])
AM_CPPFLAGS="$CPPFLAGS"
AM_LDFLAGS="$LDFLAGS"
else
AC_MSG_RESULT([yes])
fi
AM_CFLAGS="$AM_CFLAGS -DHAVE_LIBLMS"
ENABLED_LIBLMS="yes"
]
)
# SINGLE THREADED # SINGLE THREADED
AC_ARG_ENABLE([singlethreaded], AC_ARG_ENABLE([singlethreaded],

View File

@ -157,7 +157,7 @@
#include <wolfssl/wolfcrypt/ext_kyber.h> #include <wolfssl/wolfcrypt/ext_kyber.h>
#endif #endif
#endif #endif
#ifdef WOLFSSL_HAVE_LMS #if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
#include <wolfssl/wolfcrypt/lms.h> #include <wolfssl/wolfcrypt/lms.h>
#ifdef HAVE_LIBLMS #ifdef HAVE_LIBLMS
#include <wolfssl/wolfcrypt/ext_lms.h> #include <wolfssl/wolfcrypt/ext_lms.h>
@ -870,7 +870,7 @@ static const bench_alg bench_other_opt[] = {
#endif /* !WOLFSSL_BENCHMARK_ALL && !NO_MAIN_DRIVER */ #endif /* !WOLFSSL_BENCHMARK_ALL && !NO_MAIN_DRIVER */
#if defined(WOLFSSL_HAVE_LMS) #if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
typedef struct bench_pq_hash_sig_alg { typedef struct bench_pq_hash_sig_alg {
/* Command line option string. */ /* Command line option string. */
const char* str; const char* str;
@ -883,7 +883,7 @@ static const bench_pq_hash_sig_alg bench_pq_hash_sig_opt[] = {
{ "-lms_hss", BENCH_LMS_HSS}, { "-lms_hss", BENCH_LMS_HSS},
{ NULL, 0} { NULL, 0}
}; };
#endif /* if defined(WOLFSSL_HAVE_LMS) */ #endif /* if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) */
#if defined(HAVE_PQC) && defined(HAVE_LIBOQS) #if defined(HAVE_PQC) && defined(HAVE_LIBOQS)
/* The post-quantum-specific mapping of command line option to bit values and /* The post-quantum-specific mapping of command line option to bit values and
@ -2832,11 +2832,11 @@ static void* benchmarks_do(void* args)
} }
#endif #endif
#ifdef WOLFSSL_HAVE_LMS #if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
if (bench_all || (bench_pq_hash_sig_algs & BENCH_LMS_HSS)) { if (bench_all || (bench_pq_hash_sig_algs & BENCH_LMS_HSS)) {
bench_lms(); bench_lms();
} }
#endif #endif /* if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) */
#ifdef HAVE_ECC #ifdef HAVE_ECC
if (bench_all || (bench_asym_algs & BENCH_ECC_MAKEKEY) || if (bench_all || (bench_asym_algs & BENCH_ECC_MAKEKEY) ||
@ -7664,7 +7664,7 @@ void bench_kyber(int type)
} }
#endif #endif
#ifdef WOLFSSL_HAVE_LMS #if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
/* WC_LMS_PARM_L2_H10_W2 /* WC_LMS_PARM_L2_H10_W2
* signature length: 9300 */ * signature length: 9300 */
static const byte lms_priv_L2_H10_W2[64] = static const byte lms_priv_L2_H10_W2[64] =
@ -8031,7 +8031,7 @@ void bench_lms(void)
return; return;
} }
#endif /* ifdef WOLFSSL_HAVE_LMS */ #endif /* if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) */
#ifdef HAVE_ECC #ifdef HAVE_ECC
@ -10368,10 +10368,10 @@ static void Usage(void)
print_alg(bench_pq_asym_opt2[i].str, &line); print_alg(bench_pq_asym_opt2[i].str, &line);
#endif /* HAVE_LIBOQS && HAVE_SPHINCS */ #endif /* HAVE_LIBOQS && HAVE_SPHINCS */
#endif /* HAVE_PQC */ #endif /* HAVE_PQC */
#if defined(WOLFSSL_HAVE_LMS) #if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
for (i=0; bench_pq_hash_sig_opt[i].str != NULL; i++) for (i=0; bench_pq_hash_sig_opt[i].str != NULL; i++)
print_alg(bench_pq_hash_sig_opt[i].str, &line); print_alg(bench_pq_hash_sig_opt[i].str, &line);
#endif /* if defined(WOLFSSL_HAVE_LMS) */ #endif /* if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) */
printf("\n"); printf("\n");
#endif /* !WOLFSSL_BENCHMARK_ALL */ #endif /* !WOLFSSL_BENCHMARK_ALL */
e++; e++;
@ -10634,7 +10634,7 @@ int wolfcrypt_benchmark_main(int argc, char** argv)
} }
} }
#if defined(WOLFSSL_HAVE_LMS) #if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
/* post-quantum stateful hash-based signatures */ /* post-quantum stateful hash-based signatures */
for (i=0; !optMatched && bench_pq_hash_sig_opt[i].str != NULL; i++) { 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)) { if (string_matches(argv[1], bench_pq_hash_sig_opt[i].str)) {
@ -10643,7 +10643,7 @@ int wolfcrypt_benchmark_main(int argc, char** argv)
optMatched = 1; optMatched = 1;
} }
} }
#endif /* if defined(WOLFSSL_HAVE_LMS) */ #endif
#endif #endif
if (!optMatched) { if (!optMatched) {
printf("Option not recognized: %s\n", argv[1]); printf("Option not recognized: %s\n", argv[1]);

View File

@ -37,6 +37,7 @@
#include <wolfcrypt/src/misc.c> #include <wolfcrypt/src/misc.c>
#endif #endif
#ifndef WOLFSSL_LMS_VERIFY_ONLY
/* If built against hss_lib_thread.a, the hash-sigs lib will spawn /* If built against hss_lib_thread.a, the hash-sigs lib will spawn
* worker threads to parallelize cpu intensive tasks. This will mainly * worker threads to parallelize cpu intensive tasks. This will mainly
* speedup key generation and signing, and to a lesser extent * speedup key generation and signing, and to a lesser extent
@ -101,7 +102,8 @@ static bool LmsWritePrivKey(unsigned char *private_key,
} }
/* Use write callback that saves private key to non-volatile storage. */ /* Use write callback that saves private key to non-volatile storage. */
ret = key->write_private_key(private_key, len_private_key, key->context); ret = key->write_private_key(private_key, (word32)len_private_key,
key->context);
if (ret != WC_LMS_RC_SAVED_TO_NV_MEMORY) { if (ret != WC_LMS_RC_SAVED_TO_NV_MEMORY) {
WOLFSSL_MSG("error: LmsKey write_private_key failed"); WOLFSSL_MSG("error: LmsKey write_private_key failed");
@ -140,7 +142,8 @@ static bool LmsReadPrivKey(unsigned char *private_key,
} }
/* Use read callback that reads private key from non-volatile storage. */ /* Use read callback that reads private key from non-volatile storage. */
ret = key->read_private_key(private_key, len_private_key, key->context); ret = key->read_private_key(private_key, (word32)len_private_key,
key->context);
if (ret != WC_LMS_RC_READ_TO_MEMORY) { if (ret != WC_LMS_RC_READ_TO_MEMORY) {
WOLFSSL_MSG("error: LmsKey read_private_key failed"); WOLFSSL_MSG("error: LmsKey read_private_key failed");
@ -151,6 +154,7 @@ static bool LmsReadPrivKey(unsigned char *private_key,
return true; return true;
} }
#endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY */
const char * wc_LmsKey_ParmToStr(enum wc_LmsParm lmsParm) const char * wc_LmsKey_ParmToStr(enum wc_LmsParm lmsParm)
{ {
@ -242,14 +246,16 @@ int wc_LmsKey_Init(LmsKey * key, void * heap, int devId)
ForceZero(key, sizeof(LmsKey)); ForceZero(key, sizeof(LmsKey));
/* Set the max number of worker threads that hash-sigs can spawn. */ #ifndef WOLFSSL_LMS_VERIFY_ONLY
hss_init_extra_info(&key->info); hss_init_extra_info(&key->info);
/* Set the max number of worker threads that hash-sigs can spawn. */
hss_extra_info_set_threads(&key->info, EXT_LMS_MAX_THREADS); hss_extra_info_set_threads(&key->info, EXT_LMS_MAX_THREADS);
key->working_key = NULL; key->working_key = NULL;
key->write_private_key = NULL; key->write_private_key = NULL;
key->read_private_key = NULL; key->read_private_key = NULL;
key->context = NULL; key->context = NULL;
#endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY */
key->state = WC_LMS_STATE_INITED; key->state = WC_LMS_STATE_INITED;
return 0; return 0;
@ -405,6 +411,70 @@ int wc_LmsKey_SetParameters(LmsKey * key, int levels, int height,
return 0; return 0;
} }
/* Get the parameters of an LMS key.
*
* Key must be inited and parameters set before calling this.
*
* Returns 0 on success.
* */
int wc_LmsKey_GetParameters(const LmsKey * key, int * levels, int * height,
int * winternitz)
{
if (key == NULL || levels == NULL || height == NULL || winternitz == NULL) {
return BAD_FUNC_ARG;
}
/* This shouldn't happen, but check the LmsKey parameters aren't invalid. */
if (key->levels < MIN_HSS_LEVELS || key->levels > MAX_HSS_LEVELS) {
WOLFSSL_MSG("error: LmsKey invalid level parameter");
return -1;
}
*levels = key->levels;
switch (key->lm_type[0]) {
case LMS_SHA256_N32_H5:
*height = 5;
break;
case LMS_SHA256_N32_H10:
*height = 10;
break;
case LMS_SHA256_N32_H15:
*height = 15;
break;
case LMS_SHA256_N32_H20:
*height = 20;
break;
case LMS_SHA256_N32_H25:
*height = 25;
break;
default:
WOLFSSL_MSG("error: LmsKey invalid height parameter");
return -1;
}
switch (key->lm_ots_type[0]) {
case LMOTS_SHA256_N32_W1:
*winternitz = 1;
break;
case LMOTS_SHA256_N32_W2:
*winternitz = 2;
break;
case LMOTS_SHA256_N32_W4:
*winternitz = 4;
break;
case LMOTS_SHA256_N32_W8:
*winternitz = 8;
break;
default:
WOLFSSL_MSG("error: LmsKey invalid winternitz parameter");
return -1;
}
return 0;
}
/* Frees the LMS key from memory. /* Frees the LMS key from memory.
* *
* This does not affect the private key saved to non-volatile storage. * This does not affect the private key saved to non-volatile storage.
@ -415,10 +485,12 @@ void wc_LmsKey_Free(LmsKey* key)
return; return;
} }
#ifndef WOLFSSL_LMS_VERIFY_ONLY
if (key->working_key != NULL) { if (key->working_key != NULL) {
hss_free_working_key(key->working_key); hss_free_working_key(key->working_key);
key->working_key = NULL; key->working_key = NULL;
} }
#endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY */
ForceZero(key, sizeof(LmsKey)); ForceZero(key, sizeof(LmsKey));
@ -427,6 +499,7 @@ void wc_LmsKey_Free(LmsKey* key)
return; return;
} }
#ifndef WOLFSSL_LMS_VERIFY_ONLY
/* Set the write private key callback to the LMS key structure. /* Set the write private key callback to the LMS key structure.
* *
* The callback must be able to write/update the private key to * The callback must be able to write/update the private key to
@ -647,7 +720,7 @@ int wc_LmsKey_Reload(LmsKey * key)
/* Given a levels, height, winternitz parameter set, determine /* Given a levels, height, winternitz parameter set, determine
* the private key length */ * the private key length */
int wc_LmsKey_GetPrivLen(LmsKey * key, word32 * len) int wc_LmsKey_GetPrivLen(const LmsKey * key, word32 * len)
{ {
if (key == NULL || len == NULL) { if (key == NULL || len == NULL) {
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
@ -659,65 +732,6 @@ int wc_LmsKey_GetPrivLen(LmsKey * key, word32 * len)
return 0; return 0;
} }
/* Given a levels, height, winternitz parameter set, determine
* the public key length */
int wc_LmsKey_GetPubLen(LmsKey * key, word32 * len)
{
if (key == NULL || len == NULL) {
return BAD_FUNC_ARG;
}
*len = (word32) hss_get_public_key_len(key->levels, key->lm_type,
key->lm_ots_type);
return 0;
}
/* Export a generated public key and parameter set from one LmsKey
* to another. Use this to prepare a signature verification LmsKey
* that is pub only.
*
* Though the public key is all that is used to verify signatures,
* the parameter set is needed to calculate the signature length
* before hand. */
int wc_LmsKey_ExportPub(LmsKey * keyDst, const LmsKey * keySrc)
{
if (keyDst == NULL || keySrc == NULL) {
return BAD_FUNC_ARG;
}
ForceZero(keyDst, sizeof(LmsKey));
XMEMCPY(keyDst->pub, keySrc->pub, sizeof(keySrc->pub));
XMEMCPY(keyDst->lm_type, keySrc->lm_type, sizeof(keySrc->lm_type));
XMEMCPY(keyDst->lm_ots_type, keySrc->lm_ots_type,
sizeof(keySrc->lm_ots_type));
keyDst->levels = keySrc->levels;
/* Mark this key as verify only, to prevent misuse. */
keyDst->state = WC_LMS_STATE_VERIFYONLY;
return 0;
}
/* Given a levels, height, winternitz parameter set, determine
* the signature length.
*
* Call this before wc_LmsKey_Sign so you know the length of
* the required signature buffer. */
int wc_LmsKey_GetSigLen(LmsKey * key, word32 * len)
{
if (key == NULL || len == NULL) {
return BAD_FUNC_ARG;
}
*len = (word32) hss_get_signature_len(key->levels, key->lm_type,
key->lm_ots_type);
return 0;
}
int wc_LmsKey_Sign(LmsKey* key, byte * sig, word32 * sigSz, const byte * msg, int wc_LmsKey_Sign(LmsKey* key, byte * sig, word32 * sigSz, const byte * msg,
int msgSz) int msgSz)
{ {
@ -773,27 +787,6 @@ int wc_LmsKey_Sign(LmsKey* key, byte * sig, word32 * sigSz, const byte * msg,
return 0; return 0;
} }
int wc_LmsKey_Verify(LmsKey * key, const byte * sig, word32 sigSz,
const byte * msg, int msgSz)
{
bool result = true;
if (key == NULL || sig == NULL || msg == NULL) {
return BAD_FUNC_ARG;
}
result = hss_validate_signature(key->pub, (const void *) msg, msgSz, sig,
sigSz, &key->info);
if (!result) {
WOLFSSL_MSG("error: hss_validate_signature failed");
return -1;
}
return 0;
}
/* Returns 1 if there are signatures remaining. /* Returns 1 if there are signatures remaining.
* Returns 0 if available signatures are exhausted. * Returns 0 if available signatures are exhausted.
* *
@ -815,4 +808,165 @@ int wc_LmsKey_SigsLeft(LmsKey * key)
return 1; return 1;
} }
#endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY*/
/* Given a levels, height, winternitz parameter set, determine
* the public key length */
int wc_LmsKey_GetPubLen(const LmsKey * key, word32 * len)
{
if (key == NULL || len == NULL) {
return BAD_FUNC_ARG;
}
*len = (word32) hss_get_public_key_len(key->levels, key->lm_type,
key->lm_ots_type);
return 0;
}
/* Export a generated public key and parameter set from one LmsKey
* to another. Use this to prepare a signature verification LmsKey
* that is pub only.
*
* Though the public key is all that is used to verify signatures,
* the parameter set is needed to calculate the signature length
* before hand. */
int wc_LmsKey_ExportPub(LmsKey * keyDst, const LmsKey * keySrc)
{
if (keyDst == NULL || keySrc == NULL) {
return BAD_FUNC_ARG;
}
ForceZero(keyDst, sizeof(LmsKey));
XMEMCPY(keyDst->pub, keySrc->pub, sizeof(keySrc->pub));
XMEMCPY(keyDst->lm_type, keySrc->lm_type, sizeof(keySrc->lm_type));
XMEMCPY(keyDst->lm_ots_type, keySrc->lm_ots_type,
sizeof(keySrc->lm_ots_type));
keyDst->levels = keySrc->levels;
/* Mark this key as verify only, to prevent misuse. */
keyDst->state = WC_LMS_STATE_VERIFYONLY;
return 0;
}
/* Exports the raw LMS 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.
*
* - Returns 0 on success, and sets outLen to LMS pubLen.
* - Returns BUFFER_E if outLen < LMS pubLen.
*
* Call wc_LmsKey_GetPubLen beforehand to determine pubLen.
* */
int wc_LmsKey_ExportPubRaw(const LmsKey * key, byte * out, word32 * outLen)
{
int ret = 0;
word32 pubLen = 0;
if (key == NULL || out == NULL || outLen == NULL) {
return BAD_FUNC_ARG;
}
ret = wc_LmsKey_GetPubLen(key, &pubLen);
if (ret != 0) {
WOLFSSL_MSG("error: wc_LmsKey_GetPubLen failed");
return -1;
}
if (*outLen < pubLen) {
return BUFFER_E;
}
XMEMCPY(out, key->pub, pubLen);
*outLen = pubLen;
return 0;
}
/* Imports a raw public key buffer from in array to LmsKey key.
*
* The LMS parameters must be set first with wc_LmsKey_SetLmsParm or
* wc_LmsKey_SetParameters, and inLen must match the length returned
* by wc_LmsKey_GetPubLen.
*
* - Returns 0 on success.
* - Returns BUFFER_E if inlen != LMS pubLen.
*
* Call wc_LmsKey_GetPubLen beforehand to determine pubLen.
* */
int wc_LmsKey_ImportPubRaw(LmsKey * key, const byte * in, word32 inLen)
{
int ret = 0;
word32 pubLen = 0;
if (key == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
ret = wc_LmsKey_GetPubLen(key, &pubLen);
if (ret != 0) {
WOLFSSL_MSG("error: wc_LmsKey_GetPubLen failed");
return -1;
}
if (inLen != pubLen) {
/* Something inconsistent. Parameters weren't set, or input
* pub key is wrong.*/
return BUFFER_E;
}
XMEMCPY(key->pub, in, pubLen);
return 0;
}
/* Given a levels, height, winternitz parameter set, determine
* the signature length.
*
* Call this before wc_LmsKey_Sign so you know the length of
* the required signature buffer. */
int wc_LmsKey_GetSigLen(const LmsKey * key, word32 * len)
{
if (key == NULL || len == NULL) {
return BAD_FUNC_ARG;
}
*len = (word32) hss_get_signature_len(key->levels, key->lm_type,
key->lm_ots_type);
return 0;
}
int wc_LmsKey_Verify(LmsKey * key, const byte * sig, word32 sigSz,
const byte * msg, int msgSz)
{
bool result = true;
if (key == NULL || sig == NULL || msg == NULL) {
return BAD_FUNC_ARG;
}
#ifdef WOLFSSL_LMS_VERIFY_ONLY
result = hss_validate_signature(key->pub, (const void *) msg, msgSz, sig,
sigSz, NULL);
#else
result = hss_validate_signature(key->pub, (const void *) msg, msgSz, sig,
sigSz, &key->info);
#endif
if (!result) {
WOLFSSL_MSG("error: hss_validate_signature failed");
return -1;
}
return 0;
}
#endif /* WOLFSSL_HAVE_LMS */ #endif /* WOLFSSL_HAVE_LMS */

View File

@ -293,7 +293,7 @@ const byte const_byte_array[] = "A+Gd\0\0\0";
#include <wolfssl/wolfcrypt/ext_kyber.h> #include <wolfssl/wolfcrypt/ext_kyber.h>
#endif #endif
#endif #endif
#ifdef WOLFSSL_HAVE_LMS #if defined(WOLFSSL_HAVE_LMS)
#include <wolfssl/wolfcrypt/lms.h> #include <wolfssl/wolfcrypt/lms.h>
#ifdef HAVE_LIBLMS #ifdef HAVE_LIBLMS
#include <wolfssl/wolfcrypt/ext_lms.h> #include <wolfssl/wolfcrypt/ext_lms.h>
@ -574,8 +574,13 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t scrypt_test(void);
#ifdef WOLFSSL_HAVE_KYBER #ifdef WOLFSSL_HAVE_KYBER
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t kyber_test(void); WOLFSSL_TEST_SUBROUTINE wc_test_ret_t kyber_test(void);
#endif #endif
#ifdef WOLFSSL_HAVE_LMS #if defined(WOLFSSL_HAVE_LMS)
WOLFSSL_TEST_SUBROUTINE int lms_test(void); #if !defined(WOLFSSL_LMS_VERIFY_ONLY)
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void);
#endif
#if defined(WOLFSSL_LMS_VERIFY_ONLY) && !defined(WOLFSSL_SMALL_STACK)
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test_verify_only(void);
#endif
#endif #endif
#ifdef WOLFCRYPT_HAVE_ECCSI #ifdef WOLFCRYPT_HAVE_ECCSI
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t eccsi_test(void); WOLFSSL_TEST_SUBROUTINE wc_test_ret_t eccsi_test(void);
@ -1606,12 +1611,21 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\
TEST_PASS("KYBER test passed!\n"); TEST_PASS("KYBER test passed!\n");
#endif #endif
#ifdef WOLFSSL_HAVE_LMS #if defined(WOLFSSL_HAVE_LMS)
#if !defined(WOLFSSL_LMS_VERIFY_ONLY)
if ( (ret = lms_test()) != 0) if ( (ret = lms_test()) != 0)
TEST_FAIL("LMS test failed!\n", ret); TEST_FAIL("LMS test failed!\n", ret);
else else
TEST_PASS("LMS test passed!\n"); TEST_PASS("LMS test passed!\n");
#endif #endif
#if defined(WOLFSSL_LMS_VERIFY_ONLY) && !defined(WOLFSSL_SMALL_STACK)
if ( (ret = lms_test_verify_only()) != 0)
TEST_FAIL("LMS test failed!\n", ret);
else
TEST_PASS("LMS test passed!\n");
#endif
#endif /* if defined(WOLFSSL_HAVE_LMS) */
#ifdef WOLFCRYPT_HAVE_ECCSI #ifdef WOLFCRYPT_HAVE_ECCSI
if ( (ret = eccsi_test()) != 0) if ( (ret = eccsi_test()) != 0)
@ -34957,7 +34971,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t kyber_test(void)
#endif /* WOLFSSL_HAVE_KYBER */ #endif /* WOLFSSL_HAVE_KYBER */
#ifdef WOLFSSL_HAVE_LMS #if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
static int lms_write_key_mem(const byte * priv, word32 privSz, void *context) static int lms_write_key_mem(const byte * priv, word32 privSz, void *context)
{ {
/* WARNING: THIS IS AN INSECURE WRITE CALLBACK THAT SHOULD ONLY /* WARNING: THIS IS AN INSECURE WRITE CALLBACK THAT SHOULD ONLY
@ -34979,7 +34993,7 @@ static int lms_read_key_mem(byte * priv, word32 privSz, void *context)
* test has a signature of 8688 bytes. */ * test has a signature of 8688 bytes. */
#define WC_TEST_LMS_SIG_LEN (8688) #define WC_TEST_LMS_SIG_LEN (8688)
WOLFSSL_TEST_SUBROUTINE int lms_test(void) WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
{ {
int ret; int ret;
int sigsLeft = 0; int sigsLeft = 0;
@ -35092,7 +35106,283 @@ WOLFSSL_TEST_SUBROUTINE int lms_test(void)
return ret; return ret;
} }
#endif /* WOLFSSL_HAVE_LMS */ #endif /* if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) */
#if defined(WOLFSSL_HAVE_LMS) && defined(WOLFSSL_LMS_VERIFY_ONLY) && \
!defined(WOLFSSL_SMALL_STACK)
/* A simple LMS verify only test.
*
* Note: LMS signature sizes are a function of their parameters. This
* test has a signature of 1456 bytes:
* levels: 1
* height: 10
* winternitz: 8
* max sigs: 2 ** (1 * 10) = 1024
* signature length: 1456
* */
static byte lms_L1H10W8_pub[HSS_MAX_PUBLIC_KEY_LEN] =
{
0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,
0x00,0x00,0x00,0x04,0xA1,0x26,0x76,0xF8,
0xBB,0x0B,0xC0,0x82,0x21,0x71,0x0B,0x2E,
0x8C,0xA6,0xEF,0x12,0xED,0x41,0x0E,0x8C,
0xAF,0x11,0x93,0x34,0x7B,0x49,0x79,0xB7,
0xDE,0x63,0x1C,0xFE,0x1F,0xD1,0x17,0x49,
0xCD,0x5C,0xD4,0x26,0xA0,0x53,0x26,0x1A,
0xC5,0xB4,0x8F,0x23
};
#define LMS_L1H10W8_SIGLEN (1456)
static byte lms_L1H10W8_sig[LMS_L1H10W8_SIGLEN] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
0x00,0x00,0x00,0x04,0x18,0x70,0x09,0x2E,
0x21,0xC9,0x6A,0xC9,0x5C,0xB6,0xB0,0xAA,
0xC3,0xED,0x6E,0x66,0x2F,0xCC,0x45,0x81,
0xBC,0xBA,0x44,0x96,0x1C,0xBF,0x4E,0xFB,
0x7A,0x46,0xFB,0xBE,0x9A,0x0C,0xE4,0x50,
0x90,0xC7,0x92,0xAC,0x53,0xAE,0x53,0x76,
0x29,0xA6,0x65,0xF1,0x09,0xED,0x1A,0x8E,
0x03,0x2E,0x5A,0x06,0x51,0xE3,0x1E,0xE6,
0xF6,0xFE,0x3A,0x6E,0xD1,0x92,0x31,0x1D,
0xA1,0x6A,0x5C,0x30,0x3A,0xC7,0xFD,0x5B,
0xFE,0x71,0x2C,0x5C,0x2F,0x5B,0x5B,0xCF,
0xBC,0x7F,0xBF,0x6C,0xAF,0x44,0x8A,0xAE,
0x14,0x60,0xAB,0x88,0xED,0x0E,0x4F,0xF8,
0xC7,0x1B,0x74,0x28,0x72,0xB3,0x96,0xA6,
0xE6,0x46,0x22,0x82,0xCF,0x1F,0x4D,0xA6,
0xEA,0x22,0x06,0x07,0x52,0xF5,0x26,0x16,
0x0B,0x90,0xE3,0xFF,0x64,0xA9,0xE4,0x61,
0x1E,0x9C,0x12,0x9C,0xF6,0xD4,0x63,0x29,
0xEA,0x02,0xF7,0x18,0x52,0x79,0x6C,0x43,
0xDC,0xCF,0x43,0x23,0xB9,0xCC,0x4A,0x25,
0x9D,0x10,0xAF,0xA3,0xE6,0x47,0x5A,0x1C,
0xFE,0x68,0x89,0xAF,0x1B,0x2D,0x88,0x3E,
0xCA,0xDC,0x70,0xEA,0xAC,0x11,0x00,0x8A,
0x6E,0xE0,0xC7,0xD0,0xD2,0x1A,0x36,0x18,
0x97,0xB3,0x5F,0x0E,0x75,0x48,0x28,0xF8,
0xA8,0xF5,0x90,0xD1,0xA1,0x84,0xFB,0xA4,
0xAD,0x50,0xBE,0xE9,0x39,0x8C,0xC5,0xA1,
0x67,0x51,0xA1,0x8C,0xD6,0x6B,0x97,0x1F,
0x47,0x99,0xEE,0xE0,0x70,0x01,0xC7,0x07,
0x50,0xF3,0x5E,0x3F,0xE7,0x06,0xD6,0x8D,
0x26,0xD6,0x5A,0x59,0x18,0x72,0x6B,0x12,
0xD2,0xAF,0x9B,0xB4,0x2B,0xD0,0xB2,0xF2,
0x96,0x2F,0x40,0xEA,0xBE,0xE6,0xAC,0x1F,
0xB8,0x33,0xC2,0x76,0xDC,0x8C,0xAC,0xC1,
0x46,0x5E,0x04,0x84,0x1B,0xC8,0xB9,0x65,
0x8D,0xAD,0x96,0xB5,0xB1,0xF6,0x17,0x4A,
0x19,0x87,0xE7,0xBF,0x29,0xC7,0x9B,0xB9,
0xD6,0x11,0x2C,0x92,0x2F,0xB7,0x24,0xD5,
0x01,0x1D,0x80,0x37,0x54,0xED,0x33,0x32,
0xAB,0x7A,0x12,0xD4,0x02,0x1D,0x27,0x52,
0x89,0xDB,0x32,0xBF,0x61,0xD4,0xBB,0xB4,
0x46,0x78,0x1B,0x64,0x17,0x84,0x4B,0x8A,
0xBA,0xC6,0xC1,0xCF,0xC7,0x5D,0x8F,0x93,
0xC5,0x9A,0x27,0x90,0xAC,0x17,0x98,0xFF,
0xC8,0x22,0x59,0x55,0x90,0xB2,0x29,0x39,
0xA0,0xBE,0x00,0x23,0x55,0x6B,0xDA,0x83,
0xD8,0x5B,0x57,0x7C,0x67,0x1B,0xC3,0x6B,
0x6D,0xC7,0x9B,0x2B,0x9E,0xB7,0x95,0xB3,
0xF0,0x1B,0x89,0x5A,0xD7,0x4B,0x67,0xAF,
0xDC,0x9E,0xCF,0x7E,0x1A,0xBA,0x1B,0xB9,
0x3B,0x7A,0xDD,0x3F,0x0D,0xEE,0x4C,0x0B,
0xD1,0x4F,0x34,0xF2,0x93,0xF7,0x21,0x64,
0x2C,0x07,0x00,0x15,0x4F,0xE3,0x6A,0x9F,
0x08,0x52,0xC2,0x65,0x47,0x1F,0x34,0x64,
0x66,0x07,0xBC,0xEA,0xAF,0x9B,0xAA,0x39,
0x15,0x8B,0x08,0x8C,0x24,0x41,0x9B,0x46,
0x1B,0x5B,0x91,0x11,0xC4,0xFD,0xA9,0x88,
0x35,0x0E,0x7D,0xAF,0xFD,0xB7,0x90,0x7E,
0xD7,0x29,0x02,0x0A,0xDC,0xC8,0x3F,0xC0,
0xFD,0x97,0xAF,0x50,0x49,0xA6,0x5E,0x12,
0xC1,0xCD,0xEC,0x52,0xC5,0x51,0xF2,0x80,
0x17,0x61,0xC7,0x7E,0xBE,0xD1,0x1B,0x65,
0xA4,0xAB,0x92,0x8D,0x89,0xB2,0xC5,0x8F,
0xFF,0xA5,0x6F,0xFA,0x62,0x75,0xE4,0xA1,
0xD4,0x22,0xA8,0x9E,0x40,0x04,0x27,0x1F,
0xCC,0x81,0xBA,0x28,0x67,0xA0,0x1C,0x80,
0xEB,0xCA,0xB0,0x61,0xA5,0x48,0xD0,0x8A,
0x25,0xEB,0x9E,0x67,0x8C,0x8E,0x9B,0xD1,
0xAD,0xBB,0xC3,0xEA,0xD3,0xD4,0xC5,0x12,
0x7B,0xDD,0x00,0x57,0x7F,0xF6,0xF7,0xF6,
0x3C,0x05,0xCF,0xFC,0x12,0xE1,0x93,0x05,
0xE5,0x9B,0x79,0x87,0x69,0xD8,0x82,0xD9,
0xD7,0x1D,0x41,0x73,0xE4,0x52,0x1D,0x3E,
0xE5,0x8C,0x8D,0x34,0xE1,0x75,0xA9,0xF1,
0x9D,0x09,0xA2,0x5B,0xEF,0xDA,0x96,0x6E,
0x76,0x3D,0xEA,0x50,0xD9,0xCF,0x4F,0xAC,
0xAD,0x1D,0x35,0x72,0x1B,0x88,0x8B,0xCD,
0x8C,0x8A,0x8A,0xE0,0x96,0x04,0xD8,0xBB,
0x28,0x43,0x16,0x77,0x60,0x98,0x63,0xF9,
0xB9,0x71,0x46,0xB7,0xE1,0xA7,0xA9,0x84,
0xC3,0x65,0x82,0xE1,0x1B,0x67,0x04,0x2D,
0x55,0x6B,0xF9,0xC0,0x79,0x09,0x09,0xE7,
0xFD,0x06,0x4D,0x09,0x9B,0x1A,0xCE,0x35,
0xFA,0x27,0x6F,0x2F,0x01,0x65,0x0D,0xA0,
0x97,0x59,0x11,0xF0,0x48,0xD2,0xE7,0x46,
0xBE,0xB4,0x0A,0xA3,0xE2,0x75,0x0E,0x09,
0x94,0xD9,0x69,0x28,0xD4,0xDA,0x64,0xBA,
0xFE,0xA4,0xB9,0xF0,0xBA,0xEB,0xBA,0xAC,
0xA8,0xF9,0xD3,0x82,0x4C,0x36,0x80,0xFA,
0xE5,0xF6,0x76,0xC3,0x80,0xFA,0x90,0x29,
0xF4,0x85,0xA4,0xC6,0x25,0x22,0x79,0x7E,
0x39,0x1E,0x30,0xB8,0x65,0x72,0xCF,0xE1,
0x99,0xF0,0x75,0xE8,0x09,0xB4,0x92,0x96,
0x1B,0x68,0x50,0x88,0xF1,0x2C,0x97,0xE3,
0x2D,0x26,0x8F,0xC5,0x30,0xCF,0x24,0xCB,
0xB2,0x60,0x77,0xDC,0x02,0x72,0x0D,0xD9,
0x2E,0xF2,0x52,0xEA,0x00,0xF6,0x32,0x65,
0xA5,0xC6,0x43,0x29,0x29,0x69,0xAB,0x27,
0x0C,0x39,0xDF,0x76,0x3E,0x93,0x95,0xB1,
0x2C,0xA2,0x0D,0x18,0xCE,0xA0,0x97,0x10,
0x3C,0x90,0xC0,0xEF,0x0E,0x04,0xA6,0xC8,
0xA0,0x21,0x3C,0x0B,0x22,0x77,0x7A,0x66,
0xA5,0x90,0x25,0xA4,0x09,0x3E,0xD5,0x27,
0x1F,0x6C,0x99,0x85,0x5C,0xA2,0x99,0x7A,
0x25,0xEE,0x8D,0x32,0x3D,0xD3,0xDC,0xF5,
0x00,0x5A,0x34,0x61,0xB6,0xCD,0x4E,0xBC,
0x26,0x36,0xFB,0x44,0x97,0x35,0xBD,0x06,
0x7D,0x2E,0x4A,0xA2,0xDC,0x24,0xFE,0x70,
0x0A,0xF9,0x57,0xE3,0xEE,0xAB,0xD1,0x17,
0xF3,0x7C,0xD6,0x37,0x26,0xFA,0x83,0x9F,
0xDD,0xB2,0xE1,0xD7,0xF9,0xC7,0x0E,0x15,
0x01,0xA6,0x58,0x32,0x98,0x04,0x32,0xD4,
0xDE,0xB9,0xEF,0x09,0xFA,0xE4,0x5A,0xD7,
0xDD,0x09,0x1C,0xC9,0xAC,0xB8,0x6A,0xF5,
0x00,0x5D,0x6B,0x95,0x12,0x8C,0x2F,0xCC,
0xD8,0xB9,0x50,0x3A,0xEB,0x74,0x86,0xD2,
0x3F,0xA1,0x05,0x8F,0x6E,0xEF,0xF5,0xA4,
0xD6,0x6E,0x53,0xFA,0x9E,0xFA,0xCE,0xDB,
0x99,0x46,0xE7,0xC5,0xDA,0x92,0x51,0x4F,
0x22,0x07,0xF3,0xA5,0x38,0x26,0xD3,0xEC,
0xD6,0x01,0xDD,0x31,0x3A,0x48,0x93,0xF6,
0x69,0x4F,0xD8,0xF6,0xC2,0x91,0xA5,0x7C,
0xDF,0x51,0x64,0xF1,0x3B,0x79,0xBC,0x0A,
0x2C,0xDC,0x33,0x5A,0x29,0xF6,0xB2,0x09,
0x66,0xCA,0x24,0x9F,0x1A,0x18,0xF3,0x76,
0x4C,0x5E,0x0B,0x81,0x7F,0x29,0x84,0xD8,
0x7A,0xA8,0xD6,0x11,0xAC,0xEC,0xD9,0x07,
0x91,0xEC,0xB6,0x6D,0xEC,0xDB,0xBE,0x6F,
0x9F,0xC5,0x19,0x5E,0x56,0x87,0x20,0x80,
0x75,0xD5,0x64,0xE9,0x80,0xBF,0x2D,0xD5,
0x94,0x9F,0x8C,0xA4,0x54,0x41,0xAB,0xB1,
0x8E,0xAD,0x51,0xE4,0x3C,0x24,0xF7,0x1D,
0xFE,0x02,0x48,0x7C,0x6D,0xED,0xF1,0xAC,
0xD9,0x79,0x42,0xE5,0x3A,0xCF,0x6A,0x4C,
0x6D,0xE2,0x13,0xD2,0x2B,0x9D,0xAB,0x1F,
0x70,0xD3,0xC0,0x6F,0x81,0xE9,0x9A,0x86,
0x33,0x39,0x60,0xE7,0x6A,0x00,0x1F,0x97,
0xEB,0xE5,0x1D,0x0D,0x66,0x15,0xC9,0xA2,
0xB1,0xC0,0xF0,0x2E,0xF4,0x07,0xA2,0x2E,
0x49,0x92,0x95,0x13,0xA3,0x18,0x46,0x25,
0xB9,0x3C,0xA1,0x4B,0x00,0x00,0x00,0x06,
0xAB,0xAA,0xF9,0x3F,0x7E,0x21,0xF4,0x0E,
0xCE,0xFD,0xE0,0x44,0xAC,0xC7,0x1A,0x30,
0x22,0x9D,0x0A,0xD7,0x96,0x2D,0x8F,0x9A,
0x99,0x1F,0x40,0x75,0x7F,0x62,0xF9,0xC1,
0x81,0x7B,0x4A,0x1B,0xFA,0xD6,0x87,0xB9,
0xEF,0x58,0x48,0xE4,0x5C,0x79,0xE5,0xB1,
0x2C,0x59,0xA4,0x42,0xDB,0xA6,0x53,0x70,
0x80,0x61,0x17,0xD4,0xD3,0x77,0xBD,0x53,
0x26,0x7C,0x0E,0x0E,0xFF,0x30,0x4B,0xD0,
0x86,0xFC,0x02,0x20,0x24,0x46,0x5B,0xF5,
0xE3,0x99,0x73,0x85,0x60,0x00,0x36,0x47,
0x17,0xEE,0x0C,0xD2,0x80,0x71,0x46,0x0E,
0x2B,0xB0,0xEF,0x7F,0xFE,0x3B,0xE5,0xE1,
0x87,0xC2,0xAF,0x1A,0x6F,0x63,0xF4,0x5A,
0xC4,0x16,0xF7,0xAD,0x07,0x70,0x71,0x85,
0x7D,0x3D,0x67,0x08,0xB8,0xD8,0xE2,0xF0,
0xA1,0xAC,0xD2,0x94,0x7D,0x93,0x03,0xDD,
0x54,0xF9,0x64,0x19,0xB3,0xED,0x24,0x22,
0x01,0xD7,0x12,0x5E,0xC1,0x2B,0x39,0x10,
0x13,0xE2,0x56,0x1C,0xEE,0xF4,0x2A,0x49,
0x7B,0xFB,0x36,0x8D,0xF8,0xAF,0x60,0xDF,
0x10,0xF0,0x72,0xA2,0xED,0xB6,0x53,0x88,
0xA9,0x0C,0xED,0x9C,0x18,0x33,0x7D,0x65,
0x9B,0xB2,0x9C,0x3E,0xE9,0x1E,0x43,0x51,
0x7E,0xBE,0x01,0x95,0xF6,0x60,0x65,0xBE,
0xD1,0xF4,0xE2,0x83,0x6B,0xCA,0x7A,0x70,
0x41,0x83,0x72,0xC0,0x23,0x51,0x13,0x11,
0x2D,0xF9,0xC0,0x0D,0x7D,0x73,0x76,0xA5,
0x30,0x83,0x68,0x10,0x35,0xA2,0x18,0x22,
0x4E,0x21,0x93,0x27,0x6A,0x19,0x28,0x83,
0x7F,0xDD,0xDD,0xFF,0xC3,0x8A,0x64,0x00,
0x5F,0x1C,0x0D,0xF8,0xBB,0xD7,0x15,0xB9,
0xEF,0xE0,0x07,0x62,0x05,0x9E,0xCF,0xFC,
0x08,0x52,0x1E,0x65,0x41,0x56,0x6A,0xEB,
0x81,0x53,0x30,0x7B,0xF2,0xFD,0x65,0xFF,
0xA2,0x14,0xF5,0x62,0x1E,0x24,0x48,0x47,
0xA5,0x41,0x80,0xB4,0xC5,0xDC,0xB2,0xB4,
0x2D,0x17,0xE7,0xBE,0x49,0x53,0x7A,0x25,
0xC5,0x0D,0x19,0x59,0xF4,0x88,0x59,0xED,
0x92,0x13,0xEE,0x7A,0x4F,0x12,0x98,0x4C
};
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;
ret = wc_LmsKey_Init(&verifyKey, NULL, INVALID_DEVID);
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
ret = wc_LmsKey_SetParameters(&verifyKey, 1, 10, 8);
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
ret = wc_LmsKey_ImportPubRaw(&verifyKey, lms_L1H10W8_pub,
HSS_MAX_PUBLIC_KEY_LEN);
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
/* Verify parameters, pub length, and sig length are correct. */
ret = wc_LmsKey_GetParameters(&verifyKey, &levels, &height, &winternitz);
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
if (levels != 1 || height != 10 || winternitz != 8) {
printf("error: invalid LMS parameters: L%d-H%d-W%d\n", levels, height,
winternitz);
return -1;
}
ret = wc_LmsKey_GetPubLen(&verifyKey, &pubLen);
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
if (pubLen != HSS_MAX_PUBLIC_KEY_LEN) {
printf("error: got %d, expected %d\n", pubLen, HSS_MAX_PUBLIC_KEY_LEN);
return WC_TEST_RET_ENC_EC(pubLen);
}
ret = wc_LmsKey_GetSigLen(&verifyKey, &sigSz);
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
if (sigSz != LMS_L1H10W8_SIGLEN) {
printf("error: got %d, expected %d\n", sigSz, LMS_L1H10W8_SIGLEN);
return WC_TEST_RET_ENC_EC(sigSz);
}
ret = wc_LmsKey_Verify(&verifyKey, lms_L1H10W8_sig, LMS_L1H10W8_SIGLEN,
(byte *) msg, msgSz);
if (ret != 0) {
printf("error: wc_LmsKey_Verify returned %d\n", ret);
return WC_TEST_RET_ENC_EC(ret);
}
wc_LmsKey_Free(&verifyKey);
return ret;
}
#endif /* if defined(WOLFSSL_HAVE_LMS) && defined(WOLFSSL_LMS_VERIFY_ONLY) &&
* !defined(WOLFSSL_SMALL_STACK) */
static const int fiducial3 = WC_TEST_RET_LN; /* source code reference point -- static const int fiducial3 = WC_TEST_RET_LN; /* source code reference point --
* see print_fiducials() below. * see print_fiducials() below.

View File

@ -51,11 +51,13 @@ struct LmsKey {
param_set_t lm_type[MAX_HSS_LEVELS]; /* Height parm per level. */ param_set_t lm_type[MAX_HSS_LEVELS]; /* Height parm per level. */
param_set_t lm_ots_type[MAX_HSS_LEVELS]; /* Winternitz parm per level. */ param_set_t lm_ots_type[MAX_HSS_LEVELS]; /* Winternitz parm per level. */
unsigned char pub[HSS_MAX_PUBLIC_KEY_LEN]; unsigned char pub[HSS_MAX_PUBLIC_KEY_LEN];
#ifndef WOLFSSL_LMS_VERIFY_ONLY
hss_working_key * working_key; hss_working_key * working_key;
write_private_key_cb write_private_key; /* Callback to write/update key. */ write_private_key_cb write_private_key; /* Callback to write/update key. */
read_private_key_cb read_private_key; /* Callback to read key. */ read_private_key_cb read_private_key; /* Callback to read key. */
void * context; /* Context arg passed to callbacks. */ void * context; /* Context arg passed to callbacks. */
hss_extra_info info; hss_extra_info info;
#endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY */
enum wc_LmsState state; enum wc_LmsState state;
}; };

View File

@ -109,23 +109,31 @@ WOLFSSL_API int wc_LmsKey_Init(LmsKey * key, void * heap, int devId);
WOLFSSL_API int wc_LmsKey_SetLmsParm(LmsKey * key, enum wc_LmsParm lmsParm); WOLFSSL_API int wc_LmsKey_SetLmsParm(LmsKey * key, enum wc_LmsParm lmsParm);
WOLFSSL_API int wc_LmsKey_SetParameters(LmsKey * key, int levels, WOLFSSL_API int wc_LmsKey_SetParameters(LmsKey * key, int levels,
int height, int winternitz); int height, int winternitz);
WOLFSSL_API int wc_LmsKey_GetParameters(const LmsKey * key, int * levels,
int * height, int * winternitz);
#ifndef WOLFSSL_LMS_VERIFY_ONLY
WOLFSSL_API int wc_LmsKey_SetWriteCb(LmsKey * key, WOLFSSL_API int wc_LmsKey_SetWriteCb(LmsKey * key,
write_private_key_cb write_cb); write_private_key_cb write_cb);
WOLFSSL_API int wc_LmsKey_SetReadCb(LmsKey * key, WOLFSSL_API int wc_LmsKey_SetReadCb(LmsKey * key,
read_private_key_cb read_cb); read_private_key_cb read_cb);
WOLFSSL_API int wc_LmsKey_SetContext(LmsKey * key, void * context); WOLFSSL_API int wc_LmsKey_SetContext(LmsKey * key, void * context);
WOLFSSL_API void wc_LmsKey_Free(LmsKey * key);
WOLFSSL_API int wc_LmsKey_MakeKey(LmsKey * key, WC_RNG * rng); WOLFSSL_API int wc_LmsKey_MakeKey(LmsKey * key, WC_RNG * rng);
WOLFSSL_API int wc_LmsKey_Reload(LmsKey * key); WOLFSSL_API int wc_LmsKey_Reload(LmsKey * key);
WOLFSSL_API int wc_LmsKey_GetSigLen(LmsKey * key, word32 * len); WOLFSSL_API int wc_LmsKey_GetPrivLen(const LmsKey * key, word32 * len);
WOLFSSL_API int wc_LmsKey_GetPrivLen(LmsKey * key, word32 * len);
WOLFSSL_API int wc_LmsKey_GetPubLen(LmsKey * key, word32 * len);
WOLFSSL_API int wc_LmsKey_ExportPub(LmsKey * keyDst, const LmsKey * keySrc);
WOLFSSL_API int wc_LmsKey_Sign(LmsKey * key, byte * sig, word32 * sigSz, WOLFSSL_API int wc_LmsKey_Sign(LmsKey * key, byte * sig, word32 * sigSz,
const byte * msg, int msgSz); const byte * msg, int msgSz);
WOLFSSL_API int wc_LmsKey_SigsLeft(LmsKey * key);
#endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY */
WOLFSSL_API void wc_LmsKey_Free(LmsKey * key);
WOLFSSL_API int wc_LmsKey_GetSigLen(const LmsKey * key, word32 * len);
WOLFSSL_API int wc_LmsKey_GetPubLen(const LmsKey * key, word32 * len);
WOLFSSL_API int wc_LmsKey_ExportPub(LmsKey * keyDst, const LmsKey * keySrc);
WOLFSSL_API int wc_LmsKey_ExportPubRaw(const LmsKey * key, byte * out,
word32 * outLen);
WOLFSSL_API int wc_LmsKey_ImportPubRaw(LmsKey * key, const byte * in,
word32 inLen);
WOLFSSL_API int wc_LmsKey_Verify(LmsKey * key, const byte * sig, word32 sigSz, WOLFSSL_API int wc_LmsKey_Verify(LmsKey * key, const byte * sig, word32 sigSz,
const byte * msg, int msgSz); const byte * msg, int msgSz);
WOLFSSL_API int wc_LmsKey_SigsLeft(LmsKey * key);
WOLFSSL_API const char * wc_LmsKey_ParmToStr(enum wc_LmsParm lmsParm); WOLFSSL_API const char * wc_LmsKey_ParmToStr(enum wc_LmsParm lmsParm);
WOLFSSL_API const char * wc_LmsKey_RcToStr(enum wc_LmsRc lmsRc); WOLFSSL_API const char * wc_LmsKey_RcToStr(enum wc_LmsRc lmsRc);
#ifdef __cplusplus #ifdef __cplusplus