From: Dr. Stephen Henson Date: Mon, 10 Jul 2006 18:36:55 +0000 (+0000) Subject: Allow digests to supply S/MIME micalg values from a ctrl. X-Git-Tag: OpenSSL_0_9_8k^2~1206 X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff_plain;h=b7683e3a5d93aa5319263b7bbfd0fee18f25955e;hp=0ee2166cc50cffba02514b686c6bf75c76ff2e62;ds=sidebyside Allow digests to supply S/MIME micalg values from a ctrl. Send ctrls to EVP_PKEY_METHOD during signing of PKCS7 structure so customisation is possible. --- diff --git a/CHANGES b/CHANGES index 5380dd21d3..bf519ba1f6 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,16 @@ Changes between 0.9.8b and 0.9.9 [xx XXX xxxx] + *) Allow digests to supply their own micalg string for S/MIME type using + the ctrl EVP_MD_CTRL_MICALG. + [Steve Henson] + + *) During PKCS7 signing pass the PKCS7 SignerInfo structure to the + EVP_PKEY_METHOD before and after signing via the EVP_PKEY_CTRL_PKCS7_SIGN + ctrl. It can then customise the structure before and/or after signing + if necessary. + [Steve Henson] + *) New function OBJ_add_sigid() to allow application defined signature OIDs to be added to OpenSSLs internal tables. New function OBJ_sigid_free() to free up any added signature OIDs. diff --git a/crypto/dsa/dsa_pmeth.c b/crypto/dsa/dsa_pmeth.c index cdd6440dc3..bd4ee72339 100644 --- a/crypto/dsa/dsa_pmeth.c +++ b/crypto/dsa/dsa_pmeth.c @@ -169,6 +169,9 @@ static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) dctx->md = p2; return 1; + case EVP_PKEY_CTRL_PKCS7_SIGN: + return 1; + default: return -2; diff --git a/crypto/ec/ec_pmeth.c b/crypto/ec/ec_pmeth.c index caaeebdb6d..31d44d9449 100644 --- a/crypto/ec/ec_pmeth.c +++ b/crypto/ec/ec_pmeth.c @@ -230,6 +230,7 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) case EVP_PKEY_CTRL_PEER_KEY: /* Default behaviour is OK */ + case EVP_PKEY_CTRL_PKCS7_SIGN: return 1; default: diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index 11d73388d4..256efd6e9d 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -332,6 +332,8 @@ int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) OPENSSL_cleanse(ctx->md_data,ctx->digest->ctx_size); OPENSSL_free(ctx->md_data); } + if (ctx->pctx) + EVP_PKEY_CTX_free(ctx->pctx); #ifndef OPENSSL_NO_ENGINE if(ctx->engine) /* The EVP_MD we used belongs to an ENGINE, release the diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h index 509f8579af..be16b5ecee 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h @@ -218,6 +218,7 @@ typedef int evp_verify_method(int type,const unsigned char *m, /* Digest ctrls */ #define EVP_MD_CTRL_DIGALGID 0x1 +#define EVP_MD_CTRL_MICALG 0x2 /* Minimum Algorithm specific ctrl value */ @@ -455,6 +456,9 @@ typedef int (EVP_PBE_KEYGEN)(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, #define EVP_SignDigestUpdate(a,b,c) EVP_DigestUpdate(a,b,c) #define EVP_VerifyDigestUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +#define EVP_DigestSignUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +#define EVP_DigestVerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c) + #ifdef CONST_STRICT void BIO_set_md(BIO *,const EVP_MD *md); #else @@ -981,10 +985,12 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, EVP_PKEY_CTRL_MD, 0, (void *)md) #define EVP_PKEY_CTRL_MD 1 -#define EVP_PKEY_CTRL_PEER_KEY 2 +#define EVP_PKEY_CTRL_PEER_KEY 2 + +#define EVP_PKEY_CTRL_PKCS7_ENCRYPT 3 +#define EVP_PKEY_CTRL_PKCS7_DECRYPT 4 -#define EVP_PKEY_CTRL_PKCS7_ENCRYPT 3 -#define EVP_PKEY_CTRL_PKCS7_DECRYPT 4 +#define EVP_PKEY_CTRL_PKCS7_SIGN 5 #define EVP_PKEY_ALG_CTRL 0x1000 diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c index a9fb081898..478ec0ec2f 100644 --- a/crypto/pkcs7/pk7_doit.c +++ b/crypto/pkcs7/pk7_doit.c @@ -826,6 +826,7 @@ err: int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) { EVP_MD_CTX mctx; + EVP_PKEY_CTX *pctx; unsigned char *abuf = NULL; int alen; unsigned int siglen; @@ -836,20 +837,37 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) return 0; EVP_MD_CTX_init(&mctx); - if (!EVP_SignInit_ex(&mctx,md,NULL)) + if (EVP_DigestSignInit(&mctx, &pctx, md,NULL, si->pkey) <= 0) goto err; + + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, + EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0) + { + PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); + goto err; + } + alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr,&abuf, ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); if(!abuf) goto err; - if (!EVP_SignUpdate(&mctx,abuf,alen)) + if (EVP_DigestSignUpdate(&mctx,abuf,alen) <= 0) goto err; OPENSSL_free(abuf); - abuf = OPENSSL_malloc(EVP_PKEY_size(si->pkey)); + if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0) + goto err; + abuf = OPENSSL_malloc(siglen); if(!abuf) goto err; - if (!EVP_SignFinal(&mctx, abuf, &siglen, si->pkey)) + if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0) + goto err; + + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, + EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0) + { + PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); goto err; + } EVP_MD_CTX_cleanup(&mctx); @@ -864,10 +882,6 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) return 0; } - - - - int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si) diff --git a/crypto/pkcs7/pk7_mime.c b/crypto/pkcs7/pk7_mime.c index b161ae8a85..01bd59fa69 100644 --- a/crypto/pkcs7/pk7_mime.c +++ b/crypto/pkcs7/pk7_mime.c @@ -149,52 +149,65 @@ static PKCS7 *B64_read_PKCS7(BIO *bio) static int pk7_write_micalg(BIO *out, PKCS7 *p7) { STACK_OF(X509_ALGOR) *mdalgs; - STACK *mic_sk; - int i, have_unknown = 0, ret = 0; + const EVP_MD *md; + int i, have_unknown = 0, write_comma, ret = 0, md_nid; mdalgs = p7->d.sign->md_algs; - mic_sk = sk_new_null(); - if (!mic_sk) - goto err; have_unknown = 0; + write_comma = 0; for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++) { - switch(OBJ_obj2nid(sk_X509_ALGOR_value(mdalgs, i)->algorithm)) + if (write_comma) + BIO_write(out, ",", 1); + write_comma = 1; + md_nid = OBJ_obj2nid(sk_X509_ALGOR_value(mdalgs, i)->algorithm); + md = EVP_get_digestbynid(md_nid); + if (md && md->md_ctrl) { - case NID_sha1: - if (!sk_push(mic_sk, "sha1")) + int rv; + char *micstr; + rv = md->md_ctrl(NULL, EVP_MD_CTRL_MICALG, 0, &micstr); + if (rv > 0) + { + BIO_puts(out, micstr); + OPENSSL_free(micstr); + continue; + } + if (rv != -2) goto err; + } + switch(md_nid) + { + case NID_sha1: + BIO_puts(out, "sha1"); break; case NID_md5: - if (!sk_push(mic_sk, "md5")) - goto err; + BIO_puts(out, "md5"); break; case NID_sha256: - if (!sk_push(mic_sk, "sha-256")) - goto err; + BIO_puts(out, "sha-256"); break; case NID_sha384: - if (!sk_push(mic_sk, "sha-384")) - goto err; + BIO_puts(out, "sha-384"); break; case NID_sha512: - if (!sk_push(mic_sk, "sha-512")) - goto err; + BIO_puts(out, "sha-512"); break; case NID_id_GostR3411_94: - if (!sk_push(mic_sk, "gostr3411-94")) + BIO_puts(out, "gostr3411-94"); goto err; break; default: - if (!have_unknown) + if (have_unknown) + write_comma = 0; + else { - if (!sk_push(mic_sk, "unknown")) - goto err; + BIO_puts(out, "unknown"); have_unknown = 1; } break; @@ -202,18 +215,9 @@ static int pk7_write_micalg(BIO *out, PKCS7 *p7) } } - for (i = 0; i < sk_num(mic_sk); i++) - { - BIO_puts(out, sk_value(mic_sk, i)); - if (i > 0) - BIO_write(out, ",", 1); - } ret = 1; err: - if (mic_sk) - sk_free(mic_sk); - return ret; } diff --git a/crypto/pkcs7/pkcs7.h b/crypto/pkcs7/pkcs7.h index 581dfb13cc..a35b35df5d 100644 --- a/crypto/pkcs7/pkcs7.h +++ b/crypto/pkcs7/pkcs7.h @@ -435,6 +435,7 @@ void ERR_load_PKCS7_strings(void); #define PKCS7_F_PKCS7_SIGN 116 #define PKCS7_F_PKCS7_SIGNATUREVERIFY 113 #define PKCS7_F_PKCS7_SIGNER_INFO_SET 129 +#define PKCS7_F_PKCS7_SIGNER_INFO_SIGN 139 #define PKCS7_F_PKCS7_SIGN_ADD_SIGNER 137 #define PKCS7_F_PKCS7_SIMPLE_SMIMECAP 119 #define PKCS7_F_PKCS7_VERIFY 117 diff --git a/crypto/pkcs7/pkcs7err.c b/crypto/pkcs7/pkcs7err.c index e1e9add19a..2cb77071a0 100644 --- a/crypto/pkcs7/pkcs7err.c +++ b/crypto/pkcs7/pkcs7err.c @@ -103,6 +103,7 @@ static ERR_STRING_DATA PKCS7_str_functs[]= {ERR_FUNC(PKCS7_F_PKCS7_SIGN), "PKCS7_sign"}, {ERR_FUNC(PKCS7_F_PKCS7_SIGNATUREVERIFY), "PKCS7_signatureVerify"}, {ERR_FUNC(PKCS7_F_PKCS7_SIGNER_INFO_SET), "PKCS7_SIGNER_INFO_set"}, +{ERR_FUNC(PKCS7_F_PKCS7_SIGNER_INFO_SIGN), "PKCS7_SIGNER_INFO_sign"}, {ERR_FUNC(PKCS7_F_PKCS7_SIGN_ADD_SIGNER), "PKCS7_sign_add_signer"}, {ERR_FUNC(PKCS7_F_PKCS7_SIMPLE_SMIMECAP), "PKCS7_simple_smimecap"}, {ERR_FUNC(PKCS7_F_PKCS7_VERIFY), "PKCS7_verify"}, diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c index 6d21b50d6d..333d5675ac 100644 --- a/crypto/rsa/rsa_pmeth.c +++ b/crypto/rsa/rsa_pmeth.c @@ -438,6 +438,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) case EVP_PKEY_CTRL_PKCS7_ENCRYPT: case EVP_PKEY_CTRL_PKCS7_DECRYPT: + case EVP_PKEY_CTRL_PKCS7_SIGN: return 1; default: