Skip to content

Commit a649547

Browse files
levittepaulidale
authored andcommitted
RSA: Better synchronisation between ASN1 PSS params and RSA_PSS_PARAMS_30
This is needed so RSA keys created from different code paths have a chance to compare as equal. Reviewed-by: Paul Dale <[email protected]> (Merged from openssl#12544)
1 parent 6c6b20d commit a649547

File tree

1 file changed

+98
-16
lines changed

1 file changed

+98
-16
lines changed

crypto/rsa/rsa_ameth.c

+98-16
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ static int rsa_cms_encrypt(CMS_RecipientInfo *ri);
3434
#endif
3535

3636
static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg);
37+
static int rsa_sync_to_pss_params_30(RSA *rsa);
3738

3839
/* Set any parameters associated with pkey */
3940
static int rsa_param_encode(const EVP_PKEY *pkey,
@@ -78,6 +79,8 @@ static int rsa_param_decode(RSA *rsa, const X509_ALGOR *alg)
7879
rsa->pss = rsa_pss_decode(alg);
7980
if (rsa->pss == NULL)
8081
return 0;
82+
if (!rsa_sync_to_pss_params_30(rsa))
83+
return 0;
8184
return 1;
8285
}
8386

@@ -118,6 +121,20 @@ static int rsa_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
118121
RSA_free(rsa);
119122
return 0;
120123
}
124+
125+
RSA_clear_flags(rsa, RSA_FLAG_TYPE_MASK);
126+
switch (pkey->ameth->pkey_id) {
127+
case EVP_PKEY_RSA:
128+
RSA_set_flags(rsa, RSA_FLAG_TYPE_RSA);
129+
break;
130+
case EVP_PKEY_RSA_PSS:
131+
RSA_set_flags(rsa, RSA_FLAG_TYPE_RSASSAPSS);
132+
break;
133+
default:
134+
/* Leave the type bits zero */
135+
break;
136+
}
137+
121138
if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa)) {
122139
RSA_free(rsa);
123140
return 0;
@@ -729,9 +746,34 @@ static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
729746
return rv;
730747
}
731748

732-
int rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
733-
const EVP_MD **pmgf1md, int *psaltlen)
749+
static int rsa_pss_verify_param(const EVP_MD **pmd, const EVP_MD **pmgf1md,
750+
int *psaltlen, int *ptrailerField)
734751
{
752+
if (psaltlen != NULL && *psaltlen < 0) {
753+
ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_SALT_LENGTH);
754+
return 0;
755+
}
756+
/*
757+
* low-level routines support only trailer field 0xbc (value 1) and
758+
* PKCS#1 says we should reject any other value anyway.
759+
*/
760+
if (ptrailerField != NULL && *ptrailerField != 1) {
761+
ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_TRAILER);
762+
return 0;
763+
}
764+
return 1;
765+
}
766+
767+
static int rsa_pss_get_param_unverified(const RSA_PSS_PARAMS *pss,
768+
const EVP_MD **pmd,
769+
const EVP_MD **pmgf1md,
770+
int *psaltlen, int *ptrailerField)
771+
{
772+
RSA_PSS_PARAMS_30 pss_params;
773+
774+
/* Get the defaults from the ONE place */
775+
(void)rsa_pss_params_30_set_defaults(&pss_params);
776+
735777
if (pss == NULL)
736778
return 0;
737779
*pmd = rsa_algor_to_md(pss->hashAlgorithm);
@@ -740,25 +782,65 @@ int rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
740782
*pmgf1md = rsa_algor_to_md(pss->maskHash);
741783
if (*pmgf1md == NULL)
742784
return 0;
743-
if (pss->saltLength) {
785+
if (pss->saltLength)
744786
*psaltlen = ASN1_INTEGER_get(pss->saltLength);
745-
if (*psaltlen < 0) {
746-
RSAerr(RSA_F_RSA_PSS_GET_PARAM, RSA_R_INVALID_SALT_LENGTH);
747-
return 0;
748-
}
749-
} else {
750-
*psaltlen = 20;
751-
}
787+
else
788+
*psaltlen = rsa_pss_params_30_saltlen(&pss_params);
789+
if (pss->trailerField)
790+
*ptrailerField = ASN1_INTEGER_get(pss->trailerField);
791+
else
792+
*ptrailerField = rsa_pss_params_30_trailerfield(&pss_params);;
793+
794+
return 1;
795+
}
752796

797+
int rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
798+
const EVP_MD **pmgf1md, int *psaltlen)
799+
{
753800
/*
754-
* low-level routines support only trailer field 0xbc (value 1) and
755-
* PKCS#1 says we should reject any other value anyway.
801+
* Callers do not care about the trailer field, and yet, we must
802+
* pass it from get_param to verify_param, since the latter checks
803+
* its value.
804+
*
805+
* When callers start caring, it's a simple thing to add another
806+
* argument to this function.
756807
*/
757-
if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) {
758-
RSAerr(RSA_F_RSA_PSS_GET_PARAM, RSA_R_INVALID_TRAILER);
759-
return 0;
760-
}
808+
int trailerField = 0;
809+
810+
return rsa_pss_get_param_unverified(pss, pmd, pmgf1md, psaltlen,
811+
&trailerField)
812+
&& rsa_pss_verify_param(pmd, pmgf1md, psaltlen, &trailerField);
813+
}
814+
815+
static int rsa_sync_to_pss_params_30(RSA *rsa)
816+
{
817+
if (rsa != NULL && rsa->pss != NULL) {
818+
const EVP_MD *md = NULL, *mgf1md = NULL;
819+
int md_nid, mgf1md_nid, saltlen, trailerField;
820+
RSA_PSS_PARAMS_30 pss_params;
761821

822+
/*
823+
* We don't care about the validity of the fields here, we just
824+
* want to synchronise values. Verifying here makes it impossible
825+
* to even read a key with invalid values, making it hard to test
826+
* a bad situation.
827+
*
828+
* Other routines use rsa_pss_get_param(), so the values will be
829+
* checked, eventually.
830+
*/
831+
if (!rsa_pss_get_param_unverified(rsa->pss, &md, &mgf1md,
832+
&saltlen, &trailerField))
833+
return 0;
834+
md_nid = EVP_MD_type(md);
835+
mgf1md_nid = EVP_MD_type(mgf1md);
836+
if (!rsa_pss_params_30_set_defaults(&pss_params)
837+
|| !rsa_pss_params_30_set_hashalg(&pss_params, md_nid)
838+
|| !rsa_pss_params_30_set_maskgenhashalg(&pss_params, mgf1md_nid)
839+
|| !rsa_pss_params_30_set_saltlen(&pss_params, saltlen)
840+
|| !rsa_pss_params_30_set_trailerfield(&pss_params, trailerField))
841+
return 0;
842+
rsa->pss_params = pss_params;
843+
}
762844
return 1;
763845
}
764846

0 commit comments

Comments
 (0)