diff --git a/src/x509.c b/src/x509.c index fd33d8466..0b23c5fa1 100644 --- a/src/x509.c +++ b/src/x509.c @@ -8084,11 +8084,21 @@ int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out) } #ifdef WOLFSSL_DUAL_ALG_CERTS +/* Generate a der preTBS from a decoded cert, and write + * to buffer. + * + * @param[in] cert The decoded cert to parse. + * @param[out] der The der buffer to write in. + * @param[in] derZ The der buffer size. + * @return preTBS der size on success. + * */ int wc_GeneratePreTBS(DecodedCert* cert, byte *der, int derSz) { int ret = 0; WOLFSSL_X509 *x = NULL; byte certIsCSR = 0; + WOLFSSL_ENTER("wc_GeneratePreTBS"); + if ((cert == NULL) || (der == NULL) || (derSz <= 0)) { return BAD_FUNC_ARG; } diff --git a/tests/api.c b/tests/api.c index 410ea272a..5fc0683ef 100644 --- a/tests/api.c +++ b/tests/api.c @@ -1609,6 +1609,149 @@ static int test_dual_alg_support(void) } #endif /* WOLFSSL_DUAL_ALG_CERTS && !NO_FILESYSTEM */ +/** + * Test dual-alg ECDSA + ML-DSA: + * - keygen + certgen + * */ +static int test_dual_alg_ecdsa_mldsa(void) +{ + EXPECT_DECLS; +#if defined(WOLFSSL_DUAL_ALG_CERTS) && defined(HAVE_DILITHIUM) && \ + defined(HAVE_ECC) && !defined(WC_NO_RNG) && \ + defined(WOLFSSL_WC_DILITHIUM) && \ + !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && \ + !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_NO_VERIFY) + WOLFSSL_CERT_MANAGER * cm = NULL; + MlDsaKey alt_ca_key; + ecc_key ca_key; + WC_RNG rng; + int ret = 0; + DecodedCert d_cert; + Cert new_cert; + /* various tmp buffs. */ + byte alt_pub_der[LARGE_TEMP_SZ]; + word32 alt_pub_sz = LARGE_TEMP_SZ; + byte alt_sig_alg[LARGE_TEMP_SZ]; + word32 alt_sig_alg_sz = LARGE_TEMP_SZ; + byte tbs_der[LARGE_TEMP_SZ]; + word32 tbs_der_sz = LARGE_TEMP_SZ; + byte alt_sig[LARGE_TEMP_SZ]; + word32 alt_sig_sz = LARGE_TEMP_SZ; + /* Intermediate der. */ + byte der[LARGE_TEMP_SZ]; + word32 der_sz = LARGE_TEMP_SZ; + /* The final der will be large because of ML-DSA signature. */ + byte final_der[2 * LARGE_TEMP_SZ]; + word32 final_der_sz = 2 * LARGE_TEMP_SZ; + + XMEMSET(alt_pub_der, 0, alt_pub_sz); + XMEMSET(alt_sig_alg, 0, alt_sig_alg_sz); + XMEMSET(tbs_der, 0, tbs_der_sz); + XMEMSET(alt_sig, 0, alt_sig_sz); + XMEMSET(der, 0, der_sz); + XMEMSET(final_der, 0, final_der_sz); + + ExpectIntEQ(wc_InitRng(&rng), 0); + + /** + * ML-DSA key gen. + * */ + ret = wc_MlDsaKey_Init(&alt_ca_key, NULL, INVALID_DEVID); + ExpectIntEQ(ret, 0); + ret = wc_MlDsaKey_SetParams(&alt_ca_key, WC_ML_DSA_44); + ExpectIntEQ(ret, 0); + ret = wc_dilithium_make_key(&alt_ca_key, &rng); + ExpectIntEQ(ret, 0); + alt_pub_sz = wc_MlDsaKey_PublicKeyToDer(&alt_ca_key, alt_pub_der, + alt_pub_sz, 1); + ExpectIntGT(alt_pub_sz, 0); + + alt_sig_alg_sz = SetAlgoID(CTC_SHA256wECDSA, alt_sig_alg, oidSigType, 0); + ExpectIntGT(alt_sig_alg_sz, 0); + + /** + * ECC key gen. + * */ + ret = wc_ecc_init(&ca_key); + ExpectIntEQ(ret, 0); + ret = wc_ecc_make_key(&rng, KEY32, &ca_key); + ExpectIntEQ(ret, 0); + + /** + * Cert gen. + * */ + wc_InitCert(&new_cert); + strncpy(new_cert.subject.country, "US", CTC_NAME_SIZE); + strncpy(new_cert.subject.state, "MT", CTC_NAME_SIZE); + strncpy(new_cert.subject.locality, "Bozeman", CTC_NAME_SIZE); + strncpy(new_cert.subject.org, "wolfSSL", CTC_NAME_SIZE); + strncpy(new_cert.subject.unit, "Engineering", CTC_NAME_SIZE); + strncpy(new_cert.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE); + strncpy(new_cert.subject.email, "root@wolfssl.com", CTC_NAME_SIZE); + new_cert.sigType = CTC_SHA256wECDSA; + new_cert.isCA = 1; + + ret = wc_SetCustomExtension(&new_cert, 0, "1.2.3.4.5", + (const byte *)"This is NOT a critical extension", 32); + ExpectIntEQ(ret, 0); + + ExpectIntEQ(wc_SetCustomExtension(&new_cert, 0, "2.5.29.72", alt_pub_der, + alt_pub_sz), 0); + ExpectIntEQ(wc_SetCustomExtension(&new_cert, 0, "2.5.29.73", alt_sig_alg, + alt_sig_alg_sz), 0); + + ret = wc_MakeCert_ex(&new_cert, der, der_sz, ECC_TYPE, &ca_key, &rng); + ExpectIntGT(ret, 0); + + der_sz = wc_SignCert_ex(new_cert.bodySz, new_cert.sigType, der, der_sz, + ECC_TYPE, &ca_key, &rng); + ExpectIntGT(der_sz, 0); + + wc_InitDecodedCert(&d_cert, der, der_sz, 0); + ret = wc_ParseCert(&d_cert, CERT_TYPE, NO_VERIFY, NULL); + ExpectIntEQ(ret, 0); + + tbs_der_sz = wc_GeneratePreTBS(&d_cert, tbs_der, tbs_der_sz); + ExpectIntGT(tbs_der_sz, 0); + + alt_sig_sz = wc_MakeSigWithBitStr(alt_sig, alt_sig_sz, + CTC_ML_DSA_LEVEL2, tbs_der, tbs_der_sz, + ML_DSA_LEVEL2_TYPE, &alt_ca_key, &rng); + ExpectIntGT(alt_sig_sz, 0); + + ret = wc_SetCustomExtension(&new_cert, 0, "2.5.29.74", alt_sig, alt_sig_sz); + ExpectIntEQ(ret, 0); + + /* Finally generate the new certificate. */ + ret = wc_MakeCert_ex(&new_cert, final_der, final_der_sz, ECC_TYPE, &ca_key, + &rng); + ExpectIntGT(ret, 0); + + final_der_sz = wc_SignCert_ex(new_cert.bodySz, new_cert.sigType, final_der, + final_der_sz, ECC_TYPE, &ca_key, &rng); + ExpectIntGT(final_der_sz, 0); + + cm = wolfSSL_CertManagerNew(); + ExpectNotNull(cm); + + if (cm != NULL && final_der_sz > 0) { + ret = wolfSSL_CertManagerLoadCABuffer(cm, final_der, final_der_sz, + WOLFSSL_FILETYPE_ASN1); + ExpectIntEQ(ret, WOLFSSL_SUCCESS); + } + + wolfSSL_CertManagerFree(cm); + + wc_ecc_free(&ca_key); + wc_MlDsaKey_Free(&alt_ca_key); + wc_FreeRng(&rng); + +#endif /* WOLFSSL_DUAL_ALG_CERTS && DILITHIUM and more */ + return EXPECT_RESULT(); +} + + /*----------------------------------------------------------------------------* | Context *----------------------------------------------------------------------------*/ @@ -101833,6 +101976,8 @@ TEST_CASE testCases[] = { TEST_DECL(test_dual_alg_support), + TEST_DECL(test_dual_alg_ecdsa_mldsa), + /********************************* * OpenSSL compatibility API tests *********************************/ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index bfd969348..5e160c3eb 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -17947,41 +17947,6 @@ exit_cs: return ret; } -#ifdef WOLFSSL_DUAL_ALG_CERTS -int wc_ConfirmAltSignature( - const byte* buf, word32 bufSz, - const byte* key, word32 keySz, word32 keyOID, - const byte* sig, word32 sigSz, word32 sigOID, - void *heap) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - SignatureCtx* sigCtx = (SignatureCtx*)XMALLOC(sizeof(*sigCtx), heap, - DYNAMIC_TYPE_SIGNATURE); - if (sigCtx == NULL) { - ret = MEMORY_E; - } -#else - SignatureCtx sigCtx[1]; - (void)heap; -#endif - - if (ret == 0) { - InitSignatureCtx(sigCtx, heap, INVALID_DEVID); - - ret = ConfirmSignature(sigCtx, buf, bufSz, key, keySz, - keyOID, sig, sigSz, sigOID, NULL, 0, NULL); - - FreeSignatureCtx(sigCtx); - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sigCtx, heap, DYNAMIC_TYPE_SIGNATURE); -#endif - return ret; -} -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - #ifndef IGNORE_NAME_CONSTRAINTS static int MatchBaseName(int type, const char* name, int nameSz, @@ -23677,7 +23642,8 @@ Signer* findSignerByName(Signer *list, byte *hash) return NULL; } -int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm, Signer *extraCAList) +int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm, + Signer *extraCAList) { int ret = 0; #ifndef WOLFSSL_ASN_TEMPLATE @@ -30990,8 +30956,18 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, #endif } - -/* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */ +/* Make an x509 Certificate v3 from cert input using any + * key type, and write to buffer. + * + * @param [in, out] cert Certificate object. + * @param [out] derBuffer Buffer to write der in. + * @param [in] derSz Der buffer size. + * @param [in] keyType The type of key. + * @param [in] key Key data. + * @param [in] rng Random number generator. + * @return Size of encoded data in bytes on success. + * @return < 0 on error + * */ int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, void* key, WC_RNG* rng) { @@ -32159,6 +32135,19 @@ static int SignCert(int requestSz, int sType, byte* buf, word32 buffSz, } #ifdef WOLFSSL_DUAL_ALG_CERTS +/* Generate a signature from input buffer using + * any key type. + * + * @param [out] sig The signature buffer to write in. + * @param [out] sigsz The signature buffer size. + * @param [in] sType The signature type. + * @param [in] buf The input buf to sign. + * @param [in] bufSz The buffer size + * @param [in] keyType The key type. + * @param [in] rng Random number generator. + * @return Size of signature on success. + * @return < 0 on error. + * */ int wc_MakeSigWithBitStr(byte *sig, int sigSz, int sType, byte* buf, word32 bufSz, int keyType, void* key, WC_RNG* rng) { @@ -32170,6 +32159,8 @@ int wc_MakeSigWithBitStr(byte *sig, int sigSz, int sType, byte* buf, dilithium_key* dilithiumKey = NULL; sphincs_key* sphincsKey = NULL; + WOLFSSL_ENTER("wc_MakeSigWithBitStr"); + int ret = 0; int headerSz; void* heap = NULL; @@ -32285,6 +32276,18 @@ int wc_MakeSigWithBitStr(byte *sig, int sigSz, int sType, byte* buf, } #endif /* WOLFSSL_DUAL_ALG_CERTS */ +/* Sign an x509 Certificate v3 from cert input using any + * key type, and write to buffer. + * + * @param [in] requestSz Size of requested data to sign. + * @param [in] sType The signature type. + * @param [in] derSz Der buffer size. + * @param [in] keyType The type of key. + * @param [in] key Key data. + * @param [in] rng Random number generator. + * @return Size of signature on success. + * @return < 0 on error + * */ int wc_SignCert_ex(int requestSz, int sType, byte* buf, word32 buffSz, int keyType, void* key, WC_RNG* rng) { diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index a9b1aaef1..8d4e92092 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -2347,13 +2347,6 @@ WOLFSSL_LOCAL int CheckCertSignaturePubKey(const byte* cert, word32 certSz, word32 pubKeySz, int pubKeyOID); #endif /* OPENSSL_EXTRA || WOLFSSL_SMALL_CERT_VERIFY */ -#ifdef WOLFSSL_DUAL_ALG_CERTS -WOLFSSL_LOCAL int wc_ConfirmAltSignature( - const byte* buf, word32 bufSz, - const byte* key, word32 keySz, word32 keyOID, - const byte* sig, word32 sigSz, word32 sigOID, - void *heap); -#endif /* WOLFSSL_DUAL_ALG_CERTS */ #if (defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) || \ (defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT))) WOLFSSL_LOCAL int wc_CertGetPubKey(const byte* cert, word32 certSz, diff --git a/wolfssl/wolfcrypt/dilithium.h b/wolfssl/wolfcrypt/dilithium.h index bc4ae03a7..25fd1587f 100644 --- a/wolfssl/wolfcrypt/dilithium.h +++ b/wolfssl/wolfcrypt/dilithium.h @@ -894,6 +894,13 @@ WOLFSSL_API int wc_Dilithium_PrivateKeyToDer(dilithium_key* key, byte* output, #define wc_MlDsaKey_Verify(key, sig, sigSz, msg, msgSz, res) \ wc_dilithium_verify_msg(sig, sigSz, msg, msgSz, res, key) +#define wc_MlDsaKey_PublicKeyToDer(key, output, len, withAlg) \ + wc_Dilithium_PublicKeyToDer(key, output, len, withAlg) + +#define wc_MlDsaKey_PrivateKeyToDer(key, output, len) \ + wc_Dilithium_PrivateKeyToDer(key, output, len) + + WOLFSSL_API int wc_MlDsaKey_GetPrivLen(MlDsaKey* key, int* len); WOLFSSL_API int wc_MlDsaKey_GetPubLen(MlDsaKey* key, int* len); WOLFSSL_API int wc_MlDsaKey_GetSigLen(MlDsaKey* key, int* len);