@@ -1061,3 +1061,67 @@ int test_x509_ReqCertFromX509_skid_boundary(void)
10611061#endif
10621062 return EXPECT_RESULT ();
10631063}
1064+
1065+ /* Sign a certificate request with an ML-DSA key through the compat layer
1066+ * (wolfSSL_X509_REQ_sign), round-trip it through DER and verify the
1067+ * signature with the public key recovered from the parsed request. The
1068+ * REQ path sizes its DER buffer with WC_DECLARE_VAR/WC_MAX_X509_GEN,
1069+ * separately from wolfSSL_X509_sign, so it needs its own coverage. */
1070+ int test_x509_REQ_sign_mldsa (void )
1071+ {
1072+ EXPECT_DECLS ;
1073+ #if defined(WOLFSSL_CERT_REQ ) && defined(WOLFSSL_CERT_GEN ) && \
1074+ (defined(OPENSSL_EXTRA ) || defined(OPENSSL_ALL )) && \
1075+ defined(WOLFSSL_HAVE_MLDSA ) && defined(WOLFSSL_MLDSA_PRIVATE_KEY ) && \
1076+ defined(WOLFSSL_MLDSA_PUBLIC_KEY ) && !defined(WOLFSSL_MLDSA_NO_ASN1 ) && \
1077+ !defined(WOLFSSL_MLDSA_NO_SIGN ) && !defined(WOLFSSL_MLDSA_NO_VERIFY ) && \
1078+ defined(WC_ENABLE_ASYM_KEY_EXPORT ) && !defined(NO_FILESYSTEM ) && \
1079+ !defined(NO_BIO ) && !defined(NO_PWDBASED ) && !defined(WOLFSSL_NO_ML_DSA_44 )
1080+
1081+ WOLFSSL_BIO * bio = NULL ;
1082+ WOLFSSL_EVP_PKEY * pkey = NULL ;
1083+ WOLFSSL_EVP_PKEY * pubkey = NULL ;
1084+ WOLFSSL_X509 * req = NULL ;
1085+ WOLFSSL_X509 * parsed = NULL ;
1086+ WOLFSSL_X509_NAME * name = NULL ;
1087+ unsigned char * der = NULL ;
1088+ int derSz = 0 ;
1089+
1090+ ExpectNotNull (bio = wolfSSL_BIO_new_file (
1091+ "./certs/mldsa/mldsa44-key.pem" , "rb" ));
1092+ ExpectNotNull (pkey = wolfSSL_PEM_read_bio_PrivateKey (bio , NULL , NULL ,
1093+ NULL ));
1094+ wolfSSL_BIO_free (bio );
1095+ bio = NULL ;
1096+
1097+ ExpectNotNull (req = wolfSSL_X509_REQ_new ());
1098+ ExpectNotNull (name = wolfSSL_X509_NAME_new ());
1099+ ExpectIntEQ (wolfSSL_X509_NAME_add_entry_by_txt (name , "commonName" ,
1100+ MBSTRING_UTF8 , (const byte * )"mldsa-req" , -1 , -1 , 0 ), WOLFSSL_SUCCESS );
1101+ ExpectIntEQ (wolfSSL_X509_REQ_set_subject_name (req , name ), WOLFSSL_SUCCESS );
1102+ ExpectIntEQ (wolfSSL_X509_REQ_set_pubkey (req , pkey ), WOLFSSL_SUCCESS );
1103+
1104+ ExpectIntEQ (wolfSSL_X509_REQ_sign (req , pkey , wolfSSL_EVP_sha256 ()),
1105+ WOLFSSL_SUCCESS );
1106+
1107+ /* Round-trip the signed request through DER to prove the encoding is a
1108+ * complete, parseable CSR (an ML-DSA signature does not fit the old
1109+ * fixed 2048-byte buffer). */
1110+ ExpectIntGT ((derSz = wolfSSL_i2d_X509_REQ (req , & der )), 0 );
1111+ ExpectNotNull (der );
1112+ ExpectNotNull (parsed = wolfSSL_X509_REQ_d2i (NULL , der , derSz ));
1113+
1114+ /* Verify the signature with the public key from the parsed request. */
1115+ ExpectNotNull (pubkey = wolfSSL_X509_get_pubkey (parsed ));
1116+ ExpectIntEQ (wolfSSL_EVP_PKEY_id (pubkey ), WC_EVP_PKEY_DILITHIUM );
1117+ ExpectIntEQ (wolfSSL_X509_REQ_verify (parsed , pubkey ), WOLFSSL_SUCCESS );
1118+
1119+ wolfSSL_EVP_PKEY_free (pubkey );
1120+ wolfSSL_X509_free (parsed );
1121+ XFREE (der , NULL , DYNAMIC_TYPE_OPENSSL );
1122+ wolfSSL_X509_NAME_free (name );
1123+ wolfSSL_X509_free (req );
1124+ wolfSSL_EVP_PKEY_free (pkey );
1125+ #endif
1126+ return EXPECT_RESULT ();
1127+ }
0 commit comments