X-Git-Url: https://git.openssl.org/?a=blobdiff_plain;f=crypto%2Fpkcs7%2Fpk7_lib.c;h=8942ae8a53b3e964e19468386f4b09f79a6a485d;hb=11d8cdc6ad92d070dd91735511ff9616cf879bbb;hp=79f6f612dde68247229bb1c712eb6f697b415c8a;hpb=6d114240b921edc9c1135568392199a652acd0db;p=openssl.git diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c index 79f6f612dd..8942ae8a53 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) { @@ -74,6 +75,13 @@ long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg) if (nid == NID_pkcs7_signed) { ret=p7->detached=(int)larg; + if (ret && PKCS7_type_is_data(p7->d.sign->contents)) + { + ASN1_OCTET_STRING *os; + os=p7->d.sign->contents->d.data; + ASN1_OCTET_STRING_free(os); + p7->d.sign->contents->d.data = NULL; + } } else { @@ -84,7 +92,11 @@ long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg) case PKCS7_OP_GET_DETACHED_SIGNATURE: if (nid == NID_pkcs7_signed) { - ret=p7->detached; + if(!p7->d.sign || !p7->d.sign->contents->d.ptr) + ret = 1; + else ret = 0; + + p7->detached = ret; } else { @@ -123,10 +135,14 @@ int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data) { case NID_pkcs7_signed: if (p7->d.sign->contents != NULL) - PKCS7_content_free(p7->d.sign->contents); + PKCS7_free(p7->d.sign->contents); p7->d.sign->contents=p7_data; break; case NID_pkcs7_digest: + if (p7->d.digest->contents != NULL) + PKCS7_free(p7->d.digest->contents); + p7->d.digest->contents=p7_data; + break; case NID_pkcs7_data: case NID_pkcs7_enveloped: case NID_pkcs7_signedAndEnveloped: @@ -144,7 +160,7 @@ int PKCS7_set_type(PKCS7 *p7, int type) { ASN1_OBJECT *obj; - PKCS7_content_free(p7); + /*PKCS7_content_free(p7);*/ obj=OBJ_nid2obj(type); /* will not fail */ switch (type) @@ -153,11 +169,16 @@ int PKCS7_set_type(PKCS7 *p7, int type) p7->type=obj; if ((p7->d.sign=PKCS7_SIGNED_new()) == NULL) goto err; - ASN1_INTEGER_set(p7->d.sign->version,1); + if (!ASN1_INTEGER_set(p7->d.sign->version,1)) + { + PKCS7_SIGNED_free(p7->d.sign); + p7->d.sign=NULL; + goto err; + } break; case NID_pkcs7_data: p7->type=obj; - if ((p7->d.data=ASN1_OCTET_STRING_new()) == NULL) + if ((p7->d.data=M_ASN1_OCTET_STRING_new()) == NULL) goto err; break; case NID_pkcs7_signedAndEnveloped: @@ -165,18 +186,37 @@ int PKCS7_set_type(PKCS7 *p7, int type) if ((p7->d.signed_and_enveloped=PKCS7_SIGN_ENVELOPE_new()) == NULL) goto err; ASN1_INTEGER_set(p7->d.signed_and_enveloped->version,1); -/* p7->d.signed_and_enveloped->enc_data->content_type= - OBJ_nid2obj(NID_pkcs7_encrypted);*/ - + if (!ASN1_INTEGER_set(p7->d.signed_and_enveloped->version,1)) + goto err; + p7->d.signed_and_enveloped->enc_data->content_type + = OBJ_nid2obj(NID_pkcs7_data); break; case NID_pkcs7_enveloped: p7->type=obj; if ((p7->d.enveloped=PKCS7_ENVELOPE_new()) == NULL) goto err; - ASN1_INTEGER_set(p7->d.enveloped->version,0); + if (!ASN1_INTEGER_set(p7->d.enveloped->version,0)) + goto err; + p7->d.enveloped->enc_data->content_type + = OBJ_nid2obj(NID_pkcs7_data); break; - case NID_pkcs7_digest: case NID_pkcs7_encrypted: + p7->type=obj; + if ((p7->d.encrypted=PKCS7_ENCRYPT_new()) + == NULL) goto err; + if (!ASN1_INTEGER_set(p7->d.encrypted->version,0)) + goto err; + p7->d.encrypted->enc_data->content_type + = OBJ_nid2obj(NID_pkcs7_data); + break; + + case NID_pkcs7_digest: + p7->type=obj; + if ((p7->d.digest=PKCS7_DIGEST_new()) + == NULL) goto err; + if (!ASN1_INTEGER_set(p7->d.digest->version,0)) + goto err; + break; default: PKCS7err(PKCS7_F_PKCS7_SET_TYPE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); goto err; @@ -186,11 +226,18 @@ err: return(0); } +int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other) + { + p7->type = OBJ_nid2obj(type); + p7->d.other = other; + return 1; + } + int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi) { int i,j,nid; X509_ALGOR *alg; - STACK *signer_sk; + STACK_OF(PKCS7_SIGNER_INFO) *signer_sk; STACK_OF(X509_ALGOR) *md_sk; i=OBJ_obj2nid(p7->type); @@ -224,12 +271,17 @@ int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi) } if (!j) /* we need to add another algorithm */ { - alg=X509_ALGOR_new(); + if(!(alg=X509_ALGOR_new()) + || !(alg->parameter = ASN1_TYPE_new())) { + PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER,ERR_R_MALLOC_FAILURE); + return(0); + } alg->algorithm=OBJ_nid2obj(nid); + alg->parameter->type = V_ASN1_NULL; sk_X509_ALGOR_push(md_sk,alg); } - sk_push(signer_sk,(char *)psi); + sk_PKCS7_SIGNER_INFO_push(signer_sk,psi); return(1); } @@ -287,62 +339,100 @@ int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl) } int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, - EVP_MD *dgst) + const EVP_MD *dgst) { + int ret; + /* We now need to add another PKCS7_SIGNER_INFO entry */ - ASN1_INTEGER_set(p7i->version,1); - X509_NAME_set(&p7i->issuer_and_serial->issuer, - X509_get_issuer_name(x509)); + if (!ASN1_INTEGER_set(p7i->version,1)) + goto err; + if (!X509_NAME_set(&p7i->issuer_and_serial->issuer, + X509_get_issuer_name(x509))) + goto err; /* because ASN1_INTEGER_set is used to set a 'long' we will do * things the ugly way. */ - ASN1_INTEGER_free(p7i->issuer_and_serial->serial); - p7i->issuer_and_serial->serial= - ASN1_INTEGER_dup(X509_get_serialNumber(x509)); + M_ASN1_INTEGER_free(p7i->issuer_and_serial->serial); + if (!(p7i->issuer_and_serial->serial= + M_ASN1_INTEGER_dup(X509_get_serialNumber(x509)))) + goto err; /* lets keep the pkey around for a while */ CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY); p7i->pkey=pkey; /* Set the algorithms */ - if (pkey->type == EVP_PKEY_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; - p7i->digest_enc_alg->algorithm=OBJ_nid2obj(EVP_PKEY_type(pkey->type)); + 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); - if ((p7i->digest_enc_alg->parameter=ASN1_TYPE_new()) == NULL) - goto err; - p7i->digest_enc_alg->parameter->type=V_ASN1_NULL; - - return(1); + if (pkey->ameth && pkey->ameth->pkey_ctrl) + { + 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; + } + } + 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, - EVP_MD *dgst) + 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: + if (si) + PKCS7_SIGNER_INFO_free(si); return(NULL); } -STACK *PKCS7_get_signer_info(PKCS7 *p7) +int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md) + { + if (PKCS7_type_is_digest(p7)) + { + if(!(p7->d.digest->md->parameter = ASN1_TYPE_new())) + { + PKCS7err(PKCS7_F_PKCS7_SET_DIGEST,ERR_R_MALLOC_FAILURE); + return 0; + } + p7->d.digest->md->parameter->type = V_ASN1_NULL; + p7->d.digest->md->algorithm = OBJ_nid2obj(EVP_MD_nid(md)); + return 1; + } + + PKCS7err(PKCS7_F_PKCS7_SET_DIGEST,PKCS7_R_WRONG_CONTENT_TYPE); + return 1; + } + +STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7) { if (PKCS7_type_is_signed(p7)) { @@ -356,6 +446,23 @@ STACK *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; + } + +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; @@ -363,15 +470,17 @@ PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509) 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: - return(NULL); + if (ri) + PKCS7_RECIP_INFO_free(ri); + return NULL; } int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri) { int i; - STACK *sk; + STACK_OF(PKCS7_RECIP_INFO) *sk; i=OBJ_obj2nid(p7->type); switch (i) @@ -387,29 +496,60 @@ int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri) return(0); } - sk_push(sk,(char *)ri); + sk_PKCS7_RECIP_INFO_push(sk,ri); return(1); } int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509) { - ASN1_INTEGER_set(p7i->version,0); - X509_NAME_set(&p7i->issuer_and_serial->issuer, - X509_get_issuer_name(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, + X509_get_issuer_name(x509))) + return 0; + + M_ASN1_INTEGER_free(p7i->issuer_and_serial->serial); + if (!(p7i->issuer_and_serial->serial= + M_ASN1_INTEGER_dup(X509_get_serialNumber(x509)))) + 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; + } - ASN1_INTEGER_free(p7i->issuer_and_serial->serial); - p7i->issuer_and_serial->serial= - ASN1_INTEGER_dup(X509_get_serialNumber(x509)); + 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; + } - X509_ALGOR_free(p7i->key_enc_algor); - p7i->key_enc_algor=(X509_ALGOR *)ASN1_dup(i2d_X509_ALGOR, - (char *(*)())d2i_X509_ALGOR, - (char *)x509->cert_info->key->algor); + 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) @@ -425,6 +565,7 @@ X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si) int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher) { int i; + ASN1_OBJECT *objtmp; PKCS7_ENC_CONTENT *ec; i=OBJ_obj2nid(p7->type); @@ -441,9 +582,65 @@ int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher) return(0); } - /* Setup cipher OID */ + /* Check cipher OID exists and has data in it*/ + i = EVP_CIPHER_type(cipher); + if(i == NID_undef) { + 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; + } + + + + +