From: Dr. Stephen Henson Date: Mon, 17 Apr 2006 17:12:23 +0000 (+0000) Subject: Allow public key ASN1 methods to set PKCS#7 SignerInfo structures. X-Git-Tag: OpenSSL_0_9_8k^2~1376 X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff_plain;h=492a9e241550b537ef3db1719e18e9b795b6d24c Allow public key ASN1 methods to set PKCS#7 SignerInfo structures. --- diff --git a/CHANGES b/CHANGES index 90fd84834b..9fe59f9acc 100644 --- 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] diff --git a/crypto/asn1/ameth_lib.c b/crypto/asn1/ameth_lib.c index 17b3c68fc7..8c33ca5625 100644 --- a/crypto/asn1/ameth_lib.c +++ b/crypto/asn1/ameth_lib.c @@ -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; diff --git a/crypto/asn1/asn1_locl.h b/crypto/asn1/asn1_locl.h index a81f56238f..099690203a 100644 --- a/crypto/asn1/asn1_locl.h +++ b/crypto/asn1/asn1_locl.h @@ -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 */ diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index eafdc2e5d4..3178bac9bc 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -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 } diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c index 18c4265cfc..e4b8aa68bd 100644 --- a/crypto/ec/ec_ameth.c +++ b/crypto/ec/ec_ameth.c @@ -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 }; diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h index 5659f67311..f306887a20 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h @@ -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)); diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c index 58ce6791c9..649cdbf279 100644 --- a/crypto/pkcs7/pk7_lib.c +++ b/crypto/pkcs7/pk7_lib.c @@ -60,6 +60,7 @@ #include "cryptlib.h" #include #include +#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; diff --git a/crypto/pkcs7/pkcs7.h b/crypto/pkcs7/pkcs7.h index 64ce62e673..201cf4b81e 100644 --- a/crypto/pkcs7/pkcs7.h +++ b/crypto/pkcs7/pkcs7.h @@ -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 diff --git a/crypto/pkcs7/pkcs7err.c b/crypto/pkcs7/pkcs7err.c index 4cd293472f..f18976502b 100644 --- a/crypto/pkcs7/pkcs7err.c +++ b/crypto/pkcs7/pkcs7err.c @@ -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"}, diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index 4acc11db33..93b9f075c4 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -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 },