From a36f9085c12b13451d7e948f086359b153348ed3 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 11 Jul 2025 08:51:51 -0700 Subject: [PATCH 1/2] Fix for compat `wolfSSL_RSA_sign` and `wolfSSL_RSA_verify` to support RSA PSS with custom salt and mgf1 hash type. Adds compat API's for `i2d_PrivateKey_bio` , `BN_ucmp` and `X509v3_get_ext_by_NID`. ZD 20059 --- src/pk.c | 228 +++++++++++++++++++++++---------------- src/ssl.c | 39 +++++++ src/ssl_bn.c | 56 ++++++++++ src/x509.c | 59 ++++++++++ tests/api.c | 151 ++++++++++++++++++++++++++ wolfcrypt/src/evp.c | 66 +++++++++--- wolfcrypt/src/rsa.c | 6 +- wolfssl/openssl/bn.h | 2 + wolfssl/openssl/evp.h | 10 +- wolfssl/openssl/hmac.h | 1 + wolfssl/openssl/rsa.h | 66 ++++++++---- wolfssl/openssl/ssl.h | 1 + wolfssl/openssl/x509v3.h | 7 ++ wolfssl/ssl.h | 2 + 14 files changed, 563 insertions(+), 131 deletions(-) diff --git a/src/pk.c b/src/pk.c index 6f920f697..4f693a20a 100644 --- a/src/pk.c +++ b/src/pk.c @@ -3534,9 +3534,42 @@ int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* e, * RSA padding APIs */ -#if defined(WC_RSA_PSS) && (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \ - defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)) -#if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0) +#ifdef WC_RSA_PSS + +#if defined(OPENSSL_EXTRA) && !defined(HAVE_SELFTEST) +static int rsa_pss_calc_salt(int saltLen, int hashLen, int emLen) +{ + /* Calculate the salt length to use for special cases. */ + switch (saltLen) { + /* Negative saltLen values are treated differently. */ + case WC_RSA_PSS_SALTLEN_DIGEST: + saltLen = hashLen; + break; + case WC_RSA_PSS_SALTLEN_MAX_SIGN: + case WC_RSA_PSS_SALTLEN_MAX: + #ifdef WOLFSSL_PSS_LONG_SALT + saltLen = emLen - hashLen - 2; + #else + saltLen = hashLen; + (void)emLen; + #endif + break; + default: + break; + } + if (saltLen < 0) { + /* log invalid salt, let wolfCrypt handle error */ + WOLFSSL_ERROR_MSG("invalid saltLen"); + saltLen = -3; /* for wolfCrypt to produce error must be < -2 */ + } + return saltLen; +} +#endif /* OPENSSL_EXTRA && !HAVE_SELFTEST */ + +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \ + defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) + /* Add PKCS#1 PSS padding to hash. * * @@ -3654,28 +3687,7 @@ int wolfSSL_RSA_padding_add_PKCS1_PSS_mgf1(WOLFSSL_RSA *rsa, unsigned char *em, } if (ret == 1) { - /* Calculate the salt length to use for special cases. */ - /* TODO: use special case wolfCrypt values? */ - switch (saltLen) { - /* Negative saltLen values are treated differently. */ - case RSA_PSS_SALTLEN_DIGEST: - saltLen = hashLen; - break; - case RSA_PSS_SALTLEN_MAX_SIGN: - case RSA_PSS_SALTLEN_MAX: - #ifdef WOLFSSL_PSS_LONG_SALT - saltLen = emLen - hashLen - 2; - #else - saltLen = hashLen; - #endif - break; - default: - if (saltLen < 0) { - /* No other negative values implemented. */ - WOLFSSL_ERROR_MSG("invalid saltLen"); - ret = 0; - } - } + saltLen = rsa_pss_calc_salt(saltLen, hashLen, emLen); } if (ret == 1) { @@ -3767,31 +3779,7 @@ int wolfSSL_RSA_verify_PKCS1_PSS_mgf1(WOLFSSL_RSA *rsa, } if (ret == 1) { - /* Calculate the salt length to use for special cases. */ - switch (saltLen) { - /* Negative saltLen values are treated differently */ - case RSA_PSS_SALTLEN_DIGEST: - saltLen = hashLen; - break; - case RSA_PSS_SALTLEN_AUTO: - #ifdef WOLFSSL_PSS_SALT_LEN_DISCOVER - saltLen = RSA_PSS_SALT_LEN_DISCOVER; - break; - #endif - case RSA_PSS_SALTLEN_MAX: - #ifdef WOLFSSL_PSS_LONG_SALT - saltLen = emLen - hashLen - 2; - #else - saltLen = hashLen; - #endif - break; - default: - if (saltLen < 0) { - /* No other negative values implemented. */ - WOLFSSL_ERROR_MSG("invalid saltLen"); - ret = 0; - } - } + saltLen = rsa_pss_calc_salt(saltLen, hashLen, emLen); } if (ret == 1) { @@ -3856,18 +3844,23 @@ int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash, return wolfSSL_RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, hashAlg, NULL, em, saltLen); } -#endif /* !HAVE_FIPS || FIPS_VERSION_GT(2,0) */ -#endif /* WC_RSA_PSS && (OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || - * WOLFSSL_NGINX) */ +#endif /* (!HAVE_FIPS || FIPS_VERSION_GT(2,0)) && \ + (OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_NGINX) */ +#endif /* WC_RSA_PSS */ /* * RSA sign/verify APIs */ -#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER - #define DEF_PSS_SALT_LEN RSA_PSS_SALT_LEN_DEFAULT +#if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,1)) + #ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER + #define DEF_PSS_SALT_LEN RSA_PSS_SALT_LEN_DEFAULT + #else + #define DEF_PSS_SALT_LEN RSA_PSS_SALT_LEN_DISCOVER + #endif #else - #define DEF_PSS_SALT_LEN RSA_PSS_SALT_LEN_DISCOVER + #define DEF_PSS_SALT_LEN 0 /* not used */ #endif #if defined(OPENSSL_EXTRA) @@ -3980,6 +3973,14 @@ int wolfSSL_RSA_sign_ex(int hashAlg, const unsigned char* hash, return ret; } +int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash, + unsigned int hLen, unsigned char* sigRet, unsigned int* sigLen, + WOLFSSL_RSA* rsa, int flag, int padding) +{ + return wolfSSL_RSA_sign_mgf(hashAlg, hash, hLen, sigRet, sigLen, rsa, flag, + padding, hashAlg, DEF_PSS_SALT_LEN); +} + /** * Sign a message hash with the chosen message digest, padding, and RSA key. * @@ -3998,12 +3999,14 @@ int wolfSSL_RSA_sign_ex(int hashAlg, const unsigned char* hash, * @param [in] padding Padding to use. Only RSA_PKCS1_PSS_PADDING and * WC_RSA_PKCS1_PADDING are currently supported for * signing. + * @param [in] mgf1Hash MGF1 Hash NID + * @param [in] saltLen Length of RSA PSS salt * @return 1 on success. * @return 0 on failure. */ -int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash, +int wolfSSL_RSA_sign_mgf(int hashAlg, const unsigned char* hash, unsigned int hLen, unsigned char* sigRet, unsigned int* sigLen, - WOLFSSL_RSA* rsa, int flag, int padding) + WOLFSSL_RSA* rsa, int flag, int padding, int mgf1Hash, int saltLen) { int ret = 1; word32 outLen = 0; @@ -4020,8 +4023,7 @@ int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash, #endif unsigned int encSz = 0; - - WOLFSSL_ENTER("wolfSSL_RSA_sign_generic_padding"); + WOLFSSL_ENTER("wolfSSL_RSA_sign_mgf"); if (flag == 0) { /* Only encode message. */ @@ -4088,7 +4090,7 @@ int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash, case WC_RSA_NO_PAD: if ((signSz = wc_RsaDirect(encodedSig, encSz, sigRet, &outLen, (RsaKey*)rsa->internal, RSA_PRIVATE_ENCRYPT, rng)) <= 0) { - WOLFSSL_ERROR_MSG("Bad Rsa Sign no pad"); + WOLFSSL_ERROR_MSG("Bad RSA Sign no pad"); ret = 0; } break; @@ -4097,17 +4099,20 @@ int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash, (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,1)) case WC_RSA_PKCS1_PSS_PADDING: { - enum wc_HashType hType = - wc_OidGetHash((int)nid2oid(hashAlg, oidHashType)); - #ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER - WOLFSSL_MSG("Using RSA-PSS with hash length salt. " - "OpenSSL uses max length by default."); - #endif + RsaKey* key = (RsaKey*)rsa->internal; + enum wc_HashType mgf1, hType; + hType = wc_OidGetHash((int)nid2oid(hashAlg, oidHashType)); + if (mgf1Hash == WC_NID_undef) + mgf1Hash = hashAlg; + mgf1 = wc_OidGetHash((int)nid2oid(mgf1Hash, oidHashType)); + /* handle compat layer salt special cases */ + saltLen = rsa_pss_calc_salt(saltLen, wc_HashGetDigestSize(hType), + wolfSSL_RSA_size(rsa)); + /* Create RSA PSS signature. */ if ((signSz = wc_RsaPSS_Sign_ex(encodedSig, encSz, sigRet, outLen, - hType, wc_hash2mgf(hType), DEF_PSS_SALT_LEN, - (RsaKey*)rsa->internal, rng)) <= 0) { - WOLFSSL_ERROR_MSG("Bad Rsa Sign"); + hType, wc_hash2mgf(mgf1), saltLen, key, rng)) <= 0) { + WOLFSSL_ERROR_MSG("Bad RSA PSS Sign"); ret = 0; } break; @@ -4126,13 +4131,15 @@ int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash, /* Sign (private encrypt) PKCS#1 encoded signature. */ if ((signSz = wc_RsaSSL_Sign(encodedSig, encSz, sigRet, outLen, (RsaKey*)rsa->internal, rng)) <= 0) { - WOLFSSL_ERROR_MSG("Bad Rsa Sign"); + WOLFSSL_ERROR_MSG("Bad PKCS1 RSA Sign"); ret = 0; } break; } default: WOLFSSL_ERROR_MSG("Unsupported padding"); + (void)mgf1Hash; + (void)saltLen; ret = 0; break; } @@ -4153,7 +4160,7 @@ int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash, XFREE(encodedSig, NULL, DYNAMIC_TYPE_SIGNATURE); #endif - WOLFSSL_LEAVE("wolfSSL_RSA_sign_generic_padding", ret); + WOLFSSL_LEAVE("wolfSSL_RSA_sign_mgf", ret); return ret; } @@ -4177,6 +4184,14 @@ int wolfSSL_RSA_verify(int hashAlg, const unsigned char* hash, WC_RSA_PKCS1_PADDING); } +int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash, + unsigned int hLen, const unsigned char* sig, unsigned int sigLen, + WOLFSSL_RSA* rsa, int padding) +{ + return wolfSSL_RSA_verify_mgf(hashAlg, hash, hLen, sig, sigLen, rsa, + padding, hashAlg, DEF_PSS_SALT_LEN); +} + /** * Verify a message hash with the chosen message digest, padding, and RSA key. * @@ -4191,12 +4206,14 @@ int wolfSSL_RSA_verify(int hashAlg, const unsigned char* hash, * @param [in] padding Padding to use. Only RSA_PKCS1_PSS_PADDING and * WC_RSA_PKCS1_PADDING are currently supported for * signing. + * @param [in] mgf1Hash MGF1 Hash NID + * @param [in] saltLen Length of RSA PSS salt * @return 1 on success. * @return 0 on failure. */ -int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash, +int wolfSSL_RSA_verify_mgf(int hashAlg, const unsigned char* hash, unsigned int hLen, const unsigned char* sig, unsigned int sigLen, - WOLFSSL_RSA* rsa, int padding) + WOLFSSL_RSA* rsa, int padding, int mgf1Hash, int saltLen) { int ret = 1; #ifdef WOLFSSL_SMALL_STACK @@ -4211,7 +4228,7 @@ int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash, enum wc_HashType hType = WC_HASH_TYPE_NONE; #endif - WOLFSSL_ENTER("wolfSSL_RSA_verify"); + WOLFSSL_ENTER("wolfSSL_RSA_verify_mgf"); /* Validate parameters. */ if ((hash == NULL) || (sig == NULL) || (rsa == NULL)) { @@ -4228,8 +4245,49 @@ int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash, ret = 0; } } + if (ret == 1 && padding == WC_RSA_PKCS1_PSS_PADDING) { + #if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,1)) + RsaKey* key = (RsaKey*)rsa->internal; + enum wc_HashType mgf1; + hType = wc_OidGetHash((int)nid2oid(hashAlg, oidHashType)); + if (mgf1Hash == WC_NID_undef) + mgf1Hash = hashAlg; + mgf1 = wc_OidGetHash((int)nid2oid(mgf1Hash, oidHashType)); + + /* handle compat layer salt special cases */ + saltLen = rsa_pss_calc_salt(saltLen, wc_HashGetDigestSize(hType), + wolfSSL_RSA_size(rsa)); + + verLen = wc_RsaPSS_Verify_ex((byte*)sig, sigLen, sigDec, sigLen, + hType, wc_hash2mgf(mgf1), saltLen, key); + if (verLen > 0) { + /* Check PSS padding is valid. */ + if (wc_RsaPSS_CheckPadding_ex(hash, hLen, sigDec, (word32)verLen, + hType, saltLen, mp_count_bits(&key->n)) != 0) { + WOLFSSL_ERROR_MSG("wc_RsaPSS_CheckPadding_ex error"); + ret = WOLFSSL_FAILURE; + } + else { + /* Success! Free resources and return early */ + XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_SUCCESS; + } + } + else { + WOLFSSL_ERROR_MSG("wc_RsaPSS_Verify_ex failed!"); + ret = WOLFSSL_FAILURE; + } + #else + (void)mgf1Hash; + (void)saltLen; + WOLFSSL_ERROR_MSG("RSA PSS not compiled in!"); + ret = WOLFSSL_FAILURE; + #endif + } + #ifdef WOLFSSL_SMALL_STACK - if ((ret == 1) && (padding != WC_RSA_PKCS1_PSS_PADDING)) { + if (ret == 1) { /* Allocate memory for encoded signature. */ encodedSig = (unsigned char *)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -4239,7 +4297,7 @@ int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash, } } #endif - if ((ret == 1) && (padding != WC_RSA_PKCS1_PSS_PADDING)) { + if (ret == 1) { /* Make encoded signature to compare with decrypted signature. */ if (wolfssl_rsa_sig_encode(hashAlg, hash, hLen, encodedSig, &len, padding) <= 0) { @@ -4266,20 +4324,6 @@ int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash, #endif } if (ret == 1) { - #if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \ - (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 1)) - if (padding == WC_RSA_PKCS1_PSS_PADDING) { - /* Check PSS padding is valid. */ - if (wc_RsaPSS_CheckPadding_ex(hash, hLen, sigDec, (word32)verLen, - hType, DEF_PSS_SALT_LEN, - mp_count_bits(&((RsaKey*)rsa->internal)->n)) != 0) { - WOLFSSL_ERROR_MSG("wc_RsaPSS_CheckPadding_ex error"); - ret = 0; - } - } - else - #endif /* WC_RSA_PSS && !HAVE_SELFTEST && (!HAVE_FIPS || - * FIPS_VERSION >= 5.1) */ /* Compare decrypted signature to encoded signature. */ if (((int)len != verLen) || (XMEMCMP(encodedSig, sigDec, (size_t)verLen) != 0)) { @@ -4293,6 +4337,8 @@ int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash, XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + WOLFSSL_LEAVE("wolfSSL_RSA_verify_mgf", ret); return ret; } diff --git a/src/ssl.c b/src/ssl.c index 736c2db5f..9c0610d5c 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -16539,6 +16539,45 @@ int wolfSSL_i2d_PrivateKey(const WOLFSSL_EVP_PKEY* key, unsigned char** der) return wolfSSL_EVP_PKEY_get_der(key, der); } +int wolfSSL_i2d_PrivateKey_bio(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key) +{ + int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); + int derSz = 0; + byte* der = NULL; + + if (bio == NULL || key == NULL) { + return WOLFSSL_FAILURE; + } + + derSz = wolfSSL_i2d_PrivateKey(key, NULL); + if (derSz <= 0) { + WOLFSSL_MSG("wolfSSL_i2d_PrivateKey (for getting size) failed"); + return WOLFSSL_FAILURE; + } + + der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (!der) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } + + derSz = wolfSSL_i2d_PrivateKey(key, &der); + if (derSz <= 0) { + WOLFSSL_MSG("wolfSSL_i2d_PrivateKey failed"); + goto cleanup; + } + + if (wolfSSL_BIO_write(bio, der, derSz) != derSz) { + goto cleanup; + } + + ret = WOLFSSL_SUCCESS; + +cleanup: + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} + int wolfSSL_i2d_PublicKey(const WOLFSSL_EVP_PKEY *key, unsigned char **der) { #if !defined(NO_RSA) || defined(HAVE_ECC) diff --git a/src/ssl_bn.c b/src/ssl_bn.c index 0d947a8b5..8b1f4065d 100644 --- a/src/ssl_bn.c +++ b/src/ssl_bn.c @@ -1158,6 +1158,62 @@ int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b) return ret; } +/* Same as above, but compare absolute value. */ +int wolfSSL_BN_ucmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b) +{ + int ret = 0; + int bIsNull; + + WOLFSSL_ENTER("wolfSSL_BN_ucmp"); + + /* Must know whether b is NULL. */ + bIsNull = BN_IS_NULL(b); + /* Check whether a is NULL. */ + if (BN_IS_NULL(a)) { + if (bIsNull) { + /* NULL equals NULL. */ + ret = 0; + } + else { + ret = -1; /* NULL less than not NULL. */ + } + } + else if (bIsNull) { + /* not NULL greater than NULL. */ + ret = 1; + } + else { + /* Neither are NULL; copy to new instances and switch to positive if + * required, compare, and then free. Must copy because there is + * possibility of switch to positive but they are declared const. + * wolfssl_bn_set_neg() only returns -1 if the bn is NULL, but we + * already check that so we can ignore the return code. Note for + * wolfSSL_BN_is_negative if n=1 then set to positive. */ + WOLFSSL_BIGNUM* abs_a = wolfSSL_BN_dup(a); + WOLFSSL_BIGNUM* abs_b = wolfSSL_BN_dup(b); + + if (abs_a == NULL || abs_b == NULL) { + WOLFSSL_MSG("wolfSSL_BN_dup failed"); + wolfSSL_BN_free(abs_a); + wolfSSL_BN_free(abs_b); + return WOLFSSL_FATAL_ERROR; + } + + if (wolfSSL_BN_is_negative(abs_a)) { + wolfssl_bn_set_neg(abs_a, 1); + } + + if (wolfSSL_BN_is_negative(abs_b)) { + wolfssl_bn_set_neg(abs_b, 1); + } + + ret = wolfSSL_BN_cmp(abs_a, abs_b); + wolfSSL_BN_free(abs_a); + wolfSSL_BN_free(abs_b); + } + return ret; +} + /* Indicates whether a big number is the value 0. * * Return compliant with OpenSSL. diff --git a/src/x509.c b/src/x509.c index 0139ad0a9..7259b9ba3 100644 --- a/src/x509.c +++ b/src/x509.c @@ -1660,6 +1660,65 @@ int wolfSSL_X509V3_EXT_add_nconf(WOLFSSL_CONF *conf, WOLFSSL_X509V3_CTX *ctx, } #endif +/* Find extension by NID in a stack of extensions. + * + * @param sk Stack of extensions + * @param nid ID to search for + * @param lastpos Start search from this position (not inclusive, -1 means start from beginning) + * @return Index of matching extension or -1 on error/not found + */ +int wolfSSL_X509v3_get_ext_by_NID(const WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk, + int nid, int lastpos) +{ + int i; + WOLFSSL_ENTER("wolfSSL_X509v3_get_ext_by_NID"); + + if (sk == NULL) { + WOLFSSL_MSG("Stack pointer is NULL"); + return WOLFSSL_FATAL_ERROR; + } + + if (lastpos < -1 || lastpos >= wolfSSL_sk_num(sk)) { + WOLFSSL_MSG("Invalid position argument"); + return WOLFSSL_FATAL_ERROR; + } + + for (i = lastpos + 1; i < wolfSSL_sk_num(sk); i++) { + WOLFSSL_X509_EXTENSION* ext = wolfSSL_sk_X509_EXTENSION_value(sk, i); + if (ext && ext->obj) { + if (wolfSSL_OBJ_obj2nid(ext->obj) == nid) + return i; + } + } + + /* Not found */ + return -1; +} + +/* Get extension from a stack of extensions by location. + * + * @param sk Stack of extensions + * @param loc Index of extension to retrieve + * @return Pointer to extension or NULL on error + */ +WOLFSSL_X509_EXTENSION* wolfSSL_X509v3_get_ext( + const WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk, int loc) +{ + WOLFSSL_ENTER("wolfSSL_X509v3_get_ext"); + + if (sk == NULL) { + WOLFSSL_MSG("Stack pointer is NULL"); + return NULL; + } + + if (loc < 0 || loc >= wolfSSL_sk_num(sk)) { + WOLFSSL_MSG("Invalid location argument"); + return NULL; + } + + return wolfSSL_sk_X509_EXTENSION_value(sk, loc); +} + /* Returns crit flag in X509_EXTENSION object */ int wolfSSL_X509_EXTENSION_get_critical(const WOLFSSL_X509_EXTENSION* ex) { diff --git a/tests/api.c b/tests/api.c index 49b6f4634..d783b3e80 100644 --- a/tests/api.c +++ b/tests/api.c @@ -5138,6 +5138,104 @@ static int test_wolfSSL_CertRsaPss(void) #endif /* WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION */ #endif /* HAVE_CERT_CHAIN_VALIDATION */ + +/* Test RSA-PSS digital signature creation and verification */ +static int test_wc_RsaPSS_DigitalSignVerify(void) +{ + EXPECT_DECLS; + + /* Early FIPS did not support PSS. */ +#if (!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION > 2))) && \ + (!defined(HAVE_SELFTEST) || (defined(HAVE_SELFTEST_VERSION) && \ + (HAVE_SELFTEST_VERSION > 2))) && \ + !defined(NO_RSA) && defined(WC_RSA_PSS) && defined(OPENSSL_EXTRA) && \ + defined(WOLFSSL_KEY_GEN) && defined(WC_RSA_NO_PADDING) && \ + !defined(NO_SHA256) + + /* Test digest */ + const unsigned char test_digest[32] = { + 0x08, 0x09, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 + }; + const unsigned int digest_len = sizeof(test_digest); + + /* Variables for RSA key generation and signature operations */ + EVP_PKEY_CTX *pkctx = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *sign_ctx = NULL; + EVP_PKEY_CTX *verify_ctx = NULL; + unsigned char signature[256+MAX_DER_DIGEST_ASN_SZ] = {0}; + size_t signature_len = sizeof(signature); + int modulus_bits = 2048; + + /* Generate RSA key pair to avoid file dependencies */ + ExpectNotNull(pkctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)); + ExpectIntEQ(EVP_PKEY_keygen_init(pkctx), 1); + ExpectIntEQ(EVP_PKEY_CTX_set_rsa_keygen_bits(pkctx, modulus_bits), 1); + ExpectIntEQ(EVP_PKEY_keygen(pkctx, &pkey), 1); + + /* Create signing context */ + ExpectNotNull(sign_ctx = EVP_PKEY_CTX_new(pkey, NULL)); + ExpectIntEQ(EVP_PKEY_sign_init(sign_ctx), 1); + + /* Configure RSA-PSS parameters for signing. */ + ExpectIntEQ(EVP_PKEY_CTX_set_rsa_padding(sign_ctx, RSA_PKCS1_PSS_PADDING), + 1); + /* Default salt length matched hash so use 32 for SHA256 */ + ExpectIntEQ(EVP_PKEY_CTX_set_rsa_pss_saltlen(sign_ctx, 32), 1); + ExpectIntEQ(EVP_PKEY_CTX_set_rsa_mgf1_md(sign_ctx, EVP_sha256()), 1); + ExpectIntEQ(EVP_PKEY_CTX_set_signature_md(sign_ctx, EVP_sha256()), 1); + + /* Create the digital signature */ + ExpectIntEQ(EVP_PKEY_sign(sign_ctx, signature, &signature_len, test_digest, + digest_len), 1); + ExpectIntGT((int)signature_len, 0); + + /* Create verification context */ + ExpectNotNull(verify_ctx = EVP_PKEY_CTX_new(pkey, NULL)); + ExpectIntEQ(EVP_PKEY_verify_init(verify_ctx), 1); + + /* Configure RSA-PSS parameters for verification */ + ExpectIntEQ(EVP_PKEY_CTX_set_rsa_padding(verify_ctx, RSA_PKCS1_PSS_PADDING), + 1); + ExpectIntEQ(EVP_PKEY_CTX_set_rsa_pss_saltlen(verify_ctx, 32), 1); + ExpectIntEQ(EVP_PKEY_CTX_set_rsa_mgf1_md(verify_ctx, EVP_sha256()), 1); + ExpectIntEQ(EVP_PKEY_CTX_set_signature_md(verify_ctx, EVP_sha256()), 1); + + /* Verify the digital signature */ + ExpectIntEQ(EVP_PKEY_verify(verify_ctx, signature, signature_len, + test_digest, digest_len), 1); + + /* Test with wrong digest to ensure verification fails (negative test) */ + { + const unsigned char wrong_digest[32] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x00, 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x01, 0x02 + }; + ExpectIntNE(EVP_PKEY_verify(verify_ctx, signature, signature_len, + wrong_digest, digest_len), 1); + } + + /* Clean up */ + if (verify_ctx) + EVP_PKEY_CTX_free(verify_ctx); + if (sign_ctx) + EVP_PKEY_CTX_free(sign_ctx); + if (pkey) + EVP_PKEY_free(pkey); + if (pkctx) + EVP_PKEY_CTX_free(pkctx); + +#endif + + return EXPECT_RESULT(); +} + static int test_wolfSSL_CTX_load_verify_locations_ex(void) { EXPECT_DECLS; @@ -32284,6 +32382,57 @@ static int test_wolfSSL_X509_get_ext_count(void) return EXPECT_RESULT(); } + +/* Tests X509v3_get_ext_count, X509v3_get_ext_by_NID, and X509v3_get_ext + * working with a stack retrieved from wolfSSL_X509_get0_extensions(). + */ +static int test_wolfSSL_X509_stack_extensions(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \ + !defined(NO_RSA) + WOLFSSL_X509* x509 = NULL; + const WOLFSSL_STACK* ext_stack = NULL; + WOLFSSL_X509_EXTENSION* ext = NULL; + int idx = -1; + int count = 0; + XFILE f = XBADFILE; + + /* Load a certificate */ + ExpectTrue((f = XFOPEN("./certs/server-cert.pem", "rb")) != XBADFILE); + ExpectNotNull(x509 = wolfSSL_PEM_read_X509(f, NULL, NULL, NULL)); + if (f != XBADFILE) + XFCLOSE(f); + + /* Get the stack of extensions */ + ExpectNotNull(ext_stack = wolfSSL_X509_get0_extensions(x509)); + + /* Test X509v3_get_ext_count */ + ExpectIntGT((count = X509v3_get_ext_count(ext_stack)), 0); + + /* Test X509v3_get_ext_by_NID - find Basic Constraints extension */ + ExpectIntGE((idx = X509v3_get_ext_by_NID(ext_stack, NID_basic_constraints, + -1)), 0); + + /* Test X509v3_get_ext - get extension by index */ + ExpectNotNull(ext = X509v3_get_ext(ext_stack, idx)); + + /* Verify that the extension is the correct one */ + ExpectIntEQ(wolfSSL_OBJ_obj2nid(wolfSSL_X509_EXTENSION_get_object(ext)), + NID_basic_constraints); + + /* Test negative cases */ + ExpectIntEQ(X509v3_get_ext_by_NID(NULL, NID_basic_constraints, -1), + WOLFSSL_FATAL_ERROR); + ExpectNull(X509v3_get_ext(NULL, 0)); + ExpectNull(X509v3_get_ext(ext_stack, -1)); + ExpectNull(X509v3_get_ext(ext_stack, count)); + + wolfSSL_X509_free(x509); +#endif + return EXPECT_RESULT(); +} + static int test_wolfSSL_X509_sign2(void) { EXPECT_DECLS; @@ -68143,6 +68292,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_X509_get_ext_by_NID), TEST_DECL(test_wolfSSL_X509_get_ext_subj_alt_name), TEST_DECL(test_wolfSSL_X509_get_ext_count), + TEST_DECL(test_wolfSSL_X509_stack_extensions), TEST_DECL(test_wolfSSL_X509_set_ext), TEST_DECL(test_wolfSSL_X509_add_ext), TEST_DECL(test_wolfSSL_X509_EXTENSION_new), @@ -68443,6 +68593,7 @@ TEST_CASE testCases[] = { #if defined(HAVE_CERT_CHAIN_VALIDATION) && !defined(WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION) TEST_DECL(test_various_pathlen_chains), #endif +TEST_DECL(test_wc_RsaPSS_DigitalSignVerify), /********************************* * SSL/TLS API tests diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 13090c94b..94e06df91 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -2538,9 +2538,11 @@ WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_E if (ctx == NULL) return NULL; XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_PKEY_CTX)); ctx->pkey = pkey; -#if !defined(NO_RSA) +#ifndef NO_RSA ctx->padding = WC_RSA_PKCS1_PADDING; ctx->md = NULL; + ctx->mgf1_md = NULL; + ctx->saltlen = 0; #endif #ifdef HAVE_ECC if (pkey->ecc && pkey->ecc->group) { @@ -2593,6 +2595,42 @@ int wolfSSL_EVP_PKEY_CTX_set_signature_md(WOLFSSL_EVP_PKEY_CTX *ctx, return WOLFSSL_SUCCESS; } +int wolfSSL_EVP_PKEY_CTX_set_rsa_oaep_md(WOLFSSL_EVP_PKEY_CTX *ctx, + const WOLFSSL_EVP_MD *md) +{ + wolfSSL_EVP_PKEY_CTX_set_rsa_padding(ctx, WC_RSA_PKCS1_OAEP_PADDING); + return wolfSSL_EVP_PKEY_CTX_set_signature_md(ctx, md); +} + +int wolfSSL_EVP_PKEY_CTX_set_rsa_pss_saltlen(WOLFSSL_EVP_PKEY_CTX *ctx, + int saltlen) +{ + if (ctx == NULL) return 0; + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_CTX_set_rsa_pss_saltlen"); + wolfSSL_EVP_PKEY_CTX_set_rsa_padding(ctx, WC_RSA_PKCS1_PSS_PADDING); +#ifndef NO_RSA + ctx->saltlen = saltlen; +#else + (void)saltlen; +#endif + return WOLFSSL_SUCCESS; +} + +int wolfSSL_EVP_PKEY_CTX_set_rsa_mgf1_md(WOLFSSL_EVP_PKEY_CTX *ctx, + const WOLFSSL_EVP_MD *md) +{ + if (ctx == NULL) return 0; + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_CTX_set_rsa_mgf1_md"); +#ifndef NO_RSA + /* Hash digest algorithm used with Mask Generation Function 1 (MGF1) for + * RSA-PSS and RSA-OAEP. */ + ctx->mgf1_md = md; +#else + (void)md; +#endif + return WOLFSSL_SUCCESS; +} + /* create a PKEY context and return it */ WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new_id(int id, WOLFSSL_ENGINE *e) { @@ -3278,7 +3316,7 @@ int wolfSSL_EVP_PKEY_sign(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *sig, (void)tbslen; switch (ctx->pkey->type) { -#if !defined(NO_RSA) +#ifndef NO_RSA case WC_EVP_PKEY_RSA: { unsigned int usiglen = (unsigned int)*siglen; if (!sig) { @@ -3291,17 +3329,17 @@ int wolfSSL_EVP_PKEY_sign(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *sig, *siglen = (size_t)len; return WOLFSSL_SUCCESS; } - /* wolfSSL_RSA_sign_generic_padding performs a check that the output - * sig buffer is large enough */ - if (wolfSSL_RSA_sign_generic_padding(wolfSSL_EVP_MD_type(ctx->md), tbs, - (unsigned int)tbslen, sig, &usiglen, ctx->pkey->rsa, 1, - ctx->padding) != WOLFSSL_SUCCESS) { + + if (wolfSSL_RSA_sign_mgf(wolfSSL_EVP_MD_type(ctx->md), tbs, + (unsigned int)tbslen, sig, &usiglen, ctx->pkey->rsa, 1, + ctx->padding, wolfSSL_EVP_MD_type(ctx->mgf1_md), ctx->saltlen + ) != WOLFSSL_SUCCESS) { return WOLFSSL_FAILURE; } *siglen = (size_t)usiglen; return WOLFSSL_SUCCESS; } -#endif /* NO_RSA */ +#endif /* !NO_RSA */ #ifndef NO_DSA case WC_EVP_PKEY_DSA: { @@ -3434,12 +3472,12 @@ int wolfSSL_EVP_PKEY_verify(WOLFSSL_EVP_PKEY_CTX *ctx, const unsigned char *sig, return WOLFSSL_FAILURE; switch (ctx->pkey->type) { -#if !defined(NO_RSA) +#ifndef NO_RSA case WC_EVP_PKEY_RSA: - return wolfSSL_RSA_verify_ex(wolfSSL_EVP_MD_type(ctx->md), tbs, + return wolfSSL_RSA_verify_mgf(wolfSSL_EVP_MD_type(ctx->md), tbs, (unsigned int)tbslen, sig, (unsigned int)siglen, ctx->pkey->rsa, - ctx->padding); -#endif /* NO_RSA */ + ctx->padding, wolfSSL_EVP_MD_type(ctx->mgf1_md), ctx->saltlen); +#endif /* !NO_RSA */ #ifndef NO_DSA case WC_EVP_PKEY_DSA: { @@ -10193,8 +10231,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type) return WC_NID_undef; } - for( ent = md_tbl; ent->name != NULL; ent++){ - if(XSTRCMP((const char *)type, ent->name) == 0) { + for (ent = md_tbl; ent->name != NULL; ent++) { + if (XSTRCMP((const char *)type, ent->name) == 0) { return ent->nid; } } diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index ce3abf4f4..2cc3edaac 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -2924,7 +2924,8 @@ static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out, } #endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_RSA */ -#if defined(WC_RSA_DIRECT) || defined(WC_RSA_NO_PADDING) || defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +#if defined(WC_RSA_DIRECT) || defined(WC_RSA_NO_PADDING) || \ + defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) /* Performs direct RSA computation without padding. The input and output must * match the key size (ex: 2048-bits = 256 bytes). Returns the size of the * output on success or negative value on failure. */ @@ -3010,7 +3011,8 @@ int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz, return ret; } -#endif /* WC_RSA_DIRECT || WC_RSA_NO_PADDING || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ +#endif /* WC_RSA_DIRECT || WC_RSA_NO_PADDING || OPENSSL_EXTRA || \ + * OPENSSL_EXTRA_X509_SMALL */ #if defined(WOLFSSL_CRYPTOCELL) static int cc310_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, diff --git a/wolfssl/openssl/bn.h b/wolfssl/openssl/bn.h index 45411f5c1..d2ec834fd 100644 --- a/wolfssl/openssl/bn.h +++ b/wolfssl/openssl/bn.h @@ -132,6 +132,7 @@ WOLFSSL_API int wolfSSL_BN_is_negative(const WOLFSSL_BIGNUM* bn); WOLFSSL_API int wolfSSL_BN_is_word(const WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w); WOLFSSL_API int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b); +WOLFSSL_API int wolfSSL_BN_ucmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b); WOLFSSL_API int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r); WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* str, int len, @@ -243,6 +244,7 @@ typedef WOLFSSL_BN_GENCB BN_GENCB; #define BN_is_word wolfSSL_BN_is_word #define BN_cmp wolfSSL_BN_cmp +#define BN_ucmp wolfSSL_BN_ucmp #define BN_bn2bin wolfSSL_BN_bn2bin #define BN_bin2bn wolfSSL_BN_bin2bn diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index 3192dbffd..90ff8ac69 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -752,7 +752,9 @@ struct WOLFSSL_EVP_PKEY_CTX { #endif #ifndef NO_RSA const WOLFSSL_EVP_MD* md; -#endif + const WOLFSSL_EVP_MD* mgf1_md; + int saltlen; +#endif /* !NO_RSA */ }; struct WOLFSSL_ASN1_PCTX { @@ -947,6 +949,9 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_set_rsa_padding(WOLFSSL_EVP_PKEY_CTX *ctx, WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_set_signature_md(WOLFSSL_EVP_PKEY_CTX *ctx, const WOLFSSL_EVP_MD* md); WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_set_rsa_keygen_bits(WOLFSSL_EVP_PKEY_CTX *ctx, int bits); +WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_set_rsa_pss_saltlen(WOLFSSL_EVP_PKEY_CTX *ctx, int saltlen); +WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_set_rsa_mgf1_md(WOLFSSL_EVP_PKEY_CTX *ctx, const WOLFSSL_EVP_MD *md); +WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_set_rsa_oaep_md(WOLFSSL_EVP_PKEY_CTX *ctx, const WOLFSSL_EVP_MD *md); WOLFSSL_API int wolfSSL_EVP_PKEY_derive_init(WOLFSSL_EVP_PKEY_CTX *ctx); WOLFSSL_API int wolfSSL_EVP_PKEY_derive_set_peer(WOLFSSL_EVP_PKEY_CTX *ctx, WOLFSSL_EVP_PKEY *peer); @@ -1363,6 +1368,9 @@ WOLFSSL_API int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx, #define EVP_PKEY_CTX_set_signature_md wolfSSL_EVP_PKEY_CTX_set_signature_md #define EVP_PKEY_CTX_new_id wolfSSL_EVP_PKEY_CTX_new_id #define EVP_PKEY_CTX_set_rsa_keygen_bits wolfSSL_EVP_PKEY_CTX_set_rsa_keygen_bits +#define EVP_PKEY_CTX_set_rsa_mgf1_md wolfSSL_EVP_PKEY_CTX_set_rsa_mgf1_md +#define EVP_PKEY_CTX_set_rsa_pss_saltlen wolfSSL_EVP_PKEY_CTX_set_rsa_pss_saltlen +#define EVP_PKEY_CTX_set_rsa_oaep_md wolfSSL_EVP_PKEY_CTX_set_rsa_oaep_md #define EVP_PKEY_derive_init wolfSSL_EVP_PKEY_derive_init #define EVP_PKEY_derive_set_peer wolfSSL_EVP_PKEY_derive_set_peer #define EVP_PKEY_derive wolfSSL_EVP_PKEY_derive diff --git a/wolfssl/openssl/hmac.h b/wolfssl/openssl/hmac.h index b29d4fc2e..2352f9a54 100644 --- a/wolfssl/openssl/hmac.h +++ b/wolfssl/openssl/hmac.h @@ -42,6 +42,7 @@ extern "C" { #endif +#define HMAC_MAX_MD_CBLOCK WC_MAX_BLOCK_SIZE WOLFSSL_API unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, const void* key, int key_len, diff --git a/wolfssl/openssl/rsa.h b/wolfssl/openssl/rsa.h index 111a89e85..40a920315 100644 --- a/wolfssl/openssl/rsa.h +++ b/wolfssl/openssl/rsa.h @@ -42,6 +42,17 @@ #define WC_RSA_PKCS1_OAEP_PADDING 1 #define WC_RSA_PKCS1_PSS_PADDING 2 +/* RSA PSS Salt special cases */ +/* Salt length same as digest length */ +#define WC_RSA_PSS_SALTLEN_DIGEST (-1) +/* Old max salt length */ +#define WC_RSA_PSS_SALTLEN_MAX_SIGN (-2) +/* Verification only value to indicate to discover salt length. */ +#define WC_RSA_PSS_SALTLEN_AUTO (-2) +/* Max salt length */ +#define WC_RSA_PSS_SALTLEN_MAX (-3) + + #ifndef OPENSSL_COEXIST /* Padding types */ @@ -60,14 +71,10 @@ #define RSA_FLAG_NO_BLINDING (1 << 7) #define RSA_FLAG_NO_CONSTTIME (1 << 8) -/* Salt length same as digest length */ -#define RSA_PSS_SALTLEN_DIGEST (-1) -/* Old max salt length */ -#define RSA_PSS_SALTLEN_MAX_SIGN (-2) -/* Verification only value to indicate to discover salt length. */ -#define RSA_PSS_SALTLEN_AUTO (-2) -/* Max salt length */ -#define RSA_PSS_SALTLEN_MAX (-3) +#define RSA_PSS_SALTLEN_DIGEST WC_RSA_PSS_SALTLEN_DIGEST +#define RSA_PSS_SALTLEN_MAX_SIGN WC_RSA_PSS_SALTLEN_MAX_SIGN +#define RSA_PSS_SALTLEN_AUTO WC_RSA_PSS_SALTLEN_AUTO +#define RSA_PSS_SALTLEN_MAX WC_RSA_PSS_SALTLEN_MAX #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ #endif /* !OPENSSL_COEXIST */ @@ -140,21 +147,34 @@ WOLFSSL_API int wolfSSL_RSA_bits(const WOLFSSL_RSA* rsa); WOLFSSL_API int wolfSSL_RSA_sign(int type, const unsigned char* m, unsigned int mLen, unsigned char* sigRet, unsigned int* sigLen, WOLFSSL_RSA* rsa); -WOLFSSL_API int wolfSSL_RSA_sign_ex(int type, const unsigned char* m, - unsigned int mLen, unsigned char* sigRet, - unsigned int* sigLen, WOLFSSL_RSA* rsa, - int flag); -WOLFSSL_API int wolfSSL_RSA_sign_generic_padding(int type, const unsigned char* m, - unsigned int mLen, unsigned char* sigRet, - unsigned int* sigLen, WOLFSSL_RSA* rsa, int flag, - int padding); -WOLFSSL_API int wolfSSL_RSA_verify(int type, const unsigned char* m, - unsigned int mLen, const unsigned char* sig, - unsigned int sigLen, WOLFSSL_RSA* rsa); -WOLFSSL_API int wolfSSL_RSA_verify_ex(int type, const unsigned char* m, - unsigned int mLen, const unsigned char* sig, - unsigned int sigLen, WOLFSSL_RSA* rsa, - int padding); +WOLFSSL_API int wolfSSL_RSA_sign_ex(int hashAlg, + const unsigned char* hash, unsigned int hLen, + unsigned char* sigRet, unsigned int* sigLen, + WOLFSSL_RSA* rsa, int flag); +WOLFSSL_API int wolfSSL_RSA_sign_generic_padding(int hashAlg, + const unsigned char* hash, unsigned int hLen, + unsigned char* sigRet, unsigned int* sigLen, + WOLFSSL_RSA* rsa, int flag, int padding); + +WOLFSSL_LOCAL int wolfSSL_RSA_sign_mgf(int hashAlg, + const unsigned char* hash, unsigned int hLen, + unsigned char* sigRet, unsigned int* sigLen, + WOLFSSL_RSA* rsa, int flag, int padding, + int mgf1Hash, int saltLen); + +WOLFSSL_API int wolfSSL_RSA_verify(int hashAlg, + const unsigned char* hash, unsigned int hLen, + const unsigned char* sig, unsigned int sigLen, + WOLFSSL_RSA* rsa); +WOLFSSL_API int wolfSSL_RSA_verify_ex(int hashAlg, + const unsigned char* hash, unsigned int hLen, + const unsigned char* sig, unsigned int sigLen, + WOLFSSL_RSA* rsa, int padding); +WOLFSSL_LOCAL int wolfSSL_RSA_verify_mgf(int hashAlg, + const unsigned char* hash, unsigned int hLen, + const unsigned char* sig, unsigned int sigLen, + WOLFSSL_RSA* rsa, int padding, + int mgf1Hash, int saltLen); WOLFSSL_API int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from, unsigned char* to, WOLFSSL_RSA* rsa, int padding); WOLFSSL_API int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa); diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index da1616845..ec4a79529 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -505,6 +505,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define PEM_X509_INFO_read wolfSSL_PEM_X509_INFO_read #define i2d_PrivateKey wolfSSL_i2d_PrivateKey #define i2d_PublicKey wolfSSL_i2d_PublicKey +#define i2d_PrivateKey_bio wolfSSL_i2d_PrivateKey_bio #define i2d_X509_REQ wolfSSL_i2d_X509_REQ #define d2i_X509_REQ wolfSSL_d2i_X509_REQ diff --git a/wolfssl/openssl/x509v3.h b/wolfssl/openssl/x509v3.h index c0ae5cc74..dfd4d4da3 100644 --- a/wolfssl/openssl/x509v3.h +++ b/wolfssl/openssl/x509v3.h @@ -132,6 +132,11 @@ WOLFSSL_API int wolfSSL_X509V3_EXT_print(WOLFSSL_BIO *out, WOLFSSL_X509_EXTENSION *ext, unsigned long flag, int indent); WOLFSSL_API int wolfSSL_X509V3_EXT_add_nconf(WOLFSSL_CONF *conf, WOLFSSL_X509V3_CTX *ctx, const char *section, WOLFSSL_X509 *cert); +WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509v3_get_ext( + const WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk, int loc); +WOLFSSL_API int wolfSSL_X509v3_get_ext_by_NID( + const WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk, int nid, int lastpos); + WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_a2i_IPADDRESS(const char* ipa); #ifndef OPENSSL_COEXIST @@ -218,6 +223,8 @@ typedef struct WOLFSSL_ACCESS_DESCRIPTION ACCESS_DESCRIPTION; #define X509V3_set_ctx_test(ctx) wolfSSL_X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST) #define X509V3_set_ctx_nodb wolfSSL_X509V3_set_ctx_nodb #define X509v3_get_ext_count wolfSSL_sk_num +#define X509v3_get_ext_by_NID wolfSSL_X509v3_get_ext_by_NID +#define X509v3_get_ext wolfSSL_X509v3_get_ext #endif /* !OPENSSL_COEXIST */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 4c13411c1..c5d2fde44 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -2326,6 +2326,8 @@ WOLFSSL_API int wolfSSL_i2d_PrivateKey(const WOLFSSL_EVP_PKEY* key, unsigned char** der); WOLFSSL_API int wolfSSL_i2d_PublicKey(const WOLFSSL_EVP_PKEY* key, unsigned char** der); +WOLFSSL_API int wolfSSL_i2d_PrivateKey_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY* key); #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) WOLFSSL_API int wolfSSL_EVP_PKEY_print_public(WOLFSSL_BIO* out, const WOLFSSL_EVP_PKEY* pkey, From c341a9fc05615a3ad3871c41713b2c011e56cea0 Mon Sep 17 00:00:00 2001 From: Anthony Hu Date: Tue, 15 Jul 2025 07:59:20 -0400 Subject: [PATCH 2/2] FIPS > 2 --- src/pk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pk.c b/src/pk.c index 4f693a20a..d470ceb7f 100644 --- a/src/pk.c +++ b/src/pk.c @@ -3536,7 +3536,8 @@ int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* e, #ifdef WC_RSA_PSS -#if defined(OPENSSL_EXTRA) && !defined(HAVE_SELFTEST) +#if defined(OPENSSL_EXTRA) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) static int rsa_pss_calc_salt(int saltLen, int hashLen, int emLen) { /* Calculate the salt length to use for special cases. */