Hi Erwann,
Thus wrote Erwann ABALEA ([email protected]):
> I can't verify ecdsa-with-SHA256 certificates, the ones transmitted a
> few days ago (German passports), with the same error
> (d2i_ECPKParameters function).
this is strange. I've also tested Steven's version against your ecdsa
certificates and things worked ok for me.
> Of course, the verification of a subordinate certificate against the
> root is/was OK with the Feb 7 version, without the RSASSA-PSS patch.
After you reported the problem with my patch, I made an update (which I
couldn't post while the servers were down). I know it's obsolete by now
but I'll attach it anyway. Your ecdsa examples verify ok with this patch.
Maybe this helps to track down your problem.
Best regards,
Martin
diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c
index d9332ee..cd9f082 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,42 @@ 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 digest is still unknown, try to check the algorithm parameters */
+ if (!md && 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;
+ }
+ }
+
+ EVP_MD_CTX_set_padmode_from_nid(&mctx, OBJ_obj2nid(a->algorithm));
+
+ if (!EVP_DigestVerifyInit(&mctx, NULL,md, NULL, pkey))
{
ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB);
ret=0;
@@ -178,7 +208,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 +218,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..fafcc47 100644
--- a/crypto/evp/evp.h
+++ b/crypto/evp/evp.h
@@ -502,6 +502,7 @@ __owur int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out,const EVP_MD_CTX *in);
void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags);
void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags);
int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx,int flags);
+void EVP_MD_CTX_set_padmode_from_nid(EVP_MD_CTX *ctx, int nid);
__owur int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
__owur int EVP_DigestUpdate(EVP_MD_CTX *ctx,const void *d,
size_t cnt);
@@ -1038,6 +1039,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/evp_lib.c b/crypto/evp/evp_lib.c
index 40951a0..aa9467c 100644
--- a/crypto/evp/evp_lib.c
+++ b/crypto/evp/evp_lib.c
@@ -296,6 +296,16 @@ int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, int flags)
return (ctx->flags & flags);
}
+void EVP_MD_CTX_set_padmode_from_nid(EVP_MD_CTX *ctx, int nid)
+ {
+ if (nid == NID_rsassaPss)
+ EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_PAD_PSS);
+ else
+ EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_PAD_PKCS1);
+ /* TODO: what about X931? */
+ }
+
+
void EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags)
{
ctx->flags |= flags;
diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c
index f0b7f95..bbe841e 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,29 @@ 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))
+ {
+ /* in case of error, type remains NULL */
+ 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/evp/pmeth_fn.c b/crypto/evp/pmeth_fn.c
index c4676f2..67bb32c 100644
--- a/crypto/evp/pmeth_fn.c
+++ b/crypto/evp/pmeth_fn.c
@@ -144,7 +144,8 @@ int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
}
- if (ctx->operation != EVP_PKEY_OP_VERIFY)
+ if (ctx->operation != EVP_PKEY_OP_VERIFY &&
+ ctx->operation != EVP_PKEY_OP_VERIFYCTX) /* temporary workaround */
{
EVPerr(EVP_F_EVP_PKEY_VERIFY, EVP_R_OPERATON_NOT_INITIALIZED);
return -1;
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..b9d8109 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_EXP_OPT(RSASSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0),
+ ASN1_EXP_OPT(RSASSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1),
+ ASN1_EXP_OPT(RSASSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2),
+ ASN1_EXP_OPT(RSASSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3)
+} 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..9b67723 100644
--- a/crypto/rsa/rsa_pmeth.c
+++ b/crypto/rsa/rsa_pmeth.c
@@ -313,6 +313,22 @@ static int pkey_rsa_verify(EVP_PKEY_CTX *ctx,
}
+static int pkey_rsa_verifyctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
+ {
+ RSA_PKEY_CTX *rctx = ctx->data;
+
+ if (!rctx)
+ return 0;
+
+ if (EVP_MD_CTX_test_flags(mctx, EVP_MD_CTX_FLAG_PAD_PSS))
+ rctx->pad_mode = RSA_PKCS1_PSS_PADDING;
+ else
+ rctx->pad_mode = RSA_PKCS1_PADDING;
+ /* TODO: what about X931? */
+
+ return 1;
+ }
+
static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx,
unsigned char *out, size_t *outlen,
@@ -381,7 +397,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 +450,38 @@ 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 (!rctx->pad_mode == RSA_PKCS1_PSS_PADDING)
+ return 0;
+ if (!pkey->pkey.rsa->pssDigest)
+ return 0;
+ 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 = (EVP_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:
@@ -567,8 +616,9 @@ const EVP_PKEY_METHOD rsa_pkey_meth =
0,
pkey_rsa_verifyrecover,
-
- 0,0,0,0,
+ 0,0,
+ pkey_rsa_verifyctx_init,
+ 0,
0,
pkey_rsa_encrypt,