in crypto/fipsmodule/evp/p_rsa.c [493:651]
static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
RSA_PKEY_CTX *rctx = ctx->data;
switch (type) {
case EVP_PKEY_CTRL_RSA_PADDING:
if (!is_known_padding(p1) || !check_padding_md(rctx->md, p1) ||
(p1 == RSA_PKCS1_PSS_PADDING &&
0 == (ctx->operation & (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY))) ||
(p1 == RSA_PKCS1_OAEP_PADDING &&
0 == (ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))) {
OPENSSL_PUT_ERROR(EVP, EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
return 0;
}
if (p1 != RSA_PKCS1_PSS_PADDING && pkey_ctx_is_pss(ctx)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
return 0;
}
if ((p1 == RSA_PKCS1_PSS_PADDING || p1 == RSA_PKCS1_OAEP_PADDING) &&
rctx->md == NULL) {
rctx->md = EVP_sha1();
}
rctx->pad_mode = p1;
return 1;
case EVP_PKEY_CTRL_GET_RSA_PADDING:
*(int *)p2 = rctx->pad_mode;
return 1;
case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PSS_SALTLEN);
return 0;
}
if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) {
*(int *)p2 = rctx->saltlen;
} else {
// |p1| can be |-2|, |-1| and non-negative.
// The functions of these values are mentioned in the API doc of
// |EVP_PKEY_CTX_set_rsa_pss_saltlen| in |evp.h|.
// Accordingly, |-2| is the smallest value that |p1| can be.
if (p1 < -2) {
return 0;
}
int min_saltlen = rctx->min_saltlen;
if (min_saltlen != NO_PSS_SALT_LEN_RESTRICTION) {
// Check |min_saltlen| when |p1| is -1.
if ((p1 == RSA_PSS_SALTLEN_DIGEST &&
(size_t)min_saltlen > EVP_MD_size(rctx->md)) ||
// Check |min_saltlen| when |p1| is the value gives the size of
// the salt in bytes.
(p1 >= 0 && p1 < min_saltlen)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PSS_SALTLEN);
return 0;
}
}
rctx->saltlen = p1;
}
return 1;
case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
if (p1 < 256) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_KEYBITS);
return 0;
}
rctx->nbits = p1;
return 1;
case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
if (!p2) {
return 0;
}
#if defined(AWSLC_FIPS)
if (BN_get_word(p2) != RSA_F4) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_OPERATION);
return 0;
}
#endif
BN_free(rctx->pub_exp);
rctx->pub_exp = p2;
return 1;
case EVP_PKEY_CTRL_RSA_OAEP_MD:
case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE);
return 0;
}
if (type == EVP_PKEY_CTRL_GET_RSA_OAEP_MD) {
*(const EVP_MD **)p2 = rctx->md;
} else {
rctx->md = p2;
}
return 1;
case EVP_PKEY_CTRL_MD:
if (!check_padding_md(p2, rctx->pad_mode)) {
return 0;
}
// Check if the hashAlgorithm is matched.
// Sec 3.3 https://tools.ietf.org/html/rfc4055#section-3.3
if (!pss_hash_algorithm_match(ctx, rctx->min_saltlen, rctx->md, p2)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PSS_MD);
return 0;
}
rctx->md = p2;
return 1;
case EVP_PKEY_CTRL_GET_MD:
*(const EVP_MD **)p2 = rctx->md;
return 1;
case EVP_PKEY_CTRL_RSA_MGF1_MD:
case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING &&
rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_MGF1_MD);
return 0;
}
if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD) {
if (rctx->mgf1md) {
*(const EVP_MD **)p2 = rctx->mgf1md;
} else {
*(const EVP_MD **)p2 = rctx->md;
}
} else {
// Check if the hashAlgorithm is matched.
// Sec 3.3 https://tools.ietf.org/html/rfc4055#section-3.3
if (!pss_hash_algorithm_match(ctx, rctx->min_saltlen, rctx->mgf1md, p2)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_MGF1_MD);
return 0;
}
rctx->mgf1md = p2;
}
return 1;
case EVP_PKEY_CTRL_RSA_OAEP_LABEL: {
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE);
return 0;
}
OPENSSL_free(rctx->oaep_label);
RSA_OAEP_LABEL_PARAMS *params = p2;
rctx->oaep_label = params->data;
rctx->oaep_labellen = params->len;
return 1;
}
case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PADDING_MODE);
return 0;
}
CBS_init((CBS *)p2, rctx->oaep_label, rctx->oaep_labellen);
return 1;
default:
OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return 0;
}
}