Index: openssl/crypto/pkcs7/pk7_lib.c |
=================================================================== |
--- openssl/crypto/pkcs7/pk7_lib.c (revision 105093) |
+++ openssl/crypto/pkcs7/pk7_lib.c (working copy) |
@@ -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) |
{ |
@@ -314,7 +315,7 @@ |
*sk=sk_X509_new_null(); |
if (*sk == NULL) |
{ |
- PKCS7err(PKCS7_F_PKCS7_ADD_CERTIFICATE,ERR_R_MALLOC_FAILURE); |
+ PKCS7err(PKCS7_F_PKCS7_ADD_CERTIFICATE, ERR_R_MALLOC_FAILURE); |
return 0; |
} |
CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509); |
@@ -365,13 +366,8 @@ |
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; |
@@ -391,65 +387,55 @@ |
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) |
+ if (pkey->ameth && pkey->ameth->pkey_ctrl) |
{ |
- 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; |
+ 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 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) |
- { |
- 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; |
- } |
- else |
- return(0); |
- |
- return(1); |
+ PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SET, |
+ PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); |
err: |
- return(0); |
+ return 0; |
} |
PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey, |
const EVP_MD *dgst) |
{ |
- PKCS7_SIGNER_INFO *si; |
+ PKCS7_SIGNER_INFO *si = NULL; |
+ if (dgst == NULL) |
+ { |
+ int def_nid; |
+ if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0) |
+ goto err; |
+ dgst = EVP_get_digestbynid(def_nid); |
+ if (dgst == NULL) |
+ { |
+ PKCS7err(PKCS7_F_PKCS7_ADD_SIGNATURE, |
+ PKCS7_R_NO_DEFAULT_DIGEST); |
+ goto err; |
+ } |
+ } |
+ |
if ((si=PKCS7_SIGNER_INFO_new()) == NULL) goto err; |
if (!PKCS7_SIGNER_INFO_set(si,x509,pkey,dgst)) goto err; |
if (!PKCS7_add_signer(p7,si)) goto err; |
return(si); |
err: |
- PKCS7_SIGNER_INFO_free(si); |
+ if (si) |
+ PKCS7_SIGNER_INFO_free(si); |
return(NULL); |
} |
@@ -485,6 +471,23 @@ |
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; |
+ } |
+ |
+void PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc) |
+ { |
+ if (penc) |
+ *penc = ri->key_enc_algor; |
+ } |
+ |
PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509) |
{ |
PKCS7_RECIP_INFO *ri; |
@@ -492,10 +495,11 @@ |
if ((ri=PKCS7_RECIP_INFO_new()) == NULL) goto err; |
if (!PKCS7_RECIP_INFO_set(ri,x509)) goto err; |
if (!PKCS7_add_recipient_info(p7,ri)) goto err; |
- return(ri); |
+ return ri; |
err: |
- PKCS7_RECIP_INFO_free(ri); |
- return(NULL); |
+ if (ri) |
+ PKCS7_RECIP_INFO_free(ri); |
+ return NULL; |
} |
int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri) |
@@ -524,6 +528,8 @@ |
int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509) |
{ |
+ int ret; |
+ EVP_PKEY *pkey = NULL; |
if (!ASN1_INTEGER_set(p7i->version,0)) |
return 0; |
if (!X509_NAME_set(&p7i->issuer_and_serial->issuer, |
@@ -535,14 +541,41 @@ |
M_ASN1_INTEGER_dup(X509_get_serialNumber(x509)))) |
return 0; |
- X509_ALGOR_free(p7i->key_enc_algor); |
- if (!(p7i->key_enc_algor= X509_ALGOR_dup(x509->cert_info->key->algor))) |
- return 0; |
+ pkey = X509_get_pubkey(x509); |
+ if (!pkey || !pkey->ameth || !pkey->ameth->pkey_ctrl) |
+ { |
+ PKCS7err(PKCS7_F_PKCS7_RECIP_INFO_SET, |
+ PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); |
+ goto err; |
+ } |
+ |
+ ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_ENCRYPT, |
+ 0, p7i); |
+ if (ret == -2) |
+ { |
+ PKCS7err(PKCS7_F_PKCS7_RECIP_INFO_SET, |
+ PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); |
+ goto err; |
+ } |
+ if (ret <= 0) |
+ { |
+ PKCS7err(PKCS7_F_PKCS7_RECIP_INFO_SET, |
+ PKCS7_R_ENCRYPTION_CTRL_FAILURE); |
+ goto err; |
+ } |
+ |
+ EVP_PKEY_free(pkey); |
+ |
CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509); |
p7i->cert=x509; |
- return(1); |
+ return 1; |
+ |
+ err: |
+ if (pkey) |
+ EVP_PKEY_free(pkey); |
+ return 0; |
} |
X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si) |
@@ -558,7 +591,6 @@ |
int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher) |
{ |
int i; |
- ASN1_OBJECT *objtmp; |
PKCS7_ENC_CONTENT *ec; |
i=OBJ_obj2nid(p7->type); |
@@ -581,9 +613,53 @@ |
PKCS7err(PKCS7_F_PKCS7_SET_CIPHER,PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); |
return(0); |
} |
- objtmp = OBJ_nid2obj(i); |
ec->cipher = cipher; |
return 1; |
} |
+int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7) |
+ { |
+ ASN1_OCTET_STRING *os = NULL; |
+ |
+ switch (OBJ_obj2nid(p7->type)) |
+ { |
+ case NID_pkcs7_data: |
+ os = p7->d.data; |
+ break; |
+ |
+ case NID_pkcs7_signedAndEnveloped: |
+ os = p7->d.signed_and_enveloped->enc_data->enc_data; |
+ if (os == NULL) |
+ { |
+ os=M_ASN1_OCTET_STRING_new(); |
+ p7->d.signed_and_enveloped->enc_data->enc_data=os; |
+ } |
+ break; |
+ |
+ case NID_pkcs7_enveloped: |
+ os = p7->d.enveloped->enc_data->enc_data; |
+ if (os == NULL) |
+ { |
+ os=M_ASN1_OCTET_STRING_new(); |
+ p7->d.enveloped->enc_data->enc_data=os; |
+ } |
+ break; |
+ |
+ case NID_pkcs7_signed: |
+ os=p7->d.sign->contents->d.data; |
+ break; |
+ |
+ default: |
+ os = NULL; |
+ break; |
+ } |
+ |
+ if (os == NULL) |
+ return 0; |
+ |
+ os->flags |= ASN1_STRING_FLAG_NDEF; |
+ *boundary = &os->data; |
+ |
+ return 1; |
+ } |