From: Weili Qian <qianweili@huawei.com> uadk_provider mirrors the default provider's signature context and delegates its software fallbacks (DO_SOFT) to the default provider functions. On OpenSSL 3.4+ the default provider routes digest signing through EVP_PKEY_OP_SIGNMSG/VERIFYMSG, disallows SHA1 for message signing, and defaults PSS saltlen to AUTO_DIGEST_MAX (3.1+), so the 3.2-era operation values and defaults in uadk diverge from the default provider behavior on 3.4+. Align RSA/ECDSA signature behavior with the OpenSSL default provider: - Set digest_sign_init operation to EVP_PKEY_OP_SIGNMSG and digest_verify_init operation to EVP_PKEY_OP_VERIFYMSG on OpenSSL 3.4+ to match default provider routing. - Exclude EVP_PKEY_OP_SIGNMSG from sha1_allowed in RSA and ECDSA, so SHA1 is disallowed for message signing (not just direct signing). - Include EVP_PKEY_OP_SIGNMSG in ECDSA ecc_check_key to validate private key for message signing operations. - Change default PSS saltlen from RSA_PSS_SALTLEN_AUTO to RSA_PSS_SALTLEN_AUTO_DIGEST_MAX on OpenSSL 3.1+ to comply with FIPS 186-4 section 5.5 (sLen <= hLen). - Temporarily present EVP_PKEY_OP_SIGN/VERIFY to the internal sign/verify call in digest_sign_final/digest_verify_final, so a DO_SOFT fallback takes the default provider's digest path instead of re-hashing the finalized digest, which fails with an update-after-final error. Signed-off-by: Weili Qian <qianweili@huawei.com> --- src/uadk_prov_ecdsa.c | 22 ++++++++++++++-- src/uadk_prov_rsa_sign.c | 56 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/src/uadk_prov_ecdsa.c b/src/uadk_prov_ecdsa.c index 44f64f6..032bc2a 100644 --- a/src/uadk_prov_ecdsa.c +++ b/src/uadk_prov_ecdsa.c @@ -237,7 +237,11 @@ static int ecdsa_digest_get_approved_nid(struct ecdsa_ctx *ctx, const EVP_MD *md int mdnid = ecdsa_digest_get_nid(md); #ifndef OPENSSL_NO_FIPS_SECURITYCHECKS - int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); + int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN +#if OPENSSL_VERSION_NUMBER >= 0x30400000L + && ctx->operation != EVP_PKEY_OP_SIGNMSG +#endif + ); if (uadk_prov_securitycheck_enabled(ctx->libctx)) { if (mdnid == NID_undef || (mdnid == NID_sha1 && !sha1_allowed)) @@ -325,7 +329,13 @@ static int ecdsa_signverify_init(void *vctx, void *ec, if (eckey) { if (!uadk_prov_ecc_check_key(ctx->libctx, eckey, - operation == EVP_PKEY_OP_SIGN)) +#if OPENSSL_VERSION_NUMBER >= 0x30400000L + (operation == EVP_PKEY_OP_SIGN || + operation == EVP_PKEY_OP_SIGNMSG) +#else + operation == EVP_PKEY_OP_SIGN +#endif + )) return UADK_P_FAIL; if (!EC_KEY_up_ref(ec)) @@ -894,7 +904,11 @@ err: static int uadk_signature_ecdsa_digest_sign_init(void *vctx, const char *mdname, void *ec, const OSSL_PARAM params[]) { +#if OPENSSL_VERSION_NUMBER >= 0x30400000L + return ecdsa_digest_singverify_init(vctx, mdname, ec, params, EVP_PKEY_OP_SIGNMSG); +#else return ecdsa_digest_singverify_init(vctx, mdname, ec, params, EVP_PKEY_OP_SIGN); +#endif } static int ecdsa_digest_signverify_update(void *vctx, const unsigned char *data, @@ -943,7 +957,11 @@ static int uadk_signature_ecdsa_digest_sign_final(void *vctx, unsigned char *sig static int uadk_signature_ecdsa_digest_verify_init(void *vctx, const char *mdname, void *ec, const OSSL_PARAM params[]) { +#if OPENSSL_VERSION_NUMBER >= 0x30400000L + return ecdsa_digest_singverify_init(vctx, mdname, ec, params, EVP_PKEY_OP_VERIFYMSG); +#else return ecdsa_digest_singverify_init(vctx, mdname, ec, params, EVP_PKEY_OP_VERIFY); +#endif } static int uadk_signature_ecdsa_digest_verify_update(void *vctx, const unsigned char *data, diff --git a/src/uadk_prov_rsa_sign.c b/src/uadk_prov_rsa_sign.c index 370dcc1..96e3094 100644 --- a/src/uadk_prov_rsa_sign.c +++ b/src/uadk_prov_rsa_sign.c @@ -520,7 +520,11 @@ static int rsa_setup_md(struct PROV_RSA_SIG_CTX *ctx, const char *mdname, if (mdname != NULL) { EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); - int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); + int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN +#if OPENSSL_VERSION_NUMBER >= 0x30400000L + && ctx->operation != EVP_PKEY_OP_SIGNMSG +#endif + ); int md_nid = ossl_digest_rsa_sign_get_md_nid(ctx->libctx, md, sha1_allowed); size_t mdname_len = strlen(mdname); bool md_ret = (!md) || (md_nid <= 0); @@ -647,7 +651,11 @@ static int uadk_rsa_signverify_init(void *vprsactx, void *vrsa, ctx->operation = operation; /* Maximum for sign, auto for verify */ +#if OPENSSL_VERSION_NUMBER >= 0x30100000L + ctx->saltlen = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX; +#else ctx->saltlen = RSA_PSS_SALTLEN_AUTO; +#endif ctx->min_saltlen = -1; ctx->flag_allow_oneshot = 1; ctx->flag_allow_final = 1; @@ -1239,7 +1247,11 @@ static void *uadk_signature_rsa_newctx(void *provctx, const char *propq) priv->flag_allow_md = 1; priv->propq = propq_copy; /* Maximum for sign, auto for verify */ +#if OPENSSL_VERSION_NUMBER >= 0x30100000L + priv->saltlen = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX; +#else priv->saltlen = RSA_PSS_SALTLEN_AUTO; +#endif priv->min_saltlen = -1; return priv; @@ -1377,7 +1389,11 @@ static int uadk_rsa_setup_md(struct PROV_RSA_SIG_CTX *ctx, const char *mdname, if (mdname != NULL) { md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); - sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); + sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN +#if OPENSSL_VERSION_NUMBER >= 0x30400000L + && ctx->operation != EVP_PKEY_OP_SIGNMSG +#endif + ); md_nid = uadk_digest_rsa_sign_get_md_nid(ctx->libctx, md, sha1_allowed); mdname_len = strlen(mdname); if (!md || md_nid <= 0 || @@ -1458,8 +1474,13 @@ error: static int uadk_signature_rsa_digest_sign_init(void *vprsactx, const char *mdname, void *vrsa, const OSSL_PARAM params[]) { +#if OPENSSL_VERSION_NUMBER >= 0x30400000L + return uadk_signature_rsa_digest_signverify_init(vprsactx, mdname, vrsa, + params, EVP_PKEY_OP_SIGNMSG); +#else return uadk_signature_rsa_digest_signverify_init(vprsactx, mdname, vrsa, params, EVP_PKEY_OP_SIGN); +#endif } static int uadk_signature_rsa_digest_sign_update(void *vprsactx, @@ -1579,6 +1600,7 @@ static int uadk_signature_rsa_digest_sign_final(void *vprsactx, unsigned char *s struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int dlen = 0; + int operation; int ret; if (!priv) @@ -1602,7 +1624,18 @@ static int uadk_signature_rsa_digest_sign_final(void *vprsactx, unsigned char *s priv->flag_allow_md = 1; - ret = uadk_signature_rsa_sign(vprsactx, sig, siglen, sigsize, digest, (size_t)dlen); + /* + * We are called with the final digest. Presenting SIGNMSG would make + * the default provider's rsa_sign() take the message path and hash + * the digest again through the already finalized mdctx. Temporarily + * present a plain SIGN so a DO_SOFT fallback takes the digest path + * (rsa_sign_directly). + */ + operation = priv->operation; + priv->operation = EVP_PKEY_OP_SIGN; + ret = uadk_signature_rsa_sign(vprsactx, sig, siglen, sigsize, + digest, (size_t)dlen); + priv->operation = operation; if (sig != NULL) { priv->flag_allow_update = 0; priv->flag_allow_oneshot = 0; @@ -1615,8 +1648,13 @@ static int uadk_signature_rsa_digest_sign_final(void *vprsactx, unsigned char *s static int uadk_signature_rsa_digest_verify_init(void *vprsactx, const char *mdname, void *vrsa, const OSSL_PARAM params[]) { +#if OPENSSL_VERSION_NUMBER >= 0x30400000L + return uadk_signature_rsa_digest_signverify_init(vprsactx, mdname, vrsa, + params, EVP_PKEY_OP_VERIFYMSG); +#else return uadk_signature_rsa_digest_signverify_init(vprsactx, mdname, vrsa, params, EVP_PKEY_OP_VERIFY); +#endif } static int uadk_signature_rsa_digest_verify_update(void *vprsactx, const unsigned char *data, @@ -1636,6 +1674,7 @@ static int uadk_signature_rsa_digest_verify_final(void *vprsactx, const unsigned struct PROV_RSA_SIG_CTX *priv = (struct PROV_RSA_SIG_CTX *)vprsactx; unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int dlen = 0; + int operation; int ret; if (!priv) @@ -1653,7 +1692,16 @@ static int uadk_signature_rsa_digest_verify_final(void *vprsactx, const unsigned priv->flag_allow_md = 1; - ret = uadk_signature_rsa_verify(vprsactx, sig, siglen, digest, (size_t)dlen); + /* + * Same as in uadk_signature_rsa_digest_sign_final(): we are called + * with the final digest, so present a plain VERIFY operation to keep + * a DO_SOFT fallback on the default provider's digest verify path. + */ + operation = priv->operation; + priv->operation = EVP_PKEY_OP_VERIFY; + ret = uadk_signature_rsa_verify(vprsactx, sig, siglen, + digest, (size_t)dlen); + priv->operation = operation; priv->flag_allow_update = 0; priv->flag_allow_final = 0; -- 2.43.0