@@ -7890,6 +7890,196 @@ int test_mldsa_make_public_key(void)
78907890}
78917891
78927892
7893+ int test_mldsa_make_public_key_then_export(void)
7894+ {
7895+ EXPECT_DECLS;
7896+ /* Runs under WOLF_CRYPTO_CB_FIND too. */
7897+ #if defined(WOLFSSL_HAVE_MLDSA) && !defined(WOLFSSL_MLDSA_NO_ASN1) && \
7898+ !defined(WOLFSSL_MLDSA_ASSIGN_KEY) && \
7899+ !defined(WOLFSSL_MLDSA_NO_MAKE_KEY) && \
7900+ !defined(WOLFSSL_MLDSA_NO_SIGN) && !defined(WOLFSSL_MLDSA_NO_VERIFY) && \
7901+ defined(WOLFSSL_MLDSA_PUBLIC_KEY)
7902+ wc_MlDsaKey* privKey;
7903+ wc_MlDsaKey* pubKey;
7904+ word32 idx;
7905+ byte derivedPub[WC_MLDSA_87_PUB_KEY_SIZE];
7906+ word32 derivedPubSz;
7907+
7908+ privKey = (wc_MlDsaKey*)XMALLOC(sizeof(*privKey), NULL,
7909+ DYNAMIC_TYPE_TMP_BUFFER);
7910+ ExpectNotNull(privKey);
7911+ pubKey = (wc_MlDsaKey*)XMALLOC(sizeof(*pubKey), NULL,
7912+ DYNAMIC_TYPE_TMP_BUFFER);
7913+ ExpectNotNull(pubKey);
7914+ if (privKey != NULL) {
7915+ XMEMSET(privKey, 0, sizeof(*privKey));
7916+ }
7917+ if (pubKey != NULL) {
7918+ XMEMSET(pubKey, 0, sizeof(*pubKey));
7919+ }
7920+
7921+ #ifndef WOLFSSL_NO_ML_DSA_44
7922+ ExpectIntEQ(wc_MlDsaKey_Init(privKey, NULL, INVALID_DEVID), 0);
7923+ ExpectIntEQ(wc_MlDsaKey_SetParams(privKey, WC_ML_DSA_44), 0);
7924+
7925+ /* Private-only DER: Export/Der accessors fail until derived. */
7926+ idx = 0;
7927+ ExpectIntEQ(wc_MlDsaKey_PrivateKeyDecode(privKey, mldsa44_priv_only,
7928+ sizeof_mldsa44_priv_only, &idx), 0);
7929+ ExpectIntEQ(privKey->pubKeySet, 0);
7930+ derivedPubSz = sizeof(derivedPub);
7931+ ExpectIntEQ(wc_MlDsaKey_ExportPubRaw(privKey, derivedPub, &derivedPubSz),
7932+ WC_NO_ERR_TRACE(BAD_FUNC_ARG));
7933+ ExpectIntEQ(privKey->pubKeySet, 0);
7934+
7935+ /* Explicit derive, then export succeeds. */
7936+ ExpectIntEQ(wc_MlDsaKey_MakePublicKey(privKey), 0);
7937+ ExpectIntEQ(privKey->pubKeySet, 1);
7938+ derivedPubSz = sizeof(derivedPub);
7939+ ExpectIntEQ(wc_MlDsaKey_ExportPubRaw(privKey, derivedPub, &derivedPubSz),
7940+ 0);
7941+
7942+ /* Confirm derived public key matches known public key. */
7943+ ExpectIntEQ(wc_MlDsaKey_Init(pubKey, NULL, INVALID_DEVID), 0);
7944+ ExpectIntEQ(wc_MlDsaKey_SetParams(pubKey, WC_ML_DSA_44), 0);
7945+ idx = 0;
7946+ ExpectIntEQ(wc_MlDsaKey_PublicKeyDecode(pubKey, mldsa44_pub_spki,
7947+ sizeof_mldsa44_pub_spki, &idx), 0);
7948+ ExpectIntEQ(XMEMCMP(privKey->p, pubKey->p, WC_MLDSA_44_PUB_KEY_SIZE), 0);
7949+
7950+ /* KeyToDer: fails until derived, then matches known public key. */
7951+ {
7952+ wc_MlDsaKey* privKey2;
7953+ byte* der;
7954+
7955+ privKey2 = (wc_MlDsaKey*)XMALLOC(sizeof(*privKey2), NULL,
7956+ DYNAMIC_TYPE_TMP_BUFFER);
7957+ ExpectNotNull(privKey2);
7958+ der = (byte*)XMALLOC(MLDSA_MAX_DER_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
7959+ ExpectNotNull(der);
7960+ if (privKey2 != NULL) {
7961+ XMEMSET(privKey2, 0, sizeof(*privKey2));
7962+ }
7963+
7964+ ExpectIntEQ(wc_MlDsaKey_Init(privKey2, NULL, INVALID_DEVID), 0);
7965+ ExpectIntEQ(wc_MlDsaKey_SetParams(privKey2, WC_ML_DSA_44), 0);
7966+ idx = 0;
7967+ ExpectIntEQ(wc_MlDsaKey_PrivateKeyDecode(privKey2, mldsa44_priv_only,
7968+ sizeof_mldsa44_priv_only, &idx), 0);
7969+ ExpectIntEQ(privKey2->pubKeySet, 0);
7970+
7971+ ExpectIntEQ(wc_MlDsaKey_KeyToDer(privKey2, der, MLDSA_MAX_DER_SIZE),
7972+ WC_NO_ERR_TRACE(BAD_FUNC_ARG));
7973+ ExpectIntEQ(privKey2->pubKeySet, 0);
7974+
7975+ ExpectIntEQ(wc_MlDsaKey_MakePublicKey(privKey2), 0);
7976+ ExpectIntGT(wc_MlDsaKey_KeyToDer(privKey2, der, MLDSA_MAX_DER_SIZE),
7977+ 0);
7978+ ExpectIntEQ(privKey2->pubKeySet, 1);
7979+ ExpectIntEQ(XMEMCMP(privKey2->p, pubKey->p, WC_MLDSA_44_PUB_KEY_SIZE),
7980+ 0);
7981+
7982+ wc_MlDsaKey_Free(privKey2);
7983+ XFREE(privKey2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
7984+ XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
7985+ }
7986+
7987+ /* PublicKeyToDer: fails until derived, then succeeds. */
7988+ {
7989+ wc_MlDsaKey* privKey3;
7990+ byte* der;
7991+
7992+ privKey3 = (wc_MlDsaKey*)XMALLOC(sizeof(*privKey3), NULL,
7993+ DYNAMIC_TYPE_TMP_BUFFER);
7994+ ExpectNotNull(privKey3);
7995+ der = (byte*)XMALLOC(MLDSA_MAX_DER_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
7996+ ExpectNotNull(der);
7997+ if (privKey3 != NULL) {
7998+ XMEMSET(privKey3, 0, sizeof(*privKey3));
7999+ }
8000+
8001+ ExpectIntEQ(wc_MlDsaKey_Init(privKey3, NULL, INVALID_DEVID), 0);
8002+ ExpectIntEQ(wc_MlDsaKey_SetParams(privKey3, WC_ML_DSA_44), 0);
8003+ idx = 0;
8004+ ExpectIntEQ(wc_MlDsaKey_PrivateKeyDecode(privKey3, mldsa44_priv_only,
8005+ sizeof_mldsa44_priv_only, &idx), 0);
8006+ ExpectIntEQ(privKey3->pubKeySet, 0);
8007+
8008+ ExpectIntEQ(wc_MlDsaKey_PublicKeyToDer(privKey3, der,
8009+ MLDSA_MAX_DER_SIZE, 1), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
8010+ ExpectIntEQ(privKey3->pubKeySet, 0);
8011+
8012+ ExpectIntEQ(wc_MlDsaKey_MakePublicKey(privKey3), 0);
8013+ ExpectIntGT(wc_MlDsaKey_PublicKeyToDer(privKey3, der,
8014+ MLDSA_MAX_DER_SIZE, 1), 0);
8015+ ExpectIntEQ(privKey3->pubKeySet, 1);
8016+ ExpectIntEQ(XMEMCMP(privKey3->p, pubKey->p, WC_MLDSA_44_PUB_KEY_SIZE),
8017+ 0);
8018+
8019+ wc_MlDsaKey_Free(privKey3);
8020+ XFREE(privKey3, NULL, DYNAMIC_TYPE_TMP_BUFFER);
8021+ XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
8022+ }
8023+
8024+ wc_MlDsaKey_Free(privKey);
8025+ wc_MlDsaKey_Free(pubKey);
8026+ #endif /* !WOLFSSL_NO_ML_DSA_44 */
8027+
8028+ #ifndef WOLFSSL_NO_ML_DSA_65
8029+ ExpectIntEQ(wc_MlDsaKey_Init(privKey, NULL, INVALID_DEVID), 0);
8030+ ExpectIntEQ(wc_MlDsaKey_SetParams(privKey, WC_ML_DSA_65), 0);
8031+
8032+ idx = 0;
8033+ ExpectIntEQ(wc_MlDsaKey_PrivateKeyDecode(privKey, mldsa65_priv_only,
8034+ sizeof_mldsa65_priv_only, &idx), 0);
8035+ ExpectIntEQ(privKey->pubKeySet, 0);
8036+ ExpectIntEQ(wc_MlDsaKey_MakePublicKey(privKey), 0);
8037+ ExpectIntEQ(privKey->pubKeySet, 1);
8038+ derivedPubSz = sizeof(derivedPub);
8039+ ExpectIntEQ(wc_MlDsaKey_ExportPubRaw(privKey, derivedPub, &derivedPubSz),
8040+ 0);
8041+
8042+ ExpectIntEQ(wc_MlDsaKey_Init(pubKey, NULL, INVALID_DEVID), 0);
8043+ ExpectIntEQ(wc_MlDsaKey_SetParams(pubKey, WC_ML_DSA_65), 0);
8044+ idx = 0;
8045+ ExpectIntEQ(wc_MlDsaKey_PublicKeyDecode(pubKey, mldsa65_pub_spki,
8046+ sizeof_mldsa65_pub_spki, &idx), 0);
8047+ ExpectIntEQ(XMEMCMP(privKey->p, pubKey->p, WC_MLDSA_65_PUB_KEY_SIZE), 0);
8048+
8049+ wc_MlDsaKey_Free(privKey);
8050+ wc_MlDsaKey_Free(pubKey);
8051+ #endif /* !WOLFSSL_NO_ML_DSA_65 */
8052+
8053+ #ifndef WOLFSSL_NO_ML_DSA_87
8054+ ExpectIntEQ(wc_MlDsaKey_Init(privKey, NULL, INVALID_DEVID), 0);
8055+ ExpectIntEQ(wc_MlDsaKey_SetParams(privKey, WC_ML_DSA_87), 0);
8056+
8057+ idx = 0;
8058+ ExpectIntEQ(wc_MlDsaKey_PrivateKeyDecode(privKey, mldsa87_priv_only,
8059+ sizeof_mldsa87_priv_only, &idx), 0);
8060+ ExpectIntEQ(privKey->pubKeySet, 0);
8061+ ExpectIntEQ(wc_MlDsaKey_MakePublicKey(privKey), 0);
8062+ ExpectIntEQ(privKey->pubKeySet, 1);
8063+ derivedPubSz = sizeof(derivedPub);
8064+ ExpectIntEQ(wc_MlDsaKey_ExportPubRaw(privKey, derivedPub, &derivedPubSz),
8065+ 0);
8066+
8067+ ExpectIntEQ(wc_MlDsaKey_Init(pubKey, NULL, INVALID_DEVID), 0);
8068+ ExpectIntEQ(wc_MlDsaKey_SetParams(pubKey, WC_ML_DSA_87), 0);
8069+ idx = 0;
8070+ ExpectIntEQ(wc_MlDsaKey_PublicKeyDecode(pubKey, mldsa87_pub_spki,
8071+ sizeof_mldsa87_pub_spki, &idx), 0);
8072+ ExpectIntEQ(XMEMCMP(privKey->p, pubKey->p, WC_MLDSA_87_PUB_KEY_SIZE), 0);
8073+
8074+ wc_MlDsaKey_Free(privKey);
8075+ wc_MlDsaKey_Free(pubKey);
8076+ #endif /* !WOLFSSL_NO_ML_DSA_87 */
8077+
8078+ XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
8079+ XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
8080+ #endif
8081+ return EXPECT_RESULT();
8082+ }
78938083int test_mldsa_verify_pubkeyset_guard(void)
78948084{
78958085 EXPECT_DECLS;
0 commit comments