Skip to content

Commit dc2f472

Browse files
committed
fix f-1899 potential heap buffer over-read
add test coverage
1 parent 0aefd52 commit dc2f472

2 files changed

Lines changed: 109 additions & 105 deletions

File tree

src/sign-verify/clu_sign.c

Lines changed: 86 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -617,16 +617,18 @@ int wolfCLU_sign_data_dilithium (byte* data, char* out, word32 dataSz, char* pri
617617
{
618618
#ifdef HAVE_DILITHIUM
619619
int ret = 0;
620+
int privFileSz = 0;
621+
word32 index = 0;
622+
620623
XFILE privKeyFile = NULL;
621624
byte* privBuf = NULL;
622-
int privFileSz = 0;
625+
623626
word32 privBufSz = 0;
624-
word32 index = 0;
625627
byte* outBuf = NULL;
626628
word32 outBufSz = 0;
627629

628630
WC_RNG rng;
629-
XMEMSET(&rng, 0, sizeof(rng));
631+
630632

631633
#ifdef WOLFSSL_SMALL_STACK
632634
dilithium_key* key;
@@ -639,153 +641,132 @@ int wolfCLU_sign_data_dilithium (byte* data, char* out, word32 dataSz, char* pri
639641
dilithium_key key[1];
640642
#endif
641643

644+
XMEMSET(&rng, 0, sizeof(rng));
645+
XMEMSET(key, 0, sizeof(dilithium_key));
646+
642647
/* init the dilithium key */
643648
if (wc_dilithium_init(key) != 0) {
644649
wolfCLU_LogError("Failed to initialize Dilithium Key.\nRET: %d", ret);
645650
#ifdef WOLFSSL_SMALL_STACK
646651
XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
647652
#endif
648-
return WOLFCLU_FAILURE;
653+
ret = WOLFCLU_FAILURE;
649654
}
650-
XMEMSET(key, 0, sizeof(dilithium_key));
651655

652-
if (wc_InitRng(&rng) != 0) {
653-
wolfCLU_LogError("Failed to initialize rng.\nRET: %d", ret);
654-
wc_dilithium_free(key);
655-
#ifdef WOLFSSL_SMALL_STACK
656-
XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
657-
#endif
658-
return WOLFCLU_FAILURE;
656+
/* initialize RNG */
657+
if (ret == 0) {
658+
ret = wc_InitRng(&rng);
659+
if (ret != 0) {
660+
wolfCLU_LogError("Failed to initialize rng.\nRET: %d", ret);
661+
}
659662
}
660663

661664
/* open and read private key */
662-
privKeyFile = XFOPEN(privKey, "rb");
663-
if (privKeyFile == NULL) {
664-
wolfCLU_LogError("Faild to open Private key FILE.");
665-
wc_FreeRng(&rng);
666-
wc_dilithium_free(key);
667-
#ifdef WOLFSSL_SMALL_STACK
668-
XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
669-
#endif
670-
return ret;
665+
if (ret == 0) {
666+
privKeyFile = XFOPEN(privKey, "rb");
667+
if (privKeyFile == NULL) {
668+
wolfCLU_LogError("Faild to open Private key FILE.");
669+
ret = BAD_FUNC_ARG;
670+
}
671671
}
672-
673-
XFSEEK(privKeyFile, 0, SEEK_END);
674-
privFileSz = (int)XFTELL(privKeyFile);
675-
privBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
676-
if (privBuf == NULL) {
677-
XFCLOSE(privKeyFile);
678-
wc_FreeRng(&rng);
679-
wc_dilithium_free(key);
680-
#ifdef WOLFSSL_SMALL_STACK
681-
XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
682-
#endif
683-
return MEMORY_E;
672+
if (ret == 0) {
673+
XFSEEK(privKeyFile, 0, SEEK_END);
674+
privFileSz = (int)XFTELL(privKeyFile);
675+
privBuf = (byte*)XMALLOC(privFileSz+1, HEAP_HINT,
676+
DYNAMIC_TYPE_TMP_BUFFER);
677+
if (privBuf == NULL) {
678+
ret = MEMORY_E;
679+
}
684680
}
685-
686-
XMEMSET(privBuf, 0, privFileSz+1);
687-
privBufSz = privFileSz;
688-
XFSEEK(privKeyFile, 0, SEEK_SET);
689-
if (XFREAD(privBuf, 1, privBufSz, privKeyFile) != privBufSz) {
690-
wolfCLU_Log(WOLFCLU_L0, "incorecct size: %d", privFileSz);
691-
XFREE(privBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
692-
wc_FreeRng(&rng);
693-
wc_dilithium_free(key);
694-
#ifdef WOLFSSL_SMALL_STACK
695-
XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
696-
#endif
697-
return ret;
681+
if (ret == 0) {
682+
XMEMSET(privBuf, 0, privFileSz+1);
683+
privBufSz = privFileSz;
684+
if (XFSEEK(privKeyFile, 0, SEEK_SET) != 0 ||
685+
(int)XFREAD(privBuf, 1, privFileSz, privKeyFile) != privFileSz) {
686+
wolfCLU_Log(WOLFCLU_L0, "incorecct size: %d", privFileSz);
687+
ret = WOLFCLU_FATAL_ERROR;
688+
}
698689
}
699-
XFCLOSE(privKeyFile);
700690

701691
/* convert PEM to DER if necessary */
702-
if (inForm == PEM_FORM) {
692+
if (inForm == PEM_FORM && ret == 0) {
703693
ret = wolfCLU_KeyPemToDer(&privBuf, privFileSz, 0);
704694
if (ret < 0) {
705695
wolfCLU_LogError("Failed to convert PEM to DER.\nRET: %d", ret);
706-
XFREE(privBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
707-
wc_FreeRng(&rng);
708-
wc_dilithium_free(key);
709-
#ifdef WOLFSSL_SMALL_STACK
710-
XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
711-
#endif
712-
return ret;
713696
}
714697
else {
715-
privFileSz = ret;
698+
/* update privBuf and privFileSz with the converted DER data */
699+
privBufSz = privFileSz = ret;
700+
ret = 0;
716701
}
717702
}
718703

719-
/* retrieving private key and staoring in the Dilithium key */
720-
ret = wc_Dilithium_PrivateKeyDecode(privBuf, &index, key, privBufSz);
721-
XFREE(privBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
722-
if (ret != 0) {
723-
wolfCLU_LogError("Failed to decode private key.\nRET: %d", ret);
724-
wc_FreeRng(&rng);
725-
wc_dilithium_free(key);
726-
#ifdef WOLFSSL_SMALL_STACK
727-
XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
728-
#endif
729-
return ret;
704+
/* retrieving private key and storing in the Dilithium key */
705+
if (ret == 0) {
706+
ret = wc_Dilithium_PrivateKeyDecode(privBuf, &index, key, privBufSz);
707+
if (ret != 0) {
708+
wolfCLU_LogError("Failed to decode private key.\nRET: %d", ret);
709+
}
730710
}
731-
732711
/* malloc signature buffer */
733-
outBufSz = wc_dilithium_sig_size(key);
734-
outBuf = (byte*)XMALLOC(outBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
735-
if (outBuf == NULL) {
736-
wc_FreeRng(&rng);
737-
wc_dilithium_free(key);
738-
#ifdef WOLFSSL_SMALL_STACK
739-
XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
740-
#endif
741-
return MEMORY_E;
712+
if (ret == 0) {
713+
outBufSz = wc_dilithium_sig_size(key);
714+
outBuf = (byte*)XMALLOC(outBufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
715+
if (outBuf == NULL) {
716+
wolfCLU_LogError("Failed to allocate signature"
717+
" buffer.\nRET: %d", ret);
718+
ret = MEMORY_E;
719+
}
742720
}
743-
744721
/* sign the message usign Dilithium private key. Note that the context is
745722
* empty. This is for interoperability. */
746-
ret = wc_dilithium_sign_ctx_msg(NULL, 0, data, dataSz, outBuf, &outBufSz,
747-
key, &rng);
748-
if (ret != 0) {
749-
wolfCLU_LogError("Failed to sign data with Dilithium private key.\nRET: %d", ret);
750-
XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
751-
wc_FreeRng(&rng);
752-
wc_dilithium_free(key);
753-
#ifdef WOLFSSL_SMALL_STACK
754-
XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
755-
#endif
756-
return ret;
723+
if (ret == 0) {
724+
ret = wc_dilithium_sign_ctx_msg(NULL, 0, data, dataSz, outBuf,
725+
&outBufSz, key, &rng);
726+
if (ret != 0) {
727+
wolfCLU_LogError("Failed to sign data with"
728+
" Dilithium private key.\nRET: %d", ret);
729+
}
757730
}
758-
else {
731+
732+
if (ret == 0) {
759733
XFILE outFile;
760734
outFile = XFOPEN(out, "wb");
735+
761736
if (outFile == NULL) {
762737
wolfCLU_LogError("Failed to open output file %s", out);
763-
XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
764-
wc_FreeRng(&rng);
765-
wc_dilithium_free(key);
766-
#ifdef WOLFSSL_SMALL_STACK
767-
XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
768-
#endif
769-
return BAD_FUNC_ARG;
770-
}
771-
XFWRITE(outBuf, 1, outBufSz, outFile);
772-
XFCLOSE(outFile);
738+
ret = BAD_FUNC_ARG;
739+
} else {
740+
XFWRITE(outBuf, 1, outBufSz, outFile);
741+
XFCLOSE(outFile);
742+
}
773743
}
774744

775-
XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
776-
wc_FreeRng(&rng);
777-
wc_dilithium_free(key);
745+
/* cleanup allocated resources */
746+
if (privKeyFile != NULL)
747+
XFCLOSE(privKeyFile);
778748

749+
if (privBuf != NULL) {
750+
XFREE(privBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
751+
}
752+
753+
if (outBuf != NULL) {
754+
XFREE(outBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
755+
}
756+
757+
wc_dilithium_free(key);
758+
wc_FreeRng(&rng);
779759
#ifdef WOLFSSL_SMALL_STACK
780760
XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
781761
#endif
782762

783-
return WOLFCLU_SUCCESS;
763+
/* expected ret == WOLFCLU_SUCCESS */
764+
return (ret >= 0) ? WOLFCLU_SUCCESS : ret;
784765
#else
785766
(void)data;
786767
(void)out;
787768
(void)dataSz;
788-
(void) privKey;
769+
(void)privKey;
789770
(void)inForm;
790771

791772
return NOT_COMPILED_IN;

tests/genkey_sign_ver/genkey-sign-ver-test.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ cleanup_genkey_sign_ver(){
5050
rm rsa-sigout.private_result
5151
rm rsa-sigout.public_result
5252
rm mldsa-signed.sig
53+
rm -f mldsa_bad_pubkey.sig
54+
rm -f mldsa_bad_corrupt.sig
55+
rm -f mldsakey_corrupt.priv
5356
rm xmss-signed.sig
5457
# rm xmssmt-signed.sig
5558
rm sign-this.txt
@@ -263,6 +266,26 @@ RESULT=$?
263266
RESULT=$?
264267
[ $RESULT -eq 0 ] && \
265268
printf '%s\n' "dilithium sign to invalid path should have failed" && exit 99
269+
270+
# Dilithium sign with public key as inkey must fail gracefully
271+
./wolfssl -dilithium -sign -inkey mldsakey.pub -inform der \
272+
-in sign-this.txt -out mldsa_bad_pubkey.sig
273+
RESULT=$?
274+
[ $RESULT -eq 0 ] && \
275+
printf '%s\n' "dilithium sign with public key should have failed" && exit 99
276+
[ -f mldsa_bad_pubkey.sig ] && \
277+
printf '%s\n' "dilithium sign with public key: output file must not be created" && exit 99
278+
279+
# Dilithium sign with corrupted private key must fail gracefully
280+
printf '%s' "INVALID KEY DATA" > mldsakey_corrupt.priv
281+
./wolfssl -dilithium -sign -inkey mldsakey_corrupt.priv -inform der \
282+
-in sign-this.txt -out mldsa_bad_corrupt.sig
283+
RESULT=$?
284+
[ $RESULT -eq 0 ] && \
285+
printf '%s\n' "dilithium sign with corrupted key should have failed" && exit 99
286+
[ -f mldsa_bad_corrupt.sig ] && \
287+
printf '%s\n' "dilithium sign with corrupted key: output file must not be created" && exit 99
288+
rm -f mldsakey_corrupt.priv
266289
fi
267290

268291
# Check if xmss is availabe

0 commit comments

Comments
 (0)