Allow digests to supply S/MIME micalg values from a ctrl.
authorDr. Stephen Henson <steve@openssl.org>
Mon, 10 Jul 2006 18:36:55 +0000 (18:36 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 10 Jul 2006 18:36:55 +0000 (18:36 +0000)
Send ctrls to EVP_PKEY_METHOD during signing of PKCS7 structure so
customisation is possible.

CHANGES
crypto/dsa/dsa_pmeth.c
crypto/ec/ec_pmeth.c
crypto/evp/digest.c
crypto/evp/evp.h
crypto/pkcs7/pk7_doit.c
crypto/pkcs7/pk7_mime.c
crypto/pkcs7/pkcs7.h
crypto/pkcs7/pkcs7err.c
crypto/rsa/rsa_pmeth.c

diff --git a/CHANGES b/CHANGES
index 5380dd21d3b0dc3dffe54c3c2adfd224ef02d16d..bf519ba1f692bc7c733232e3b8f337006f86c923 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,16 @@
 
  Changes between 0.9.8b and 0.9.9  [xx XXX xxxx]
 
 
  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.
   *) 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.
index cdd6440dc37f25a97b8b36657783fa8272271170..bd4ee72339a5f7855eb3d8362067aaab80474f13 100644 (file)
@@ -169,6 +169,9 @@ static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                dctx->md = p2;
                return 1;
 
                dctx->md = p2;
                return 1;
 
+               case EVP_PKEY_CTRL_PKCS7_SIGN:
+               return 1;
+
                default:
                return -2;
 
                default:
                return -2;
 
index caaeebdb6d0fed0bcee7841585b562a23a0dd8e0..31d44d944966ba530448bc8b795599d366bb7355 100644 (file)
@@ -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_PEER_KEY:
                /* Default behaviour is OK */
+               case EVP_PKEY_CTRL_PKCS7_SIGN:
                return 1;
 
                default:
                return 1;
 
                default:
index 11d73388d4b7b6d969065e626789f6c583bff86f..256efd6e9ddda7ca1f6548ea1121f439b50ca4e6 100644 (file)
@@ -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);
                }
                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
 #ifndef OPENSSL_NO_ENGINE
        if(ctx->engine)
                /* The EVP_MD we used belongs to an ENGINE, release the
index 509f8579af2a40d66c7ea97e67c077eab1c032df..be16b5eceee1b879e17350045cbc5975029355cf 100644 (file)
@@ -218,6 +218,7 @@ typedef int evp_verify_method(int type,const unsigned char *m,
 /* Digest ctrls */
 
 #define        EVP_MD_CTRL_DIGALGID                    0x1
 /* Digest ctrls */
 
 #define        EVP_MD_CTRL_DIGALGID                    0x1
+#define        EVP_MD_CTRL_MICALG                      0x2
 
 /* Minimum Algorithm specific ctrl value */
 
 
 /* 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_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
 #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
                                        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
 
 
 #define EVP_PKEY_ALG_CTRL              0x1000
 
index a9fb08189802e7fda12a3297efb9680c968be788..478ec0ec2f85f2b3d3192cac891f975aeec82c4a 100644 (file)
@@ -826,6 +826,7 @@ err:
 int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
        {
        EVP_MD_CTX mctx;
 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;
        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);
                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;
                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;
        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);
                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(!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;
                goto err;
+               }
 
        EVP_MD_CTX_cleanup(&mctx);
 
 
        EVP_MD_CTX_cleanup(&mctx);
 
@@ -864,10 +882,6 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
        return 0;
 
        }
        return 0;
 
        }
-       
-
-       
-       
 
 int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
             PKCS7 *p7, PKCS7_SIGNER_INFO *si)
 
 int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
             PKCS7 *p7, PKCS7_SIGNER_INFO *si)
index b161ae8a858612ea769726d591a007253003eb00..01bd59fa6979a1bf1a2d1545ccd8fff4351aeb84 100644 (file)
@@ -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;
 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;
        mdalgs = p7->d.sign->md_algs;
-       mic_sk = sk_new_null();
-       if (!mic_sk)
-               goto err;
        have_unknown = 0;
        have_unknown = 0;
+       write_comma = 0;
        for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++)
                {
        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;
                                goto err;
+                       }
+               switch(md_nid)
+                       {
+                       case NID_sha1:
+                       BIO_puts(out, "sha1");
                        break;
 
                        case NID_md5:
                        break;
 
                        case NID_md5:
-                       if (!sk_push(mic_sk, "md5"))
-                               goto err;
+                       BIO_puts(out, "md5");
                        break;
 
                        case NID_sha256:
                        break;
 
                        case NID_sha256:
-                       if (!sk_push(mic_sk, "sha-256"))
-                               goto err;
+                       BIO_puts(out, "sha-256");
                        break;
 
                        case NID_sha384:
                        break;
 
                        case NID_sha384:
-                       if (!sk_push(mic_sk, "sha-384"))
-                               goto err;
+                       BIO_puts(out, "sha-384");
                        break;
 
                        case NID_sha512:
                        break;
 
                        case NID_sha512:
-                       if (!sk_push(mic_sk, "sha-512"))
-                               goto err;
+                       BIO_puts(out, "sha-512");
                        break;
 
                        case NID_id_GostR3411_94:
                        break;
 
                        case NID_id_GostR3411_94:
-                       if (!sk_push(mic_sk, "gostr3411-94"))
+                       BIO_puts(out, "gostr3411-94");
                                goto err;
                        break;
 
                        default:
                                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;
                                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:
 
        ret = 1;
        err:
 
-       if (mic_sk)
-               sk_free(mic_sk);        
-
        return ret;
 
        }
        return ret;
 
        }
index 581dfb13cc0a9910d5b618e14ac1e01b1a131ea3..a35b35df5d229ed30fd97eb01cad25c60254236b 100644 (file)
@@ -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_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
 #define PKCS7_F_PKCS7_SIGN_ADD_SIGNER                   137
 #define PKCS7_F_PKCS7_SIMPLE_SMIMECAP                   119
 #define PKCS7_F_PKCS7_VERIFY                            117
index e1e9add19ae241591d282caa38229b49b0cd6159..2cb77071a01080cbc55c0385699b93387abf1ab9 100644 (file)
@@ -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_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"},
 {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"},
index 6d21b50d6d19ed8386bc9f02f45e097b99deb402..333d5675ac2036d24677c32586af7640a3f0a7c7 100644 (file)
@@ -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_ENCRYPT:
                case EVP_PKEY_CTRL_PKCS7_DECRYPT:
+               case EVP_PKEY_CTRL_PKCS7_SIGN:
                return 1;
 
                default:
                return 1;
 
                default: