@@ -685,6 +685,82 @@ int test_wc_dilithium(void)
685685 return EXPECT_RESULT();
686686}
687687
688+ /*
689+ * Test that wc_dilithium_sign_msg() rejects a public-key-only key object.
690+ * A key with prvKeySet=0 must not silently sign with zeroed key data.
691+ */
692+ int test_wc_dilithium_sign_pubonly_fails(void)
693+ {
694+ EXPECT_DECLS;
695+ #if defined(HAVE_DILITHIUM) && defined(WOLFSSL_WC_DILITHIUM) && \
696+ !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \
697+ !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && \
698+ !defined(WOLFSSL_DILITHIUM_NO_CTX)
699+ dilithium_key* key;
700+ dilithium_key* pubOnlyKey;
701+ WC_RNG rng;
702+ byte* pubBuf = NULL;
703+ word32 pubLen = DILITHIUM_MAX_PUB_KEY_SIZE;
704+ byte msg[] = "test message for pubonly check";
705+ byte* sig = NULL;
706+ word32 sigLen = DILITHIUM_MAX_SIG_SIZE;
707+
708+ key = (dilithium_key*)XMALLOC(sizeof(*key), NULL,
709+ DYNAMIC_TYPE_TMP_BUFFER);
710+ ExpectNotNull(key);
711+ pubOnlyKey = (dilithium_key*)XMALLOC(sizeof(*pubOnlyKey), NULL,
712+ DYNAMIC_TYPE_TMP_BUFFER);
713+ ExpectNotNull(pubOnlyKey);
714+ pubBuf = (byte*)XMALLOC(DILITHIUM_MAX_PUB_KEY_SIZE, NULL,
715+ DYNAMIC_TYPE_TMP_BUFFER);
716+ ExpectNotNull(pubBuf);
717+ sig = (byte*)XMALLOC(DILITHIUM_MAX_SIG_SIZE, NULL,
718+ DYNAMIC_TYPE_TMP_BUFFER);
719+ ExpectNotNull(sig);
720+
721+ if (key != NULL)
722+ XMEMSET(key, 0, sizeof(*key));
723+ if (pubOnlyKey != NULL)
724+ XMEMSET(pubOnlyKey, 0, sizeof(*pubOnlyKey));
725+ XMEMSET(&rng, 0, sizeof(rng));
726+
727+ ExpectIntEQ(wc_InitRng(&rng), 0);
728+ ExpectIntEQ(wc_dilithium_init(key), 0);
729+ ExpectIntEQ(wc_dilithium_init(pubOnlyKey), 0);
730+
731+ #ifndef WOLFSSL_NO_ML_DSA_44
732+ ExpectIntEQ(wc_dilithium_set_level(key, WC_ML_DSA_44), 0);
733+ ExpectIntEQ(wc_dilithium_set_level(pubOnlyKey, WC_ML_DSA_44), 0);
734+ #elif !defined(WOLFSSL_NO_ML_DSA_65)
735+ ExpectIntEQ(wc_dilithium_set_level(key, WC_ML_DSA_65), 0);
736+ ExpectIntEQ(wc_dilithium_set_level(pubOnlyKey, WC_ML_DSA_65), 0);
737+ #else
738+ ExpectIntEQ(wc_dilithium_set_level(key, WC_ML_DSA_87), 0);
739+ ExpectIntEQ(wc_dilithium_set_level(pubOnlyKey, WC_ML_DSA_87), 0);
740+ #endif
741+
742+ /* Generate a real key pair and export its public key. */
743+ ExpectIntEQ(wc_dilithium_make_key(key, &rng), 0);
744+ ExpectIntEQ(wc_dilithium_export_public(key, pubBuf, &pubLen), 0);
745+
746+ /* Import only the public key into a fresh key object. */
747+ ExpectIntEQ(wc_dilithium_import_public(pubBuf, pubLen, pubOnlyKey), 0);
748+
749+ /* Signing with a public-key-only object must fail. */
750+ ExpectIntEQ(wc_dilithium_sign_ctx_msg(NULL, 0, msg, sizeof(msg), sig,
751+ &sigLen, pubOnlyKey, &rng), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
752+
753+ DoExpectIntEQ(wc_FreeRng(&rng), 0);
754+ wc_dilithium_free(pubOnlyKey);
755+ wc_dilithium_free(key);
756+ XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
757+ XFREE(pubBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
758+ XFREE(pubOnlyKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
759+ XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
760+ #endif
761+ return EXPECT_RESULT();
762+ } /* END test_wc_dilithium_sign_pubonly_fails */
763+
688764int test_wc_dilithium_make_key(void)
689765{
690766 EXPECT_DECLS;
0 commit comments