Steve, all, just some quick status update.
Thus wrote Dr. Stephen Henson (st...@openssl.org): > EVP_PKEY_CTX was introduced (by me!) to contain parameters relating to > a specific cryptographic operation. Fixed parameters should go in > EVP_PKEY. PSS can have both so we'd need a new EVP_PKEY type and/or > expand the RSA structure too. In the pss certificates I've seen so far, the rsa public key is not different from certificates with pkcs1.5 signature. All pss parameters are encoded in the signature itself. Therefore, I don't think I can distinguish pss and pkcs1.5 before entering ASN1_item_verify. One approach I could get to work is as follows: sha1_md is hard-wired to pkcs1.5 signature. I created a new sha1Pss_md that can be used for pss. It has an md_ctrl function that reads the pss parameters from the certificate and stores them in the evp_pkey_ctx that's used for the signature verification. An entry in obj_xref.txt links pss to an rsa key and the sha1Pss. This works ok without hard-coding any NIDs. The only drawback is that pss supports only sha1 in this approach. (Sha1 is the default anyway. Other hashes could be used with pss but I've never seen this). > Use of the ctrl mechanism will require some changes to ASN1_item_sign > and ASN1_item_verify. The current code uses EVP_Sign*() and > EVP_Verify*() which isn't flexible enough the new EVP_Digest*() API > will need to be used instead. Ok, I use EVP_DigestVerify.. now. I've attached another preliminary patch that shows this idea. Please let me know if that approach makes sense to you. Best regards, Martin
diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c index cecdb13..085a746 100644 --- a/crypto/asn1/a_verify.c +++ b/crypto/asn1/a_verify.c @@ -129,14 +129,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; + EVP_PKEY_CTX *pctx; 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)) @@ -144,8 +145,8 @@ 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) + md=EVP_get_digestbynid(mdnid); + if (md == NULL) { ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); goto err; @@ -158,13 +159,18 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signat goto err; } - if (!EVP_VerifyInit_ex(&ctx,type, NULL)) + if (!EVP_DigestVerifyInit(&mctx, &pctx, md, NULL, pkey)) { ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB); ret=0; goto err; } + if (md && md->md_ctrl) + { + md->md_ctrl(&mctx, EVP_MD_CTRL_SET_PCTX_PARAMS, 0, (void *)a->parameter); + } + inl = ASN1_item_i2d(asn, &buf_in, it); if (buf_in == NULL) @@ -173,24 +179,24 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signat goto err; } - EVP_VerifyUpdate(&ctx,(unsigned char *)buf_in,inl); + EVP_DigestVerifyUpdate(&mctx,(unsigned char *)buf_in,inl); 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(mctx)); */ ret=1; err: - EVP_MD_CTX_cleanup(&ctx); + EVP_MD_CTX_cleanup(&mctx); return(ret); } diff --git a/crypto/evp/c_alld.c b/crypto/evp/c_alld.c index 5032e7c..cee322d 100644 --- a/crypto/evp/c_alld.c +++ b/crypto/evp/c_alld.c @@ -85,6 +85,7 @@ void OpenSSL_add_all_digests(void) EVP_add_digest(EVP_sha1()); EVP_add_digest_alias(SN_sha1,"ssl3-sha1"); EVP_add_digest_alias(SN_sha1WithRSAEncryption,SN_sha1WithRSA); + EVP_add_digest(EVP_sha1Pss()); #ifndef OPENSSL_NO_DSA EVP_add_digest(EVP_dss1()); EVP_add_digest_alias(SN_dsaWithSHA1,SN_dsaWithSHA1_2); diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h index 4eecdbe..7260301 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h @@ -224,6 +224,7 @@ typedef int evp_verify_method(int type,const unsigned char *m, /* Minimum Algorithm specific ctrl value */ #define EVP_MD_CTRL_ALG_CTRL 0x1000 +#define EVP_MD_CTRL_SET_PCTX_PARAMS (EVP_MD_CTRL_ALG_CTRL + 0x10) #define EVP_PKEY_NULL_method NULL,NULL,{0,0,0,0} diff --git a/crypto/evp/m_sha1.c b/crypto/evp/m_sha1.c index 9a2790f..aa11456 100644 --- a/crypto/evp/m_sha1.c +++ b/crypto/evp/m_sha1.c @@ -97,6 +97,51 @@ const EVP_MD *EVP_sha1(void) { return(&sha1_md); } + + +int sha1Pss_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2) + { + ASN1_TYPE *at; + + printf("sha1Pss_ctrl()\n"); + + if (cmd == EVP_MD_CTRL_SET_PCTX_PARAMS) + { + if (!ctx->pctx) + return -1; + + printf("set PSS padding\n"); + EVP_PKEY_CTX_set_rsa_padding(ctx->pctx, RSA_PKCS1_PSS_PADDING); + + if (p2) + at = (ASN1_TYPE *)p2; + } + + /* TODO: what should this function return in case of ok, error? */ + return 0; + } + +static const EVP_MD sha1Pss_md= + { + NID_sha1Pss, + NID_rsaSsaPss, + SHA_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_DIGEST, + init, + update, + final, + NULL, + NULL, + EVP_PKEY_RSA_method, + SHA_CBLOCK, + sizeof(EVP_MD *)+sizeof(SHA_CTX), + sha1Pss_ctrl + }; + +const EVP_MD *EVP_sha1Pss(void) + { + return(&sha1Pss_md); + } #endif #ifndef OPENSSL_NO_SHA256 diff --git a/crypto/objects/obj_xref.txt b/crypto/objects/obj_xref.txt index e45b3d3..0117cfa 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 sha1Pss rsaEncryption md4WithRSAEncryption md4 rsaEncryption sha256WithRSAEncryption sha256 rsaEncryption sha384WithRSAEncryption sha384 rsaEncryption diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt index 52ac0a6..45ddb59 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 @@ -645,6 +647,7 @@ algorithm 17 : DES-EDE : des-ede : DESX-CBC : desx-cbc algorithm 18 : SHA : sha algorithm 26 : SHA1 : sha1 + : SHA1PSS : sha1Pss !Cname dsaWithSHA1-2 algorithm 27 : DSA-SHA1-old : dsaWithSHA1-old algorithm 29 : RSA-SHA1-2 : sha1WithRSA