mirror of
https://github.com/openssl/openssl.git
synced 2024-11-23 18:13:39 +08:00
rsa: Add option to disable implicit rejection
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)
This commit is contained in:
parent
8ae4f0e68e
commit
5ab3ec1bb1
@ -608,6 +608,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)
|
||||
|
@ -2201,6 +2201,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_STRING, 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 },
|
||||
|
@ -390,6 +390,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);
|
||||
@ -488,7 +494,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
|
||||
@ -564,11 +570,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);
|
||||
|
@ -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);
|
||||
@ -345,6 +349,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
|
||||
@ -365,7 +370,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);
|
||||
@ -585,6 +595,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
|
||||
|
@ -272,6 +272,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
|
||||
|
@ -399,6 +399,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
|
||||
|
||||
|
@ -235,6 +235,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()
|
||||
|
@ -302,6 +302,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"
|
||||
@ -482,6 +483,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
|
||||
|
@ -189,6 +189,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
|
||||
@ -198,6 +200,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)
|
||||
|
@ -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:
|
||||
@ -195,6 +198,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())
|
||||
@ -270,8 +274,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);
|
||||
@ -395,6 +403,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;
|
||||
}
|
||||
|
||||
@ -406,6 +418,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
|
||||
};
|
||||
|
||||
@ -543,6 +556,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;
|
||||
}
|
||||
@ -555,6 +576,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
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user