@@ -1603,6 +1603,153 @@ static int test_dual_alg_support(void)
16031603}
16041604#endif /* WOLFSSL_DUAL_ALG_CERTS && !NO_FILESYSTEM */
16051605
1606+ /**
1607+ * Test dual-alg ECDSA + ML-DSA:
1608+ * - keygen + certgen + cert manager load
1609+ * */
1610+ static int test_dual_alg_ecdsa_mldsa(void)
1611+ {
1612+ EXPECT_DECLS;
1613+ #if defined(WOLFSSL_DUAL_ALG_CERTS) && defined(HAVE_DILITHIUM) && \
1614+ defined(HAVE_ECC) && !defined(WC_NO_RNG) && \
1615+ defined(WOLFSSL_WC_DILITHIUM) && \
1616+ !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && \
1617+ !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \
1618+ !defined(WOLFSSL_DILITHIUM_NO_VERIFY) && !defined(WOLFSSL_SMALL_STACK)
1619+ WOLFSSL_CERT_MANAGER * cm = NULL;
1620+ MlDsaKey alt_ca_key;
1621+ ecc_key ca_key;
1622+ WC_RNG rng;
1623+ int ret = 0;
1624+ DecodedCert d_cert;
1625+ Cert new_cert;
1626+ /* various tmp buffs. */
1627+ byte alt_pub_der[LARGE_TEMP_SZ];
1628+ word32 alt_pub_sz = LARGE_TEMP_SZ;
1629+ byte alt_sig_alg[LARGE_TEMP_SZ];
1630+ word32 alt_sig_alg_sz = LARGE_TEMP_SZ;
1631+ byte tbs_der[LARGE_TEMP_SZ];
1632+ word32 tbs_der_sz = LARGE_TEMP_SZ;
1633+ byte alt_sig[LARGE_TEMP_SZ];
1634+ word32 alt_sig_sz = LARGE_TEMP_SZ;
1635+ /* Intermediate der. */
1636+ byte der[LARGE_TEMP_SZ];
1637+ word32 der_sz = LARGE_TEMP_SZ;
1638+ /* The final der will be large because of ML-DSA signature. */
1639+ byte final_der[2 * LARGE_TEMP_SZ];
1640+ word32 final_der_sz = 2 * LARGE_TEMP_SZ;
1641+
1642+ XMEMSET(alt_pub_der, 0, alt_pub_sz);
1643+ XMEMSET(alt_sig_alg, 0, alt_sig_alg_sz);
1644+ XMEMSET(tbs_der, 0, tbs_der_sz);
1645+ XMEMSET(alt_sig, 0, alt_sig_sz);
1646+ XMEMSET(der, 0, der_sz);
1647+ XMEMSET(final_der, 0, final_der_sz);
1648+
1649+ ExpectIntEQ(wc_InitRng(&rng), 0);
1650+
1651+ /**
1652+ * ML-DSA key gen.
1653+ * */
1654+ ret = wc_MlDsaKey_Init(&alt_ca_key, NULL, INVALID_DEVID);
1655+ ExpectIntEQ(ret, 0);
1656+ ret = wc_MlDsaKey_SetParams(&alt_ca_key, WC_ML_DSA_44);
1657+ ExpectIntEQ(ret, 0);
1658+ ret = wc_MlDsaKey_MakeKey(&alt_ca_key, &rng);
1659+ ExpectIntEQ(ret, 0);
1660+ alt_pub_sz = wc_MlDsaKey_PublicKeyToDer(&alt_ca_key, alt_pub_der,
1661+ alt_pub_sz, 1);
1662+ ExpectIntGT(alt_pub_sz, 0);
1663+
1664+ alt_sig_alg_sz = SetAlgoID(CTC_SHA256wECDSA, alt_sig_alg, oidSigType, 0);
1665+ ExpectIntGT(alt_sig_alg_sz, 0);
1666+
1667+ /**
1668+ * ECC key gen.
1669+ * */
1670+ ret = wc_ecc_init(&ca_key);
1671+ ExpectIntEQ(ret, 0);
1672+ ret = wc_ecc_make_key(&rng, KEY32, &ca_key);
1673+ ExpectIntEQ(ret, 0);
1674+
1675+ /**
1676+ * Cert gen.
1677+ * */
1678+ wc_InitCert(&new_cert);
1679+ strncpy(new_cert.subject.country, "US", CTC_NAME_SIZE);
1680+ strncpy(new_cert.subject.state, "MT", CTC_NAME_SIZE);
1681+ strncpy(new_cert.subject.locality, "Bozeman", CTC_NAME_SIZE);
1682+ strncpy(new_cert.subject.org, "wolfSSL", CTC_NAME_SIZE);
1683+ strncpy(new_cert.subject.unit, "Engineering", CTC_NAME_SIZE);
1684+ strncpy(new_cert.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE);
1685+ strncpy(new_cert.subject.email, "root@wolfssl.com", CTC_NAME_SIZE);
1686+ new_cert.sigType = CTC_SHA256wECDSA;
1687+ new_cert.isCA = 1;
1688+
1689+ ret = wc_SetCustomExtension(&new_cert, 0, "1.2.3.4.5",
1690+ (const byte *)"This is NOT a critical extension", 32);
1691+ ExpectIntEQ(ret, 0);
1692+
1693+ ExpectIntEQ(wc_SetCustomExtension(&new_cert, 0, "2.5.29.72", alt_pub_der,
1694+ alt_pub_sz), 0);
1695+ ExpectIntEQ(wc_SetCustomExtension(&new_cert, 0, "2.5.29.73", alt_sig_alg,
1696+ alt_sig_alg_sz), 0);
1697+
1698+ ret = wc_MakeCert_ex(&new_cert, der, der_sz, ECC_TYPE, &ca_key, &rng);
1699+ ExpectIntGT(ret, 0);
1700+
1701+ der_sz = wc_SignCert_ex(new_cert.bodySz, new_cert.sigType, der, der_sz,
1702+ ECC_TYPE, &ca_key, &rng);
1703+ ExpectIntGT(der_sz, 0);
1704+
1705+ wc_InitDecodedCert(&d_cert, der, der_sz, 0);
1706+ ret = wc_ParseCert(&d_cert, CERT_TYPE, NO_VERIFY, NULL);
1707+ ExpectIntEQ(ret, 0);
1708+
1709+ tbs_der_sz = wc_GeneratePreTBS(&d_cert, tbs_der, tbs_der_sz);
1710+ ExpectIntGT(tbs_der_sz, 0);
1711+
1712+ alt_sig_sz = wc_MakeSigWithBitStr(alt_sig, alt_sig_sz,
1713+ CTC_ML_DSA_LEVEL2, tbs_der, tbs_der_sz,
1714+ ML_DSA_LEVEL2_TYPE, &alt_ca_key, &rng);
1715+ ExpectIntGT(alt_sig_sz, 0);
1716+
1717+ ret = wc_SetCustomExtension(&new_cert, 0, "2.5.29.74", alt_sig, alt_sig_sz);
1718+ ExpectIntEQ(ret, 0);
1719+
1720+ /* Finally generate the new certificate. */
1721+ ret = wc_MakeCert_ex(&new_cert, final_der, final_der_sz, ECC_TYPE, &ca_key,
1722+ &rng);
1723+ ExpectIntGT(ret, 0);
1724+
1725+ final_der_sz = wc_SignCert_ex(new_cert.bodySz, new_cert.sigType, final_der,
1726+ final_der_sz, ECC_TYPE, &ca_key, &rng);
1727+ ExpectIntGT(final_der_sz, 0);
1728+
1729+ cm = wolfSSL_CertManagerNew();
1730+ ExpectNotNull(cm);
1731+
1732+ /* Load the certificate into CertManager. */
1733+ if (cm != NULL && final_der_sz > 0) {
1734+ ret = wolfSSL_CertManagerLoadCABuffer(cm, final_der, final_der_sz,
1735+ WOLFSSL_FILETYPE_ASN1);
1736+ ExpectIntEQ(ret, WOLFSSL_SUCCESS);
1737+ }
1738+
1739+ if (cm != NULL) {
1740+ wolfSSL_CertManagerFree(cm);
1741+ cm = NULL;
1742+ }
1743+
1744+ wc_ecc_free(&ca_key);
1745+ wc_MlDsaKey_Free(&alt_ca_key);
1746+ wc_FreeRng(&rng);
1747+
1748+ #endif /* WOLFSSL_DUAL_ALG_CERTS && DILITHIUM and more */
1749+ return EXPECT_RESULT();
1750+ }
1751+
1752+
16061753/*----------------------------------------------------------------------------*
16071754 | Context
16081755 *----------------------------------------------------------------------------*/
@@ -99002,6 +99149,8 @@ TEST_CASE testCases[] = {
9900299149
9900399150 TEST_DECL(test_dual_alg_support),
9900499151
99152+ TEST_DECL(test_dual_alg_ecdsa_mldsa),
99153+
9900599154 /*********************************
9900699155 * OpenSSL compatibility API tests
9900799156 *********************************/
0 commit comments