Allow public key ASN1 methods to set PKCS#7 SignerInfo structures.
authorDr. Stephen Henson <steve@openssl.org>
Mon, 17 Apr 2006 17:12:23 +0000 (17:12 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 17 Apr 2006 17:12:23 +0000 (17:12 +0000)
CHANGES
crypto/asn1/ameth_lib.c
crypto/asn1/asn1_locl.h
crypto/dsa/dsa_ameth.c
crypto/ec/ec_ameth.c
crypto/evp/evp.h
crypto/pkcs7/pk7_lib.c
crypto/pkcs7/pkcs7.h
crypto/pkcs7/pkcs7err.c
crypto/rsa/rsa_ameth.c

diff --git a/CHANGES b/CHANGES
index 90fd848..9fe59f9 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,11 @@
 
  Changes between 0.9.8a and 0.9.9  [xx XXX xxxx]
 
+  *) Remove algorithm specific dependencies when setting PKCS7_SIGNER_INFO
+     structures for PKCS7_sign(). They are now set up by the relevant public
+     key ASN1 method.
+     [Steve Henson]
+
   *) Add provisional EC pkey method with support for ECDSA and ECDH.
      [Steve Henson]
 
index 17b3c68..8c33ca5 100644 (file)
@@ -340,7 +340,7 @@ void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
        }
 
 void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
-               void (*pkey_ctrl)(EVP_PKEY *pkey, int op,
+               int (*pkey_ctrl)(EVP_PKEY *pkey, int op,
                                                        long arg1, void *arg2))
        {
        ameth->pkey_ctrl = pkey_ctrl;
index a81f562..0996902 100644 (file)
@@ -104,7 +104,7 @@ struct evp_pkey_asn1_method_st
                                                        ASN1_PCTX *pctx);
 
        void (*pkey_free)(EVP_PKEY *pkey);
-       void (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2);
+       int (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2);
 
        /* Legacy functions for old PEM */
 
index eafdc2e..3178bac 100644 (file)
@@ -528,6 +528,29 @@ static int old_dsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
        return i2d_DSAPrivateKey(pkey->pkey.dsa, pder);
        }
 
+static int dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
+       {
+       switch (op)
+               {
+               case ASN1_PKEY_CTRL_PKCS7_SIGN:
+               if (arg1 == 0)
+                       {
+                       X509_ALGOR *alg1, *alg2;
+                       PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
+                       X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_sha1),
+                                                       V_ASN1_NULL, 0);
+                       X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_dsaWithSHA1),
+                                                       V_ASN1_UNDEF, 0);
+                       }
+               return 1;
+
+               default:
+               return -2;
+
+               }
+
+       }
+
 /* NB these are sorted in pkey_id order, lowest first */
 
 const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] = 
@@ -585,7 +608,7 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] =
                dsa_param_print,
 
                int_dsa_free,
-               0,
+               dsa_pkey_ctrl,
                old_dsa_priv_decode,
                old_dsa_priv_encode
                }
index 18c4265..e4b8aa6 100644 (file)
@@ -570,6 +570,29 @@ static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
        return i2d_ECPrivateKey(pkey->pkey.ec, pder);
        }
 
+static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
+       {
+       switch (op)
+               {
+               case ASN1_PKEY_CTRL_PKCS7_SIGN:
+               if (arg1 == 0)
+                       {
+                       X509_ALGOR *alg1, *alg2;
+                       PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
+                       X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_sha1),
+                                                       V_ASN1_NULL, 0);
+                       X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ecdsa_with_SHA1),
+                                                       V_ASN1_NULL, 0);
+                       }
+               return 1;
+
+               default:
+               return -2;
+
+               }
+
+       }
+
 EVP_PKEY_ASN1_METHOD eckey_asn1_meth = 
        {
        EVP_PKEY_EC,
@@ -598,7 +621,7 @@ EVP_PKEY_ASN1_METHOD eckey_asn1_meth =
        eckey_param_print,
 
        int_ec_free,
-       0,
+       ec_pkey_ctrl,
        old_ec_priv_decode,
        old_ec_priv_encode
        };
index 5659f67..f306887 100644 (file)
@@ -860,6 +860,8 @@ void EVP_PBE_cleanup(void);
 #define ASN1_PKEY_ALIAS                0x1
 #define ASN1_PKEY_DYNAMIC      0x2
 
+#define ASN1_PKEY_CTRL_PKCS7_SIGN      0x1
+
 int EVP_PKEY_asn1_get_count(void);
 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx);
 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(int type);
@@ -899,7 +901,7 @@ void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
 void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
                void (*pkey_free)(EVP_PKEY *pkey));
 void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
-               void (*pkey_ctrl)(EVP_PKEY *pkey, int op,
+               int (*pkey_ctrl)(EVP_PKEY *pkey, int op,
                                                        long arg1, void *arg2));
 
 
index 58ce679..649cdbf 100644 (file)
@@ -60,6 +60,7 @@
 #include "cryptlib.h"
 #include <openssl/objects.h>
 #include <openssl/x509.h>
+#include "asn1_locl.h"
 
 long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg)
        {
@@ -340,13 +341,8 @@ int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl)
 int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
             const EVP_MD *dgst)
        {
-       int nid;
-       char is_dsa;
+       int ret;
 
-       if (pkey->type == EVP_PKEY_DSA || pkey->type == EVP_PKEY_EC)
-               is_dsa = 1;
-       else
-               is_dsa = 0;
        /* We now need to add another PKCS7_SIGNER_INFO entry */
        if (!ASN1_INTEGER_set(p7i->version,1))
                goto err;
@@ -366,50 +362,28 @@ int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
        p7i->pkey=pkey;
 
        /* Set the algorithms */
-       if (is_dsa) p7i->digest_alg->algorithm=OBJ_nid2obj(NID_sha1);
-       else    
-               p7i->digest_alg->algorithm=OBJ_nid2obj(EVP_MD_type(dgst));
 
-       if (p7i->digest_alg->parameter != NULL)
-               ASN1_TYPE_free(p7i->digest_alg->parameter);
-       if ((p7i->digest_alg->parameter=ASN1_TYPE_new()) == NULL)
-               goto err;
-       p7i->digest_alg->parameter->type=V_ASN1_NULL;
+       X509_ALGOR_set0(p7i->digest_alg, OBJ_nid2obj(EVP_MD_type(dgst)),
+                               V_ASN1_NULL, NULL);
 
        if (p7i->digest_enc_alg->parameter != NULL)
                ASN1_TYPE_free(p7i->digest_enc_alg->parameter);
-       nid = EVP_PKEY_type(pkey->type);
-       if (nid == EVP_PKEY_RSA)
-               {
-               p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_rsaEncryption);
-               if (!(p7i->digest_enc_alg->parameter=ASN1_TYPE_new()))
-                       goto err;
-               p7i->digest_enc_alg->parameter->type=V_ASN1_NULL;
-               }
-       else if (nid == EVP_PKEY_DSA)
-               {
-#if 1
-               /* use 'dsaEncryption' OID for compatibility with other software
-                * (PKCS #7 v1.5 does specify how to handle DSA) ... */
-               p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_dsa);
-#else
-               /* ... although the 'dsaWithSHA1' OID (as required by RFC 2630 for CMS)
-                * would make more sense. */
-               p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_dsaWithSHA1);
-#endif
-               p7i->digest_enc_alg->parameter = NULL; /* special case for DSA: omit 'parameter'! */
-               }
-       else if (nid == EVP_PKEY_EC)
+       if (pkey->ameth && pkey->ameth->pkey_ctrl)
                {
-               p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_ecdsa_with_SHA1);
-               if (!(p7i->digest_enc_alg->parameter=ASN1_TYPE_new()))
-                       goto err;
-               p7i->digest_enc_alg->parameter->type=V_ASN1_NULL;
+               ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_SIGN,
+                                               0, p7i);
+               if (ret > 0)
+                       return 1;
+               if (ret != -2)
+                       {
+                       PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SET,
+                                       PKCS7_R_SIGNING_CTRL_FAILURE);
+                       return 0;
+                       }
                }
-       else
-               return(0);
-
-       return(1);
+       PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SET,
+                       PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+       return 0;
 err:
        return(0);
        }
@@ -424,6 +398,8 @@ PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey,
        if (!PKCS7_add_signer(p7,si)) goto err;
        return(si);
 err:
+       if (si)
+               PKCS7_SIGNER_INFO_free(si);
        return(NULL);
        }
 
@@ -459,6 +435,17 @@ STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7)
                return(NULL);
        }
 
+void PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk,
+                                       X509_ALGOR **pdig, X509_ALGOR **psig)
+       {
+       if (pk)
+               *pk = si->pkey;
+       if (pdig)
+               *pdig = si->digest_alg;
+       if (psig)
+               *psig = si->digest_enc_alg;
+       }
+
 PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509)
        {
        PKCS7_RECIP_INFO *ri;
index 64ce62e..201cf4b 100644 (file)
@@ -340,6 +340,8 @@ int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md);
 STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7);
 
 PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509);
+void PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk,
+                                       X509_ALGOR **pdig, X509_ALGOR **psig);
 int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri);
 int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509);
 int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher);
@@ -409,6 +411,7 @@ void ERR_load_PKCS7_strings(void);
 #define PKCS7_F_PKCS7_SET_TYPE                          110
 #define PKCS7_F_PKCS7_SIGN                              116
 #define PKCS7_F_PKCS7_SIGNATUREVERIFY                   113
+#define PKCS7_F_PKCS7_SIGNER_INFO_SET                   129
 #define PKCS7_F_PKCS7_SIMPLE_SMIMECAP                   119
 #define PKCS7_F_PKCS7_VERIFY                            117
 #define PKCS7_F_SMIME_READ_PKCS7                        122
@@ -450,6 +453,8 @@ void ERR_load_PKCS7_strings(void);
 #define PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE  127
 #define PKCS7_R_SIGNATURE_FAILURE                       105
 #define PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND            128
+#define PKCS7_R_SIGNING_CTRL_FAILURE                    147
+#define PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE         148
 #define PKCS7_R_SIG_INVALID_MIME_TYPE                   141
 #define PKCS7_R_SMIME_TEXT_ERROR                        129
 #define PKCS7_R_UNABLE_TO_FIND_CERTIFICATE              106
index 4cd2934..f189765 100644 (file)
@@ -78,7 +78,7 @@ static ERR_STRING_DATA PKCS7_str_functs[]=
 {ERR_FUNC(PKCS7_F_PKCS7_ADD_RECIPIENT_INFO),   "PKCS7_add_recipient_info"},
 {ERR_FUNC(PKCS7_F_PKCS7_ADD_SIGNER),   "PKCS7_add_signer"},
 {ERR_FUNC(PKCS7_F_PKCS7_BIO_ADD_DIGEST),       "PKCS7_BIO_ADD_DIGEST"},
-{ERR_FUNC(PKCS7_F_PKCS7_CTRL), "PKCS7_ctrl"},
+{ERR_FUNC(PKCS7_F_PKCS7_CTRL), "PKCS7_CTRL"},
 {ERR_FUNC(PKCS7_F_PKCS7_DATADECODE),   "PKCS7_dataDecode"},
 {ERR_FUNC(PKCS7_F_PKCS7_DATAFINAL),    "PKCS7_dataFinal"},
 {ERR_FUNC(PKCS7_F_PKCS7_DATAINIT),     "PKCS7_dataInit"},
@@ -87,13 +87,14 @@ static ERR_STRING_DATA PKCS7_str_functs[]=
 {ERR_FUNC(PKCS7_F_PKCS7_DECRYPT),      "PKCS7_decrypt"},
 {ERR_FUNC(PKCS7_F_PKCS7_ENCRYPT),      "PKCS7_encrypt"},
 {ERR_FUNC(PKCS7_F_PKCS7_FIND_DIGEST),  "PKCS7_FIND_DIGEST"},
-{ERR_FUNC(PKCS7_F_PKCS7_GET0_SIGNERS), "PKCS7_get0_signers"},
+{ERR_FUNC(PKCS7_F_PKCS7_GET0_SIGNERS), "PKCS7_GET0_SIGNERS"},
 {ERR_FUNC(PKCS7_F_PKCS7_SET_CIPHER),   "PKCS7_set_cipher"},
 {ERR_FUNC(PKCS7_F_PKCS7_SET_CONTENT),  "PKCS7_set_content"},
 {ERR_FUNC(PKCS7_F_PKCS7_SET_DIGEST),   "PKCS7_set_digest"},
 {ERR_FUNC(PKCS7_F_PKCS7_SET_TYPE),     "PKCS7_set_type"},
 {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_SIMPLE_SMIMECAP),      "PKCS7_simple_smimecap"},
 {ERR_FUNC(PKCS7_F_PKCS7_VERIFY),       "PKCS7_verify"},
 {ERR_FUNC(PKCS7_F_SMIME_READ_PKCS7),   "SMIME_read_PKCS7"},
@@ -138,6 +139,8 @@ static ERR_STRING_DATA PKCS7_str_reasons[]=
 {ERR_REASON(PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE),"private key does not match certificate"},
 {ERR_REASON(PKCS7_R_SIGNATURE_FAILURE)   ,"signature failure"},
 {ERR_REASON(PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND),"signer certificate not found"},
+{ERR_REASON(PKCS7_R_SIGNING_CTRL_FAILURE),"signing ctrl failure"},
+{ERR_REASON(PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE),"signing not supported for this key type"},
 {ERR_REASON(PKCS7_R_SIG_INVALID_MIME_TYPE),"sig invalid mime type"},
 {ERR_REASON(PKCS7_R_SMIME_TEXT_ERROR)    ,"smime text error"},
 {ERR_REASON(PKCS7_R_UNABLE_TO_FIND_CERTIFICATE),"unable to find certificate"},
index 4acc11d..93b9f07 100644 (file)
@@ -261,6 +261,29 @@ static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
        return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
        }
 
+
+static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
+       {
+       switch (op)
+               {
+               case ASN1_PKEY_CTRL_PKCS7_SIGN:
+               if (arg1 == 0)
+                       {
+                       X509_ALGOR *alg;
+                       PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, NULL, &alg);
+                       X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption),
+                                                       V_ASN1_NULL, 0);
+                       }
+               return 1;
+
+               default:
+               return -2;
+
+               }
+
+       }
+
+
 const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] = 
        {
                {
@@ -286,7 +309,7 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] =
                0,0,0,0,0,0,
 
                int_rsa_free,
-               0,
+               rsa_pkey_ctrl,
                old_rsa_priv_decode,
                old_rsa_priv_encode
                },