summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Mraz <tomas@openssl.org>2021-01-29 17:02:32 +0100
committerTomas Mraz <tomas@openssl.org>2021-02-05 14:04:59 +0100
commitbbde8566191e5851f4418cbb8acb0d50b16170d8 (patch)
tree0f8ff9ecdc3f3c3f57a865c8b659da89e4a14d51
parent26372a4d44f0b4ef5423228b8bf975a5a7c814cb (diff)
downloadopenssl-new-bbde8566191e5851f4418cbb8acb0d50b16170d8.tar.gz
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)
-rw-r--r--crypto/rsa/rsa_ameth.c4
-rw-r--r--crypto/rsa/rsa_backend.c8
-rw-r--r--crypto/rsa/rsa_pss.c4
-rw-r--r--include/crypto/rsa.h1
-rw-r--r--providers/common/der/der_rsa.h.in5
-rw-r--r--providers/common/der/der_rsa_key.c32
-rw-r--r--providers/common/der/der_rsa_sig.c2
-rw-r--r--providers/implementations/keymgmt/rsa_kmgmt.c17
-rw-r--r--providers/implementations/signature/rsa.c295
-rw-r--r--test/recipes/25-test_req.t54
-rw-r--r--test/testrsapssmandatory.pem29
11 files changed, 318 insertions, 133 deletions
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
index 852facf577..e2dec1c98d 100644
--- a/crypto/rsa/rsa_ameth.c
+++ b/crypto/rsa/rsa_ameth.c
@@ -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) {
diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c
index 2f430b34d4..84f070a7ce 100644
--- a/crypto/rsa/rsa_backend.c
+++ b/crypto/rsa/rsa_backend.c
@@ -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);
diff --git a/crypto/rsa/rsa_pss.c b/crypto/rsa/rsa_pss.c
index 1b73cbb0f6..3a92ed04dd 100644
--- a/crypto/rsa/rsa_pss.c
+++ b/crypto/rsa/rsa_pss.c
@@ -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)
diff --git a/include/crypto/rsa.h b/include/crypto/rsa.h
index cb53b5dde6..599978dc3b 100644
--- a/include/crypto/rsa.h
+++ b/include/crypto/rsa.h
@@ -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);
diff --git a/providers/common/der/der_rsa.h.in b/providers/common/der/der_rsa.h.in
index 412d5bbe7f..733b9d60d6 100644
--- a/providers/common/der/der_rsa.h.in
+++ b/providers/common/der/der_rsa.h.in
@@ -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);
diff --git a/providers/common/der/der_rsa_key.c b/providers/common/der/der_rsa_key.c
index 1cc5874290..70b8edb63b 100644
--- a/providers/common/der/der_rsa_key.c
+++ b/providers/common/der/der_rsa_key.c
@@ -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);
+}
diff --git a/providers/common/der/der_rsa_sig.c b/providers/common/der/der_rsa_sig.c
index 1ff9bf789b..94ed60b69f 100644
--- a/providers/common/der/der_rsa_sig.c
+++ b/providers/common/der/der_rsa_sig.c
@@ -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;
diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c
index 9f783c56d8..64779ca6be 100644
--- a/providers/implementations/keymgmt/rsa_kmgmt.c
+++ b/providers/implementations/keymgmt/rsa_kmgmt.c
@@ -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[] */
diff --git a/providers/implementations/signature/rsa.c b/providers/implementations/signature/rsa.c
index 98ebf6b243..e61d8ab04e 100644
--- a/providers/implementations/signature/rsa.c
+++ b/providers/implementations/signature/rsa.c
@@ -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;
- }
+ 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;
- /* non-PSS code follows */
- if (!rsa_setup_mgf1_md(prsactx, mdname, pmdprops))
+ 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;
}
diff --git a/test/recipes/25-test_req.t b/test/recipes/25-test_req.t
index 3f0d9f59e7..ab6c6e681b 100644
--- a/test/recipes/25-test_req.t
+++ b/test/recipes/25-test_req.t
@@ -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");
}
};
diff --git a/test/testrsapssmandatory.pem b/test/testrsapssmandatory.pem
new file mode 100644
index 0000000000..d01ae82c88
--- /dev/null
+++ b/test/testrsapssmandatory.pem
@@ -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-----