From 64fe29efaecc8e22d0895bf6185d6dddc5863b5d Mon Sep 17 00:00:00 2001 From: Hideki Miyazaki Date: Wed, 8 Apr 2026 16:14:21 +0900 Subject: [PATCH 1/5] fix f-1899 potential heap buffer over-read add test coverage --- src/sign-verify/clu_sign.c | 188 +++++----- tests/genkey_sign_ver/genkey-sign-ver-test.sh | 343 ++++++++++++++++++ 2 files changed, 427 insertions(+), 104 deletions(-) create mode 100755 tests/genkey_sign_ver/genkey-sign-ver-test.sh diff --git a/src/sign-verify/clu_sign.c b/src/sign-verify/clu_sign.c index 6699d850..0943ea8b 100644 --- a/src/sign-verify/clu_sign.c +++ b/src/sign-verify/clu_sign.c @@ -618,16 +618,18 @@ int wolfCLU_sign_data_dilithium (byte* data, char* out, word32 dataSz, char* pri { #ifdef HAVE_DILITHIUM int ret = 0; + int privFileSz = 0; + word32 index = 0; + XFILE privKeyFile = NULL; byte* privBuf = NULL; - int privFileSz = 0; + word32 privBufSz = 0; - word32 index = 0; byte* outBuf = NULL; word32 outBufSz = 0; WC_RNG rng; - XMEMSET(&rng, 0, sizeof(rng)); + #ifdef WOLFSSL_SMALL_STACK dilithium_key* key; @@ -641,6 +643,7 @@ int wolfCLU_sign_data_dilithium (byte* data, char* out, word32 dataSz, char* pri #endif /* zero before init for defensive security */ + XMEMSET(&rng, 0, sizeof(rng)); XMEMSET(key, 0, sizeof(dilithium_key)); /* init the dilithium key */ @@ -650,146 +653,123 @@ int wolfCLU_sign_data_dilithium (byte* data, char* out, word32 dataSz, char* pri #ifdef WOLFSSL_SMALL_STACK XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #endif - return WOLFCLU_FAILURE; + ret = WOLFCLU_FAILURE; } - if (wc_InitRng(&rng) != 0) { - wolfCLU_LogError("Failed to initialize rng.\nRET: %d", ret); - wc_dilithium_free(key); - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return WOLFCLU_FAILURE; + /* initialize RNG */ + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret != 0) { + wolfCLU_LogError("Failed to initialize rng.\nRET: %d", ret); + } } /* open and read private key */ - privKeyFile = XFOPEN(privKey, "rb"); - if (privKeyFile == NULL) { - wolfCLU_LogError("Faild to open Private key FILE."); - wc_FreeRng(&rng); - wc_dilithium_free(key); - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return WOLFCLU_FATAL_ERROR; + if (ret == 0) { + privKeyFile = XFOPEN(privKey, "rb"); + if (privKeyFile == NULL) { + wolfCLU_LogError("Faild to open Private key FILE."); + ret = BAD_FUNC_ARG; + } } - - XFSEEK(privKeyFile, 0, SEEK_END); - privFileSz = (int)XFTELL(privKeyFile); - privBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (privBuf == NULL) { - XFCLOSE(privKeyFile); - wc_FreeRng(&rng); - wc_dilithium_free(key); - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return MEMORY_E; + if (ret == 0) { + XFSEEK(privKeyFile, 0, SEEK_END); + privFileSz = (int)XFTELL(privKeyFile); + privBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (privBuf == NULL) { + ret = MEMORY_E; + } } - - XMEMSET(privBuf, 0, privFileSz+1); - privBufSz = privFileSz; - XFSEEK(privKeyFile, 0, SEEK_SET); - if (XFREAD(privBuf, 1, privBufSz, privKeyFile) != privBufSz) { - wolfCLU_Log(WOLFCLU_L0, "incorecct size: %d", privFileSz); - XFREE(privBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - wc_dilithium_free(key); - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return WOLFCLU_FATAL_ERROR; + if (ret == 0) { + XMEMSET(privBuf, 0, privFileSz+1); + privBufSz = privFileSz; + if (XFSEEK(privKeyFile, 0, SEEK_SET) != 0 || + (int)XFREAD(privBuf, 1, privFileSz, privKeyFile) != privFileSz) { + wolfCLU_Log(WOLFCLU_L0, "incorecct size: %d", privFileSz); + ret = WOLFCLU_FATAL_ERROR; + } } - XFCLOSE(privKeyFile); /* convert PEM to DER if necessary */ - if (inForm == PEM_FORM) { + if (inForm == PEM_FORM && ret == 0) { ret = wolfCLU_KeyPemToDer(&privBuf, privFileSz, 0); if (ret < 0) { wolfCLU_LogError("Failed to convert PEM to DER.\nRET: %d", ret); - XFREE(privBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - wc_dilithium_free(key); - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; } else { - privFileSz = ret; + /* update privBuf and privFileSz with the converted DER data */ + privBufSz = privFileSz = ret; + ret = 0; } } - /* retrieving private key and staoring in the Dilithium key */ - ret = wc_Dilithium_PrivateKeyDecode(privBuf, &index, key, privBufSz); - XFREE(privBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (ret != 0) { - wolfCLU_LogError("Failed to decode private key.\nRET: %d", ret); - wc_FreeRng(&rng); - wc_dilithium_free(key); - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; + /* retrieving private key and storing in the Dilithium key */ + if (ret == 0) { + ret = wc_Dilithium_PrivateKeyDecode(privBuf, &index, key, privBufSz); + if (ret != 0) { + wolfCLU_LogError("Failed to decode private key.\nRET: %d", ret); + } } - /* malloc signature buffer */ - outBufSz = wc_dilithium_sig_size(key); - outBuf = (byte*)XMALLOC(outBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (outBuf == NULL) { - wc_FreeRng(&rng); - wc_dilithium_free(key); - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return MEMORY_E; + if (ret == 0) { + outBufSz = wc_dilithium_sig_size(key); + outBuf = (byte*)XMALLOC(outBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (outBuf == NULL) { + wolfCLU_LogError("Failed to allocate signature" + " buffer.\nRET: %d", ret); + ret = MEMORY_E; + } } - /* sign the message usign Dilithium private key. Note that the context is * empty. This is for interoperability. */ - ret = wc_dilithium_sign_ctx_msg(NULL, 0, data, dataSz, outBuf, &outBufSz, - key, &rng); - if (ret != 0) { - wolfCLU_LogError("Failed to sign data with Dilithium private key.\nRET: %d", ret); - XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - wc_dilithium_free(key); - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; + if (ret == 0) { + ret = wc_dilithium_sign_ctx_msg(NULL, 0, data, dataSz, outBuf, + &outBufSz, key, &rng); + if (ret != 0) { + wolfCLU_LogError("Failed to sign data with" + " Dilithium private key.\nRET: %d", ret); + } } - else { + + if (ret == 0) { XFILE outFile; outFile = XFOPEN(out, "wb"); + if (outFile == NULL) { wolfCLU_LogError("Failed to open output file %s", out); - XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - wc_dilithium_free(key); - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return BAD_FUNC_ARG; - } - XFWRITE(outBuf, 1, outBufSz, outFile); - XFCLOSE(outFile); + ret = BAD_FUNC_ARG; + } else { + XFWRITE(outBuf, 1, outBufSz, outFile); + XFCLOSE(outFile); + } } - XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); - wc_dilithium_free(key); + /* cleanup allocated resources */ + if (privKeyFile != NULL) + XFCLOSE(privKeyFile); + if (privBuf != NULL) { + XFREE(privBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } + + if (outBuf != NULL) { + XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } + + wc_dilithium_free(key); + wc_FreeRng(&rng); #ifdef WOLFSSL_SMALL_STACK XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #endif - return WOLFCLU_SUCCESS; + /* expected ret == WOLFCLU_SUCCESS */ + return (ret >= 0) ? WOLFCLU_SUCCESS : ret; #else (void)data; (void)out; (void)dataSz; - (void) privKey; + (void)privKey; (void)inForm; return NOT_COMPILED_IN; diff --git a/tests/genkey_sign_ver/genkey-sign-ver-test.sh b/tests/genkey_sign_ver/genkey-sign-ver-test.sh new file mode 100755 index 00000000..46c3efb6 --- /dev/null +++ b/tests/genkey_sign_ver/genkey-sign-ver-test.sh @@ -0,0 +1,343 @@ +#!/bin/sh + +# genkey-sign-ver-test.sh +# +# Copyright (C) 2006-2025 wolfSSL Inc. +# +# This file is part of wolfSSL. +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# wolfSSL is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA +#/ +#/ +# + +# Skip test if filesystem disabled +FILESYSTEM=`cat config.log | grep "disable\-filesystem"` +if [ "$FILESYSTEM" != "" ] +then + exit 77 +fi + +cleanup_genkey_sign_ver(){ + rm -f ecckey + rm ecckey.priv + rm ecckey.pub + rm edkey.priv + rm edkey.pub + rm rsakey.priv + rm rsakey.pub + rm mldsakey.priv + rm mldsakey.pub + rm mldsakey_pub.pub + rm mldsakey_pub.priv + rm mldsakey_priv.pub + rm mldsakey_priv.priv + rm ecc-signed.sig + rm ed-signed.sig + rm rsa-signed.sig + rm rsa-sigout.private_result + rm rsa-sigout.public_result + rm mldsa-signed.sig + rm -f mldsa_bad_pubkey.sig + rm -f mldsa_bad_corrupt.sig + rm -f mldsakey_corrupt.priv + rm xmss-signed.sig + # rm xmssmt-signed.sig + rm sign-this.txt + + # XMSS/XMSS^MT key files + rm XMSS-SHA2_10_256.priv + rm XMSS-SHA2_10_256.pub + # rm XMSS-SHA2_16_256.priv + # rm XMSS-SHA2_16_256.pub + # rm XMSS-SHA2_20_256.priv + # rm XMSS-SHA2_20_256.pub + + # rm XMSSMT-SHA2_20-2_256.priv + # rm XMSSMT-SHA2_20-2_256.pub + # rm XMSSMT-SHA2_20-4_256.priv + # rm XMSSMT-SHA2_20-4_256.pub + # rm XMSSMT-SHA2_40-2_256.priv + # rm XMSSMT-SHA2_40-2_256.pub + # rm XMSSMT-SHA2_40-4_256.priv + # rm XMSSMT-SHA2_40-4_256.pub + # rm XMSSMT-SHA2_40-8_256.priv + # rm XMSSMT-SHA2_40-8_256.pub + # rm XMSSMT-SHA2_60-3_256.priv + # rm XMSSMT-SHA2_60-3_256.pub + # rm XMSSMT-SHA2_60-6_256.priv + # rm XMSSMT-SHA2_60-6_256.pub + # rm XMSSMT-SHA2_60-12_256.priv + # rm XMSSMT-SHA2_60-12_256.pub +} +trap cleanup_genkey_sign_ver INT TERM EXIT + +create_sign_data_file(){ + printf '%s\n' "Sign this data" > sign-this.txt +} + +rsa_compare_decrypted(){ + if [ "${1}" = "${2}" ]; then + printf '%s\n' "Decrypted matches original, success!" + printf '%s\n' "DECRYPTED --> ${1}" + printf '%s\n' "ORIGINAL --> ${2}" + else + printf '%s\n' "Decrypted mismatch with original, FAILURE!" + printf '%s\n' "DECRYPTED --> ${1}" + printf '%s\n' "ORIGINAL --> ${2}" && exit 99 + fi +} + +gen_key_sign_ver_test(){ + + # generate a key pair for signing + if [ $1 = "dilithium" ]; then + ./wolfssl -genkey $1 -level $5 -out $2 -outform $4 -output KEYPAIR + elif [ $1 = "xmss" ]; then + ./wolfssl -genkey $1 -height $5 -out $2 -outform $4 -output KEYPAIR + elif [ $1 = "xmssmt" ]; then + ./wolfssl -genkey $1 -height $5 -layer $6 -out $2 -outform $4 -output KEYPAIR + else + ./wolfssl -genkey $1 -out $2 -outform $4 KEYPAIR + fi + RESULT=$? + printf '%s\n' "genkey RESULT - $RESULT" + [ $RESULT -ne 0 ] && printf '%s\n' "Failed $1 genkey" && \ + printf '%s\n' "Before running this test please configure wolfssl with" && \ + printf '%s\n' "--enable-keygen" && exit 99 + + # test signing with priv key + ./wolfssl -$1 -sign -inkey $2.priv -inform $4 -in sign-this.txt -out $3 + RESULT=$? + printf '%s\n' "sign RESULT - $RESULT" + [ $RESULT -ne 0 ] && printf '%s\n' "Failed $1 sign" && exit 99 + + # test verifying with priv key + if [ "${1}" = "rsa" ]; then + ./wolfssl -$1 -verify -inkey $2.priv -inform $4 -sigfile $3 -in sign-this.txt \ + -out $5.private_result + elif [ "${1}" = "dilithium" ] || [ "${1}" = "xmss" ] || [ "${1}" = "xmssmt" ]; then + # ./wolfssl -$1 -verify -inkey $2.priv -inform $4 -sigfile $3 -in sign-this.txt + # pass + : + else + ./wolfssl -$1 -verify -inkey $2.priv -inform $4 -sigfile $3 -in sign-this.txt + fi + RESULT=$? + printf '%s\n' "private verify RESULT - $RESULT" + [ $RESULT -ne 0 ] && printf '%s\n' "Failed $1 private verify" && exit 99 + + # test verifying with pub key + if [ "${1}" = "rsa" ]; then + ./wolfssl -$1 -verify -inkey $2.pub -inform $4 -sigfile $3 -in sign-this.txt \ + -out $5.public_result -pubin + else + ./wolfssl -$1 -verify -inkey $2.pub -inform $4 -sigfile $3 -in sign-this.txt -pubin + fi + RESULT=$? + printf '%s\n' "public verify RESULT - $RESULT" + [ $RESULT -ne 0 ] && printf '%s\n' "Failed $1 public verify " && exit 99 + + if [ $1 = "rsa" ]; then + ORIGINAL=`cat -A sign-this.txt` + + DECRYPTED=`cat -A $5.private_result` + rsa_compare_decrypted "${DECRYPTED}" "${ORIGINAL}" + + DECRYPTED=`cat -A $5.public_result` + rsa_compare_decrypted "${DECRYPTED}" "${ORIGINAL}" + fi + +} + +create_sign_data_file + +ALGORITHM="ed25519" +KEYFILENAME="edkey" +SIGOUTNAME="ed-signed.sig" +DERPEMRAW="der" +gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} + +ALGORITHM="ecc" +KEYFILENAME="ecckey" +SIGOUTNAME="ecc-signed.sig" +DERPEMRAW="der" +gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} + +ALGORITHM="rsa" +KEYFILENAME="rsakey" +SIGOUTNAME="rsa-signed.sig" +DERPEMRAW="der" +VERIFYOUTNAME="rsa-sigout" +gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${VERIFYOUTNAME} + +# A verify with invalid signature must fail gracefully. +./wolfssl -rsa -verify -inkey rsakey.pub -inform der \ + -sigfile sign-this.txt -in sign-this.txt \ + -out rsa_badverify_out.txt -pubin +RESULT=$? +[ $RESULT -eq 0 ] && \ + printf '%s\n' "RSA verify with invalid sig should have failed" && exit 99 +[ -f rsa_badverify_out.txt ] && \ + printf '%s\n' "RSA verify with invalid sig: output file must not be created" && exit 99 + +# Regression test: -exponent value must not overwrite -size (was stored in +# sizeArg instead of expArg, corrupting the key size). +./wolfssl -genkey rsa -size 2048 -exponent 65537 -out rsakey_exp \ + -outform der -output KEYPAIR +RESULT=$? +[ $RESULT -ne 0 ] && printf '%s\n' "Failed rsa genkey with explicit -exponent" && exit 99 +rm -f rsakey_exp.priv rsakey_exp.pub + +ALGORITHM="ed25519" +KEYFILENAME="edkey" +SIGOUTNAME="ed-signed.sig" +DERPEMRAW="pem" +gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} + +ALGORITHM="ecc" +KEYFILENAME="ecckey" +SIGOUTNAME="ecc-signed.sig" +DERPEMRAW="pem" +gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} + +ALGORITHM="rsa" +KEYFILENAME="rsakey" +SIGOUTNAME="rsa-signed.sig" +DERPEMRAW="pem" +VERIFYOUTNAME="rsa-sigout" +gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${VERIFYOUTNAME} + +ALGORITHM="ed25519" +KEYFILENAME="edkey" +SIGOUTNAME="ed-signed.sig" +DERPEMRAW="raw" +gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} + +if ./wolfssl -genkey -h 2>&1 | grep -A6 "Available keys with current configure" | grep dilithium; then + ALGORITHM="dilithium" + KEYFILENAME="mldsakey" + SIGOUTNAME="mldsa-signed.sig" + DERPEMRAW="der" + for level in 2 3 5 + do + gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${level} + done + +ALGORITHM="dilithium" +KEYFILENAME="mldsakey" +SIGOUTNAME="mldsa-signed.sig" +DERPEMRAW="pem" +for level in 2 3 5 +do + gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${level} +done + +# Verifies that -output PUB generates only the public key file. +./wolfssl -genkey dilithium -level 2 -out mldsakey_pub -outform der -output pub +RESULT=$? +[ $RESULT -ne 0 ] && printf '%s\n' "Failed dilithium genkey -output PUB" && exit 99 +[ ! -f mldsakey_pub.pub ] && printf '%s\n' "dilithium -output PUB: .pub file missing" && exit 99 +[ -f mldsakey_pub.priv ] && printf '%s\n' "dilithium -output PUB: .priv unexpectedly created" && exit 99 + +# Verifies that -output PRIV generates only the private key file. +./wolfssl -genkey dilithium -level 2 -out mldsakey_priv -outform der -output priv +RESULT=$? +[ $RESULT -ne 0 ] && printf '%s\n' "Failed dilithium genkey -output PRIV" && exit 99 +[ ! -f mldsakey_priv.priv ] && printf '%s\n' "dilithium -output PRIV: .priv file missing" && exit 99 +[ -f mldsakey_priv.pub ] && printf '%s\n' "dilithium -output PRIV: .pub unexpectedly created" && exit 99 + +# Dilithium sign to an unwritable path must fail gracefully +./wolfssl -genkey dilithium -level 2 -out mldsakey -outform der -output keypair +./wolfssl -dilithium -sign -inkey mldsakey.priv -inform der \ + -in sign-this.txt -out /nonexistent_dir/mldsa_bad.sig +RESULT=$? +[ $RESULT -eq 0 ] && \ + printf '%s\n' "dilithium sign to invalid path should have failed" && exit 99 + +# Dilithium sign with public key as inkey must fail gracefully +./wolfssl -dilithium -sign -inkey mldsakey.pub -inform der \ + -in sign-this.txt -out mldsa_bad_pubkey.sig +RESULT=$? +[ $RESULT -eq 0 ] && \ + printf '%s\n' "dilithium sign with public key should have failed" && exit 99 +[ -f mldsa_bad_pubkey.sig ] && \ + printf '%s\n' "dilithium sign with public key: output file must not be created" && exit 99 + +# Dilithium sign with corrupted private key must fail gracefully +printf '%s' "INVALID KEY DATA" > mldsakey_corrupt.priv +./wolfssl -dilithium -sign -inkey mldsakey_corrupt.priv -inform der \ + -in sign-this.txt -out mldsa_bad_corrupt.sig +RESULT=$? +[ $RESULT -eq 0 ] && \ + printf '%s\n' "dilithium sign with corrupted key should have failed" && exit 99 +[ -f mldsa_bad_corrupt.sig ] && \ + printf '%s\n' "dilithium sign with corrupted key: output file must not be created" && exit 99 +rm -f mldsakey_corrupt.priv +fi + +# Check if xmss is availabe +if ./wolfssl xmss -help 2>&1 | grep -A6 "Available keys with current configure" | grep xmss; then + printf "Testing XMSS sign/verify\n" + ALGORITHM="xmss" + SIGOUTNAME="xmss-signed.sig" + DERPEMRAW="raw" + HEIGHT=10 + + gen_key_sign_ver_test ${ALGORITHM} "XMSS-SHA2_${HEIGHT}_256" ${SIGOUTNAME} ${DERPEMRAW} ${HEIGHT} + + # Too long to run + # for HEIGHT in 10 16 20 + # do + # KEYFILENAME="XMSS-SHA2_${HEIGHT}_256" + # gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${HEIGHT} + # done + + # ALGORITHM="xmssmt" + # SIGOUTNAME="xmssmt-signed.sig" + # DERPEMRAW="raw" + # HEIGHT=20 + + # for LAYER in 2 4 + # do + # KEYFILENAME="XMSSMT-SHA2_${HEIGHT}-${LAYER}_256" + # gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${HEIGHT} ${LAYER} + # done + + # ALGORITHM="xmssmt" + # SIGOUTNAME="xmssmt-signed.sig" + # DERPEMRAW="raw" + # HEIGHT=40 + + # for LAYER in 2 4 8 + # do + # KEYFILENAME="XMSSMT-SHA2_${HEIGHT}-${LAYER}_256" + # gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${HEIGHT} ${LAYER} + # done + + # ALGORITHM="xmssmt" + # SIGOUTNAME="xmssmt-signed.sig" + # DERPEMRAW="raw" + # HEIGHT=60 + + # for LAYER in 3 6 12 + # do + # KEYFILENAME="XMSSMT-SHA2_${HEIGHT}-${LAYER}_256" + # gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${HEIGHT} ${LAYER} + # done +fi + + +exit 0 From 84cfd0c2eacc3f85ba4186a931fa3a3e880ced43 Mon Sep 17 00:00:00 2001 From: Hideki Miyazaki Date: Thu, 9 Apr 2026 08:41:40 +0900 Subject: [PATCH 2/5] addressed Copilot review comments --- src/sign-verify/clu_sign.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/sign-verify/clu_sign.c b/src/sign-verify/clu_sign.c index 0943ea8b..e495e280 100644 --- a/src/sign-verify/clu_sign.c +++ b/src/sign-verify/clu_sign.c @@ -650,10 +650,6 @@ int wolfCLU_sign_data_dilithium (byte* data, char* out, word32 dataSz, char* pri ret = wc_dilithium_init(key); if (ret != 0) { wolfCLU_LogError("Failed to initialize Dilithium Key.\nRET: %d", ret); - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - #endif - ret = WOLFCLU_FAILURE; } /* initialize RNG */ @@ -673,12 +669,24 @@ int wolfCLU_sign_data_dilithium (byte* data, char* out, word32 dataSz, char* pri } } if (ret == 0) { - XFSEEK(privKeyFile, 0, SEEK_END); - privFileSz = (int)XFTELL(privKeyFile); - privBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT, + if (XFSEEK(privKeyFile, 0, SEEK_END) != 0) { + wolfCLU_LogError("Failed to seek to end of file."); + ret = WOLFCLU_FATAL_ERROR; + } + if (ret == 0) { + privFileSz = (int)XFTELL(privKeyFile); + if (privFileSz > 0 && + privFileSz <= DILITHIUM_MAX_BOTH_KEY_PEM_SIZE) { + privBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (privBuf == NULL) { - ret = MEMORY_E; + if (privBuf == NULL) { + ret = MEMORY_E; + } + } else { + wolfCLU_LogError("Incorrect private key file size: %d", + privFileSz); + ret = WOLFCLU_FATAL_ERROR; + } } } if (ret == 0) { @@ -686,7 +694,7 @@ int wolfCLU_sign_data_dilithium (byte* data, char* out, word32 dataSz, char* pri privBufSz = privFileSz; if (XFSEEK(privKeyFile, 0, SEEK_SET) != 0 || (int)XFREAD(privBuf, 1, privFileSz, privKeyFile) != privFileSz) { - wolfCLU_Log(WOLFCLU_L0, "incorecct size: %d", privFileSz); + wolfCLU_LogError("Incorrect private key file size: %d", privFileSz); ret = WOLFCLU_FATAL_ERROR; } } From 7d03ee9289b98ed001dc6f1cb2d1fc7cd8d1d633 Mon Sep 17 00:00:00 2001 From: Hideki Miyazaki Date: Fri, 17 Apr 2026 13:13:47 +0900 Subject: [PATCH 3/5] Addressed code review migrate tests to python --- src/sign-verify/clu_sign.c | 64 +++++++++++++++---- tests/genkey_sign_ver/genkey-sign-ver-test.py | 31 +++++++++ 2 files changed, 83 insertions(+), 12 deletions(-) diff --git a/src/sign-verify/clu_sign.c b/src/sign-verify/clu_sign.c index e495e280..d1dc00c7 100644 --- a/src/sign-verify/clu_sign.c +++ b/src/sign-verify/clu_sign.c @@ -205,11 +205,23 @@ int wolfCLU_sign_data_rsa(byte* data, char* out, word32 dataSz, char* privKey, } } if (ret == 0) { - XFSEEK(privKeyFile, 0, SEEK_END); + if (XFSEEK(privKeyFile, 0, SEEK_END) != 0) { + wolfCLU_LogError("Failed to seek to end of file."); + ret = WOLFCLU_FATAL_ERROR; + } + } + if (ret == 0) { privFileSz = (int)XFTELL(privKeyFile); - keyBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (keyBuf == NULL) { - ret = MEMORY_E; + if (privFileSz > 0 && privFileSz <= (RSA_MAX_SIZE / 8 * 16)) { + keyBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (keyBuf == NULL) { + ret = MEMORY_E; + } + } + else { + wolfCLU_LogError("Incorrect private key file size: %d", privFileSz); + ret = WOLFCLU_FATAL_ERROR; } } if (ret == 0) { @@ -344,11 +356,23 @@ int wolfCLU_sign_data_ecc(byte* data, char* out, word32 fSz, char* privKey, } } if (ret == 0) { - XFSEEK(privKeyFile, 0, SEEK_END); + if (XFSEEK(privKeyFile, 0, SEEK_END) != 0) { + wolfCLU_LogError("Failed to seek to end of file."); + ret = WOLFCLU_FATAL_ERROR; + } + } + if (ret == 0) { privFileSz = (int)XFTELL(privKeyFile); - keyBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (keyBuf == NULL) { - ret = MEMORY_E; + if (privFileSz > 0 && privFileSz <= (MAX_ECC_BITS_NEEDED / 8 * 16)) { + keyBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (keyBuf == NULL) { + ret = MEMORY_E; + } + } + else { + wolfCLU_LogError("Incorrect private key file size: %d", privFileSz); + ret = WOLFCLU_FATAL_ERROR; } } if (ret == 0) { @@ -506,11 +530,23 @@ int wolfCLU_sign_data_ed25519 (byte* data, char* out, word32 fSz, char* privKey, } } if (ret == 0) { - XFSEEK(privKeyFile, 0, SEEK_END); + if (XFSEEK(privKeyFile, 0, SEEK_END) != 0) { + wolfCLU_LogError("Failed to seek to end of file."); + ret = WOLFCLU_FATAL_ERROR; + } + } + if (ret == 0) { privFileSz = (int)XFTELL(privKeyFile); - keyBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (keyBuf == NULL) { - ret = MEMORY_E; + if (privFileSz > 0 && privFileSz <= (ED25519_PRV_KEY_SIZE * 16)) { + keyBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (keyBuf == NULL) { + ret = MEMORY_E; + } + } + else { + wolfCLU_LogError("Incorrect private key file size: %d", privFileSz); + ret = WOLFCLU_FATAL_ERROR; } } if (ret == 0) { @@ -650,6 +686,10 @@ int wolfCLU_sign_data_dilithium (byte* data, char* out, word32 dataSz, char* pri ret = wc_dilithium_init(key); if (ret != 0) { wolfCLU_LogError("Failed to initialize Dilithium Key.\nRET: %d", ret); + #ifdef WOLFSSL_SMALL_STACK + XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; } /* initialize RNG */ diff --git a/tests/genkey_sign_ver/genkey-sign-ver-test.py b/tests/genkey_sign_ver/genkey-sign-ver-test.py index eb4b856e..9551d864 100644 --- a/tests/genkey_sign_ver/genkey-sign-ver-test.py +++ b/tests/genkey_sign_ver/genkey-sign-ver-test.py @@ -337,6 +337,37 @@ def test_sign_nonexistent_key_fails(self): "Dilithium sign with nonexistent key should have " "failed") + def test_sign_with_pub_key_fails(self): + """Signing with a public key instead of private key must fail gracefully.""" + priv, pub = self._genkey("dilithium", "mldsakey", "der", ["-level", "2"]) + bad_sig = "mldsa_bad_pubkey.sig" + self._track(bad_sig) + r = run_wolfssl("-dilithium", "-sign", "-inkey", pub, + "-inform", "der", "-in", self.SIGN_FILE, + "-out", bad_sig) + self.assertNotEqual(r.returncode, 0, + "dilithium sign with public key should have failed") + self.assertFalse(os.path.exists(bad_sig), + "output file must not be created when signing with " + "public key") + + def test_sign_corrupted_key_fails(self): + """Signing with a corrupted private key must fail gracefully.""" + corrupt_key = "mldsakey_corrupt.priv" + bad_sig = "mldsa_bad_corrupt.sig" + self._track(corrupt_key, bad_sig) + with open(corrupt_key, "w") as f: + f.write("INVALID KEY DATA") + r = run_wolfssl("-dilithium", "-sign", "-inkey", corrupt_key, + "-inform", "der", "-in", self.SIGN_FILE, + "-out", bad_sig) + self.assertNotEqual(r.returncode, 0, + "dilithium sign with corrupted key should have " + "failed") + self.assertFalse(os.path.exists(bad_sig), + "output file must not be created when signing with " + "corrupted key") + @unittest.skipUnless(_has_algorithm("xmss"), "xmss not available") class XmssTest(_GenkeySignVerifyBase): From 95c91af20abe6cf6024ad2249d65bfe461e0bed8 Mon Sep 17 00:00:00 2001 From: Hideki Miyazaki Date: Fri, 17 Apr 2026 13:30:46 +0900 Subject: [PATCH 4/5] Addressed review comments --- src/sign-verify/clu_sign.c | 4 +- src/sign-verify/clu_verify.c | 6 +- tests/genkey_sign_ver/genkey-sign-ver-test.sh | 343 ------------------ 3 files changed, 5 insertions(+), 348 deletions(-) delete mode 100755 tests/genkey_sign_ver/genkey-sign-ver-test.sh diff --git a/src/sign-verify/clu_sign.c b/src/sign-verify/clu_sign.c index d1dc00c7..278ce9a6 100644 --- a/src/sign-verify/clu_sign.c +++ b/src/sign-verify/clu_sign.c @@ -704,7 +704,7 @@ int wolfCLU_sign_data_dilithium (byte* data, char* out, word32 dataSz, char* pri if (ret == 0) { privKeyFile = XFOPEN(privKey, "rb"); if (privKeyFile == NULL) { - wolfCLU_LogError("Faild to open Private key FILE."); + wolfCLU_LogError("Failed to open Private key FILE."); ret = BAD_FUNC_ARG; } } @@ -764,9 +764,9 @@ int wolfCLU_sign_data_dilithium (byte* data, char* out, word32 dataSz, char* pri outBufSz = wc_dilithium_sig_size(key); outBuf = (byte*)XMALLOC(outBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (outBuf == NULL) { + ret = MEMORY_E; wolfCLU_LogError("Failed to allocate signature" " buffer.\nRET: %d", ret); - ret = MEMORY_E; } } /* sign the message usign Dilithium private key. Note that the context is diff --git a/src/sign-verify/clu_verify.c b/src/sign-verify/clu_verify.c index b9391716..6e7b4716 100644 --- a/src/sign-verify/clu_verify.c +++ b/src/sign-verify/clu_verify.c @@ -814,7 +814,7 @@ int wolfCLU_verify_signature_dilithium(byte* sig, int sigSz, byte* msg, /* open and read public key */ keyFile = XFOPEN(keyPath, "rb"); if (keyFile == NULL) { - wolfCLU_LogError("Faild to open Private key FILE."); + wolfCLU_LogError("Failed to open Private key FILE."); wc_dilithium_free(key); #ifdef WOLFSSL_SMALL_STACK XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); @@ -951,7 +951,7 @@ int wolfCLU_verify_signature_xmss(byte* sig, int sigSz, keyFile = XFOPEN(pubKey, "rb"); if (keyFile == NULL) { ret = OUTPUT_FILE_ERROR; - wolfCLU_LogError("Faild to open Public key FILE."); + wolfCLU_LogError("Failed to open Public key FILE."); } } @@ -1107,7 +1107,7 @@ int wolfCLU_verify_signature_xmssmt(byte* sig, int sigSz, keyFile = XFOPEN(pubKey, "rb"); if (keyFile == NULL) { ret = OUTPUT_FILE_ERROR; - wolfCLU_LogError("Faild to open Public key FILE."); + wolfCLU_LogError("Failed to open Public key FILE."); } } diff --git a/tests/genkey_sign_ver/genkey-sign-ver-test.sh b/tests/genkey_sign_ver/genkey-sign-ver-test.sh deleted file mode 100755 index 46c3efb6..00000000 --- a/tests/genkey_sign_ver/genkey-sign-ver-test.sh +++ /dev/null @@ -1,343 +0,0 @@ -#!/bin/sh - -# genkey-sign-ver-test.sh -# -# Copyright (C) 2006-2025 wolfSSL Inc. -# -# This file is part of wolfSSL. -# -# wolfSSL is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# wolfSSL is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA -#/ -#/ -# - -# Skip test if filesystem disabled -FILESYSTEM=`cat config.log | grep "disable\-filesystem"` -if [ "$FILESYSTEM" != "" ] -then - exit 77 -fi - -cleanup_genkey_sign_ver(){ - rm -f ecckey - rm ecckey.priv - rm ecckey.pub - rm edkey.priv - rm edkey.pub - rm rsakey.priv - rm rsakey.pub - rm mldsakey.priv - rm mldsakey.pub - rm mldsakey_pub.pub - rm mldsakey_pub.priv - rm mldsakey_priv.pub - rm mldsakey_priv.priv - rm ecc-signed.sig - rm ed-signed.sig - rm rsa-signed.sig - rm rsa-sigout.private_result - rm rsa-sigout.public_result - rm mldsa-signed.sig - rm -f mldsa_bad_pubkey.sig - rm -f mldsa_bad_corrupt.sig - rm -f mldsakey_corrupt.priv - rm xmss-signed.sig - # rm xmssmt-signed.sig - rm sign-this.txt - - # XMSS/XMSS^MT key files - rm XMSS-SHA2_10_256.priv - rm XMSS-SHA2_10_256.pub - # rm XMSS-SHA2_16_256.priv - # rm XMSS-SHA2_16_256.pub - # rm XMSS-SHA2_20_256.priv - # rm XMSS-SHA2_20_256.pub - - # rm XMSSMT-SHA2_20-2_256.priv - # rm XMSSMT-SHA2_20-2_256.pub - # rm XMSSMT-SHA2_20-4_256.priv - # rm XMSSMT-SHA2_20-4_256.pub - # rm XMSSMT-SHA2_40-2_256.priv - # rm XMSSMT-SHA2_40-2_256.pub - # rm XMSSMT-SHA2_40-4_256.priv - # rm XMSSMT-SHA2_40-4_256.pub - # rm XMSSMT-SHA2_40-8_256.priv - # rm XMSSMT-SHA2_40-8_256.pub - # rm XMSSMT-SHA2_60-3_256.priv - # rm XMSSMT-SHA2_60-3_256.pub - # rm XMSSMT-SHA2_60-6_256.priv - # rm XMSSMT-SHA2_60-6_256.pub - # rm XMSSMT-SHA2_60-12_256.priv - # rm XMSSMT-SHA2_60-12_256.pub -} -trap cleanup_genkey_sign_ver INT TERM EXIT - -create_sign_data_file(){ - printf '%s\n' "Sign this data" > sign-this.txt -} - -rsa_compare_decrypted(){ - if [ "${1}" = "${2}" ]; then - printf '%s\n' "Decrypted matches original, success!" - printf '%s\n' "DECRYPTED --> ${1}" - printf '%s\n' "ORIGINAL --> ${2}" - else - printf '%s\n' "Decrypted mismatch with original, FAILURE!" - printf '%s\n' "DECRYPTED --> ${1}" - printf '%s\n' "ORIGINAL --> ${2}" && exit 99 - fi -} - -gen_key_sign_ver_test(){ - - # generate a key pair for signing - if [ $1 = "dilithium" ]; then - ./wolfssl -genkey $1 -level $5 -out $2 -outform $4 -output KEYPAIR - elif [ $1 = "xmss" ]; then - ./wolfssl -genkey $1 -height $5 -out $2 -outform $4 -output KEYPAIR - elif [ $1 = "xmssmt" ]; then - ./wolfssl -genkey $1 -height $5 -layer $6 -out $2 -outform $4 -output KEYPAIR - else - ./wolfssl -genkey $1 -out $2 -outform $4 KEYPAIR - fi - RESULT=$? - printf '%s\n' "genkey RESULT - $RESULT" - [ $RESULT -ne 0 ] && printf '%s\n' "Failed $1 genkey" && \ - printf '%s\n' "Before running this test please configure wolfssl with" && \ - printf '%s\n' "--enable-keygen" && exit 99 - - # test signing with priv key - ./wolfssl -$1 -sign -inkey $2.priv -inform $4 -in sign-this.txt -out $3 - RESULT=$? - printf '%s\n' "sign RESULT - $RESULT" - [ $RESULT -ne 0 ] && printf '%s\n' "Failed $1 sign" && exit 99 - - # test verifying with priv key - if [ "${1}" = "rsa" ]; then - ./wolfssl -$1 -verify -inkey $2.priv -inform $4 -sigfile $3 -in sign-this.txt \ - -out $5.private_result - elif [ "${1}" = "dilithium" ] || [ "${1}" = "xmss" ] || [ "${1}" = "xmssmt" ]; then - # ./wolfssl -$1 -verify -inkey $2.priv -inform $4 -sigfile $3 -in sign-this.txt - # pass - : - else - ./wolfssl -$1 -verify -inkey $2.priv -inform $4 -sigfile $3 -in sign-this.txt - fi - RESULT=$? - printf '%s\n' "private verify RESULT - $RESULT" - [ $RESULT -ne 0 ] && printf '%s\n' "Failed $1 private verify" && exit 99 - - # test verifying with pub key - if [ "${1}" = "rsa" ]; then - ./wolfssl -$1 -verify -inkey $2.pub -inform $4 -sigfile $3 -in sign-this.txt \ - -out $5.public_result -pubin - else - ./wolfssl -$1 -verify -inkey $2.pub -inform $4 -sigfile $3 -in sign-this.txt -pubin - fi - RESULT=$? - printf '%s\n' "public verify RESULT - $RESULT" - [ $RESULT -ne 0 ] && printf '%s\n' "Failed $1 public verify " && exit 99 - - if [ $1 = "rsa" ]; then - ORIGINAL=`cat -A sign-this.txt` - - DECRYPTED=`cat -A $5.private_result` - rsa_compare_decrypted "${DECRYPTED}" "${ORIGINAL}" - - DECRYPTED=`cat -A $5.public_result` - rsa_compare_decrypted "${DECRYPTED}" "${ORIGINAL}" - fi - -} - -create_sign_data_file - -ALGORITHM="ed25519" -KEYFILENAME="edkey" -SIGOUTNAME="ed-signed.sig" -DERPEMRAW="der" -gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} - -ALGORITHM="ecc" -KEYFILENAME="ecckey" -SIGOUTNAME="ecc-signed.sig" -DERPEMRAW="der" -gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} - -ALGORITHM="rsa" -KEYFILENAME="rsakey" -SIGOUTNAME="rsa-signed.sig" -DERPEMRAW="der" -VERIFYOUTNAME="rsa-sigout" -gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${VERIFYOUTNAME} - -# A verify with invalid signature must fail gracefully. -./wolfssl -rsa -verify -inkey rsakey.pub -inform der \ - -sigfile sign-this.txt -in sign-this.txt \ - -out rsa_badverify_out.txt -pubin -RESULT=$? -[ $RESULT -eq 0 ] && \ - printf '%s\n' "RSA verify with invalid sig should have failed" && exit 99 -[ -f rsa_badverify_out.txt ] && \ - printf '%s\n' "RSA verify with invalid sig: output file must not be created" && exit 99 - -# Regression test: -exponent value must not overwrite -size (was stored in -# sizeArg instead of expArg, corrupting the key size). -./wolfssl -genkey rsa -size 2048 -exponent 65537 -out rsakey_exp \ - -outform der -output KEYPAIR -RESULT=$? -[ $RESULT -ne 0 ] && printf '%s\n' "Failed rsa genkey with explicit -exponent" && exit 99 -rm -f rsakey_exp.priv rsakey_exp.pub - -ALGORITHM="ed25519" -KEYFILENAME="edkey" -SIGOUTNAME="ed-signed.sig" -DERPEMRAW="pem" -gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} - -ALGORITHM="ecc" -KEYFILENAME="ecckey" -SIGOUTNAME="ecc-signed.sig" -DERPEMRAW="pem" -gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} - -ALGORITHM="rsa" -KEYFILENAME="rsakey" -SIGOUTNAME="rsa-signed.sig" -DERPEMRAW="pem" -VERIFYOUTNAME="rsa-sigout" -gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${VERIFYOUTNAME} - -ALGORITHM="ed25519" -KEYFILENAME="edkey" -SIGOUTNAME="ed-signed.sig" -DERPEMRAW="raw" -gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} - -if ./wolfssl -genkey -h 2>&1 | grep -A6 "Available keys with current configure" | grep dilithium; then - ALGORITHM="dilithium" - KEYFILENAME="mldsakey" - SIGOUTNAME="mldsa-signed.sig" - DERPEMRAW="der" - for level in 2 3 5 - do - gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${level} - done - -ALGORITHM="dilithium" -KEYFILENAME="mldsakey" -SIGOUTNAME="mldsa-signed.sig" -DERPEMRAW="pem" -for level in 2 3 5 -do - gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${level} -done - -# Verifies that -output PUB generates only the public key file. -./wolfssl -genkey dilithium -level 2 -out mldsakey_pub -outform der -output pub -RESULT=$? -[ $RESULT -ne 0 ] && printf '%s\n' "Failed dilithium genkey -output PUB" && exit 99 -[ ! -f mldsakey_pub.pub ] && printf '%s\n' "dilithium -output PUB: .pub file missing" && exit 99 -[ -f mldsakey_pub.priv ] && printf '%s\n' "dilithium -output PUB: .priv unexpectedly created" && exit 99 - -# Verifies that -output PRIV generates only the private key file. -./wolfssl -genkey dilithium -level 2 -out mldsakey_priv -outform der -output priv -RESULT=$? -[ $RESULT -ne 0 ] && printf '%s\n' "Failed dilithium genkey -output PRIV" && exit 99 -[ ! -f mldsakey_priv.priv ] && printf '%s\n' "dilithium -output PRIV: .priv file missing" && exit 99 -[ -f mldsakey_priv.pub ] && printf '%s\n' "dilithium -output PRIV: .pub unexpectedly created" && exit 99 - -# Dilithium sign to an unwritable path must fail gracefully -./wolfssl -genkey dilithium -level 2 -out mldsakey -outform der -output keypair -./wolfssl -dilithium -sign -inkey mldsakey.priv -inform der \ - -in sign-this.txt -out /nonexistent_dir/mldsa_bad.sig -RESULT=$? -[ $RESULT -eq 0 ] && \ - printf '%s\n' "dilithium sign to invalid path should have failed" && exit 99 - -# Dilithium sign with public key as inkey must fail gracefully -./wolfssl -dilithium -sign -inkey mldsakey.pub -inform der \ - -in sign-this.txt -out mldsa_bad_pubkey.sig -RESULT=$? -[ $RESULT -eq 0 ] && \ - printf '%s\n' "dilithium sign with public key should have failed" && exit 99 -[ -f mldsa_bad_pubkey.sig ] && \ - printf '%s\n' "dilithium sign with public key: output file must not be created" && exit 99 - -# Dilithium sign with corrupted private key must fail gracefully -printf '%s' "INVALID KEY DATA" > mldsakey_corrupt.priv -./wolfssl -dilithium -sign -inkey mldsakey_corrupt.priv -inform der \ - -in sign-this.txt -out mldsa_bad_corrupt.sig -RESULT=$? -[ $RESULT -eq 0 ] && \ - printf '%s\n' "dilithium sign with corrupted key should have failed" && exit 99 -[ -f mldsa_bad_corrupt.sig ] && \ - printf '%s\n' "dilithium sign with corrupted key: output file must not be created" && exit 99 -rm -f mldsakey_corrupt.priv -fi - -# Check if xmss is availabe -if ./wolfssl xmss -help 2>&1 | grep -A6 "Available keys with current configure" | grep xmss; then - printf "Testing XMSS sign/verify\n" - ALGORITHM="xmss" - SIGOUTNAME="xmss-signed.sig" - DERPEMRAW="raw" - HEIGHT=10 - - gen_key_sign_ver_test ${ALGORITHM} "XMSS-SHA2_${HEIGHT}_256" ${SIGOUTNAME} ${DERPEMRAW} ${HEIGHT} - - # Too long to run - # for HEIGHT in 10 16 20 - # do - # KEYFILENAME="XMSS-SHA2_${HEIGHT}_256" - # gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${HEIGHT} - # done - - # ALGORITHM="xmssmt" - # SIGOUTNAME="xmssmt-signed.sig" - # DERPEMRAW="raw" - # HEIGHT=20 - - # for LAYER in 2 4 - # do - # KEYFILENAME="XMSSMT-SHA2_${HEIGHT}-${LAYER}_256" - # gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${HEIGHT} ${LAYER} - # done - - # ALGORITHM="xmssmt" - # SIGOUTNAME="xmssmt-signed.sig" - # DERPEMRAW="raw" - # HEIGHT=40 - - # for LAYER in 2 4 8 - # do - # KEYFILENAME="XMSSMT-SHA2_${HEIGHT}-${LAYER}_256" - # gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${HEIGHT} ${LAYER} - # done - - # ALGORITHM="xmssmt" - # SIGOUTNAME="xmssmt-signed.sig" - # DERPEMRAW="raw" - # HEIGHT=60 - - # for LAYER in 3 6 12 - # do - # KEYFILENAME="XMSSMT-SHA2_${HEIGHT}-${LAYER}_256" - # gen_key_sign_ver_test ${ALGORITHM} ${KEYFILENAME} ${SIGOUTNAME} ${DERPEMRAW} ${HEIGHT} ${LAYER} - # done -fi - - -exit 0 From 8a01c6d91bfc0552d0019a1f1683beeb8be2052d Mon Sep 17 00:00:00 2001 From: Hideki Miyazaki Date: Sat, 18 Apr 2026 08:06:35 +0900 Subject: [PATCH 5/5] Addressed review comments --- src/sign-verify/clu_sign.c | 18 +++++++++++++----- src/sign-verify/clu_verify.c | 7 +++++-- tests/genkey_sign_ver/genkey-sign-ver-test.py | 4 ++-- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/sign-verify/clu_sign.c b/src/sign-verify/clu_sign.c index 278ce9a6..db4e2e4e 100644 --- a/src/sign-verify/clu_sign.c +++ b/src/sign-verify/clu_sign.c @@ -280,7 +280,9 @@ int wolfCLU_sign_data_rsa(byte* data, char* out, word32 dataSz, char* privKey, ret = BAD_FUNC_ARG; } else { - XFWRITE(outBuf, 1, outBufSz, s); + if ((int)XFWRITE(outBuf, 1, outBufSz, s) <= 0) { + ret = OUTPUT_FILE_ERROR; + } XFCLOSE(s); } } @@ -455,7 +457,9 @@ int wolfCLU_sign_data_ecc(byte* data, char* out, word32 fSz, char* privKey, ret = BAD_FUNC_ARG; } else { - XFWRITE(outBuf, 1, outLen, s); + if ((int)XFWRITE(outBuf, 1, outLen, s) <= 0) { + ret = OUTPUT_FILE_ERROR; + } XFCLOSE(s); } } @@ -618,7 +622,9 @@ int wolfCLU_sign_data_ed25519 (byte* data, char* out, word32 fSz, char* privKey, ret = BAD_FUNC_ARG; } else { - XFWRITE(outBuf, 1, outLen, s); + if ((int)XFWRITE(outBuf, 1, outLen, s) <= 0) { + ret = OUTPUT_FILE_ERROR; + } XFCLOSE(s); } } @@ -734,7 +740,7 @@ int wolfCLU_sign_data_dilithium (byte* data, char* out, word32 dataSz, char* pri privBufSz = privFileSz; if (XFSEEK(privKeyFile, 0, SEEK_SET) != 0 || (int)XFREAD(privBuf, 1, privFileSz, privKeyFile) != privFileSz) { - wolfCLU_LogError("Incorrect private key file size: %d", privFileSz); + wolfCLU_LogError("Failed to read private key file."); ret = WOLFCLU_FATAL_ERROR; } } @@ -788,7 +794,9 @@ int wolfCLU_sign_data_dilithium (byte* data, char* out, word32 dataSz, char* pri wolfCLU_LogError("Failed to open output file %s", out); ret = BAD_FUNC_ARG; } else { - XFWRITE(outBuf, 1, outBufSz, outFile); + if ((int)XFWRITE(outBuf, 1, outBufSz, outFile) <= 0) { + ret = OUTPUT_FILE_ERROR; + } XFCLOSE(outFile); } } diff --git a/src/sign-verify/clu_verify.c b/src/sign-verify/clu_verify.c index 6e7b4716..11a25f20 100644 --- a/src/sign-verify/clu_verify.c +++ b/src/sign-verify/clu_verify.c @@ -450,13 +450,16 @@ int wolfCLU_verify_signature_rsa(byte* sig, char* out, int sigSz, char* keyPath, /* write the output to the specified file */ if (ret > 0) { + int writeSz = ret; XFILE s = XFOPEN(out, "wb"); if (s == NULL) { wolfCLU_LogError("Unable to open file %s", out); ret = BAD_FUNC_ARG; } else { - XFWRITE(outBuf, 1, ret, s); + if ((int)XFWRITE(outBuf, 1, writeSz, s) <= 0) { + ret = OUTPUT_FILE_ERROR; + } XFCLOSE(s); } } @@ -814,7 +817,7 @@ int wolfCLU_verify_signature_dilithium(byte* sig, int sigSz, byte* msg, /* open and read public key */ keyFile = XFOPEN(keyPath, "rb"); if (keyFile == NULL) { - wolfCLU_LogError("Failed to open Private key FILE."); + wolfCLU_LogError("Failed to open public key FILE."); wc_dilithium_free(key); #ifdef WOLFSSL_SMALL_STACK XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); diff --git a/tests/genkey_sign_ver/genkey-sign-ver-test.py b/tests/genkey_sign_ver/genkey-sign-ver-test.py index 9551d864..0757cb03 100644 --- a/tests/genkey_sign_ver/genkey-sign-ver-test.py +++ b/tests/genkey_sign_ver/genkey-sign-ver-test.py @@ -356,8 +356,8 @@ def test_sign_corrupted_key_fails(self): corrupt_key = "mldsakey_corrupt.priv" bad_sig = "mldsa_bad_corrupt.sig" self._track(corrupt_key, bad_sig) - with open(corrupt_key, "w") as f: - f.write("INVALID KEY DATA") + with open(corrupt_key, "wb") as f: + f.write(b"INVALID KEY DATA") r = run_wolfssl("-dilithium", "-sign", "-inkey", corrupt_key, "-inform", "der", "-in", self.SIGN_FILE, "-out", bad_sig)