RSA: properly generate algorithm identifier for RSA-PSS signatures

Fixes #13969

- properly handle the mandatory RSA-PSS key parameters
- improve parameter checking when setting the parameters
- compute the algorithm id at the time it is requested so it
  reflects the actual parameters set
- when generating keys do not override previously set parameters
  with defaults
- tests added to the test_req recipe that should cover the PSS signature
  handling

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/13988)
This commit is contained in:
Tomas Mraz 2021-01-29 17:02:32 +01:00
parent 26372a4d44
commit bbde856619
11 changed files with 320 additions and 135 deletions

View File

@ -943,6 +943,7 @@ static int rsa_int_import_from(const OSSL_PARAM params[], void *vpctx,
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
RSA *rsa = ossl_rsa_new_with_ctx(pctx->libctx);
RSA_PSS_PARAMS_30 rsa_pss_params = { 0, };
int pss_defaults_set = 0;
int ok = 0;
if (rsa == NULL) {
@ -953,7 +954,8 @@ static int rsa_int_import_from(const OSSL_PARAM params[], void *vpctx,
RSA_clear_flags(rsa, RSA_FLAG_TYPE_MASK);
RSA_set_flags(rsa, rsa_type);
if (!ossl_rsa_pss_params_30_fromdata(&rsa_pss_params, params, pctx->libctx))
if (!ossl_rsa_pss_params_30_fromdata(&rsa_pss_params, &pss_defaults_set,
params, pctx->libctx))
goto err;
switch (rsa_type) {

View File

@ -217,6 +217,7 @@ int ossl_rsa_pss_params_30_todata(const RSA_PSS_PARAMS_30 *pss,
}
int ossl_rsa_pss_params_30_fromdata(RSA_PSS_PARAMS_30 *pss_params,
int *defaults_set,
const OSSL_PARAM params[],
OSSL_LIB_CTX *libctx)
{
@ -249,10 +250,13 @@ int ossl_rsa_pss_params_30_fromdata(RSA_PSS_PARAMS_30 *pss_params,
* restrictions, so we start by setting default values, and let each
* parameter override their specific restriction data.
*/
if (param_md != NULL || param_mgf != NULL || param_mgf1md != NULL
|| param_saltlen != NULL)
if (!*defaults_set
&& (param_md != NULL || param_mgf != NULL || param_mgf1md != NULL
|| param_saltlen != NULL)) {
if (!ossl_rsa_pss_params_30_set_defaults(pss_params))
return 0;
*defaults_set = 1;
}
if (param_mgf != NULL) {
int default_maskgenalg_nid = ossl_rsa_pss_params_30_maskgenalg(NULL);

View File

@ -113,7 +113,9 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
goto err;
}
if (sLen != RSA_PSS_SALTLEN_AUTO && (maskedDBLen - i) != sLen) {
ERR_raise(ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED);
ERR_raise_data(ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED,
"expected: %d retrieved: %d", sLen,
maskedDBLen - i);
goto err;
}
if (!EVP_DigestInit_ex(ctx, Hash, NULL)

View File

@ -65,6 +65,7 @@ int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[]);
int ossl_rsa_pss_params_30_todata(const RSA_PSS_PARAMS_30 *pss,
OSSL_PARAM_BLD *bld, OSSL_PARAM params[]);
int ossl_rsa_pss_params_30_fromdata(RSA_PSS_PARAMS_30 *pss_params,
int *defaults_set,
const OSSL_PARAM params[],
OSSL_LIB_CTX *libctx);

View File

@ -23,6 +23,9 @@ int ossl_DER_w_RSASSA_PSS_params(WPACKET *pkt, int tag,
const RSA_PSS_PARAMS_30 *pss);
/* Subject Public Key Info */
int ossl_DER_w_algorithmIdentifier_RSA(WPACKET *pkt, int tag, RSA *rsa);
int ossl_DER_w_algorithmIdentifier_RSA_PSS(WPACKET *pkt, int tag,
int rsa_type,
const RSA_PSS_PARAMS_30 *pss);
/* Signature */
int ossl_DER_w_algorithmIdentifier_MDWithRSAEncryption(WPACKET *pkt, int tag,
RSA *rsa, int mdnid);
int mdnid);

View File

@ -52,18 +52,16 @@
* around that, we make them non-static, and declare them an extra time to
* avoid compilers complaining about definitions without declarations.
*/
#if 0 /* Currently unused */
#define DER_AID_V_sha1Identifier \
DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
DER_OID_SZ_id_sha1 + DER_SZ_NULL, \
DER_OID_V_id_sha1, \
DER_V_NULL
extern const unsigned char der_aid_sha1Identifier[];
const unsigned char der_aid_sha1Identifier[] = {
extern const unsigned char ossl_der_aid_sha1Identifier[];
const unsigned char ossl_der_aid_sha1Identifier[] = {
DER_AID_V_sha1Identifier
};
#define DER_AID_SZ_sha1Identifier sizeof(der_aid_sha1Identifier)
#endif
#define DER_AID_SZ_sha1Identifier sizeof(ossl_der_aid_sha1Identifier)
#define DER_AID_V_sha224Identifier \
DER_P_SEQUENCE|DER_F_CONSTRUCTED, \
@ -277,8 +275,8 @@ static int DER_w_MaskGenAlgorithm(WPACKET *pkt, int tag,
#define OAEP_PSS_MD_CASE(name, var) \
case NID_##name: \
var = ossl_der_oid_id_##name; \
var##_sz = sizeof(ossl_der_oid_id_##name); \
var = ossl_der_aid_##name##Identifier; \
var##_sz = sizeof(ossl_der_aid_##name##Identifier); \
break;
int ossl_DER_w_RSASSA_PSS_params(WPACKET *pkt, int tag,
@ -356,14 +354,15 @@ int ossl_DER_w_RSASSA_PSS_params(WPACKET *pkt, int tag,
var##_oid_sz = sizeof(ossl_der_oid_##name); \
break;
int ossl_DER_w_algorithmIdentifier_RSA(WPACKET *pkt, int tag, RSA *rsa)
int ossl_DER_w_algorithmIdentifier_RSA_PSS(WPACKET *pkt, int tag,
int rsa_type,
const RSA_PSS_PARAMS_30 *pss)
{
int rsa_nid = NID_undef;
const unsigned char *rsa_oid = NULL;
size_t rsa_oid_sz = 0;
RSA_PSS_PARAMS_30 *pss_params = ossl_rsa_get0_pss_params_30(rsa);
switch (RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK)) {
switch (rsa_type) {
case RSA_FLAG_TYPE_RSA:
RSA_CASE(rsaEncryption, rsa);
case RSA_FLAG_TYPE_RSASSAPSS:
@ -375,8 +374,17 @@ int ossl_DER_w_algorithmIdentifier_RSA(WPACKET *pkt, int tag, RSA *rsa)
return ossl_DER_w_begin_sequence(pkt, tag)
&& (rsa_nid != NID_rsassaPss
|| ossl_rsa_pss_params_30_is_unrestricted(pss_params)
|| ossl_DER_w_RSASSA_PSS_params(pkt, -1, pss_params))
|| ossl_rsa_pss_params_30_is_unrestricted(pss)
|| ossl_DER_w_RSASSA_PSS_params(pkt, -1, pss))
&& ossl_DER_w_precompiled(pkt, -1, rsa_oid, rsa_oid_sz)
&& ossl_DER_w_end_sequence(pkt, tag);
}
int ossl_DER_w_algorithmIdentifier_RSA(WPACKET *pkt, int tag, RSA *rsa)
{
int rsa_type = RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK);
RSA_PSS_PARAMS_30 *pss_params = ossl_rsa_get0_pss_params_30(rsa);
return ossl_DER_w_algorithmIdentifier_RSA_PSS(pkt, tag, rsa_type,
pss_params);
}

View File

@ -29,7 +29,7 @@
break;
int ossl_DER_w_algorithmIdentifier_MDWithRSAEncryption(WPACKET *pkt, int tag,
RSA *rsa, int mdnid)
int mdnid)
{
const unsigned char *precompiled = NULL;
size_t precompiled_sz = 0;

View File

@ -56,11 +56,12 @@ static OSSL_FUNC_keymgmt_query_operation_name_fn rsa_query_operation_name;
DEFINE_STACK_OF(BIGNUM)
DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
static int pss_params_fromdata(RSA_PSS_PARAMS_30 *pss_params,
static int pss_params_fromdata(RSA_PSS_PARAMS_30 *pss_params, int *defaults_set,
const OSSL_PARAM params[], int rsa_type,
OSSL_LIB_CTX *libctx)
{
if (!ossl_rsa_pss_params_30_fromdata(pss_params, params, libctx))
if (!ossl_rsa_pss_params_30_fromdata(pss_params, defaults_set,
params, libctx))
return 0;
/* If not a PSS type RSA, sending us PSS parameters is wrong */
@ -153,6 +154,7 @@ static int rsa_import(void *keydata, int selection, const OSSL_PARAM params[])
RSA *rsa = keydata;
int rsa_type;
int ok = 1;
int pss_defaults_set = 0;
if (!ossl_prov_is_running() || rsa == NULL)
return 0;
@ -165,8 +167,10 @@ static int rsa_import(void *keydata, int selection, const OSSL_PARAM params[])
/* TODO(3.0) OAEP should bring on parameters as well */
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
ok = ok && pss_params_fromdata(ossl_rsa_get0_pss_params_30(rsa), params,
rsa_type, ossl_rsa_get0_libctx(rsa));
ok = ok && pss_params_fromdata(ossl_rsa_get0_pss_params_30(rsa),
&pss_defaults_set,
params, rsa_type,
ossl_rsa_get0_libctx(rsa));
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
ok = ok && ossl_rsa_fromdata(rsa, params);
@ -391,6 +395,7 @@ struct rsa_gen_ctx {
/* For PSS */
RSA_PSS_PARAMS_30 pss_params;
int pss_defaults_set;
/* For generation callback */
OSSL_CALLBACK *cb;
@ -470,8 +475,8 @@ static int rsa_gen_set_params(void *genctx, const OSSL_PARAM params[])
return 0;
/* Only attempt to get PSS parameters when generating an RSA-PSS key */
if (gctx->rsa_type == RSA_FLAG_TYPE_RSASSAPSS
&& !pss_params_fromdata(&gctx->pss_params, params, gctx->rsa_type,
gctx->libctx))
&& !pss_params_fromdata(&gctx->pss_params, &gctx->pss_defaults_set, params,
gctx->rsa_type, gctx->libctx))
return 0;
#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
/* Any ACVP test related parameters are copied into a params[] */

View File

@ -13,6 +13,7 @@
*/
#include "internal/deprecated.h"
#include "e_os.h" /* strcasecmp */
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/core_dispatch.h>
@ -86,11 +87,7 @@ typedef struct {
* by their Final function.
*/
unsigned int flag_allow_md : 1;
/* The Algorithm Identifier of the combined signature algorithm */
unsigned char aid_buf[128];
unsigned char *aid;
size_t aid_len;
unsigned int mgf1_md_set : 1;
/* main digest */
EVP_MD *md;
@ -102,6 +99,7 @@ typedef struct {
int pad_mode;
/* message digest for MGF1 */
EVP_MD *mgf1_md;
int mgf1_mdnid;
char mgf1_mdname[OSSL_MAX_NAME_SIZE]; /* Purely informational */
/* PSS salt length */
int saltlen;
@ -113,6 +111,9 @@ typedef struct {
} PROV_RSA_CTX;
/* True if PSS parameters are restricted */
#define rsa_pss_restricted(prsactx) (prsactx->min_saltlen != -1)
static size_t rsa_get_md_size(const PROV_RSA_CTX *prsactx)
{
if (prsactx->md != NULL)
@ -120,24 +121,37 @@ static size_t rsa_get_md_size(const PROV_RSA_CTX *prsactx)
return 0;
}
static int rsa_check_padding(int mdnid, int padding)
static int rsa_check_padding(const PROV_RSA_CTX *prsactx,
const char *mdname, const char *mgf1_mdname,
int mdnid)
{
if (padding == RSA_NO_PADDING) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE);
return 0;
}
if (padding == RSA_X931_PADDING) {
if (RSA_X931_hash_id(mdnid) == -1) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_X931_DIGEST);
switch(prsactx->pad_mode) {
case RSA_NO_PADDING:
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE);
return 0;
}
case RSA_X931_PADDING:
if (RSA_X931_hash_id(mdnid) == -1) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_X931_DIGEST);
return 0;
}
break;
case RSA_PKCS1_PSS_PADDING:
if (rsa_pss_restricted(prsactx))
if ((mdname != NULL && !EVP_MD_is_a(prsactx->md, mdname))
|| (mgf1_mdname != NULL
&& !EVP_MD_is_a(prsactx->mgf1_md, mgf1_mdname))) {
ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
return 0;
}
break;
default:
break;
}
return 1;
}
static int rsa_check_parameters(PROV_RSA_CTX *prsactx)
static int rsa_check_parameters(PROV_RSA_CTX *prsactx, int min_saltlen)
{
if (prsactx->pad_mode == RSA_PKCS1_PSS_PADDING) {
int max_saltlen;
@ -146,10 +160,11 @@ static int rsa_check_parameters(PROV_RSA_CTX *prsactx)
max_saltlen = RSA_size(prsactx->rsa) - EVP_MD_size(prsactx->md);
if ((RSA_bits(prsactx->rsa) & 0x7) == 1)
max_saltlen--;
if (prsactx->min_saltlen < 0 || prsactx->min_saltlen > max_saltlen) {
if (min_saltlen < 0 || min_saltlen > max_saltlen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH);
return 0;
}
prsactx->min_saltlen = min_saltlen;
}
return 1;
}
@ -176,8 +191,81 @@ static void *rsa_newctx(void *provctx, const char *propq)
return prsactx;
}
/* True if PSS parameters are restricted */
#define rsa_pss_restricted(prsactx) (prsactx->min_saltlen != -1)
static int rsa_pss_compute_saltlen(PROV_RSA_CTX *ctx)
{
int saltlen = ctx->saltlen;
if (saltlen == RSA_PSS_SALTLEN_DIGEST) {
saltlen = EVP_MD_size(ctx->md);
} else if (saltlen == RSA_PSS_SALTLEN_AUTO || saltlen == RSA_PSS_SALTLEN_MAX) {
saltlen = RSA_size(ctx->rsa) - EVP_MD_size(ctx->md) - 2;
if ((RSA_bits(ctx->rsa) & 0x7) == 1)
saltlen--;
}
if (saltlen < 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
return -1;
} else if (saltlen < ctx->min_saltlen) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL,
"minimum salt length: %d, actual salt length: %d",
ctx->min_saltlen, saltlen);
return -1;
}
return saltlen;
}
static unsigned char *rsa_generate_signature_aid(PROV_RSA_CTX *ctx,
unsigned char *aid_buf,
size_t buf_len,
size_t *aid_len)
{
WPACKET pkt;
unsigned char *aid = NULL;
int saltlen;
RSA_PSS_PARAMS_30 pss_params;
if (!WPACKET_init_der(&pkt, aid_buf, buf_len)) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
switch(ctx->pad_mode) {
case RSA_PKCS1_PADDING:
if (!ossl_DER_w_algorithmIdentifier_MDWithRSAEncryption(&pkt, -1,
ctx->mdnid)) {
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
goto cleanup;
}
break;
case RSA_PKCS1_PSS_PADDING:
saltlen = rsa_pss_compute_saltlen(ctx);
if (saltlen < 0)
goto cleanup;
if (!ossl_rsa_pss_params_30_set_defaults(&pss_params)
|| !ossl_rsa_pss_params_30_set_hashalg(&pss_params, ctx->mdnid)
|| !ossl_rsa_pss_params_30_set_maskgenhashalg(&pss_params,
ctx->mgf1_mdnid)
|| !ossl_rsa_pss_params_30_set_saltlen(&pss_params, saltlen)
|| !ossl_DER_w_algorithmIdentifier_RSA_PSS(&pkt, -1,
RSA_FLAG_TYPE_RSASSAPSS,
&pss_params)) {
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
goto cleanup;
}
break;
default:
ERR_raise_data(ERR_LIB_PROV, ERR_R_UNSUPPORTED,
"Algorithm ID generation");
goto cleanup;
}
if (WPACKET_finish(&pkt)) {
WPACKET_get_total_written(&pkt, aid_len);
aid = WPACKET_get_curr(&pkt);
}
cleanup:
WPACKET_cleanup(&pkt);
return aid;
}
static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname,
const char *mdprops)
@ -186,7 +274,6 @@ static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname,
mdprops = ctx->propq;
if (mdname != NULL) {
WPACKET pkt;
EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN);
int md_nid = digest_rsa_sign_get_md_nid(md, sha1_allowed);
@ -194,7 +281,7 @@ static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname,
if (md == NULL
|| md_nid == NID_undef
|| !rsa_check_padding(md_nid, ctx->pad_mode)
|| !rsa_check_padding(ctx, mdname, NULL, md_nid)
|| mdname_len >= sizeof(ctx->mdname)) {
if (md == NULL)
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
@ -209,27 +296,20 @@ static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname,
return 0;
}
if (!ctx->mgf1_md_set) {
if (!EVP_MD_up_ref(md)) {
EVP_MD_free(md);
return 0;
}
EVP_MD_free(ctx->mgf1_md);
ctx->mgf1_md = md;
ctx->mgf1_mdnid = md_nid;
OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname));
}
EVP_MD_CTX_free(ctx->mdctx);
EVP_MD_free(ctx->md);
/*
* TODO(3.0) Should we care about DER writing errors?
* All it really means is that for some reason, there's no
* AlgorithmIdentifier to be had (consider RSA with MD5-SHA1),
* but the operation itself is still valid, just as long as it's
* not used to construct anything that needs an AlgorithmIdentifier.
*/
ctx->aid_len = 0;
if (WPACKET_init_der(&pkt, ctx->aid_buf, sizeof(ctx->aid_buf))
&& ossl_DER_w_algorithmIdentifier_MDWithRSAEncryption(&pkt, -1,
ctx->rsa,
md_nid)
&& WPACKET_finish(&pkt)) {
WPACKET_get_total_written(&pkt, &ctx->aid_len);
ctx->aid = WPACKET_get_curr(&pkt);
}
WPACKET_cleanup(&pkt);
ctx->mdctx = NULL;
ctx->md = md;
ctx->mdnid = md_nid;
@ -244,33 +324,37 @@ static int rsa_setup_mgf1_md(PROV_RSA_CTX *ctx, const char *mdname,
{
size_t len;
EVP_MD *md = NULL;
int mdnid;
if (mdprops == NULL)
mdprops = ctx->propq;
if (ctx->mgf1_mdname[0] != '\0')
EVP_MD_free(ctx->mgf1_md);
if ((md = EVP_MD_fetch(ctx->libctx, mdname, mdprops)) == NULL) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
"%s could not be fetched", mdname);
return 0;
}
/* The default for mgf1 is SHA1 - so allow SHA1 */
if (digest_rsa_sign_get_md_nid(md, 1) == NID_undef) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
"digest=%s", mdname);
if ((mdnid = digest_rsa_sign_get_md_nid(md, 1)) == NID_undef
|| !rsa_check_padding(ctx, NULL, mdname, mdnid)) {
if (mdnid == NID_undef)
ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
"digest=%s", mdname);
EVP_MD_free(md);
return 0;
}
ctx->mgf1_md = md;
len = OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname));
if (len >= sizeof(ctx->mgf1_mdname)) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
"%s exceeds name buffer length", mdname);
EVP_MD_free(md);
return 0;
}
EVP_MD_free(ctx->mgf1_md);
ctx->mgf1_md = md;
ctx->mgf1_mdnid = mdnid;
ctx->mgf1_md_set = 1;
return 1;
}
@ -317,7 +401,6 @@ static int rsa_signverify_init(void *vprsactx, void *vrsa, int operation)
mdname = ossl_rsa_oaeppss_nid2name(md_nid);
mgf1mdname = ossl_rsa_oaeppss_nid2name(mgf1md_nid);
prsactx->min_saltlen = min_saltlen;
if (mdname == NULL) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
@ -346,9 +429,10 @@ static int rsa_signverify_init(void *vprsactx, void *vrsa, int operation)
}
prsactx->saltlen = min_saltlen;
return rsa_setup_md(prsactx, mdname, prsactx->propq)
&& rsa_setup_mgf1_md(prsactx, mgf1mdname, prsactx->propq)
&& rsa_check_parameters(prsactx);
/* call rsa_setup_mgf1_md before rsa_setup_md to avoid duplication */
return rsa_setup_mgf1_md(prsactx, mgf1mdname, prsactx->propq)
&& rsa_setup_md(prsactx, mdname, prsactx->propq)
&& rsa_check_parameters(prsactx, min_saltlen);
}
}
@ -727,8 +811,12 @@ static int rsa_digest_signverify_init(void *vprsactx, const char *mdname,
if (prsactx != NULL)
prsactx->flag_allow_md = 0;
if (!rsa_signverify_init(vprsactx, vrsa, operation)
|| !rsa_setup_md(prsactx, mdname, NULL)) /* TODO RL */
if (!rsa_signverify_init(vprsactx, vrsa, operation))
return 0;
if (mdname != NULL
/* was rsa_setup_md already called in rsa_signverify_init()? */
&& (mdname[0] == '\0' || strcasecmp(prsactx->mdname, mdname) != 0)
&& !rsa_setup_md(prsactx, mdname, prsactx->propq))
return 0;
prsactx->mdctx = EVP_MD_CTX_new();
@ -912,9 +1000,17 @@ static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
return 0;
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
if (p != NULL
&& !OSSL_PARAM_set_octet_string(p, prsactx->aid, prsactx->aid_len))
return 0;
if (p != NULL) {
/* The Algorithm Identifier of the combined signature algorithm */
unsigned char aid_buf[128];
unsigned char *aid;
size_t aid_len;
aid = rsa_generate_signature_aid(prsactx, aid_buf,
sizeof(aid_buf), &aid_len);
if (aid == NULL || !OSSL_PARAM_set_octet_string(p, aid, aid_len))
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PAD_MODE);
if (p != NULL)
@ -1011,6 +1107,12 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
{
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
const OSSL_PARAM *p;
int pad_mode = prsactx->pad_mode;
int saltlen = prsactx->saltlen;
char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = NULL;
char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = NULL;
char mgf1mdname[OSSL_MAX_NAME_SIZE] = "", *pmgf1mdname = NULL;
char mgf1mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmgf1mdprops = NULL;
if (prsactx == NULL || params == NULL)
return 0;
@ -1020,37 +1122,24 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
if (p != NULL && !prsactx->flag_allow_md)
return 0;
if (p != NULL) {
char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = mdname;
char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = mdprops;
const OSSL_PARAM *propsp =
OSSL_PARAM_locate_const(params,
OSSL_SIGNATURE_PARAM_PROPERTIES);
pmdname = mdname;
if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname)))
return 0;
if (propsp == NULL)
pmdprops = NULL;
else if (!OSSL_PARAM_get_utf8_string(propsp,
&pmdprops, sizeof(mdprops)))
return 0;
if (rsa_pss_restricted(prsactx)) {
/* TODO(3.0) figure out what to do for prsactx->md == NULL */
if (prsactx->md == NULL || EVP_MD_is_a(prsactx->md, mdname))
return 1;
ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
return 0;
if (propsp != NULL) {
pmdprops = mdprops;
if (!OSSL_PARAM_get_utf8_string(propsp,
&pmdprops, sizeof(mdprops)))
return 0;
}
/* non-PSS code follows */
if (!rsa_setup_md(prsactx, mdname, pmdprops))
return 0;
}
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PAD_MODE);
if (p != NULL) {
int pad_mode = 0;
const char *err_extra_text = NULL;
switch (p->data_type) {
@ -1092,10 +1181,6 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
"PSS padding only allowed for sign and verify operations";
goto bad_pad;
}
if (prsactx->md == NULL
&& !rsa_setup_md(prsactx, RSA_DEFAULT_DIGEST_NAME, NULL)) {
return 0;
}
break;
case RSA_PKCS1_PADDING:
err_extra_text = "PKCS#1 padding not allowed with RSA-PSS";
@ -1124,16 +1209,11 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
err_extra_text);
return 0;
}
if (!rsa_check_padding(prsactx->mdnid, pad_mode))
return 0;
prsactx->pad_mode = pad_mode;
}
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN);
if (p != NULL) {
int saltlen;
if (prsactx->pad_mode != RSA_PKCS1_PSS_PADDING) {
if (pad_mode != RSA_PKCS1_PSS_PADDING) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED,
"PSS saltlen can only be specified if "
"PSS padding has been specified first");
@ -1199,46 +1279,49 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
}
}
}
prsactx->saltlen = saltlen;
}
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST);
if (p != NULL) {
char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = mdname;
char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = mdprops;
const OSSL_PARAM *propsp =
OSSL_PARAM_locate_const(params,
OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES);
if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname)))
pmgf1mdname = mgf1mdname;
if (!OSSL_PARAM_get_utf8_string(p, &pmgf1mdname, sizeof(mgf1mdname)))
return 0;
if (propsp == NULL)
pmdprops = NULL;
else if (!OSSL_PARAM_get_utf8_string(propsp,
&pmdprops, sizeof(mdprops)))
return 0;
if (propsp != NULL) {
pmgf1mdprops = mgf1mdprops;
if (!OSSL_PARAM_get_utf8_string(propsp,
&pmgf1mdprops, sizeof(mgf1mdprops)))
return 0;
}
if (prsactx->pad_mode != RSA_PKCS1_PSS_PADDING) {
if (pad_mode != RSA_PKCS1_PSS_PADDING) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MGF1_MD);
return 0;
}
if (rsa_pss_restricted(prsactx)) {
/* TODO(3.0) figure out what to do for prsactx->mgf1_md == NULL */
if (prsactx->mgf1_md == NULL
|| EVP_MD_is_a(prsactx->mgf1_md, mdname))
return 1;
ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
return 0;
}
/* non-PSS code follows */
if (!rsa_setup_mgf1_md(prsactx, mdname, pmdprops))
return 0;
}
prsactx->saltlen = saltlen;
prsactx->pad_mode = pad_mode;
if (prsactx->md == NULL && pmdname == NULL
&& pad_mode == RSA_PKCS1_PSS_PADDING)
pmdname = RSA_DEFAULT_DIGEST_NAME;
if (pmgf1mdname != NULL
&& !rsa_setup_mgf1_md(prsactx, pmgf1mdname, pmgf1mdprops))
return 0;
if (pmdname != NULL) {
if (!rsa_setup_md(prsactx, pmdname, pmdprops))
return 0;
} else {
if (!rsa_check_padding(prsactx, NULL, NULL, prsactx->mdnid))
return 0;
}
return 1;
}

View File

@ -93,7 +93,7 @@ subtest "generating certificate requests with RSA" => sub {
};
subtest "generating certificate requests with RSA-PSS" => sub {
plan tests => 4;
plan tests => 12;
SKIP: {
skip "RSA is not supported by this OpenSSL build", 2
@ -104,7 +104,6 @@ subtest "generating certificate requests with RSA-PSS" => sub {
"-new", "-out", "testreq-rsapss.pem", "-utf8",
"-key", srctop_file("test", "testrsapss.pem")])),
"Generating request");
ok(run(app(["openssl", "req",
"-config", srctop_file("test", "test.cnf"),
"-verify", "-in", "testreq-rsapss.pem", "-noout"])),
@ -117,11 +116,60 @@ subtest "generating certificate requests with RSA-PSS" => sub {
"-sigopt", "rsa_pss_saltlen:-1",
"-key", srctop_file("test", "testrsapss.pem")])),
"Generating request");
ok(run(app(["openssl", "req",
"-config", srctop_file("test", "test.cnf"),
"-verify", "-in", "testreq-rsapss2.pem", "-noout"])),
"Verifying signature on request");
ok(run(app(["openssl", "req",
"-config", srctop_file("test", "test.cnf"),
"-new", "-out", "testreq-rsapssmand.pem", "-utf8",
"-sigopt", "rsa_padding_mode:pss",
"-key", srctop_file("test", "testrsapssmandatory.pem")])),
"Generating request");
ok(run(app(["openssl", "req",
"-config", srctop_file("test", "test.cnf"),
"-verify", "-in", "testreq-rsapssmand.pem", "-noout"])),
"Verifying signature on request");
ok(run(app(["openssl", "req",
"-config", srctop_file("test", "test.cnf"),
"-new", "-out", "testreq-rsapssmand2.pem", "-utf8",
"-sigopt", "rsa_pss_saltlen:100",
"-key", srctop_file("test", "testrsapssmandatory.pem")])),
"Generating request");
ok(run(app(["openssl", "req",
"-config", srctop_file("test", "test.cnf"),
"-verify", "-in", "testreq-rsapssmand2.pem", "-noout"])),
"Verifying signature on request");
ok(!run(app(["openssl", "req",
"-config", srctop_file("test", "test.cnf"),
"-new", "-out", "testreq-rsapss3.pem", "-utf8",
"-sigopt", "rsa_padding_mode:pkcs1",
"-key", srctop_file("test", "testrsapss.pem")])),
"Generating request with expected failure");
ok(!run(app(["openssl", "req",
"-config", srctop_file("test", "test.cnf"),
"-new", "-out", "testreq-rsapss3.pem", "-utf8",
"-sigopt", "rsa_pss_saltlen:-4",
"-key", srctop_file("test", "testrsapss.pem")])),
"Generating request with expected failure");
ok(!run(app(["openssl", "req",
"-config", srctop_file("test", "test.cnf"),
"-new", "-out", "testreq-rsapssmand3.pem", "-utf8",
"-sigopt", "rsa_pss_saltlen:10",
"-key", srctop_file("test", "testrsapssmandatory.pem")])),
"Generating request with expected failure");
ok(!run(app(["openssl", "req",
"-config", srctop_file("test", "test.cnf"),
"-new", "-out", "testreq-rsapssmand3.pem", "-utf8",
"-sha256",
"-key", srctop_file("test", "testrsapssmandatory.pem")])),
"Generating request with expected failure");
}
};

View File

@ -0,0 +1,29 @@
-----BEGIN PRIVATE KEY-----
MIIE7gIBADA9BgkqhkiG9w0BAQowMKANMAsGCWCGSAFlAwQCA6EaMBgGCSqGSIb3
DQEBCDALBglghkgBZQMEAgOiAwIBQASCBKgwggSkAgEAAoIBAQDdiLMYj8fgrXKB
dEC704hcfmeJebCyaZbYHBE/1YthJOptbhisBbNk4onKMITO6hkYOoH12rNxqwY5
d9J1Ray6SJETVHxYCKftJ1LlrUJGqpyRCAAff1LYjjGRyqcMzVItWffy2iCgKGud
uUqs9Og3wsVxUeXfTSGnLo1UevVc1qTKZJuDRWD2EItuwnFt7GA89IgGx8/liLsg
cdlnm81gGdDmNKxNGi3VeOaJqFWnP9CpL8iXybG7F32U9mgEdE+EYt8GhQfNLzjL
j17xfLl5K0SMqL8q+phas6Md0OmTl3Xg8Tupdoo/okAoYGXrv/sHDiV1YBSkXD4i
dbV42aUfAgMBAAECggEAEyEJrfZEYR85Avqh2FYksS/tCs7qNg2uC80opCVxWpsQ
bxCRqtD3M5/oHABih2dpcVEkBbGzyv3klLPHBX9VseQwOsYR0pw0u+KoYtK6JVX4
HQHe2Nlqsu5cU2V3VUCpducM5Ph21r2GxWDJlPO01ZPI7scOnWCQpln7tC7F3xU0
jNQ0SnFZ6SO4FrrBxOMjnIFiNMexxZt0fU7khy/dGck9aN4DtmQENcQkGdXj5xRv
lInh92mQ16yMCbEU8cslWaAwqRF/k/5QxoIwTXr8PqaWshH9TIAht0rvTilWpHPg
zpW6Pog/wGzVat3NeU3vBDYIUayHc6n3gbfJZDNxmQKBgQD41lAkxNsA89mYY7S9
5NkDJ1N1hKNwg+iEyCZJkjxUk+SymdO7U/iD27Hgn/XyXm4RC5aHYpXJSnuiOk7R
Z1Az1jjqLzPxsP72sWLORzGq82smYrK+iV2rhozWNlfVyazDkBcRRz2bLSESzgvO
JWD3K3pjvj8U9ZSUhz+zXo4sUwKBgQDj6TBTKGDb8Au8sUOC916GrIrUEq5SkMDT
A4CiD4fmvbdNs90AhD/mmqBw/dP3TbCPNmP8tGMUT0BDev6BoRKYOt+1XGYXt2de
P38teVU/ZUcAO2RGdMNSdWT5o9BCWQZ18qSoOR/QanckOnkhKCgU/wqSdIvBBRMQ
5e4qdI0qhQKBgB2MJTwYfADi88WaoU2jLPmo48oik926bBPISHOX/73zScbDaVbn
I61UmwyXMfczq1Iu1BMDa9HZHFEpJ07KO8XL/DoinMJoR/43Fgp0fbtU6DZIpfzm
Bs9lTLfrAAcMyYz3QSX2FaSleTXobZJu8dKnwQKzBn6QorH4VWIRKkStAoGBAIYL
M1nlaLpSf4S2OT/A376Ton9CkXaMHmy9JZ2rRsHmGPZBcB0Kq06k6PIrx8wuzEYe
tkX9jjx2tBQ8NY3mPzp7ffF766vNOaWL8O+86e+EUHMJe1uY9vv7gaz1tNog5BTg
5gjuuBBrXbFYFr/yj0hyDDTBCSU4J9OLeD1OGWzFAoGBAMGc9h8oLyA3rQEjIuVA
CuzgvZxOFPbtODFPcL4EQgAKLiKS+oZK0jONfCHaQB1AhIq8/nT/4suw7tWqYoKp
KGH/+8tKNodKZfZLjVp0k8gsehyMDz1002/RLMJyFRIJWa1BqEJs7v7XgWW3RcmC
PWznhdpNx3BYDSao5Ibl7I5E
-----END PRIVATE KEY-----