Dear OpenSSL team and all, finally, here's my patch (against today's 1.1 snapshot) for verification of X.509 certificates using an RSASSA-PSS signature. I believe it is fairly complete in terms of checking parameters.
The patch follows the idea that I outlined in previous posts - two new ASN.1 objects for pss, mgf1 - in obj_xref.txt, pss uses digest undef -> verify routine has to determine the digest by itself - ASN1_item_verify() uses EVP_DigestVerify... API - rsa_st gets two new elements - param_decode method for rsa parses rsa key's parameters in the certificate - at verification time, pss parameters are copied into EVP_PKEY_CTX This time, I really do hope to get some feedback. Reviewing this won't be wasted time, I'm happy to improve the code until it is ready for merging. As such pss certificates are now being deployed by the millions for digital pay-tv in Europe (www.ci-plus.com), I feel that OpenSSL should support them. Best regards, Martin
diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c index d9332ee..aed0fdb 100644 --- a/crypto/asn1/a_verify.c +++ b/crypto/asn1/a_verify.c @@ -134,14 +134,15 @@ err: int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey) { - EVP_MD_CTX ctx; - const EVP_MD *type = NULL; + EVP_MD_CTX mctx; + const EVP_MD *md = NULL; + unsigned char *buf_in=NULL; int ret= -1,inl; int mdnid, pknid; - EVP_MD_CTX_init(&ctx); + EVP_MD_CTX_init(&mctx); /* Convert signature OID into digest and public key OIDs */ if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) @@ -149,12 +150,7 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signat ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); goto err; } - type=EVP_get_digestbynid(mdnid); - if (type == NULL) - { - ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); - goto err; - } + md=EVP_get_digestbynid(mdnid); /* md == NULL is no longer an error */ /* Check public key OID matches public key type */ if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) @@ -162,8 +158,39 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signat ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_WRONG_PUBLIC_KEY_TYPE); goto err; } - - if (!EVP_VerifyInit_ex(&ctx,type, NULL)) + if (pkey->ameth->param_decode && a) + { + int plen; + + /* this is ok for a->parameter==NULL, result is plen=0 */ + plen = i2d_ASN1_TYPE(a->parameter, NULL); + if (plen > 0) + { + const unsigned char *cp; + unsigned char *p; + unsigned char *pder=NULL; + int ok; + + pder = (unsigned char *)OPENSSL_malloc(plen); + if (pder == NULL) + { + ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_MALLOC_FAILURE); + goto err; + } + + /* call i2d_...() routines like in pem_pkey.c */ + p = pder; + plen = i2d_ASN1_TYPE(a->parameter, &p); + cp = pder; + + ok = pkey->ameth->param_decode(pkey, &cp, plen); + OPENSSL_free(pder); + if (!ok) + goto err; + } + } + + if (!EVP_DigestVerifyInit(&mctx, NULL,md, NULL, pkey)) { ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB); ret=0; @@ -178,7 +205,7 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signat goto err; } - if (!EVP_VerifyUpdate(&ctx,(unsigned char *)buf_in,inl)) + if (!EVP_DigestVerifyUpdate(&mctx,(unsigned char *)buf_in,inl)) { ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB); ret=0; @@ -188,19 +215,19 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signat OPENSSL_cleanse(buf_in,(unsigned int)inl); OPENSSL_free(buf_in); - if (EVP_VerifyFinal(&ctx,(unsigned char *)signature->data, - (unsigned int)signature->length,pkey) <= 0) + if (EVP_DigestVerifyFinal(&mctx,(unsigned char *)signature->data, + (unsigned int)signature->length) <= 0) { ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB); ret=0; goto err; } - /* we don't need to zero the 'ctx' because we just checked + /* we don't need to zero the 'mctx' because we just checked * public information */ - /* memset(&ctx,0,sizeof(ctx)); */ + /* memset(&mctx,0,sizeof(ctx)); */ ret=1; err: - EVP_MD_CTX_cleanup(&ctx); + EVP_MD_CTX_cleanup(&mctx); return(ret); } diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h index 9064164..344cc03 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h @@ -1038,6 +1038,9 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, #define EVP_PKEY_CTRL_CMS_DECRYPT 10 #define EVP_PKEY_CTRL_CMS_SIGN 11 +#define EVP_PKEY_CTRL_PARAM_SET_FROM_PKEY 20 +#define EVP_PKEY_CTRL_GET_DIGEST 21 + #define EVP_PKEY_ALG_CTRL 0x1000 diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c index f0b7f95..170f6a9 100644 --- a/crypto/evp/m_sigver.c +++ b/crypto/evp/m_sigver.c @@ -72,19 +72,6 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, if (ctx->pctx == NULL) return 0; - if (type == NULL) - { - int def_nid; - if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0) - type = EVP_get_digestbynid(def_nid); - } - - if (type == NULL) - { - EVPerr(EVP_F_DO_SIGVER_INIT, EVP_R_NO_DEFAULT_DIGEST); - return 0; - } - if (ver) { if (ctx->pctx->pmeth->verifyctx_init) @@ -107,6 +94,28 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, else if (EVP_PKEY_sign_init(ctx->pctx) <= 0) return 0; } + + if (type == NULL) + { + if (EVP_PKEY_CTX_ctrl(ctx->pctx, -1, ctx->pctx->operation, + EVP_PKEY_CTRL_PARAM_SET_FROM_PKEY, 0, pkey)) + { + EVP_PKEY_CTX_ctrl(ctx->pctx, -1, ctx->pctx->operation, + EVP_PKEY_CTRL_GET_DIGEST, 0, &type); + } + else + { + int def_nid; + if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0) + type = EVP_get_digestbynid(def_nid); + } + } + if (type == NULL) + { + EVPerr(EVP_F_DO_SIGVER_INIT, EVP_R_NO_DEFAULT_DIGEST); + return 0; + } + if (EVP_PKEY_CTX_set_signature_md(ctx->pctx, type) <= 0) return 0; if (pctx) diff --git a/crypto/objects/o_names.c b/crypto/objects/o_names.c index 84380a9..f96352f 100644 --- a/crypto/objects/o_names.c +++ b/crypto/objects/o_names.c @@ -159,6 +159,10 @@ const char *OBJ_NAME_get(const char *name, int type) if (name == NULL) return(NULL); if ((names_lh == NULL) && !OBJ_NAME_init()) return(NULL); + /* we have to treat the undef case specially because + several digests (mainly from engines) register themselves with + name==undef */ + if (OBJ_sn2nid(name) == NID_undef) return(NULL); alias=type&OBJ_NAME_ALIAS; type&= ~OBJ_NAME_ALIAS; diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h index cbccf5a..be5fd90 100644 --- a/crypto/objects/obj_dat.h +++ b/crypto/objects/obj_dat.h @@ -62,12 +62,12 @@ * [including the GNU Public Licence.] */ -#define NUM_NID 894 -#define NUM_SN 887 -#define NUM_LN 887 -#define NUM_OBJ 841 +#define NUM_NID 896 +#define NUM_SN 889 +#define NUM_LN 889 +#define NUM_OBJ 843 -static const unsigned char lvalues[5835]={ +static const unsigned char lvalues[5853]={ 0x00, /* [ 0] OBJ_undef */ 0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 1] OBJ_rsadsi */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 7] OBJ_pkcs */ @@ -909,6 +909,8 @@ static const unsigned char lvalues[5835]={ 0x55,0x04,0x35, /* [5817] OBJ_deltaRevocationList */ 0x55,0x04,0x36, /* [5820] OBJ_dmdName */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x09,/* [5823] OBJ_id_alg_PWRI_KEK */ +0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x08,/* [5834] OBJ_mgf1 */ +0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0A,/* [5843] OBJ_rsassaPss */ }; static const ASN1_OBJECT nid_objs[NUM_NID]={ @@ -2354,6 +2356,8 @@ static const ASN1_OBJECT nid_objs[NUM_NID]={ {"dmdName","dmdName",NID_dmdName,3,&(lvalues[5820]),0}, {"id-alg-PWRI-KEK","id-alg-PWRI-KEK",NID_id_alg_PWRI_KEK,11, &(lvalues[5823]),0}, +{"MGF1","mgf1",NID_mgf1,9,&(lvalues[5834]),0}, +{"RSASSA-PSS","rsassaPss",NID_rsassaPss,9,&(lvalues[5843]),0}, }; static const unsigned int sn_objs[NUM_SN]={ @@ -2454,6 +2458,7 @@ static const unsigned int sn_objs[NUM_SN]={ 4, /* "MD5" */ 114, /* "MD5-SHA1" */ 95, /* "MDC2" */ +894, /* "MGF1" */ 388, /* "Mail" */ 393, /* "NULL" */ 404, /* "NULL" */ @@ -2510,6 +2515,7 @@ static const unsigned int sn_objs[NUM_SN]={ 668, /* "RSA-SHA256" */ 669, /* "RSA-SHA384" */ 670, /* "RSA-SHA512" */ +895, /* "RSASSA-PSS" */ 777, /* "SEED-CBC" */ 779, /* "SEED-CFB" */ 776, /* "SEED-ECB" */ @@ -3811,6 +3817,7 @@ static const unsigned int ln_objs[NUM_LN]={ 602, /* "merchant initiated auth" */ 514, /* "message extensions" */ 51, /* "messageDigest" */ +894, /* "mgf1" */ 506, /* "mime-mhs-bodies" */ 505, /* "mime-mhs-headings" */ 488, /* "mobileTelephoneNumber" */ @@ -3910,6 +3917,7 @@ static const unsigned int ln_objs[NUM_LN]={ 6, /* "rsaEncryption" */ 644, /* "rsaOAEPEncryptionSET" */ 377, /* "rsaSignature" */ +895, /* "rsassaPss" */ 124, /* "run length compression" */ 482, /* "sOARecord" */ 155, /* "safeContentsBag" */ @@ -4725,6 +4733,8 @@ static const unsigned int obj_objs[NUM_OBJ]={ 8, /* OBJ_md5WithRSAEncryption 1 2 840 113549 1 1 4 */ 65, /* OBJ_sha1WithRSAEncryption 1 2 840 113549 1 1 5 */ 644, /* OBJ_rsaOAEPEncryptionSET 1 2 840 113549 1 1 6 */ +894, /* OBJ_mgf1 1 2 840 113549 1 1 8 */ +895, /* OBJ_rsassaPss 1 2 840 113549 1 1 10 */ 668, /* OBJ_sha256WithRSAEncryption 1 2 840 113549 1 1 11 */ 669, /* OBJ_sha384WithRSAEncryption 1 2 840 113549 1 1 12 */ 670, /* OBJ_sha512WithRSAEncryption 1 2 840 113549 1 1 13 */ diff --git a/crypto/objects/obj_mac.h b/crypto/objects/obj_mac.h index a432663..13c8a96 100644 --- a/crypto/objects/obj_mac.h +++ b/crypto/objects/obj_mac.h @@ -580,6 +580,16 @@ #define NID_sha1WithRSAEncryption 65 #define OBJ_sha1WithRSAEncryption OBJ_pkcs1,5L +#define SN_mgf1 "MGF1" +#define LN_mgf1 "mgf1" +#define NID_mgf1 894 +#define OBJ_mgf1 OBJ_pkcs1,8L + +#define SN_rsassaPss "RSASSA-PSS" +#define LN_rsassaPss "rsassaPss" +#define NID_rsassaPss 895 +#define OBJ_rsassaPss OBJ_pkcs1,10L + #define SN_sha256WithRSAEncryption "RSA-SHA256" #define LN_sha256WithRSAEncryption "sha256WithRSAEncryption" #define NID_sha256WithRSAEncryption 668 diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num index 65ca66f..108fd4f 100644 --- a/crypto/objects/obj_mac.num +++ b/crypto/objects/obj_mac.num @@ -891,3 +891,5 @@ supportedAlgorithms 890 deltaRevocationList 891 dmdName 892 id_alg_PWRI_KEK 893 +mgf1 894 +rsassaPss 895 diff --git a/crypto/objects/obj_xref.h b/crypto/objects/obj_xref.h index d5b9b8e..e23938c 100644 --- a/crypto/objects/obj_xref.h +++ b/crypto/objects/obj_xref.h @@ -38,10 +38,12 @@ static const nid_triple sigoid_srt[] = {NID_id_GostR3411_94_with_GostR3410_94, NID_id_GostR3411_94, NID_id_GostR3410_94}, {NID_id_GostR3411_94_with_GostR3410_94_cc, NID_id_GostR3411_94, NID_id_GostR3410_94_cc}, {NID_id_GostR3411_94_with_GostR3410_2001_cc, NID_id_GostR3411_94, NID_id_GostR3410_2001_cc}, + {NID_rsassaPss, NID_undef, NID_rsaEncryption}, }; static const nid_triple * const sigoid_srt_xref[] = { + &sigoid_srt[29], &sigoid_srt[17], &sigoid_srt[18], &sigoid_srt[0], diff --git a/crypto/objects/obj_xref.txt b/crypto/objects/obj_xref.txt index e45b3d3..ab69e79 100644 --- a/crypto/objects/obj_xref.txt +++ b/crypto/objects/obj_xref.txt @@ -6,6 +6,7 @@ md2WithRSAEncryption md2 rsaEncryption md5WithRSAEncryption md5 rsaEncryption shaWithRSAEncryption sha rsaEncryption sha1WithRSAEncryption sha1 rsaEncryption +rsassaPss undef rsaEncryption md4WithRSAEncryption md4 rsaEncryption sha256WithRSAEncryption sha256 rsaEncryption sha384WithRSAEncryption sha384 rsaEncryption diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt index 97be877..56e156e 100644 --- a/crypto/objects/objects.txt +++ b/crypto/objects/objects.txt @@ -166,6 +166,8 @@ pkcs1 3 : RSA-MD4 : md4WithRSAEncryption pkcs1 4 : RSA-MD5 : md5WithRSAEncryption pkcs1 5 : RSA-SHA1 : sha1WithRSAEncryption # According to PKCS #1 version 2.1 +pkcs1 8 : MGF1 : mgf1 +pkcs1 10 : RSASSA-PSS : rsassaPss pkcs1 11 : RSA-SHA256 : sha256WithRSAEncryption pkcs1 12 : RSA-SHA384 : sha384WithRSAEncryption pkcs1 13 : RSA-SHA512 : sha512WithRSAEncryption diff --git a/crypto/rsa/rsa.h b/crypto/rsa/rsa.h index cf74343..8395fb0 100644 --- a/crypto/rsa/rsa.h +++ b/crypto/rsa/rsa.h @@ -158,6 +158,10 @@ struct rsa_st char *bignum_data; BN_BLINDING *blinding; BN_BLINDING *mt_blinding; + + /* PSS parameters */ + const EVP_MD *pssDigest; + int pssSaltlen; }; #ifndef OPENSSL_RSA_MAX_MODULUS_BITS @@ -300,6 +304,17 @@ const RSA_METHOD *RSA_null_method(void); DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPublicKey) DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPrivateKey) +typedef struct rsassaPssParams_st +{ + X509_ALGOR *hashAlgorithm; + X509_ALGOR *maskGenAlgorithm; + ASN1_INTEGER *saltLength; + ASN1_INTEGER *trailerField; +} RSASSA_PSS_PARAMS; + +DECLARE_ASN1_FUNCTIONS(RSASSA_PSS_PARAMS) + + #ifndef OPENSSL_NO_FP_API int RSA_print_fp(FILE *fp, const RSA *r,int offset); #endif @@ -445,6 +460,7 @@ void ERR_load_RSA_strings(void); #define RSA_F_RSA_VERIFY 119 #define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING 120 #define RSA_F_RSA_VERIFY_PKCS1_PSS 126 +#define RSA_F_RSA_PARAM_DECODE 150 /* Reason codes. */ #define RSA_R_ALGORITHM_MISMATCH 100 diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index 8c32098..e47294f 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -170,6 +170,103 @@ static void int_rsa_free(EVP_PKEY *pkey) RSA_free(pkey->pkey.rsa); } +static int rsa_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) + { + int ret=0; + RSASSA_PSS_PARAMS *pss=NULL; + int pssHashNid; + X509_ALGOR *mgf1HashAlg=NULL; + ASN1_OBJECT *algObj; + int ptype; + void *pval; + ASN1_STRING *pseq; + const unsigned char *pm; + + if (!pkey || pkey->type!=EVP_PKEY_RSA) + { + RSAerr(RSA_F_RSA_PARAM_DECODE, RSA_R_UNKNOWN_ALGORITHM_TYPE); + goto end; + } + if (!pder) + goto end; + + pss = d2i_RSASSA_PSS_PARAMS(NULL, pder, derlen); + if (!pss) + { + /* no pss parameters present (this is not an error) */ + pkey->pkey.rsa->pssDigest = NULL; + pkey->pkey.rsa->pssSaltlen = 0; + ret=1; + } + else + { + if (pss->hashAlgorithm) + { + X509_ALGOR_get0(&algObj, &ptype, NULL, pss->hashAlgorithm); + pssHashNid = OBJ_obj2nid(algObj); + pkey->pkey.rsa->pssDigest = EVP_get_digestbynid(pssHashNid); + if (ptype != V_ASN1_NULL) + goto end; + } + else + { + pssHashNid = NID_sha1; + pkey->pkey.rsa->pssDigest = EVP_get_digestbynid(pssHashNid); + } + + if (pss->maskGenAlgorithm) + { + X509_ALGOR_get0(&algObj, &ptype, &pval, pss->maskGenAlgorithm); + /* low-level routines support only MGF1 */ + if (OBJ_obj2nid(algObj) != NID_mgf1) + goto end; + + if (ptype == V_ASN1_SEQUENCE) + { + pseq = pval; + if (pseq == NULL) + goto end; + pm = pseq->data; + mgf1HashAlg = d2i_X509_ALGOR(NULL, &pm, pseq->length); + if (!mgf1HashAlg) goto end; + X509_ALGOR_get0(&algObj, &ptype, NULL, mgf1HashAlg); + /* low-level routines require pss hash algo == mgf1 hash algo */ + if (pssHashNid != OBJ_obj2nid(algObj)) + goto end; + if (ptype != V_ASN1_NULL) /* of mgf1HashAlg */ + goto end; + } + else if (ptype != V_ASN1_NULL) /* of pss->maskGenAlgorithm */ + goto end; + } + + if (pss->saltLength) + { + pkey->pkey.rsa->pssSaltlen = ASN1_INTEGER_get(pss->saltLength); + } + else + { + pkey->pkey.rsa->pssSaltlen = 20; + } + + /* low-level routines support only trailer field 0xbc (value 1) */ + if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) + goto end; + + ret=1; + } +end: + if (!ret && pkey && pkey->type==EVP_PKEY_RSA) + { + pkey->pkey.rsa->pssDigest = NULL; + pkey->pkey.rsa->pssSaltlen = 0; + } + if (pss) + RSASSA_PSS_PARAMS_free(pss); + if (mgf1HashAlg) + X509_ALGOR_free(mgf1HashAlg); + return(ret); + } static void update_buflen(const BIGNUM *b, size_t *pbuflen) { @@ -333,7 +430,8 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] = int_rsa_size, rsa_bits, - 0,0,0,0,0,0, + rsa_param_decode, + 0,0,0,0,0, int_rsa_free, rsa_pkey_ctrl, diff --git a/crypto/rsa/rsa_asn1.c b/crypto/rsa/rsa_asn1.c index 4efca8c..bfc16a0 100644 --- a/crypto/rsa/rsa_asn1.c +++ b/crypto/rsa/rsa_asn1.c @@ -61,6 +61,7 @@ #include <openssl/bn.h> #include <openssl/rsa.h> #include <openssl/asn1t.h> +#include <openssl/x509.h> /* Override the default free and new methods */ static int rsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, @@ -96,10 +97,20 @@ ASN1_SEQUENCE_cb(RSAPublicKey, rsa_cb) = { ASN1_SIMPLE(RSA, e, BIGNUM), } ASN1_SEQUENCE_END_cb(RSA, RSAPublicKey) +ASN1_SEQUENCE(RSASSA_PSS_PARAMS) = { + ASN1_OPT(RSASSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR), + ASN1_OPT(RSASSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR), + ASN1_OPT(RSASSA_PSS_PARAMS, saltLength, ASN1_INTEGER), + ASN1_OPT(RSASSA_PSS_PARAMS, trailerField, ASN1_INTEGER) +} ASN1_SEQUENCE_END(RSASSA_PSS_PARAMS) + + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPrivateKey, RSAPrivateKey) IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPublicKey, RSAPublicKey) +IMPLEMENT_ASN1_FUNCTIONS(RSASSA_PSS_PARAMS) + RSA *RSAPublicKey_dup(RSA *rsa) { return ASN1_item_dup(ASN1_ITEM_rptr(RSAPublicKey), rsa); diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index de45088..8810754 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -180,6 +180,8 @@ RSA *RSA_new_method(ENGINE *engine) ret->_method_mod_q=NULL; ret->blinding=NULL; ret->mt_blinding=NULL; + ret->pssDigest=NULL; + ret->pssSaltlen=0; ret->bignum_data=NULL; ret->flags=ret->meth->flags; if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data)) @@ -243,6 +245,7 @@ void RSA_free(RSA *r) if (r->iqmp != NULL) BN_clear_free(r->iqmp); if (r->blinding != NULL) BN_BLINDING_free(r->blinding); if (r->mt_blinding != NULL) BN_BLINDING_free(r->mt_blinding); + /* no need to free pssDigest, it's just a reference */ if (r->bignum_data != NULL) OPENSSL_free_locked(r->bignum_data); OPENSSL_free(r); } diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c index 297e17c..a983555 100644 --- a/crypto/rsa/rsa_pmeth.c +++ b/crypto/rsa/rsa_pmeth.c @@ -381,7 +381,8 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) if (p1 == RSA_PKCS1_PSS_PADDING) { if (!(ctx->operation & - (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY))) + (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY | + EVP_PKEY_OP_SIGNCTX | EVP_PKEY_OP_VERIFYCTX))) goto bad_pad; if (!rctx->md) rctx->md = EVP_sha1(); @@ -433,6 +434,37 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) rctx->md = p2; return 1; + case EVP_PKEY_CTRL_PARAM_SET_FROM_PKEY: + if (p2) + { + EVP_PKEY *pkey = (EVP_PKEY *)p2; + if (pkey->type!=EVP_PKEY_RSA) + return -2; + if (!pkey->pkey.rsa->pssDigest) + return 0; + rctx->pad_mode = RSA_PKCS1_PSS_PADDING; + rctx->md = pkey->pkey.rsa->pssDigest; + rctx->saltlen = pkey->pkey.rsa->pssSaltlen; + return 1; + } + else + return -2; + + case EVP_PKEY_CTRL_GET_DIGEST: + if (p2) + { + EVP_MD **md = (EVP_MD **)p2; + if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING && rctx->md) + { + *md = rctx->md; + return 1; + } + else + return 0; + } + else + return -2; + case EVP_PKEY_CTRL_DIGESTINIT: case EVP_PKEY_CTRL_PKCS7_ENCRYPT: case EVP_PKEY_CTRL_PKCS7_DECRYPT: