155714Skris/* crypto/pkcs7/pk7_doit.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 8280297Sjkim * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15280297Sjkim * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 22280297Sjkim * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 37280297Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40280297Sjkim * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 52280297Sjkim * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 6055714Skris#include "cryptlib.h" 6155714Skris#include <openssl/rand.h> 6255714Skris#include <openssl/objects.h> 6355714Skris#include <openssl/x509.h> 6459191Skris#include <openssl/x509v3.h> 65160814Ssimon#include <openssl/err.h> 6655714Skris 6755714Skrisstatic int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, 68280297Sjkim void *value); 6955714Skrisstatic ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid); 7055714Skris 71280297Sjkimstatic int PKCS7_type_is_other(PKCS7 *p7) 72280297Sjkim{ 73280297Sjkim int isOther = 1; 74100928Snectar 75280297Sjkim int nid = OBJ_obj2nid(p7->type); 76100928Snectar 77280297Sjkim switch (nid) { 78280297Sjkim case NID_pkcs7_data: 79280297Sjkim case NID_pkcs7_signed: 80280297Sjkim case NID_pkcs7_enveloped: 81280297Sjkim case NID_pkcs7_signedAndEnveloped: 82280297Sjkim case NID_pkcs7_digest: 83280297Sjkim case NID_pkcs7_encrypted: 84280297Sjkim isOther = 0; 85280297Sjkim break; 86280297Sjkim default: 87280297Sjkim isOther = 1; 88280297Sjkim } 89100928Snectar 90280297Sjkim return isOther; 91100928Snectar 92280297Sjkim} 93280297Sjkim 94127128Snectarstatic ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7) 95280297Sjkim{ 96280297Sjkim if (PKCS7_type_is_data(p7)) 97280297Sjkim return p7->d.data; 98280297Sjkim if (PKCS7_type_is_other(p7) && p7->d.other 99280297Sjkim && (p7->d.other->type == V_ASN1_OCTET_STRING)) 100280297Sjkim return p7->d.other->value.octet_string; 101280297Sjkim return NULL; 102280297Sjkim} 103100928Snectar 104160814Ssimonstatic int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg) 105280297Sjkim{ 106280297Sjkim BIO *btmp; 107280297Sjkim const EVP_MD *md; 108280297Sjkim if ((btmp = BIO_new(BIO_f_md())) == NULL) { 109280297Sjkim PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, ERR_R_BIO_LIB); 110280297Sjkim goto err; 111280297Sjkim } 112160814Ssimon 113280297Sjkim md = EVP_get_digestbyobj(alg->algorithm); 114280297Sjkim if (md == NULL) { 115280297Sjkim PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, PKCS7_R_UNKNOWN_DIGEST_TYPE); 116280297Sjkim goto err; 117280297Sjkim } 118160814Ssimon 119280297Sjkim BIO_set_md(btmp, md); 120280297Sjkim if (*pbio == NULL) 121280297Sjkim *pbio = btmp; 122280297Sjkim else if (!BIO_push(*pbio, btmp)) { 123280297Sjkim PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, ERR_R_BIO_LIB); 124280297Sjkim goto err; 125280297Sjkim } 126280297Sjkim btmp = NULL; 127160814Ssimon 128280297Sjkim return 1; 129160814Ssimon 130280297Sjkim err: 131280297Sjkim if (btmp) 132280297Sjkim BIO_free(btmp); 133280297Sjkim return 0; 134160814Ssimon 135280297Sjkim} 136160814Ssimon 137238405Sjkimstatic int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, 138280297Sjkim unsigned char *key, int keylen) 139280297Sjkim{ 140280297Sjkim EVP_PKEY_CTX *pctx = NULL; 141280297Sjkim EVP_PKEY *pkey = NULL; 142280297Sjkim unsigned char *ek = NULL; 143280297Sjkim int ret = 0; 144280297Sjkim size_t eklen; 145238405Sjkim 146280297Sjkim pkey = X509_get_pubkey(ri->cert); 147238405Sjkim 148280297Sjkim if (!pkey) 149280297Sjkim return 0; 150238405Sjkim 151280297Sjkim pctx = EVP_PKEY_CTX_new(pkey, NULL); 152280297Sjkim if (!pctx) 153280297Sjkim return 0; 154238405Sjkim 155280297Sjkim if (EVP_PKEY_encrypt_init(pctx) <= 0) 156280297Sjkim goto err; 157238405Sjkim 158280297Sjkim if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT, 159280297Sjkim EVP_PKEY_CTRL_PKCS7_ENCRYPT, 0, ri) <= 0) { 160280297Sjkim PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, PKCS7_R_CTRL_ERROR); 161280297Sjkim goto err; 162280297Sjkim } 163238405Sjkim 164280297Sjkim if (EVP_PKEY_encrypt(pctx, NULL, &eklen, key, keylen) <= 0) 165280297Sjkim goto err; 166238405Sjkim 167280297Sjkim ek = OPENSSL_malloc(eklen); 168238405Sjkim 169280297Sjkim if (ek == NULL) { 170280297Sjkim PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, ERR_R_MALLOC_FAILURE); 171280297Sjkim goto err; 172280297Sjkim } 173238405Sjkim 174280297Sjkim if (EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen) <= 0) 175280297Sjkim goto err; 176238405Sjkim 177280297Sjkim ASN1_STRING_set0(ri->enc_key, ek, eklen); 178280297Sjkim ek = NULL; 179238405Sjkim 180280297Sjkim ret = 1; 181238405Sjkim 182280297Sjkim err: 183280297Sjkim if (pkey) 184280297Sjkim EVP_PKEY_free(pkey); 185280297Sjkim if (pctx) 186280297Sjkim EVP_PKEY_CTX_free(pctx); 187280297Sjkim if (ek) 188280297Sjkim OPENSSL_free(ek); 189280297Sjkim return ret; 190238405Sjkim 191280297Sjkim} 192238405Sjkim 193238405Sjkimstatic int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, 194352193Sjkim PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey, 195352193Sjkim size_t fixlen) 196280297Sjkim{ 197280297Sjkim EVP_PKEY_CTX *pctx = NULL; 198280297Sjkim unsigned char *ek = NULL; 199280297Sjkim size_t eklen; 200238405Sjkim 201280297Sjkim int ret = -1; 202238405Sjkim 203280297Sjkim pctx = EVP_PKEY_CTX_new(pkey, NULL); 204280297Sjkim if (!pctx) 205280297Sjkim return -1; 206238405Sjkim 207280297Sjkim if (EVP_PKEY_decrypt_init(pctx) <= 0) 208280297Sjkim goto err; 209238405Sjkim 210280297Sjkim if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT, 211280297Sjkim EVP_PKEY_CTRL_PKCS7_DECRYPT, 0, ri) <= 0) { 212280297Sjkim PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, PKCS7_R_CTRL_ERROR); 213280297Sjkim goto err; 214280297Sjkim } 215238405Sjkim 216280297Sjkim if (EVP_PKEY_decrypt(pctx, NULL, &eklen, 217280297Sjkim ri->enc_key->data, ri->enc_key->length) <= 0) 218280297Sjkim goto err; 219238405Sjkim 220280297Sjkim ek = OPENSSL_malloc(eklen); 221238405Sjkim 222280297Sjkim if (ek == NULL) { 223280297Sjkim PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_MALLOC_FAILURE); 224280297Sjkim goto err; 225280297Sjkim } 226238405Sjkim 227280297Sjkim if (EVP_PKEY_decrypt(pctx, ek, &eklen, 228352193Sjkim ri->enc_key->data, ri->enc_key->length) <= 0 229352193Sjkim || eklen == 0 230352193Sjkim || (fixlen != 0 && eklen != fixlen)) { 231280297Sjkim ret = 0; 232280297Sjkim PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB); 233280297Sjkim goto err; 234280297Sjkim } 235238405Sjkim 236280297Sjkim ret = 1; 237238405Sjkim 238280297Sjkim if (*pek) { 239280297Sjkim OPENSSL_cleanse(*pek, *peklen); 240280297Sjkim OPENSSL_free(*pek); 241280297Sjkim } 242238405Sjkim 243280297Sjkim *pek = ek; 244280297Sjkim *peklen = eklen; 245238405Sjkim 246280297Sjkim err: 247280297Sjkim if (pctx) 248280297Sjkim EVP_PKEY_CTX_free(pctx); 249280297Sjkim if (!ret && ek) 250280297Sjkim OPENSSL_free(ek); 251238405Sjkim 252280297Sjkim return ret; 253280297Sjkim} 254238405Sjkim 25555714SkrisBIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) 256280297Sjkim{ 257280297Sjkim int i; 258280297Sjkim BIO *out = NULL, *btmp = NULL; 259280297Sjkim X509_ALGOR *xa = NULL; 260280297Sjkim const EVP_CIPHER *evp_cipher = NULL; 261280297Sjkim STACK_OF(X509_ALGOR) *md_sk = NULL; 262280297Sjkim STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; 263280297Sjkim X509_ALGOR *xalg = NULL; 264280297Sjkim PKCS7_RECIP_INFO *ri = NULL; 265280297Sjkim ASN1_OCTET_STRING *os = NULL; 26655714Skris 267280297Sjkim if (p7 == NULL) { 268280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER); 269280297Sjkim return NULL; 270280297Sjkim } 271280297Sjkim /* 272280297Sjkim * The content field in the PKCS7 ContentInfo is optional, but that really 273280297Sjkim * only applies to inner content (precisely, detached signatures). 274280297Sjkim * 275280297Sjkim * When reading content, missing outer content is therefore treated as an 276280297Sjkim * error. 277280297Sjkim * 278280297Sjkim * When creating content, PKCS7_content_new() must be called before 279280297Sjkim * calling this method, so a NULL p7->d is always an error. 280280297Sjkim */ 281280297Sjkim if (p7->d.ptr == NULL) { 282280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT); 283280297Sjkim return NULL; 284280297Sjkim } 28555714Skris 286280297Sjkim i = OBJ_obj2nid(p7->type); 287280297Sjkim p7->state = PKCS7_S_HEADER; 28855714Skris 289280297Sjkim switch (i) { 290280297Sjkim case NID_pkcs7_signed: 291280297Sjkim md_sk = p7->d.sign->md_algs; 292280297Sjkim os = PKCS7_get_octet_string(p7->d.sign->contents); 293280297Sjkim break; 294280297Sjkim case NID_pkcs7_signedAndEnveloped: 295280297Sjkim rsk = p7->d.signed_and_enveloped->recipientinfo; 296280297Sjkim md_sk = p7->d.signed_and_enveloped->md_algs; 297280297Sjkim xalg = p7->d.signed_and_enveloped->enc_data->algorithm; 298280297Sjkim evp_cipher = p7->d.signed_and_enveloped->enc_data->cipher; 299280297Sjkim if (evp_cipher == NULL) { 300280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); 301280297Sjkim goto err; 302280297Sjkim } 303280297Sjkim break; 304280297Sjkim case NID_pkcs7_enveloped: 305280297Sjkim rsk = p7->d.enveloped->recipientinfo; 306280297Sjkim xalg = p7->d.enveloped->enc_data->algorithm; 307280297Sjkim evp_cipher = p7->d.enveloped->enc_data->cipher; 308280297Sjkim if (evp_cipher == NULL) { 309280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); 310280297Sjkim goto err; 311280297Sjkim } 312280297Sjkim break; 313280297Sjkim case NID_pkcs7_digest: 314280297Sjkim xa = p7->d.digest->md; 315280297Sjkim os = PKCS7_get_octet_string(p7->d.digest->contents); 316280297Sjkim break; 317280297Sjkim case NID_pkcs7_data: 318280297Sjkim break; 319280297Sjkim default: 320280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 321280297Sjkim goto err; 322280297Sjkim } 32355714Skris 324280297Sjkim for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) 325280297Sjkim if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i))) 326280297Sjkim goto err; 32755714Skris 328280297Sjkim if (xa && !PKCS7_bio_add_digest(&out, xa)) 329280297Sjkim goto err; 33055714Skris 331280297Sjkim if (evp_cipher != NULL) { 332280297Sjkim unsigned char key[EVP_MAX_KEY_LENGTH]; 333280297Sjkim unsigned char iv[EVP_MAX_IV_LENGTH]; 334280297Sjkim int keylen, ivlen; 335280297Sjkim EVP_CIPHER_CTX *ctx; 33655714Skris 337280297Sjkim if ((btmp = BIO_new(BIO_f_cipher())) == NULL) { 338280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAINIT, ERR_R_BIO_LIB); 339280297Sjkim goto err; 340280297Sjkim } 341280297Sjkim BIO_get_cipher_ctx(btmp, &ctx); 342280297Sjkim keylen = EVP_CIPHER_key_length(evp_cipher); 343280297Sjkim ivlen = EVP_CIPHER_iv_length(evp_cipher); 344280297Sjkim xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); 345280297Sjkim if (ivlen > 0) 346306195Sjkim if (RAND_bytes(iv, ivlen) <= 0) 347280297Sjkim goto err; 348280297Sjkim if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1) <= 0) 349280297Sjkim goto err; 350280297Sjkim if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0) 351280297Sjkim goto err; 352280297Sjkim if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0) 353280297Sjkim goto err; 35455714Skris 355280297Sjkim if (ivlen > 0) { 356280297Sjkim if (xalg->parameter == NULL) { 357280297Sjkim xalg->parameter = ASN1_TYPE_new(); 358280297Sjkim if (xalg->parameter == NULL) 359280297Sjkim goto err; 360280297Sjkim } 361280297Sjkim if (EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0) 362280297Sjkim goto err; 363280297Sjkim } 36455714Skris 365280297Sjkim /* Lets do the pub key stuff :-) */ 366280297Sjkim for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { 367280297Sjkim ri = sk_PKCS7_RECIP_INFO_value(rsk, i); 368280297Sjkim if (pkcs7_encode_rinfo(ri, key, keylen) <= 0) 369280297Sjkim goto err; 370280297Sjkim } 371280297Sjkim OPENSSL_cleanse(key, keylen); 37255714Skris 373280297Sjkim if (out == NULL) 374280297Sjkim out = btmp; 375280297Sjkim else 376280297Sjkim BIO_push(out, btmp); 377280297Sjkim btmp = NULL; 378280297Sjkim } 37955714Skris 380280297Sjkim if (bio == NULL) { 381331638Sjkim if (PKCS7_is_detached(p7)) { 382280297Sjkim bio = BIO_new(BIO_s_null()); 383331638Sjkim } else if (os && os->length > 0) { 384280297Sjkim bio = BIO_new_mem_buf(os->data, os->length); 385331638Sjkim } else { 386280297Sjkim bio = BIO_new(BIO_s_mem()); 387280297Sjkim if (bio == NULL) 388280297Sjkim goto err; 389280297Sjkim BIO_set_mem_eof_return(bio, 0); 390280297Sjkim } 391331638Sjkim if (bio == NULL) 392331638Sjkim goto err; 393280297Sjkim } 394280297Sjkim if (out) 395280297Sjkim BIO_push(out, bio); 396280297Sjkim else 397280297Sjkim out = bio; 398280297Sjkim bio = NULL; 399280297Sjkim if (0) { 400280297Sjkim err: 401280297Sjkim if (out != NULL) 402280297Sjkim BIO_free_all(out); 403280297Sjkim if (btmp != NULL) 404280297Sjkim BIO_free_all(btmp); 405280297Sjkim out = NULL; 406280297Sjkim } 407280297Sjkim return (out); 408280297Sjkim} 409280297Sjkim 410160814Ssimonstatic int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert) 411280297Sjkim{ 412280297Sjkim int ret; 413280297Sjkim ret = X509_NAME_cmp(ri->issuer_and_serial->issuer, 414280297Sjkim pcert->cert_info->issuer); 415280297Sjkim if (ret) 416280297Sjkim return ret; 417280297Sjkim return M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber, 418280297Sjkim ri->issuer_and_serial->serial); 419280297Sjkim} 420160814Ssimon 42155714Skris/* int */ 42255714SkrisBIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) 423280297Sjkim{ 424280297Sjkim int i, j; 425280297Sjkim BIO *out = NULL, *btmp = NULL, *etmp = NULL, *bio = NULL; 426280297Sjkim X509_ALGOR *xa; 427280297Sjkim ASN1_OCTET_STRING *data_body = NULL; 428280297Sjkim const EVP_MD *evp_md; 429280297Sjkim const EVP_CIPHER *evp_cipher = NULL; 430280297Sjkim EVP_CIPHER_CTX *evp_ctx = NULL; 431280297Sjkim X509_ALGOR *enc_alg = NULL; 432280297Sjkim STACK_OF(X509_ALGOR) *md_sk = NULL; 433280297Sjkim STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; 434280297Sjkim PKCS7_RECIP_INFO *ri = NULL; 435280297Sjkim unsigned char *ek = NULL, *tkey = NULL; 436280297Sjkim int eklen = 0, tkeylen = 0; 43755714Skris 438280297Sjkim if (p7 == NULL) { 439280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER); 440280297Sjkim return NULL; 441280297Sjkim } 44255714Skris 443280297Sjkim if (p7->d.ptr == NULL) { 444280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); 445280297Sjkim return NULL; 446280297Sjkim } 44755714Skris 448280297Sjkim i = OBJ_obj2nid(p7->type); 449280297Sjkim p7->state = PKCS7_S_HEADER; 45055714Skris 451280297Sjkim switch (i) { 452280297Sjkim case NID_pkcs7_signed: 453284283Sjkim /* 454284283Sjkim * p7->d.sign->contents is a PKCS7 structure consisting of a contentType 455284283Sjkim * field and optional content. 456284283Sjkim * data_body is NULL if that structure has no (=detached) content 457284283Sjkim * or if the contentType is wrong (i.e., not "data"). 458284283Sjkim */ 459280297Sjkim data_body = PKCS7_get_octet_string(p7->d.sign->contents); 460280297Sjkim if (!PKCS7_is_detached(p7) && data_body == NULL) { 461280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, 462280297Sjkim PKCS7_R_INVALID_SIGNED_DATA_TYPE); 463280297Sjkim goto err; 464280297Sjkim } 465280297Sjkim md_sk = p7->d.sign->md_algs; 466280297Sjkim break; 467280297Sjkim case NID_pkcs7_signedAndEnveloped: 468280297Sjkim rsk = p7->d.signed_and_enveloped->recipientinfo; 469280297Sjkim md_sk = p7->d.signed_and_enveloped->md_algs; 470284283Sjkim /* data_body is NULL if the optional EncryptedContent is missing. */ 471280297Sjkim data_body = p7->d.signed_and_enveloped->enc_data->enc_data; 472280297Sjkim enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm; 473280297Sjkim evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); 474280297Sjkim if (evp_cipher == NULL) { 475280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, 476280297Sjkim PKCS7_R_UNSUPPORTED_CIPHER_TYPE); 477280297Sjkim goto err; 478280297Sjkim } 479280297Sjkim break; 480280297Sjkim case NID_pkcs7_enveloped: 481280297Sjkim rsk = p7->d.enveloped->recipientinfo; 482280297Sjkim enc_alg = p7->d.enveloped->enc_data->algorithm; 483284283Sjkim /* data_body is NULL if the optional EncryptedContent is missing. */ 484280297Sjkim data_body = p7->d.enveloped->enc_data->enc_data; 485280297Sjkim evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); 486280297Sjkim if (evp_cipher == NULL) { 487280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, 488280297Sjkim PKCS7_R_UNSUPPORTED_CIPHER_TYPE); 489280297Sjkim goto err; 490280297Sjkim } 491280297Sjkim break; 492280297Sjkim default: 493280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 494280297Sjkim goto err; 495280297Sjkim } 49655714Skris 497284283Sjkim /* Detached content must be supplied via in_bio instead. */ 498284283Sjkim if (data_body == NULL && in_bio == NULL) { 499284283Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); 500284283Sjkim goto err; 501284283Sjkim } 502284283Sjkim 503280297Sjkim /* We will be checking the signature */ 504280297Sjkim if (md_sk != NULL) { 505280297Sjkim for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) { 506280297Sjkim xa = sk_X509_ALGOR_value(md_sk, i); 507280297Sjkim if ((btmp = BIO_new(BIO_f_md())) == NULL) { 508280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_BIO_LIB); 509280297Sjkim goto err; 510280297Sjkim } 51155714Skris 512280297Sjkim j = OBJ_obj2nid(xa->algorithm); 513280297Sjkim evp_md = EVP_get_digestbynid(j); 514280297Sjkim if (evp_md == NULL) { 515280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, 516280297Sjkim PKCS7_R_UNKNOWN_DIGEST_TYPE); 517280297Sjkim goto err; 518280297Sjkim } 519280297Sjkim 520280297Sjkim BIO_set_md(btmp, evp_md); 521280297Sjkim if (out == NULL) 522280297Sjkim out = btmp; 523280297Sjkim else 524280297Sjkim BIO_push(out, btmp); 525280297Sjkim btmp = NULL; 526280297Sjkim } 527280297Sjkim } 528280297Sjkim 529280297Sjkim if (evp_cipher != NULL) { 53055714Skris#if 0 531280297Sjkim unsigned char key[EVP_MAX_KEY_LENGTH]; 532280297Sjkim unsigned char iv[EVP_MAX_IV_LENGTH]; 533280297Sjkim unsigned char *p; 534280297Sjkim int keylen, ivlen; 535280297Sjkim int max; 536280297Sjkim X509_OBJECT ret; 53755714Skris#endif 53855714Skris 539280297Sjkim if ((etmp = BIO_new(BIO_f_cipher())) == NULL) { 540280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_BIO_LIB); 541280297Sjkim goto err; 542280297Sjkim } 54355714Skris 544280297Sjkim /* 545280297Sjkim * It was encrypted, we need to decrypt the secret key with the 546280297Sjkim * private key 547280297Sjkim */ 54855714Skris 549280297Sjkim /* 550280297Sjkim * Find the recipientInfo which matches the passed certificate (if 551280297Sjkim * any) 552280297Sjkim */ 55355714Skris 554280297Sjkim if (pcert) { 555280297Sjkim for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { 556280297Sjkim ri = sk_PKCS7_RECIP_INFO_value(rsk, i); 557280297Sjkim if (!pkcs7_cmp_ri(ri, pcert)) 558280297Sjkim break; 559280297Sjkim ri = NULL; 560280297Sjkim } 561280297Sjkim if (ri == NULL) { 562280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, 563280297Sjkim PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); 564280297Sjkim goto err; 565280297Sjkim } 566280297Sjkim } 56755714Skris 568280297Sjkim /* If we haven't got a certificate try each ri in turn */ 569280297Sjkim if (pcert == NULL) { 570280297Sjkim /* 571280297Sjkim * Always attempt to decrypt all rinfo even after sucess as a 572280297Sjkim * defence against MMA timing attacks. 573280297Sjkim */ 574280297Sjkim for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { 575280297Sjkim ri = sk_PKCS7_RECIP_INFO_value(rsk, i); 57655714Skris 577352193Sjkim if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, 578352193Sjkim EVP_CIPHER_key_length(evp_cipher)) < 0) 579280297Sjkim goto err; 580280297Sjkim ERR_clear_error(); 581280297Sjkim } 582280297Sjkim } else { 583280297Sjkim /* Only exit on fatal errors, not decrypt failure */ 584352193Sjkim if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, 0) < 0) 585280297Sjkim goto err; 586280297Sjkim ERR_clear_error(); 587280297Sjkim } 58855714Skris 589280297Sjkim evp_ctx = NULL; 590280297Sjkim BIO_get_cipher_ctx(etmp, &evp_ctx); 591280297Sjkim if (EVP_CipherInit_ex(evp_ctx, evp_cipher, NULL, NULL, NULL, 0) <= 0) 592280297Sjkim goto err; 593280297Sjkim if (EVP_CIPHER_asn1_to_param(evp_ctx, enc_alg->parameter) < 0) 594280297Sjkim goto err; 595280297Sjkim /* Generate random key as MMA defence */ 596280297Sjkim tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx); 597280297Sjkim tkey = OPENSSL_malloc(tkeylen); 598280297Sjkim if (!tkey) 599280297Sjkim goto err; 600280297Sjkim if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0) 601280297Sjkim goto err; 602280297Sjkim if (ek == NULL) { 603280297Sjkim ek = tkey; 604280297Sjkim eklen = tkeylen; 605280297Sjkim tkey = NULL; 606280297Sjkim } 60755714Skris 608280297Sjkim if (eklen != EVP_CIPHER_CTX_key_length(evp_ctx)) { 609280297Sjkim /* 610280297Sjkim * Some S/MIME clients don't use the same key and effective key 611280297Sjkim * length. The key length is determined by the size of the 612280297Sjkim * decrypted RSA key. 613280297Sjkim */ 614280297Sjkim if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen)) { 615280297Sjkim /* Use random key as MMA defence */ 616280297Sjkim OPENSSL_cleanse(ek, eklen); 617280297Sjkim OPENSSL_free(ek); 618280297Sjkim ek = tkey; 619280297Sjkim eklen = tkeylen; 620280297Sjkim tkey = NULL; 621280297Sjkim } 622280297Sjkim } 623280297Sjkim /* Clear errors so we don't leak information useful in MMA */ 624280297Sjkim ERR_clear_error(); 625280297Sjkim if (EVP_CipherInit_ex(evp_ctx, NULL, NULL, ek, NULL, 0) <= 0) 626280297Sjkim goto err; 627234954Sbz 628280297Sjkim if (ek) { 629280297Sjkim OPENSSL_cleanse(ek, eklen); 630280297Sjkim OPENSSL_free(ek); 631280297Sjkim ek = NULL; 632280297Sjkim } 633280297Sjkim if (tkey) { 634280297Sjkim OPENSSL_cleanse(tkey, tkeylen); 635280297Sjkim OPENSSL_free(tkey); 636280297Sjkim tkey = NULL; 637280297Sjkim } 63855714Skris 639280297Sjkim if (out == NULL) 640280297Sjkim out = etmp; 641280297Sjkim else 642280297Sjkim BIO_push(out, etmp); 643280297Sjkim etmp = NULL; 644280297Sjkim } 64555714Skris#if 1 646284283Sjkim if (in_bio != NULL) { 647280297Sjkim bio = in_bio; 648280297Sjkim } else { 649280297Sjkim# if 0 650280297Sjkim bio = BIO_new(BIO_s_mem()); 651306195Sjkim if (bio == NULL) 652306195Sjkim goto err; 653280297Sjkim /* 654280297Sjkim * We need to set this so that when we have read all the data, the 655280297Sjkim * encrypt BIO, if present, will read EOF and encode the last few 656280297Sjkim * bytes 657280297Sjkim */ 658280297Sjkim BIO_set_mem_eof_return(bio, 0); 65955714Skris 660280297Sjkim if (data_body->length > 0) 661280297Sjkim BIO_write(bio, (char *)data_body->data, data_body->length); 662280297Sjkim# else 663280297Sjkim if (data_body->length > 0) 664280297Sjkim bio = BIO_new_mem_buf(data_body->data, data_body->length); 665280297Sjkim else { 666280297Sjkim bio = BIO_new(BIO_s_mem()); 667291719Sjkim if (bio == NULL) 668291719Sjkim goto err; 669280297Sjkim BIO_set_mem_eof_return(bio, 0); 670280297Sjkim } 671280297Sjkim if (bio == NULL) 672280297Sjkim goto err; 673280297Sjkim# endif 674280297Sjkim } 675280297Sjkim BIO_push(out, bio); 676280297Sjkim bio = NULL; 67759191Skris#endif 678280297Sjkim if (0) { 679280297Sjkim err: 680280297Sjkim if (ek) { 681280297Sjkim OPENSSL_cleanse(ek, eklen); 682280297Sjkim OPENSSL_free(ek); 683280297Sjkim } 684280297Sjkim if (tkey) { 685280297Sjkim OPENSSL_cleanse(tkey, tkeylen); 686280297Sjkim OPENSSL_free(tkey); 687280297Sjkim } 688280297Sjkim if (out != NULL) 689280297Sjkim BIO_free_all(out); 690280297Sjkim if (btmp != NULL) 691280297Sjkim BIO_free_all(btmp); 692280297Sjkim if (etmp != NULL) 693280297Sjkim BIO_free_all(etmp); 694280297Sjkim if (bio != NULL) 695280297Sjkim BIO_free_all(bio); 696280297Sjkim out = NULL; 697280297Sjkim } 698280297Sjkim return (out); 699280297Sjkim} 70055714Skris 701160814Ssimonstatic BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid) 702280297Sjkim{ 703280297Sjkim for (;;) { 704280297Sjkim bio = BIO_find_type(bio, BIO_TYPE_MD); 705280297Sjkim if (bio == NULL) { 706280297Sjkim PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST, 707280297Sjkim PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 708280297Sjkim return NULL; 709280297Sjkim } 710280297Sjkim BIO_get_md_ctx(bio, pmd); 711280297Sjkim if (*pmd == NULL) { 712280297Sjkim PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST, ERR_R_INTERNAL_ERROR); 713280297Sjkim return NULL; 714280297Sjkim } 715280297Sjkim if (EVP_MD_CTX_type(*pmd) == nid) 716280297Sjkim return bio; 717280297Sjkim bio = BIO_next(bio); 718280297Sjkim } 719280297Sjkim return NULL; 720280297Sjkim} 721160814Ssimon 722238405Sjkimstatic int do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx) 723280297Sjkim{ 724280297Sjkim unsigned char md_data[EVP_MAX_MD_SIZE]; 725280297Sjkim unsigned int md_len; 726238405Sjkim 727280297Sjkim /* Add signing time if not already present */ 728280297Sjkim if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) { 729280297Sjkim if (!PKCS7_add0_attrib_signing_time(si, NULL)) { 730280297Sjkim PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE); 731280297Sjkim return 0; 732280297Sjkim } 733280297Sjkim } 734238405Sjkim 735280297Sjkim /* Add digest */ 736280297Sjkim if (!EVP_DigestFinal_ex(mctx, md_data, &md_len)) { 737280297Sjkim PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_EVP_LIB); 738280297Sjkim return 0; 739280297Sjkim } 740280297Sjkim if (!PKCS7_add1_attrib_digest(si, md_data, md_len)) { 741280297Sjkim PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE); 742280297Sjkim return 0; 743280297Sjkim } 744238405Sjkim 745280297Sjkim /* Now sign the attributes */ 746280297Sjkim if (!PKCS7_SIGNER_INFO_sign(si)) 747280297Sjkim return 0; 748238405Sjkim 749280297Sjkim return 1; 750280297Sjkim} 751280297Sjkim 75255714Skrisint PKCS7_dataFinal(PKCS7 *p7, BIO *bio) 753280297Sjkim{ 754280297Sjkim int ret = 0; 755280297Sjkim int i, j; 756280297Sjkim BIO *btmp; 757280297Sjkim PKCS7_SIGNER_INFO *si; 758280297Sjkim EVP_MD_CTX *mdc, ctx_tmp; 759280297Sjkim STACK_OF(X509_ATTRIBUTE) *sk; 760280297Sjkim STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL; 761280297Sjkim ASN1_OCTET_STRING *os = NULL; 76255714Skris 763280297Sjkim if (p7 == NULL) { 764280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER); 765280297Sjkim return 0; 766280297Sjkim } 76755714Skris 768280297Sjkim if (p7->d.ptr == NULL) { 769280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT); 770280297Sjkim return 0; 771280297Sjkim } 772160814Ssimon 773280297Sjkim EVP_MD_CTX_init(&ctx_tmp); 774280297Sjkim i = OBJ_obj2nid(p7->type); 775280297Sjkim p7->state = PKCS7_S_HEADER; 776160814Ssimon 777280297Sjkim switch (i) { 778280297Sjkim case NID_pkcs7_data: 779280297Sjkim os = p7->d.data; 780280297Sjkim break; 781280297Sjkim case NID_pkcs7_signedAndEnveloped: 782280297Sjkim /* XXXXXXXXXXXXXXXX */ 783280297Sjkim si_sk = p7->d.signed_and_enveloped->signer_info; 784280297Sjkim os = p7->d.signed_and_enveloped->enc_data->enc_data; 785280297Sjkim if (!os) { 786280297Sjkim os = M_ASN1_OCTET_STRING_new(); 787280297Sjkim if (!os) { 788280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); 789280297Sjkim goto err; 790280297Sjkim } 791280297Sjkim p7->d.signed_and_enveloped->enc_data->enc_data = os; 792280297Sjkim } 793280297Sjkim break; 794280297Sjkim case NID_pkcs7_enveloped: 795280297Sjkim /* XXXXXXXXXXXXXXXX */ 796280297Sjkim os = p7->d.enveloped->enc_data->enc_data; 797280297Sjkim if (!os) { 798280297Sjkim os = M_ASN1_OCTET_STRING_new(); 799280297Sjkim if (!os) { 800280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); 801280297Sjkim goto err; 802280297Sjkim } 803280297Sjkim p7->d.enveloped->enc_data->enc_data = os; 804280297Sjkim } 805280297Sjkim break; 806280297Sjkim case NID_pkcs7_signed: 807280297Sjkim si_sk = p7->d.sign->signer_info; 808280297Sjkim os = PKCS7_get_octet_string(p7->d.sign->contents); 809280297Sjkim /* If detached data then the content is excluded */ 810280297Sjkim if (PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) { 811280297Sjkim M_ASN1_OCTET_STRING_free(os); 812280297Sjkim os = NULL; 813280297Sjkim p7->d.sign->contents->d.data = NULL; 814280297Sjkim } 815280297Sjkim break; 81655714Skris 817280297Sjkim case NID_pkcs7_digest: 818280297Sjkim os = PKCS7_get_octet_string(p7->d.digest->contents); 819280297Sjkim /* If detached data then the content is excluded */ 820280297Sjkim if (PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) { 821280297Sjkim M_ASN1_OCTET_STRING_free(os); 822280297Sjkim os = NULL; 823280297Sjkim p7->d.digest->contents->d.data = NULL; 824280297Sjkim } 825280297Sjkim break; 82655714Skris 827280297Sjkim default: 828280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 829280297Sjkim goto err; 830280297Sjkim } 83155714Skris 832280297Sjkim if (si_sk != NULL) { 833280297Sjkim for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(si_sk); i++) { 834280297Sjkim si = sk_PKCS7_SIGNER_INFO_value(si_sk, i); 835280297Sjkim if (si->pkey == NULL) 836280297Sjkim continue; 837160814Ssimon 838280297Sjkim j = OBJ_obj2nid(si->digest_alg->algorithm); 839160814Ssimon 840280297Sjkim btmp = bio; 841160814Ssimon 842280297Sjkim btmp = PKCS7_find_digest(&mdc, btmp, j); 84355714Skris 844280297Sjkim if (btmp == NULL) 845280297Sjkim goto err; 84655714Skris 847280297Sjkim /* 848280297Sjkim * We now have the EVP_MD_CTX, lets do the signing. 849280297Sjkim */ 850280297Sjkim if (!EVP_MD_CTX_copy_ex(&ctx_tmp, mdc)) 851280297Sjkim goto err; 85255714Skris 853280297Sjkim sk = si->auth_attr; 85455714Skris 855280297Sjkim /* 856280297Sjkim * If there are attributes, we add the digest attribute and only 857280297Sjkim * sign the attributes 858280297Sjkim */ 859280297Sjkim if (sk_X509_ATTRIBUTE_num(sk) > 0) { 860280297Sjkim if (!do_pkcs7_signed_attrib(si, &ctx_tmp)) 861280297Sjkim goto err; 862280297Sjkim } else { 863280297Sjkim unsigned char *abuf = NULL; 864280297Sjkim unsigned int abuflen; 865280297Sjkim abuflen = EVP_PKEY_size(si->pkey); 866280297Sjkim abuf = OPENSSL_malloc(abuflen); 867280297Sjkim if (!abuf) 868280297Sjkim goto err; 86955714Skris 870280297Sjkim if (!EVP_SignFinal(&ctx_tmp, abuf, &abuflen, si->pkey)) { 871280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_EVP_LIB); 872280297Sjkim goto err; 873280297Sjkim } 874280297Sjkim ASN1_STRING_set0(si->enc_digest, abuf, abuflen); 875280297Sjkim } 876280297Sjkim } 877280297Sjkim } else if (i == NID_pkcs7_digest) { 878280297Sjkim unsigned char md_data[EVP_MAX_MD_SIZE]; 879280297Sjkim unsigned int md_len; 880280297Sjkim if (!PKCS7_find_digest(&mdc, bio, 881280297Sjkim OBJ_obj2nid(p7->d.digest->md->algorithm))) 882280297Sjkim goto err; 883280297Sjkim if (!EVP_DigestFinal_ex(mdc, md_data, &md_len)) 884280297Sjkim goto err; 885280297Sjkim M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len); 886280297Sjkim } 887280297Sjkim 888280297Sjkim if (!PKCS7_is_detached(p7)) { 889280297Sjkim /* 890280297Sjkim * NOTE(emilia): I think we only reach os == NULL here because detached 891280297Sjkim * digested data support is broken. 892280297Sjkim */ 893280297Sjkim if (os == NULL) 894280297Sjkim goto err; 895280297Sjkim if (!(os->flags & ASN1_STRING_FLAG_NDEF)) { 896280297Sjkim char *cont; 897280297Sjkim long contlen; 898280297Sjkim btmp = BIO_find_type(bio, BIO_TYPE_MEM); 899280297Sjkim if (btmp == NULL) { 900280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNABLE_TO_FIND_MEM_BIO); 901280297Sjkim goto err; 902280297Sjkim } 903280297Sjkim contlen = BIO_get_mem_data(btmp, &cont); 904280297Sjkim /* 905280297Sjkim * Mark the BIO read only then we can use its copy of the data 906280297Sjkim * instead of making an extra copy. 907280297Sjkim */ 908280297Sjkim BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); 909280297Sjkim BIO_set_mem_eof_return(btmp, 0); 910280297Sjkim ASN1_STRING_set0(os, (unsigned char *)cont, contlen); 911280297Sjkim } 912280297Sjkim } 913280297Sjkim ret = 1; 914280297Sjkim err: 915280297Sjkim EVP_MD_CTX_cleanup(&ctx_tmp); 916280297Sjkim return (ret); 917280297Sjkim} 918280297Sjkim 919238405Sjkimint PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) 920280297Sjkim{ 921280297Sjkim EVP_MD_CTX mctx; 922280297Sjkim EVP_PKEY_CTX *pctx; 923280297Sjkim unsigned char *abuf = NULL; 924280297Sjkim int alen; 925280297Sjkim size_t siglen; 926280297Sjkim const EVP_MD *md = NULL; 927238405Sjkim 928280297Sjkim md = EVP_get_digestbyobj(si->digest_alg->algorithm); 929280297Sjkim if (md == NULL) 930280297Sjkim return 0; 931238405Sjkim 932280297Sjkim EVP_MD_CTX_init(&mctx); 933280297Sjkim if (EVP_DigestSignInit(&mctx, &pctx, md, NULL, si->pkey) <= 0) 934280297Sjkim goto err; 935238405Sjkim 936280297Sjkim if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, 937280297Sjkim EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0) { 938280297Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); 939280297Sjkim goto err; 940280297Sjkim } 941238405Sjkim 942280297Sjkim alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr, &abuf, 943280297Sjkim ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); 944280297Sjkim if (!abuf) 945280297Sjkim goto err; 946280297Sjkim if (EVP_DigestSignUpdate(&mctx, abuf, alen) <= 0) 947280297Sjkim goto err; 948280297Sjkim OPENSSL_free(abuf); 949280297Sjkim abuf = NULL; 950280297Sjkim if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0) 951280297Sjkim goto err; 952280297Sjkim abuf = OPENSSL_malloc(siglen); 953280297Sjkim if (!abuf) 954280297Sjkim goto err; 955280297Sjkim if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0) 956280297Sjkim goto err; 957238405Sjkim 958280297Sjkim if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, 959280297Sjkim EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0) { 960280297Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); 961280297Sjkim goto err; 962280297Sjkim } 963238405Sjkim 964280297Sjkim EVP_MD_CTX_cleanup(&mctx); 965238405Sjkim 966280297Sjkim ASN1_STRING_set0(si->enc_digest, abuf, siglen); 967238405Sjkim 968280297Sjkim return 1; 969238405Sjkim 970280297Sjkim err: 971280297Sjkim if (abuf) 972280297Sjkim OPENSSL_free(abuf); 973280297Sjkim EVP_MD_CTX_cleanup(&mctx); 974280297Sjkim return 0; 975238405Sjkim 976280297Sjkim} 977238405Sjkim 97855714Skrisint PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, 979280297Sjkim PKCS7 *p7, PKCS7_SIGNER_INFO *si) 980280297Sjkim{ 981280297Sjkim PKCS7_ISSUER_AND_SERIAL *ias; 982280297Sjkim int ret = 0, i; 983280297Sjkim STACK_OF(X509) *cert; 984280297Sjkim X509 *x509; 98555714Skris 986280297Sjkim if (p7 == NULL) { 987280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_INVALID_NULL_POINTER); 988280297Sjkim return 0; 989280297Sjkim } 99055714Skris 991280297Sjkim if (p7->d.ptr == NULL) { 992280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_NO_CONTENT); 993280297Sjkim return 0; 994280297Sjkim } 99555714Skris 996280297Sjkim if (PKCS7_type_is_signed(p7)) { 997280297Sjkim cert = p7->d.sign->cert; 998280297Sjkim } else if (PKCS7_type_is_signedAndEnveloped(p7)) { 999280297Sjkim cert = p7->d.signed_and_enveloped->cert; 1000280297Sjkim } else { 1001280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); 1002280297Sjkim goto err; 1003280297Sjkim } 1004280297Sjkim /* XXXXXXXXXXXXXXXXXXXXXXX */ 1005280297Sjkim ias = si->issuer_and_serial; 100655714Skris 1007280297Sjkim x509 = X509_find_by_issuer_and_serial(cert, ias->issuer, ias->serial); 100855714Skris 1009280297Sjkim /* were we able to find the cert in passed to us */ 1010280297Sjkim if (x509 == NULL) { 1011280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, 1012280297Sjkim PKCS7_R_UNABLE_TO_FIND_CERTIFICATE); 1013280297Sjkim goto err; 1014280297Sjkim } 101555714Skris 1016280297Sjkim /* Lets verify */ 1017280297Sjkim if (!X509_STORE_CTX_init(ctx, cert_store, x509, cert)) { 1018280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, ERR_R_X509_LIB); 1019280297Sjkim goto err; 1020280297Sjkim } 1021280297Sjkim X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN); 1022280297Sjkim i = X509_verify_cert(ctx); 1023280297Sjkim if (i <= 0) { 1024280297Sjkim PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, ERR_R_X509_LIB); 1025280297Sjkim X509_STORE_CTX_cleanup(ctx); 1026280297Sjkim goto err; 1027280297Sjkim } 1028280297Sjkim X509_STORE_CTX_cleanup(ctx); 1029280297Sjkim 1030280297Sjkim return PKCS7_signatureVerify(bio, p7, si, x509); 1031280297Sjkim err: 1032280297Sjkim return ret; 1033280297Sjkim} 1034280297Sjkim 103555714Skrisint PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, 1036280297Sjkim X509 *x509) 1037280297Sjkim{ 1038280297Sjkim ASN1_OCTET_STRING *os; 1039280297Sjkim EVP_MD_CTX mdc_tmp, *mdc; 1040280297Sjkim int ret = 0, i; 1041280297Sjkim int md_type; 1042280297Sjkim STACK_OF(X509_ATTRIBUTE) *sk; 1043280297Sjkim BIO *btmp; 1044280297Sjkim EVP_PKEY *pkey; 104555714Skris 1046280297Sjkim EVP_MD_CTX_init(&mdc_tmp); 1047109998Smarkm 1048280297Sjkim if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { 1049280297Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); 1050280297Sjkim goto err; 1051280297Sjkim } 105255714Skris 1053280297Sjkim md_type = OBJ_obj2nid(si->digest_alg->algorithm); 105455714Skris 1055280297Sjkim btmp = bio; 1056280297Sjkim for (;;) { 1057280297Sjkim if ((btmp == NULL) || 1058280297Sjkim ((btmp = BIO_find_type(btmp, BIO_TYPE_MD)) == NULL)) { 1059280297Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1060280297Sjkim PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 1061280297Sjkim goto err; 1062280297Sjkim } 1063280297Sjkim BIO_get_md_ctx(btmp, &mdc); 1064280297Sjkim if (mdc == NULL) { 1065280297Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_INTERNAL_ERROR); 1066280297Sjkim goto err; 1067280297Sjkim } 1068280297Sjkim if (EVP_MD_CTX_type(mdc) == md_type) 1069280297Sjkim break; 1070280297Sjkim /* 1071280297Sjkim * Workaround for some broken clients that put the signature OID 1072280297Sjkim * instead of the digest OID in digest_alg->algorithm 1073280297Sjkim */ 1074280297Sjkim if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type) 1075280297Sjkim break; 1076280297Sjkim btmp = BIO_next(btmp); 1077280297Sjkim } 107855714Skris 1079280297Sjkim /* 1080280297Sjkim * mdc is the digest ctx that we want, unless there are attributes, in 1081280297Sjkim * which case the digest is the signed attributes 1082280297Sjkim */ 1083280297Sjkim if (!EVP_MD_CTX_copy_ex(&mdc_tmp, mdc)) 1084280297Sjkim goto err; 108555714Skris 1086280297Sjkim sk = si->auth_attr; 1087280297Sjkim if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { 1088280297Sjkim unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; 1089280297Sjkim unsigned int md_len; 1090280297Sjkim int alen; 1091280297Sjkim ASN1_OCTET_STRING *message_digest; 109255714Skris 1093280297Sjkim if (!EVP_DigestFinal_ex(&mdc_tmp, md_dat, &md_len)) 1094280297Sjkim goto err; 1095280297Sjkim message_digest = PKCS7_digest_from_attributes(sk); 1096280297Sjkim if (!message_digest) { 1097280297Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1098280297Sjkim PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 1099280297Sjkim goto err; 1100280297Sjkim } 1101280297Sjkim if ((message_digest->length != (int)md_len) || 1102280297Sjkim (memcmp(message_digest->data, md_dat, md_len))) { 110355714Skris#if 0 1104280297Sjkim { 1105280297Sjkim int ii; 1106280297Sjkim for (ii = 0; ii < message_digest->length; ii++) 1107280297Sjkim printf("%02X", message_digest->data[ii]); 1108280297Sjkim printf(" sent\n"); 1109280297Sjkim for (ii = 0; ii < md_len; ii++) 1110280297Sjkim printf("%02X", md_dat[ii]); 1111280297Sjkim printf(" calc\n"); 1112280297Sjkim } 111355714Skris#endif 1114280297Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_DIGEST_FAILURE); 1115280297Sjkim ret = -1; 1116280297Sjkim goto err; 1117280297Sjkim } 111855714Skris 1119280297Sjkim if (!EVP_VerifyInit_ex(&mdc_tmp, EVP_get_digestbynid(md_type), NULL)) 1120280297Sjkim goto err; 112155714Skris 1122280297Sjkim alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, 1123280297Sjkim ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); 1124280297Sjkim if (alen <= 0) { 1125280297Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_ASN1_LIB); 1126280297Sjkim ret = -1; 1127280297Sjkim goto err; 1128280297Sjkim } 1129280297Sjkim if (!EVP_VerifyUpdate(&mdc_tmp, abuf, alen)) 1130280297Sjkim goto err; 1131109998Smarkm 1132280297Sjkim OPENSSL_free(abuf); 1133280297Sjkim } 113455714Skris 1135280297Sjkim os = si->enc_digest; 1136280297Sjkim pkey = X509_get_pubkey(x509); 1137280297Sjkim if (!pkey) { 1138280297Sjkim ret = -1; 1139280297Sjkim goto err; 1140280297Sjkim } 114155714Skris 1142280297Sjkim i = EVP_VerifyFinal(&mdc_tmp, os->data, os->length, pkey); 1143280297Sjkim EVP_PKEY_free(pkey); 1144280297Sjkim if (i <= 0) { 1145280297Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); 1146280297Sjkim ret = -1; 1147280297Sjkim goto err; 1148280297Sjkim } else 1149280297Sjkim ret = 1; 1150280297Sjkim err: 1151280297Sjkim EVP_MD_CTX_cleanup(&mdc_tmp); 1152280297Sjkim return (ret); 1153280297Sjkim} 115455714Skris 115555714SkrisPKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx) 1156280297Sjkim{ 1157280297Sjkim STACK_OF(PKCS7_RECIP_INFO) *rsk; 1158280297Sjkim PKCS7_RECIP_INFO *ri; 1159280297Sjkim int i; 116055714Skris 1161280297Sjkim i = OBJ_obj2nid(p7->type); 1162280297Sjkim if (i != NID_pkcs7_signedAndEnveloped) 1163280297Sjkim return NULL; 1164280297Sjkim if (p7->d.signed_and_enveloped == NULL) 1165280297Sjkim return NULL; 1166280297Sjkim rsk = p7->d.signed_and_enveloped->recipientinfo; 1167280297Sjkim if (rsk == NULL) 1168280297Sjkim return NULL; 1169280297Sjkim if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) 1170280297Sjkim return (NULL); 1171280297Sjkim ri = sk_PKCS7_RECIP_INFO_value(rsk, idx); 1172280297Sjkim return (ri->issuer_and_serial); 1173280297Sjkim} 117455714Skris 117555714SkrisASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid) 1176280297Sjkim{ 1177280297Sjkim return (get_attribute(si->auth_attr, nid)); 1178280297Sjkim} 117955714Skris 118055714SkrisASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid) 1181280297Sjkim{ 1182280297Sjkim return (get_attribute(si->unauth_attr, nid)); 1183280297Sjkim} 118455714Skris 118555714Skrisstatic ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid) 1186280297Sjkim{ 1187280297Sjkim int i; 1188280297Sjkim X509_ATTRIBUTE *xa; 1189280297Sjkim ASN1_OBJECT *o; 119055714Skris 1191280297Sjkim o = OBJ_nid2obj(nid); 1192280297Sjkim if (!o || !sk) 1193280297Sjkim return (NULL); 1194280297Sjkim for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { 1195280297Sjkim xa = sk_X509_ATTRIBUTE_value(sk, i); 1196280297Sjkim if (OBJ_cmp(xa->object, o) == 0) { 1197280297Sjkim if (!xa->single && sk_ASN1_TYPE_num(xa->value.set)) 1198280297Sjkim return (sk_ASN1_TYPE_value(xa->value.set, 0)); 1199280297Sjkim else 1200280297Sjkim return (NULL); 1201280297Sjkim } 1202280297Sjkim } 1203280297Sjkim return (NULL); 1204280297Sjkim} 120555714Skris 120655714SkrisASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk) 120755714Skris{ 1208280297Sjkim ASN1_TYPE *astype; 1209280297Sjkim if (!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) 1210280297Sjkim return NULL; 1211280297Sjkim return astype->value.octet_string; 121255714Skris} 121355714Skris 121455714Skrisint PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, 1215280297Sjkim STACK_OF(X509_ATTRIBUTE) *sk) 1216280297Sjkim{ 1217280297Sjkim int i; 121855714Skris 1219280297Sjkim if (p7si->auth_attr != NULL) 1220280297Sjkim sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr, X509_ATTRIBUTE_free); 1221280297Sjkim p7si->auth_attr = sk_X509_ATTRIBUTE_dup(sk); 1222280297Sjkim if (p7si->auth_attr == NULL) 1223280297Sjkim return 0; 1224280297Sjkim for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { 1225280297Sjkim if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr, i, 1226280297Sjkim X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value 1227280297Sjkim (sk, i)))) 1228280297Sjkim == NULL) 1229280297Sjkim return (0); 1230280297Sjkim } 1231280297Sjkim return (1); 1232280297Sjkim} 123355714Skris 1234280297Sjkimint PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, 1235280297Sjkim STACK_OF(X509_ATTRIBUTE) *sk) 1236280297Sjkim{ 1237280297Sjkim int i; 123855714Skris 1239280297Sjkim if (p7si->unauth_attr != NULL) 1240280297Sjkim sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr, X509_ATTRIBUTE_free); 1241280297Sjkim p7si->unauth_attr = sk_X509_ATTRIBUTE_dup(sk); 1242280297Sjkim if (p7si->unauth_attr == NULL) 1243280297Sjkim return 0; 1244280297Sjkim for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { 1245280297Sjkim if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr, i, 1246280297Sjkim X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value 1247280297Sjkim (sk, i)))) 1248280297Sjkim == NULL) 1249280297Sjkim return (0); 1250280297Sjkim } 1251280297Sjkim return (1); 1252280297Sjkim} 125355714Skris 125455714Skrisint PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, 1255280297Sjkim void *value) 1256280297Sjkim{ 1257280297Sjkim return (add_attribute(&(p7si->auth_attr), nid, atrtype, value)); 1258280297Sjkim} 125955714Skris 126055714Skrisint PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, 1261280297Sjkim void *value) 1262280297Sjkim{ 1263280297Sjkim return (add_attribute(&(p7si->unauth_attr), nid, atrtype, value)); 1264280297Sjkim} 126555714Skris 126655714Skrisstatic int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, 1267280297Sjkim void *value) 1268280297Sjkim{ 1269280297Sjkim X509_ATTRIBUTE *attr = NULL; 127055714Skris 1271280297Sjkim if (*sk == NULL) { 1272280297Sjkim *sk = sk_X509_ATTRIBUTE_new_null(); 1273280297Sjkim if (*sk == NULL) 1274280297Sjkim return 0; 1275280297Sjkim new_attrib: 1276280297Sjkim if (!(attr = X509_ATTRIBUTE_create(nid, atrtype, value))) 1277280297Sjkim return 0; 1278280297Sjkim if (!sk_X509_ATTRIBUTE_push(*sk, attr)) { 1279280297Sjkim X509_ATTRIBUTE_free(attr); 1280280297Sjkim return 0; 1281280297Sjkim } 1282280297Sjkim } else { 1283280297Sjkim int i; 128455714Skris 1285280297Sjkim for (i = 0; i < sk_X509_ATTRIBUTE_num(*sk); i++) { 1286280297Sjkim attr = sk_X509_ATTRIBUTE_value(*sk, i); 1287280297Sjkim if (OBJ_obj2nid(attr->object) == nid) { 1288280297Sjkim X509_ATTRIBUTE_free(attr); 1289280297Sjkim attr = X509_ATTRIBUTE_create(nid, atrtype, value); 1290280297Sjkim if (attr == NULL) 1291280297Sjkim return 0; 1292280297Sjkim if (!sk_X509_ATTRIBUTE_set(*sk, i, attr)) { 1293280297Sjkim X509_ATTRIBUTE_free(attr); 1294280297Sjkim return 0; 1295280297Sjkim } 1296280297Sjkim goto end; 1297280297Sjkim } 1298280297Sjkim } 1299280297Sjkim goto new_attrib; 1300280297Sjkim } 1301280297Sjkim end: 1302280297Sjkim return (1); 1303280297Sjkim} 1304