diff --git a/INSTALL b/INSTALL index 62a1adb78..1ad6cde17 100644 --- a/INSTALL +++ b/INSTALL @@ -264,20 +264,20 @@ We also have vcpkg ports for wolftpm, wolfmqtt and curl. branch of the hash-sigs project. 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_thread.a: a multi-threaded static lib. The multi-threaded version will mainly have speedups for key generation and signing. - Additionally, the hash-sigs project can be modified to build - and install a shared library in /usr/local with either single - or multi-threaded versions. If the shared version has been - built, libhss.so is the assumed name. + The default LMS build (--enable-lms) will look for + hss_lib.a first, and hss_lib_thread.a second, in a specified + hash-sigs dir. - wolfSSL supports either option, and by default will look for - hss_lib.a first, and hss_lib_thread.a second, and libhss.so - lastly, in a specified hash-sigs dir. + The LMS verify-only build (--enable-lms=verify-only) will look + for hss_verify.a only, which is a slimmer library that includes + only the minimal functions necessary for signature verification. How to get and build the hash-sigs library: $ mkdir ~/hash_sigs @@ -299,12 +299,17 @@ We also have vcpkg ports for wolftpm, wolfmqtt and curl. $ ls *.a hss_lib_thread.a + To build verify-only: + $ make hss_verify.a + $ ls *.a + hss_verify.a + Build wolfSSL with $ ./configure \ --enable-static \ --disable-shared \ - --enable-lms=yes \ - --with-liblms= + --enable-lms \ + --with-liblms= $ make Run the benchmark against LMS/HSS with: diff --git a/configure.ac b/configure.ac index 16f0ba138..c0d93663c 100644 --- a/configure.ac +++ b/configure.ac @@ -1141,69 +1141,6 @@ then 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 ]], [[ 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 ]], [[ 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 AC_ARG_ENABLE([lms], [AS_HELP_STRING([--enable-lms],[Enable stateful LMS/HSS signatures (default: disabled)])], @@ -1219,6 +1156,10 @@ do ;; no) ;; + verify-only) + LMS_VERIFY_ONLY=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_LMS_VERIFY_ONLY" + ;; wolfssl) ENABLED_WC_LMS=yes AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_LMS" @@ -1243,6 +1184,72 @@ 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 ]], [[ 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 AC_ARG_ENABLE([singlethreaded], diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 77d778fec..b00c428a0 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -157,7 +157,7 @@ #include #endif #endif -#ifdef WOLFSSL_HAVE_LMS +#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) #include #ifdef HAVE_LIBLMS #include @@ -870,7 +870,7 @@ static const bench_alg bench_other_opt[] = { #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 { /* Command line option string. */ const char* str; @@ -883,7 +883,7 @@ static const bench_pq_hash_sig_alg bench_pq_hash_sig_opt[] = { { "-lms_hss", BENCH_LMS_HSS}, { 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) /* The post-quantum-specific mapping of command line option to bit values and @@ -2832,11 +2832,11 @@ static void* benchmarks_do(void* args) } #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)) { bench_lms(); } -#endif +#endif /* if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) */ #ifdef HAVE_ECC if (bench_all || (bench_asym_algs & BENCH_ECC_MAKEKEY) || @@ -7664,7 +7664,7 @@ void bench_kyber(int type) } #endif -#ifdef WOLFSSL_HAVE_LMS +#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) /* WC_LMS_PARM_L2_H10_W2 * signature length: 9300 */ static const byte lms_priv_L2_H10_W2[64] = @@ -8031,7 +8031,7 @@ void bench_lms(void) return; } -#endif /* ifdef WOLFSSL_HAVE_LMS */ +#endif /* if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) */ #ifdef HAVE_ECC @@ -10368,10 +10368,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) +#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) 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) */ +#endif /* if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) */ printf("\n"); #endif /* !WOLFSSL_BENCHMARK_ALL */ 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 */ 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)) { @@ -10643,7 +10643,7 @@ int wolfcrypt_benchmark_main(int argc, char** argv) optMatched = 1; } } - #endif /* if defined(WOLFSSL_HAVE_LMS) */ + #endif #endif if (!optMatched) { printf("Option not recognized: %s\n", argv[1]); diff --git a/wolfcrypt/src/ext_lms.c b/wolfcrypt/src/ext_lms.c index 351746f6e..ebd07e26c 100644 --- a/wolfcrypt/src/ext_lms.c +++ b/wolfcrypt/src/ext_lms.c @@ -37,6 +37,7 @@ #include #endif +#ifndef WOLFSSL_LMS_VERIFY_ONLY /* If built against hss_lib_thread.a, the hash-sigs lib will spawn * worker threads to parallelize cpu intensive tasks. This will mainly * 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. */ - 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) { 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. */ - 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) { WOLFSSL_MSG("error: LmsKey read_private_key failed"); @@ -151,6 +154,7 @@ static bool LmsReadPrivKey(unsigned char *private_key, return true; } +#endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY */ 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)); - /* Set the max number of worker threads that hash-sigs can spawn. */ +#ifndef WOLFSSL_LMS_VERIFY_ONLY 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); key->working_key = NULL; key->write_private_key = NULL; key->read_private_key = NULL; key->context = NULL; +#endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY */ key->state = WC_LMS_STATE_INITED; return 0; @@ -405,6 +411,70 @@ int wc_LmsKey_SetParameters(LmsKey * key, int levels, int height, 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. * * This does not affect the private key saved to non-volatile storage. @@ -415,10 +485,12 @@ void wc_LmsKey_Free(LmsKey* key) return; } +#ifndef WOLFSSL_LMS_VERIFY_ONLY if (key->working_key != NULL) { hss_free_working_key(key->working_key); key->working_key = NULL; } +#endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY */ ForceZero(key, sizeof(LmsKey)); @@ -427,6 +499,7 @@ void wc_LmsKey_Free(LmsKey* key) return; } +#ifndef WOLFSSL_LMS_VERIFY_ONLY /* Set the write private key callback to the LMS key structure. * * 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 * 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) { return BAD_FUNC_ARG; @@ -659,65 +732,6 @@ int wc_LmsKey_GetPrivLen(LmsKey * key, word32 * len) 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 msgSz) { @@ -773,27 +787,6 @@ int wc_LmsKey_Sign(LmsKey* key, byte * sig, word32 * sigSz, const byte * msg, 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 0 if available signatures are exhausted. * @@ -815,4 +808,165 @@ int wc_LmsKey_SigsLeft(LmsKey * key) 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 */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 3dde3cb55..143681c78 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -293,7 +293,7 @@ const byte const_byte_array[] = "A+Gd\0\0\0"; #include #endif #endif -#ifdef WOLFSSL_HAVE_LMS +#if defined(WOLFSSL_HAVE_LMS) #include #ifdef HAVE_LIBLMS #include @@ -574,8 +574,13 @@ 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 -#ifdef WOLFSSL_HAVE_LMS - WOLFSSL_TEST_SUBROUTINE int lms_test(void); +#if defined(WOLFSSL_HAVE_LMS) + #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 #ifdef WOLFCRYPT_HAVE_ECCSI 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"); #endif -#ifdef WOLFSSL_HAVE_LMS +#if defined(WOLFSSL_HAVE_LMS) + #if !defined(WOLFSSL_LMS_VERIFY_ONLY) if ( (ret = lms_test()) != 0) TEST_FAIL("LMS test failed!\n", ret); else 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 if ( (ret = eccsi_test()) != 0) @@ -34957,7 +34971,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t kyber_test(void) #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) { /* 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. */ #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 sigsLeft = 0; @@ -35092,7 +35106,283 @@ WOLFSSL_TEST_SUBROUTINE int lms_test(void) 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 -- * see print_fiducials() below. diff --git a/wolfssl/wolfcrypt/ext_lms.h b/wolfssl/wolfcrypt/ext_lms.h index faf833ad1..8b8a8f728 100644 --- a/wolfssl/wolfcrypt/ext_lms.h +++ b/wolfssl/wolfcrypt/ext_lms.h @@ -51,11 +51,13 @@ struct LmsKey { 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. */ unsigned char pub[HSS_MAX_PUBLIC_KEY_LEN]; +#ifndef WOLFSSL_LMS_VERIFY_ONLY hss_working_key * working_key; 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. */ hss_extra_info info; +#endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY */ enum wc_LmsState state; }; diff --git a/wolfssl/wolfcrypt/lms.h b/wolfssl/wolfcrypt/lms.h index 6a696ec63..d3ab07571 100644 --- a/wolfssl/wolfcrypt/lms.h +++ b/wolfssl/wolfcrypt/lms.h @@ -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_SetParameters(LmsKey * key, int levels, 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, write_private_key_cb write_cb); WOLFSSL_API int wc_LmsKey_SetReadCb(LmsKey * key, read_private_key_cb read_cb); 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_Reload(LmsKey * key); -WOLFSSL_API int wc_LmsKey_GetSigLen(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_GetPrivLen(const LmsKey * key, word32 * len); WOLFSSL_API int wc_LmsKey_Sign(LmsKey * key, byte * sig, word32 * sigSz, 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, 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_RcToStr(enum wc_LmsRc lmsRc); #ifdef __cplusplus