new file mode 100644
@@ -0,0 +1,618 @@
+From 24734088e1034392de981151dfe57e3a379ada18 Mon Sep 17 00:00:00 2001
+From: Hubert Kario <hkario@redhat.com>
+Date: Tue, 15 Mar 2022 13:58:08 +0100
+Subject: [PATCH 1/3] rsa: add implicit rejection in PKCS#1 v1.5
+
+The RSA decryption as implemented before required very careful handling
+of both the exit code returned by OpenSSL and the potentially returned
+ciphertext. Looking at the recent security vulnerabilities
+(CVE-2020-25659 and CVE-2020-25657) it is unlikely that most users of
+OpenSSL do it correctly.
+
+Given that correct code requires side channel secure programming in
+application code, we can classify the existing RSA decryption methods
+as CWE-676, which in turn likely causes CWE-208 and CWE-385 in
+application code.
+
+To prevent that, we can use a technique called "implicit rejection".
+For that we generate a random message to be returned in case the
+padding check fails. We generate the message based on static secret
+data (the private exponent) and the provided ciphertext (so that the
+attacker cannot determine that the returned value is randomly generated
+instead of result of decryption and de-padding). We return it in case
+any part of padding check fails.
+
+The upshot of this approach is that then not only is the length of the
+returned message useless as the Bleichenbacher oracle, so are the
+actual bytes of the returned message. So application code doesn't have
+to perform any operations on the returned message in side-channel free
+way to remain secure against Bleichenbacher attacks.
+
+Note: this patch implements a specific algorithm, shared with Mozilla
+NSS, so that the attacker cannot use one library as an oracle against the
+other in heterogeneous environments.
+
+CVE: CVE-2023-50781
+
+Upstream-Status: Backport
+[https://github.com/openssl/openssl/commit/7fc67e0a33102aa47bbaa56533eeecb98c0450f7]
+
+Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
+Reviewed-by: Tim Hudson <tjh@openssl.org>
+Reviewed-by: Tomas Mraz <tomas@openssl.org>
+(Merged from https://github.com/openssl/openssl/pull/13817)
+
+Signed-off-by: Jiaying Song <jiaying.song.cn@windriver.com>
+---
+ crypto/rsa/rsa_ossl.c | 95 +++++++-
+ crypto/rsa/rsa_pk1.c | 252 ++++++++++++++++++++++
+ doc/man1/openssl-pkeyutl.pod.in | 5 +
+ doc/man1/openssl-rsautl.pod.in | 5 +
+ doc/man3/EVP_PKEY_CTX_ctrl.pod | 7 +
+ doc/man3/EVP_PKEY_decrypt.pod | 12 ++
+ doc/man3/RSA_padding_add_PKCS1_type_1.pod | 7 +-
+ doc/man3/RSA_public_encrypt.pod | 11 +-
+ include/crypto/rsa.h | 4 +
+ 9 files changed, 393 insertions(+), 5 deletions(-)
+
+diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c
+index 0fc642e777..330302ae55 100644
+--- a/crypto/rsa/rsa_ossl.c
++++ b/crypto/rsa/rsa_ossl.c
+@@ -17,6 +17,9 @@
+ #include "crypto/bn.h"
+ #include "rsa_local.h"
+ #include "internal/constant_time.h"
++#include <openssl/evp.h>
++#include <openssl/sha.h>
++#include <openssl/hmac.h>
+
+ static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding);
+@@ -377,8 +380,13 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
+ BIGNUM *f, *ret;
+ int j, num = 0, r = -1;
+ unsigned char *buf = NULL;
++ unsigned char d_hash[SHA256_DIGEST_LENGTH] = {0};
++ HMAC_CTX *hmac = NULL;
++ unsigned int md_len = SHA256_DIGEST_LENGTH;
++ unsigned char kdk[SHA256_DIGEST_LENGTH] = {0};
+ BN_CTX *ctx = NULL;
+ int local_blinding = 0;
++ EVP_MD *md = NULL;
+ /*
+ * Used only if the blinding structure is shared. A non-NULL unblind
+ * instructs rsa_blinding_convert() and rsa_blinding_invert() to store
+@@ -408,6 +416,11 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
+ goto err;
+ }
+
++ if (flen < 1) {
++ ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_SMALL);
++ goto err;
++ }
++
+ /* make data into a big number */
+ if (BN_bin2bn(from, (int)flen, f) == NULL)
+ goto err;
+@@ -472,13 +485,91 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
+ if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
+ goto err;
+
++ /*
++ * derive the Key Derivation Key from private exponent and public
++ * ciphertext
++ */
++ if (!(rsa->flags & RSA_FLAG_EXT_PKEY)) {
++ /*
++ * because we use d as a handle to rsa->d we need to keep it local and
++ * free before any further use of rsa->d
++ */
++ BIGNUM *d = BN_new();
++ if (d == NULL) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++ if (rsa->d == NULL) {
++ ERR_raise(ERR_LIB_RSA, RSA_R_MISSING_PRIVATE_KEY);
++ BN_free(d);
++ goto err;
++ }
++ BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
++ if (BN_bn2binpad(d, buf, num) < 0) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ BN_free(d);
++ goto err;
++ }
++ BN_free(d);
++
++ /*
++ * we use hardcoded hash so that migrating between versions that use
++ * different hash doesn't provide a Bleichenbacher oracle:
++ * if the attacker can see that different versions return different
++ * messages for the same ciphertext, they'll know that the message is
++ * syntethically generated, which means that the padding check failed
++ */
++ md = EVP_MD_fetch(rsa->libctx, "sha256", NULL);
++ if (md == NULL) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++
++ if (EVP_Digest(buf, num, d_hash, NULL, md, NULL) <= 0) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++
++ hmac = HMAC_CTX_new();
++ if (hmac == NULL) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ if (HMAC_Init_ex(hmac, d_hash, sizeof(d_hash), md, NULL) <= 0) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++
++ if (flen < num) {
++ memset(buf, 0, num - flen);
++ if (HMAC_Update(hmac, buf, num - flen) <= 0) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++ }
++ if (HMAC_Update(hmac, from, flen) <= 0) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++
++ md_len = SHA256_DIGEST_LENGTH;
++ if (HMAC_Final(hmac, kdk, &md_len) <= 0) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++ }
++
+ j = BN_bn2binpad(ret, buf, num);
+ if (j < 0)
+ goto err;
+
+ switch (padding) {
+ case RSA_PKCS1_PADDING:
+- r = RSA_padding_check_PKCS1_type_2(to, num, buf, j, num);
++ if (rsa->flags & RSA_FLAG_EXT_PKEY)
++ r = RSA_padding_check_PKCS1_type_2(to, num, buf, j, num);
++ else
++ r = ossl_rsa_padding_check_PKCS1_type_2(rsa->libctx, to, num, buf, j, num, kdk);
+ break;
+ case RSA_PKCS1_OAEP_PADDING:
+ r = RSA_padding_check_PKCS1_OAEP(to, num, buf, j, num, NULL, 0);
+@@ -501,6 +592,8 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
+ #endif
+
+ err:
++ HMAC_CTX_free(hmac);
++ EVP_MD_free(md);
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ OPENSSL_clear_free(buf, num);
+diff --git a/crypto/rsa/rsa_pk1.c b/crypto/rsa/rsa_pk1.c
+index 51507fc030..5cd2b26879 100644
+--- a/crypto/rsa/rsa_pk1.c
++++ b/crypto/rsa/rsa_pk1.c
+@@ -21,10 +21,14 @@
+ #include <openssl/rand.h>
+ /* Just for the SSL_MAX_MASTER_KEY_LENGTH value */
+ #include <openssl/prov_ssl.h>
++#include <openssl/evp.h>
++#include <openssl/sha.h>
++#include <openssl/hmac.h>
+ #include "internal/cryptlib.h"
+ #include "crypto/rsa.h"
+ #include "rsa_local.h"
+
++
+ int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen,
+ const unsigned char *from, int flen)
+ {
+@@ -273,6 +277,254 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
+ return constant_time_select_int(good, mlen, -1);
+ }
+
++
++static int ossl_rsa_prf(OSSL_LIB_CTX *ctx,
++ unsigned char *to, int tlen,
++ const char *label, int llen,
++ const unsigned char *kdk,
++ uint16_t bitlen)
++{
++ int pos;
++ int ret = -1;
++ uint16_t iter = 0;
++ unsigned char be_iter[sizeof(iter)];
++ unsigned char be_bitlen[sizeof(bitlen)];
++ HMAC_CTX *hmac = NULL;
++ EVP_MD *md = NULL;
++ unsigned char hmac_out[SHA256_DIGEST_LENGTH];
++ unsigned int md_len;
++
++ if (tlen * 8 != bitlen) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ return ret;
++ }
++
++ be_bitlen[0] = (bitlen >> 8) & 0xff;
++ be_bitlen[1] = bitlen & 0xff;
++
++ hmac = HMAC_CTX_new();
++ if (hmac == NULL) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++
++ /*
++ * we use hardcoded hash so that migrating between versions that use
++ * different hash doesn't provide a Bleichenbacher oracle:
++ * if the attacker can see that different versions return different
++ * messages for the same ciphertext, they'll know that the message is
++ * syntethically generated, which means that the padding check failed
++ */
++ md = EVP_MD_fetch(ctx, "sha256", NULL);
++ if (md == NULL) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++
++ if (HMAC_Init_ex(hmac, kdk, SHA256_DIGEST_LENGTH, md, NULL) <= 0) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++
++ for (pos = 0; pos < tlen; pos += SHA256_DIGEST_LENGTH, iter++) {
++ if (HMAC_Init_ex(hmac, NULL, 0, NULL, NULL) <= 0) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++
++ be_iter[0] = (iter >> 8) & 0xff;
++ be_iter[1] = iter & 0xff;
++
++ if (HMAC_Update(hmac, be_iter, sizeof(be_iter)) <= 0) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++ if (HMAC_Update(hmac, (unsigned char *)label, llen) <= 0) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++ if (HMAC_Update(hmac, be_bitlen, sizeof(be_bitlen)) <= 0) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++
++ /*
++ * HMAC_Final requires the output buffer to fit the whole MAC
++ * value, so we need to use the intermediate buffer for the last
++ * unaligned block
++ */
++ md_len = SHA256_DIGEST_LENGTH;
++ if (pos + SHA256_DIGEST_LENGTH > tlen) {
++ if (HMAC_Final(hmac, hmac_out, &md_len) <= 0) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++ memcpy(to + pos, hmac_out, tlen - pos);
++ } else {
++ if (HMAC_Final(hmac, to + pos, &md_len) <= 0) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
++ }
++ }
++
++ ret = 0;
++
++err:
++ HMAC_CTX_free(hmac);
++ EVP_MD_free(md);
++ return ret;
++}
++
++/*
++ * ossl_rsa_padding_check_PKCS1_type_2() checks and removes the PKCS#1 type 2
++ * padding from a decrypted RSA message. Unlike the
++ * RSA_padding_check_PKCS1_type_2() it will not return an error in case it
++ * detects a padding error, rather it will return a deterministically generated
++ * random message. In other words it will perform an implicit rejection
++ * of an invalid padding. This means that the returned value does not indicate
++ * if the padding of the encrypted message was correct or not, making
++ * side channel attacks like the ones described by Bleichenbacher impossible
++ * without access to the full decrypted value and a brute-force search of
++ * remaining padding bytes
++ */
++int ossl_rsa_padding_check_PKCS1_type_2(OSSL_LIB_CTX *ctx,
++ unsigned char *to, int tlen,
++ const unsigned char *from, int flen,
++ int num, unsigned char *kdk)
++{
++/*
++ * We need to generate a random length for the synthethic message, to avoid
++ * bias towards zero and avoid non-constant timeness of DIV, we prepare
++ * 128 values to check if they are not too large for the used key size,
++ * and use 0 in case none of them are small enough, as 2^-128 is a good enough
++ * safety margin
++ */
++#define MAX_LEN_GEN_TRIES 128
++ unsigned char *synthetic = NULL;
++ int synthethic_length;
++ uint16_t len_candidate;
++ unsigned char candidate_lengths[MAX_LEN_GEN_TRIES * sizeof(len_candidate)];
++ uint16_t len_mask;
++ uint16_t max_sep_offset;
++ int synth_msg_index = 0;
++ int ret = -1;
++ int i, j;
++ unsigned int good, found_zero_byte;
++ int zero_index = 0, msg_index;
++
++ /*
++ * If these checks fail then either the message in publicly invalid, or
++ * we've been called incorrectly. We can fail immediately.
++ * Since this code is called only internally by openssl, those are just
++ * sanity checks
++ */
++ if (num != flen || tlen <= 0 || flen <= 0) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ return -1;
++ }
++
++ /* Generate a random message to return in case the padding checks fail */
++ synthetic = OPENSSL_malloc(flen);
++ if (synthetic == NULL) {
++ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
++ return -1;
++ }
++
++ if (ossl_rsa_prf(ctx, synthetic, flen, "message", 7, kdk, flen * 8) < 0)
++ goto err;
++
++ /* decide how long the random message should be */
++ if (ossl_rsa_prf(ctx, candidate_lengths, sizeof(candidate_lengths),
++ "length", 6, kdk,
++ MAX_LEN_GEN_TRIES * sizeof(len_candidate) * 8) < 0)
++ goto err;
++
++ /*
++ * max message size is the size of the modulus size less 2 bytes for
++ * version and padding type and a minimum of 8 bytes padding
++ */
++ len_mask = max_sep_offset = flen - 2 - 8;
++ /*
++ * we want a mask so lets propagate the high bit to all positions less
++ * significant than it
++ */
++ len_mask |= len_mask >> 1;
++ len_mask |= len_mask >> 2;
++ len_mask |= len_mask >> 4;
++ len_mask |= len_mask >> 8;
++
++ synthethic_length = 0;
++ for (i = 0; i < MAX_LEN_GEN_TRIES * (int)sizeof(len_candidate);
++ i += sizeof(len_candidate)) {
++ len_candidate = (candidate_lengths[i] << 8) | candidate_lengths[i + 1];
++ len_candidate &= len_mask;
++
++ synthethic_length = constant_time_select_int(
++ constant_time_lt(len_candidate, max_sep_offset),
++ len_candidate, synthethic_length);
++ }
++
++ synth_msg_index = flen - synthethic_length;
++
++ /* we have alternative message ready, check the real one */
++ good = constant_time_is_zero(from[0]);
++ good &= constant_time_eq(from[1], 2);
++
++ /* then look for the padding|message separator (the first zero byte) */
++ found_zero_byte = 0;
++ for (i = 2; i < flen; i++) {
++ unsigned int equals0 = constant_time_is_zero(from[i]);
++ zero_index = constant_time_select_int(~found_zero_byte & equals0,
++ i, zero_index);
++ found_zero_byte |= equals0;
++ }
++
++ /*
++ * padding must be at least 8 bytes long, and it starts two bytes into
++ * |from|. If we never found a 0-byte, then |zero_index| is 0 and the check
++ * also fails.
++ */
++ good &= constant_time_ge(zero_index, 2 + 8);
++
++ /*
++ * Skip the zero byte. This is incorrect if we never found a zero-byte
++ * but in this case we also do not copy the message out.
++ */
++ msg_index = zero_index + 1;
++
++ /*
++ * old code returned an error in case the decrypted message wouldn't fit
++ * into the |to|, since that would leak information, return the synthethic
++ * message instead
++ */
++ good &= constant_time_ge(tlen, num - msg_index);
++
++ msg_index = constant_time_select_int(good, msg_index, synth_msg_index);
++
++ /*
++ * since at this point the |msg_index| does not provide the signal
++ * indicating if the padding check failed or not, we don't have to worry
++ * about leaking the length of returned message, we still need to ensure
++ * that we read contents of both buffers so that cache accesses don't leak
++ * the value of |good|
++ */
++ for (i = msg_index, j = 0; i < flen && j < tlen; i++, j++)
++ to[j] = constant_time_select_8(good, from[i], synthetic[i]);
++ ret = j;
++
++err:
++ /*
++ * the only time ret < 0 is when the ciphertext is publicly invalid
++ * or we were called with invalid parameters, so we don't have to perform
++ * a side-channel secure raising of the error
++ */
++ if (ret < 0)
++ ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
++ OPENSSL_free(synthetic);
++ return ret;
++}
++
+ /*
+ * ossl_rsa_padding_check_PKCS1_type_2_TLS() checks and removes the PKCS1 type 2
+ * padding from a decrypted RSA message in a TLS signature. The result is stored
+diff --git a/doc/man1/openssl-pkeyutl.pod.in b/doc/man1/openssl-pkeyutl.pod.in
+index 2f6ef0021d..015265a74d 100644
+--- a/doc/man1/openssl-pkeyutl.pod.in
++++ b/doc/man1/openssl-pkeyutl.pod.in
+@@ -273,6 +273,11 @@ signed or verified directly instead of using a B<DigestInfo> structure. If a
+ digest is set, then the B<DigestInfo> structure is used and its length
+ must correspond to the digest type.
+
++Note, for B<pkcs1> padding, as a protection against Bleichenbacher attack,
++the decryption will not fail in case of padding check failures. Use B<none>
++and manual inspection of the decrypted message to verify if the decrypted
++value has correct PKCS#1 v1.5 padding.
++
+ For B<oaep> mode only encryption and decryption is supported.
+
+ For B<x931> if the digest type is set it is used to format the block data
+diff --git a/doc/man1/openssl-rsautl.pod.in b/doc/man1/openssl-rsautl.pod.in
+index 0a32fd965b..4c462abc8c 100644
+--- a/doc/man1/openssl-rsautl.pod.in
++++ b/doc/man1/openssl-rsautl.pod.in
+@@ -105,6 +105,11 @@ The padding to use: PKCS#1 v1.5 (the default), PKCS#1 OAEP,
+ ANSI X9.31, or no padding, respectively.
+ For signatures, only B<-pkcs> and B<-raw> can be used.
+
++Note: because of protection against Bleichenbacher attacks, decryption
++using PKCS#1 v1.5 mode will not return errors in case padding check failed.
++Use B<-raw> and inspect the returned value manually to check if the
++padding is correct.
++
+ =item B<-hexdump>
+
+ Hex dump the output data.
+diff --git a/doc/man3/EVP_PKEY_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod
+index 3075eaafd6..e788f38809 100644
+--- a/doc/man3/EVP_PKEY_CTX_ctrl.pod
++++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod
+@@ -386,6 +386,13 @@ this behaviour should be tolerated then
+ OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION should be set to the actual
+ negotiated protocol version. Otherwise it should be left unset.
+
++Similarly to the B<RSA_PKCS1_WITH_TLS_PADDING> above, since OpenSSL version
++3.1.0, the use of B<RSA_PKCS1_PADDING> will return a randomly generated message
++instead of padding errors in case padding checks fail. Applications that
++want to remain secure while using earlier versions of OpenSSL, still need to
++handle both the error code from the RSA decryption operation and the
++returned message in a side channel secure manner.
++
+ =head2 DSA parameters
+
+ EVP_PKEY_CTX_set_dsa_paramgen_bits() sets the number of bits used for DSA
+diff --git a/doc/man3/EVP_PKEY_decrypt.pod b/doc/man3/EVP_PKEY_decrypt.pod
+index b6f9bad5f1..898535a7a2 100644
+--- a/doc/man3/EVP_PKEY_decrypt.pod
++++ b/doc/man3/EVP_PKEY_decrypt.pod
+@@ -51,6 +51,18 @@ return 1 for success and 0 or a negative value for failure. In particular a
+ return value of -2 indicates the operation is not supported by the public key
+ algorithm.
+
++=head1 WARNINGS
++
++In OpenSSL versions before 3.1.0, when used in PKCS#1 v1.5 padding,
++both the return value from the EVP_PKEY_decrypt() and the B<outlen> provided
++information useful in mounting a Bleichenbacher attack against the
++used private key. They had to processed in a side-channel free way.
++
++Since version 3.1.0, the EVP_PKEY_decrypt() method when used with PKCS#1
++v1.5 padding doesn't return an error in case it detects an error in padding,
++instead it returns a pseudo-randomly generated message, removing the need
++of side-channel secure code from applications using OpenSSL.
++
+ =head1 EXAMPLES
+
+ Decrypt data using OAEP (for RSA keys):
+diff --git a/doc/man3/RSA_padding_add_PKCS1_type_1.pod b/doc/man3/RSA_padding_add_PKCS1_type_1.pod
+index 9f7025c497..36ae18563f 100644
+--- a/doc/man3/RSA_padding_add_PKCS1_type_1.pod
++++ b/doc/man3/RSA_padding_add_PKCS1_type_1.pod
+@@ -121,8 +121,8 @@ L<ERR_get_error(3)>.
+
+ =head1 WARNINGS
+
+-The result of RSA_padding_check_PKCS1_type_2() is a very sensitive
+-information which can potentially be used to mount a Bleichenbacher
++The result of RSA_padding_check_PKCS1_type_2() is exactly the
++information which is used to mount a classical Bleichenbacher
+ padding oracle attack. This is an inherent weakness in the PKCS #1
+ v1.5 padding design. Prefer PKCS1_OAEP padding. If that is not
+ possible, the result of RSA_padding_check_PKCS1_type_2() should be
+@@ -137,6 +137,9 @@ as this would create a small timing side channel which could be
+ used to mount a Bleichenbacher attack against any padding mode
+ including PKCS1_OAEP.
+
++You should prefer the use of EVP PKEY APIs for PKCS#1 v1.5 decryption
++as they implement the necessary workarounds internally.
++
+ =head1 SEE ALSO
+
+ L<RSA_public_encrypt(3)>,
+diff --git a/doc/man3/RSA_public_encrypt.pod b/doc/man3/RSA_public_encrypt.pod
+index 1d38073aea..bd3f835ac6 100644
+--- a/doc/man3/RSA_public_encrypt.pod
++++ b/doc/man3/RSA_public_encrypt.pod
+@@ -52,8 +52,8 @@ Encrypting user data directly with RSA is insecure.
+
+ =back
+
+-B<flen> must not be more than RSA_size(B<rsa>) - 11 for the PKCS #1 v1.5
+-based padding modes, not more than RSA_size(B<rsa>) - 42 for
++When encrypting B<flen> must not be more than RSA_size(B<rsa>) - 11 for the
++PKCS #1 v1.5 based padding modes, not more than RSA_size(B<rsa>) - 42 for
+ RSA_PKCS1_OAEP_PADDING and exactly RSA_size(B<rsa>) for RSA_NO_PADDING.
+ When a padding mode other than RSA_NO_PADDING is in use, then
+ RSA_public_encrypt() will include some random bytes into the ciphertext
+@@ -92,6 +92,13 @@ which can potentially be used to mount a Bleichenbacher padding oracle
+ attack. This is an inherent weakness in the PKCS #1 v1.5 padding
+ design. Prefer RSA_PKCS1_OAEP_PADDING.
+
++In OpenSSL before version 3.1.0, both the return value and the length of
++returned value could be used to mount the Bleichenbacher attack.
++Since version 3.1.0, OpenSSL does not return an error in case of padding
++checks failed. Instead it generates a random message based on used private
++key and provided ciphertext so that application code doesn't have to implement
++a side-channel secure error handling.
++
+ =head1 CONFORMING TO
+
+ SSL, PKCS #1 v2.0
+diff --git a/include/crypto/rsa.h b/include/crypto/rsa.h
+index 949873d0ee..f267e5d9d1 100644
+--- a/include/crypto/rsa.h
++++ b/include/crypto/rsa.h
+@@ -83,6 +83,10 @@ int ossl_rsa_param_decode(RSA *rsa, const X509_ALGOR *alg);
+ RSA *ossl_rsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
++int ossl_rsa_padding_check_PKCS1_type_2(OSSL_LIB_CTX *ctx,
++ unsigned char *to, int tlen,
++ const unsigned char *from, int flen,
++ int num, unsigned char *kdk);
+ int ossl_rsa_padding_check_PKCS1_type_2_TLS(OSSL_LIB_CTX *ctx, unsigned char *to,
+ size_t tlen,
+ const unsigned char *from,
+--
+2.34.1
+
new file mode 100644
@@ -0,0 +1,358 @@
+From e92f0cd3b03e5aca948b03df7e3d02e536700f68 Mon Sep 17 00:00:00 2001
+From: Hubert Kario <hkario@redhat.com>
+Date: Thu, 27 Oct 2022 19:16:58 +0200
+Subject: [PATCH 2/3] rsa: Add option to disable implicit rejection
+
+CVE: CVE-2023-50781
+
+Upstream-Status: Backport
+[https://github.com/openssl/openssl/commit/5ab3ec1bb1eaa795d775f5896818cfaa84d33a1a]
+
+Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
+Reviewed-by: Tim Hudson <tjh@openssl.org>
+Reviewed-by: Tomas Mraz <tomas@openssl.org>
+(Merged from https://github.com/openssl/openssl/pull/13817)
+
+Signed-off-by: Jiaying Song <jiaying.song.cn@windriver.com>
+---
+ crypto/cms/cms_env.c | 7 +++++
+ crypto/evp/ctrl_params_translate.c | 6 +++++
+ crypto/rsa/rsa_ossl.c | 16 ++++++++----
+ crypto/rsa/rsa_pmeth.c | 20 +++++++++++++-
+ doc/man1/openssl-pkeyutl.pod.in | 10 +++++++
+ doc/man3/EVP_PKEY_CTX_ctrl.pod | 2 ++
+ doc/man7/provider-asym_cipher.pod | 9 +++++++
+ include/openssl/core_names.h | 2 ++
+ include/openssl/rsa.h | 5 ++++
+ .../implementations/asymciphers/rsa_enc.c | 26 +++++++++++++++++--
+ 10 files changed, 95 insertions(+), 8 deletions(-)
+
+diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c
+index 445a16fb77..49b0289114 100644
+--- a/crypto/cms/cms_env.c
++++ b/crypto/cms/cms_env.c
+@@ -581,6 +581,13 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
+ if (!ossl_cms_env_asn1_ctrl(ri, 1))
+ goto err;
+
++ if (EVP_PKEY_is_a(pkey, "RSA"))
++ /* upper layer CMS code incorrectly assumes that a successful RSA
++ * decryption means that the key matches ciphertext (which never
++ * was the case, implicit rejection or not), so to make it work
++ * disable implicit rejection for RSA keys */
++ EVP_PKEY_CTX_ctrl_str(ktri->pctx, "rsa_pkcs1_implicit_rejection", "0");
++
+ if (EVP_PKEY_decrypt(ktri->pctx, NULL, &eklen,
+ ktri->encryptedKey->data,
+ ktri->encryptedKey->length) <= 0)
+diff --git a/crypto/evp/ctrl_params_translate.c b/crypto/evp/ctrl_params_translate.c
+index 44d0895bcf..db7325439a 100644
+--- a/crypto/evp/ctrl_params_translate.c
++++ b/crypto/evp/ctrl_params_translate.c
+@@ -2269,6 +2269,12 @@ static const struct translation_st evp_pkey_ctx_translations[] = {
+ EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, NULL, NULL,
+ OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, OSSL_PARAM_OCTET_PTR, NULL },
+
++ { SET, EVP_PKEY_RSA, 0, EVP_PKEY_OP_TYPE_CRYPT,
++ EVP_PKEY_CTRL_RSA_IMPLICIT_REJECTION, NULL,
++ "rsa_pkcs1_implicit_rejection",
++ OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION, OSSL_PARAM_UNSIGNED_INTEGER,
++ NULL },
++
+ { SET, EVP_PKEY_RSA_PSS, 0, EVP_PKEY_OP_TYPE_GEN,
+ EVP_PKEY_CTRL_MD, "rsa_pss_keygen_md", NULL,
+ OSSL_ALG_PARAM_DIGEST, OSSL_PARAM_UTF8_STRING, fix_md },
+diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c
+index 330302ae55..4bdacd5ed9 100644
+--- a/crypto/rsa/rsa_ossl.c
++++ b/crypto/rsa/rsa_ossl.c
+@@ -395,6 +395,12 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
+ BIGNUM *unblind = NULL;
+ BN_BLINDING *blinding = NULL;
+
++ /*
++ * we need the value of the private exponent to perform implicit rejection
++ */
++ if ((rsa->flags & RSA_FLAG_EXT_PKEY) && (padding == RSA_PKCS1_PADDING))
++ padding = RSA_PKCS1_NO_IMPLICIT_REJECT_PADDING;
++
+ if ((ctx = BN_CTX_new_ex(rsa->libctx)) == NULL)
+ goto err;
+ BN_CTX_start(ctx);
+@@ -489,7 +495,7 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
+ * derive the Key Derivation Key from private exponent and public
+ * ciphertext
+ */
+- if (!(rsa->flags & RSA_FLAG_EXT_PKEY)) {
++ if (padding == RSA_PKCS1_PADDING) {
+ /*
+ * because we use d as a handle to rsa->d we need to keep it local and
+ * free before any further use of rsa->d
+@@ -565,11 +571,11 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
+ goto err;
+
+ switch (padding) {
++ case RSA_PKCS1_NO_IMPLICIT_REJECT_PADDING:
++ r = RSA_padding_check_PKCS1_type_2(to, num, buf, j, num);
++ break;
+ case RSA_PKCS1_PADDING:
+- if (rsa->flags & RSA_FLAG_EXT_PKEY)
+- r = RSA_padding_check_PKCS1_type_2(to, num, buf, j, num);
+- else
+- r = ossl_rsa_padding_check_PKCS1_type_2(rsa->libctx, to, num, buf, j, num, kdk);
++ r = ossl_rsa_padding_check_PKCS1_type_2(rsa->libctx, to, num, buf, j, num, kdk);
+ break;
+ case RSA_PKCS1_OAEP_PADDING:
+ r = RSA_padding_check_PKCS1_OAEP(to, num, buf, j, num, NULL, 0);
+diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c
+index 0bf5ac098a..81b031f81b 100644
+--- a/crypto/rsa/rsa_pmeth.c
++++ b/crypto/rsa/rsa_pmeth.c
+@@ -52,6 +52,8 @@ typedef struct {
+ /* OAEP label */
+ unsigned char *oaep_label;
+ size_t oaep_labellen;
++ /* if to use implicit rejection in PKCS#1 v1.5 decryption */
++ int implicit_rejection;
+ } RSA_PKEY_CTX;
+
+ /* True if PSS parameters are restricted */
+@@ -72,6 +74,7 @@ static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
+ /* Maximum for sign, auto for verify */
+ rctx->saltlen = RSA_PSS_SALTLEN_AUTO;
+ rctx->min_saltlen = -1;
++ rctx->implicit_rejection = 1;
+ ctx->data = rctx;
+ ctx->keygen_info = rctx->gentmp;
+ ctx->keygen_info_count = 2;
+@@ -97,6 +100,7 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
+ dctx->md = sctx->md;
+ dctx->mgf1md = sctx->mgf1md;
+ dctx->saltlen = sctx->saltlen;
++ dctx->implicit_rejection = sctx->implicit_rejection;
+ if (sctx->oaep_label) {
+ OPENSSL_free(dctx->oaep_label);
+ dctx->oaep_label = OPENSSL_memdup(sctx->oaep_label, sctx->oaep_labellen);
+@@ -347,6 +351,7 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx,
+ const unsigned char *in, size_t inlen)
+ {
+ int ret;
++ int pad_mode;
+ RSA_PKEY_CTX *rctx = ctx->data;
+ /*
+ * Discard const. Its marked as const because this may be a cached copy of
+@@ -367,7 +372,12 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx,
+ rctx->oaep_labellen,
+ rctx->md, rctx->mgf1md);
+ } else {
+- ret = RSA_private_decrypt(inlen, in, out, rsa, rctx->pad_mode);
++ if (rctx->pad_mode == RSA_PKCS1_PADDING &&
++ rctx->implicit_rejection == 0)
++ pad_mode = RSA_PKCS1_NO_IMPLICIT_REJECT_PADDING;
++ else
++ pad_mode = rctx->pad_mode;
++ ret = RSA_private_decrypt(inlen, in, out, rsa, pad_mode);
+ }
+ *outlen = constant_time_select_s(constant_time_msb_s(ret), *outlen, ret);
+ ret = constant_time_select_int(constant_time_msb(ret), ret, 1);
+@@ -591,6 +601,14 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+ *(unsigned char **)p2 = rctx->oaep_label;
+ return rctx->oaep_labellen;
+
++ case EVP_PKEY_CTRL_RSA_IMPLICIT_REJECTION:
++ if (rctx->pad_mode != RSA_PKCS1_PADDING) {
++ ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE);
++ return -2;
++ }
++ rctx->implicit_rejection = p1;
++ return 1;
++
+ case EVP_PKEY_CTRL_DIGESTINIT:
+ case EVP_PKEY_CTRL_PKCS7_SIGN:
+ #ifndef OPENSSL_NO_CMS
+diff --git a/doc/man1/openssl-pkeyutl.pod.in b/doc/man1/openssl-pkeyutl.pod.in
+index 015265a74d..5e62551d34 100644
+--- a/doc/man1/openssl-pkeyutl.pod.in
++++ b/doc/man1/openssl-pkeyutl.pod.in
+@@ -305,6 +305,16 @@ explicitly set in PSS mode then the signing digest is used.
+ Sets the digest used for the OAEP hash function. If not explicitly set then
+ SHA1 is used.
+
++=item B<rsa_pkcs1_implicit_rejection:>I<flag>
++
++Disables (when set to 0) or enables (when set to 1) the use of implicit
++rejection with PKCS#1 v1.5 decryption. When enabled (the default), as a
++protection against Bleichenbacher attack, the library will generate a
++deterministic random plaintext that it will return to the caller in case
++of padding check failure.
++When disabled, it's the callers' responsibility to handle the returned
++errors in a side-channel free manner.
++
+ =back
+
+ =head1 RSA-PSS ALGORITHM
+diff --git a/doc/man3/EVP_PKEY_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod
+index e788f38809..3844aa2199 100644
+--- a/doc/man3/EVP_PKEY_CTX_ctrl.pod
++++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod
+@@ -392,6 +392,8 @@ instead of padding errors in case padding checks fail. Applications that
+ want to remain secure while using earlier versions of OpenSSL, still need to
+ handle both the error code from the RSA decryption operation and the
+ returned message in a side channel secure manner.
++This protection against Bleichenbacher attacks can be disabled by setting
++the OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION (an unsigned integer) to 0.
+
+ =head2 DSA parameters
+
+diff --git a/doc/man7/provider-asym_cipher.pod b/doc/man7/provider-asym_cipher.pod
+index 0976a263a8..2a8426a6ed 100644
+--- a/doc/man7/provider-asym_cipher.pod
++++ b/doc/man7/provider-asym_cipher.pod
+@@ -234,6 +234,15 @@ The TLS protocol version first requested by the client.
+
+ The negotiated TLS protocol version.
+
++=item "implicit-rejection" (B<OSSL_PKEY_PARAM_IMPLICIT_REJECTION>) <unsigned integer>
++
++Gets of sets the use of the implicit rejection mechanism for RSA PKCS#1 v1.5
++decryption. When set (non zero value), the decryption API will return
++a deterministically random value if the PKCS#1 v1.5 padding check fails.
++This makes explotation of the Bleichenbacher significantly harder, even
++if the code using the RSA decryption API is not implemented in side-channel
++free manner. Set by default.
++
+ =back
+
+ OSSL_FUNC_asym_cipher_gettable_ctx_params() and OSSL_FUNC_asym_cipher_settable_ctx_params()
+diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
+index 6bed5a8a67..5a350b537f 100644
+--- a/include/openssl/core_names.h
++++ b/include/openssl/core_names.h
+@@ -292,6 +292,7 @@ extern "C" {
+ #define OSSL_PKEY_PARAM_DIST_ID "distid"
+ #define OSSL_PKEY_PARAM_PUB_KEY "pub"
+ #define OSSL_PKEY_PARAM_PRIV_KEY "priv"
++#define OSSL_PKEY_PARAM_IMPLICIT_REJECTION "implicit-rejection"
+
+ /* Diffie-Hellman/DSA Parameters */
+ #define OSSL_PKEY_PARAM_FFC_P "p"
+@@ -467,6 +468,7 @@ extern "C" {
+ #define OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL "oaep-label"
+ #define OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION "tls-client-version"
+ #define OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION "tls-negotiated-version"
++#define OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION "implicit-rejection"
+
+ /*
+ * Encoder / decoder parameters
+diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h
+index a55c9727c6..247f9014e3 100644
+--- a/include/openssl/rsa.h
++++ b/include/openssl/rsa.h
+@@ -183,6 +183,8 @@ int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char **label);
+
+ # define EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES (EVP_PKEY_ALG_CTRL + 13)
+
++# define EVP_PKEY_CTRL_RSA_IMPLICIT_REJECTION (EVP_PKEY_ALG_CTRL + 14)
++
+ # define RSA_PKCS1_PADDING 1
+ # define RSA_NO_PADDING 3
+ # define RSA_PKCS1_OAEP_PADDING 4
+@@ -192,6 +194,9 @@ int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char **label);
+ # define RSA_PKCS1_PSS_PADDING 6
+ # define RSA_PKCS1_WITH_TLS_PADDING 7
+
++/* internal RSA_ only */
++# define RSA_PKCS1_NO_IMPLICIT_REJECT_PADDING 8
++
+ # define RSA_PKCS1_PADDING_SIZE 11
+
+ # define RSA_set_app_data(s,arg) RSA_set_ex_data(s,0,arg)
+diff --git a/providers/implementations/asymciphers/rsa_enc.c b/providers/implementations/asymciphers/rsa_enc.c
+index c8921acd6e..11a91e62b1 100644
+--- a/providers/implementations/asymciphers/rsa_enc.c
++++ b/providers/implementations/asymciphers/rsa_enc.c
+@@ -75,6 +75,8 @@ typedef struct {
+ /* TLS padding */
+ unsigned int client_version;
+ unsigned int alt_version;
++ /* PKCS#1 v1.5 decryption mode */
++ unsigned int implicit_rejection;
+ } PROV_RSA_CTX;
+
+ static void *rsa_newctx(void *provctx)
+@@ -107,6 +109,7 @@ static int rsa_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[],
+ RSA_free(prsactx->rsa);
+ prsactx->rsa = vrsa;
+ prsactx->operation = operation;
++ prsactx->implicit_rejection = 1;
+
+ switch (RSA_test_flags(prsactx->rsa, RSA_FLAG_TYPE_MASK)) {
+ case RSA_FLAG_TYPE_RSA:
+@@ -199,6 +202,7 @@ static int rsa_decrypt(void *vprsactx, unsigned char *out, size_t *outlen,
+ {
+ PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+ int ret;
++ int pad_mode;
+ size_t len = RSA_size(prsactx->rsa);
+
+ if (!ossl_prov_is_running())
+@@ -276,8 +280,12 @@ static int rsa_decrypt(void *vprsactx, unsigned char *out, size_t *outlen,
+ }
+ OPENSSL_free(tbuf);
+ } else {
+- ret = RSA_private_decrypt(inlen, in, out, prsactx->rsa,
+- prsactx->pad_mode);
++ if ((prsactx->implicit_rejection == 0) &&
++ (prsactx->pad_mode == RSA_PKCS1_PADDING))
++ pad_mode = RSA_PKCS1_NO_IMPLICIT_REJECT_PADDING;
++ else
++ pad_mode = prsactx->pad_mode;
++ ret = RSA_private_decrypt(inlen, in, out, prsactx->rsa, pad_mode);
+ }
+ *outlen = constant_time_select_s(constant_time_msb_s(ret), *outlen, ret);
+ ret = constant_time_select_int(constant_time_msb(ret), 0, 1);
+@@ -401,6 +409,10 @@ static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
+ if (p != NULL && !OSSL_PARAM_set_uint(p, prsactx->alt_version))
+ return 0;
+
++ p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION);
++ if (p != NULL && !OSSL_PARAM_set_uint(p, prsactx->implicit_rejection))
++ return 0;
++
+ return 1;
+ }
+
+@@ -412,6 +424,7 @@ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ NULL, 0),
+ OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, NULL),
+ OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, NULL),
++ OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION, NULL),
+ OSSL_PARAM_END
+ };
+
+@@ -549,6 +562,14 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
+ return 0;
+ prsactx->alt_version = alt_version;
+ }
++ p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION);
++ if (p != NULL) {
++ unsigned int implicit_rejection;
++
++ if (!OSSL_PARAM_get_uint(p, &implicit_rejection))
++ return 0;
++ prsactx->implicit_rejection = implicit_rejection;
++ }
+
+ return 1;
+ }
+@@ -562,6 +583,7 @@ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_octet_string(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, NULL, 0),
+ OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, NULL),
+ OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, NULL),
++ OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION, NULL),
+ OSSL_PARAM_END
+ };
+
+--
+2.34.1
+
new file mode 100644
@@ -0,0 +1,41 @@
+From ba78f7b0599ba5bfb5032dd2664465c5b13388e3 Mon Sep 17 00:00:00 2001
+From: Hubert Kario <hkario@redhat.com>
+Date: Tue, 22 Nov 2022 18:25:49 +0100
+Subject: [PATCH 3/3] smime/pkcs7: disable the Bleichenbacher workaround
+
+CVE: CVE-2023-50781
+
+Upstream-Status: Backport
+[https://github.com/openssl/openssl/commit/056dade341d2589975a3aae71f81c8d7061583c7]
+
+Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
+Reviewed-by: Tim Hudson <tjh@openssl.org>
+Reviewed-by: Tomas Mraz <tomas@openssl.org>
+(Merged from https://github.com/openssl/openssl/pull/13817)
+
+Signed-off-by: Jiaying Song <jiaying.song.cn@windriver.com>
+---
+ crypto/pkcs7/pk7_doit.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c
+index e9de097da1..6d3124da87 100644
+--- a/crypto/pkcs7/pk7_doit.c
++++ b/crypto/pkcs7/pk7_doit.c
+@@ -170,6 +170,13 @@ static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen,
+ if (EVP_PKEY_decrypt_init(pctx) <= 0)
+ goto err;
+
++ if (EVP_PKEY_is_a(pkey, "RSA"))
++ /* upper layer pkcs7 code incorrectly assumes that a successful RSA
++ * decryption means that the key matches ciphertext (which never
++ * was the case, implicit rejection or not), so to make it work
++ * disable implicit rejection for RSA keys */
++ EVP_PKEY_CTX_ctrl_str(pctx, "rsa_pkcs1_implicit_rejection", "0");
++
+ if (EVP_PKEY_decrypt(pctx, NULL, &eklen,
+ ri->enc_key->data, ri->enc_key->length) <= 0)
+ goto err;
+--
+2.34.1
+
@@ -13,6 +13,9 @@ SRC_URI = "https://github.com/openssl/openssl/releases/download/openssl-${PV}/op
file://afalg.patch \
file://0001-Configure-do-not-tweak-mips-cflags.patch \
file://CVE-2024-41996.patch \
+ file://CVE-2023-50781-1.patch \
+ file://CVE-2023-50781-2.patch \
+ file://CVE-2023-50781-3.patch \
"
SRC_URI:append:class-nativesdk = " \