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. 8280304Sjkim * 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). 15280304Sjkim * 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. 22280304Sjkim * 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 :-). 37280304Sjkim * 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)" 40280304Sjkim * 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. 52280304Sjkim * 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, 68280304Sjkim void *value); 6955714Skrisstatic ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid); 7055714Skris 71280304Sjkimstatic int PKCS7_type_is_other(PKCS7 *p7) 72280304Sjkim{ 73280304Sjkim int isOther = 1; 74100928Snectar 75280304Sjkim int nid = OBJ_obj2nid(p7->type); 76100928Snectar 77280304Sjkim switch (nid) { 78280304Sjkim case NID_pkcs7_data: 79280304Sjkim case NID_pkcs7_signed: 80280304Sjkim case NID_pkcs7_enveloped: 81280304Sjkim case NID_pkcs7_signedAndEnveloped: 82280304Sjkim case NID_pkcs7_digest: 83280304Sjkim case NID_pkcs7_encrypted: 84280304Sjkim isOther = 0; 85280304Sjkim break; 86280304Sjkim default: 87280304Sjkim isOther = 1; 88280304Sjkim } 89100928Snectar 90280304Sjkim return isOther; 91100928Snectar 92280304Sjkim} 93280304Sjkim 94127128Snectarstatic ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7) 95280304Sjkim{ 96280304Sjkim if (PKCS7_type_is_data(p7)) 97280304Sjkim return p7->d.data; 98280304Sjkim if (PKCS7_type_is_other(p7) && p7->d.other 99280304Sjkim && (p7->d.other->type == V_ASN1_OCTET_STRING)) 100280304Sjkim return p7->d.other->value.octet_string; 101280304Sjkim return NULL; 102280304Sjkim} 103100928Snectar 104160814Ssimonstatic int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg) 105280304Sjkim{ 106280304Sjkim BIO *btmp; 107280304Sjkim const EVP_MD *md; 108280304Sjkim if ((btmp = BIO_new(BIO_f_md())) == NULL) { 109280304Sjkim PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, ERR_R_BIO_LIB); 110280304Sjkim goto err; 111280304Sjkim } 112160814Ssimon 113280304Sjkim md = EVP_get_digestbyobj(alg->algorithm); 114280304Sjkim if (md == NULL) { 115280304Sjkim PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, PKCS7_R_UNKNOWN_DIGEST_TYPE); 116280304Sjkim goto err; 117280304Sjkim } 118160814Ssimon 119280304Sjkim BIO_set_md(btmp, md); 120280304Sjkim if (*pbio == NULL) 121280304Sjkim *pbio = btmp; 122280304Sjkim else if (!BIO_push(*pbio, btmp)) { 123280304Sjkim PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, ERR_R_BIO_LIB); 124280304Sjkim goto err; 125280304Sjkim } 126280304Sjkim btmp = NULL; 127160814Ssimon 128280304Sjkim return 1; 129160814Ssimon 130280304Sjkim err: 131280304Sjkim if (btmp) 132280304Sjkim BIO_free(btmp); 133280304Sjkim return 0; 134160814Ssimon 135280304Sjkim} 136160814Ssimon 137238405Sjkimstatic int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, 138280304Sjkim unsigned char *key, int keylen) 139280304Sjkim{ 140280304Sjkim EVP_PKEY_CTX *pctx = NULL; 141280304Sjkim EVP_PKEY *pkey = NULL; 142280304Sjkim unsigned char *ek = NULL; 143280304Sjkim int ret = 0; 144280304Sjkim size_t eklen; 145238405Sjkim 146280304Sjkim pkey = X509_get_pubkey(ri->cert); 147238405Sjkim 148280304Sjkim if (!pkey) 149280304Sjkim return 0; 150238405Sjkim 151280304Sjkim pctx = EVP_PKEY_CTX_new(pkey, NULL); 152280304Sjkim if (!pctx) 153280304Sjkim return 0; 154238405Sjkim 155280304Sjkim if (EVP_PKEY_encrypt_init(pctx) <= 0) 156280304Sjkim goto err; 157238405Sjkim 158280304Sjkim if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT, 159280304Sjkim EVP_PKEY_CTRL_PKCS7_ENCRYPT, 0, ri) <= 0) { 160280304Sjkim PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, PKCS7_R_CTRL_ERROR); 161280304Sjkim goto err; 162280304Sjkim } 163238405Sjkim 164280304Sjkim if (EVP_PKEY_encrypt(pctx, NULL, &eklen, key, keylen) <= 0) 165280304Sjkim goto err; 166238405Sjkim 167280304Sjkim ek = OPENSSL_malloc(eklen); 168238405Sjkim 169280304Sjkim if (ek == NULL) { 170280304Sjkim PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, ERR_R_MALLOC_FAILURE); 171280304Sjkim goto err; 172280304Sjkim } 173238405Sjkim 174280304Sjkim if (EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen) <= 0) 175280304Sjkim goto err; 176238405Sjkim 177280304Sjkim ASN1_STRING_set0(ri->enc_key, ek, eklen); 178280304Sjkim ek = NULL; 179238405Sjkim 180280304Sjkim ret = 1; 181238405Sjkim 182280304Sjkim err: 183280304Sjkim if (pkey) 184280304Sjkim EVP_PKEY_free(pkey); 185280304Sjkim if (pctx) 186280304Sjkim EVP_PKEY_CTX_free(pctx); 187280304Sjkim if (ek) 188280304Sjkim OPENSSL_free(ek); 189280304Sjkim return ret; 190238405Sjkim 191280304Sjkim} 192238405Sjkim 193238405Sjkimstatic int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, 194280304Sjkim PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey) 195280304Sjkim{ 196280304Sjkim EVP_PKEY_CTX *pctx = NULL; 197280304Sjkim unsigned char *ek = NULL; 198280304Sjkim size_t eklen; 199238405Sjkim 200280304Sjkim int ret = -1; 201238405Sjkim 202280304Sjkim pctx = EVP_PKEY_CTX_new(pkey, NULL); 203280304Sjkim if (!pctx) 204280304Sjkim return -1; 205238405Sjkim 206280304Sjkim if (EVP_PKEY_decrypt_init(pctx) <= 0) 207280304Sjkim goto err; 208238405Sjkim 209280304Sjkim if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT, 210280304Sjkim EVP_PKEY_CTRL_PKCS7_DECRYPT, 0, ri) <= 0) { 211280304Sjkim PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, PKCS7_R_CTRL_ERROR); 212280304Sjkim goto err; 213280304Sjkim } 214238405Sjkim 215280304Sjkim if (EVP_PKEY_decrypt(pctx, NULL, &eklen, 216280304Sjkim ri->enc_key->data, ri->enc_key->length) <= 0) 217280304Sjkim goto err; 218238405Sjkim 219280304Sjkim ek = OPENSSL_malloc(eklen); 220238405Sjkim 221280304Sjkim if (ek == NULL) { 222280304Sjkim PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_MALLOC_FAILURE); 223280304Sjkim goto err; 224280304Sjkim } 225238405Sjkim 226280304Sjkim if (EVP_PKEY_decrypt(pctx, ek, &eklen, 227280304Sjkim ri->enc_key->data, ri->enc_key->length) <= 0) { 228280304Sjkim ret = 0; 229280304Sjkim PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB); 230280304Sjkim goto err; 231280304Sjkim } 232238405Sjkim 233280304Sjkim ret = 1; 234238405Sjkim 235280304Sjkim if (*pek) { 236280304Sjkim OPENSSL_cleanse(*pek, *peklen); 237280304Sjkim OPENSSL_free(*pek); 238280304Sjkim } 239238405Sjkim 240280304Sjkim *pek = ek; 241280304Sjkim *peklen = eklen; 242238405Sjkim 243280304Sjkim err: 244280304Sjkim if (pctx) 245280304Sjkim EVP_PKEY_CTX_free(pctx); 246280304Sjkim if (!ret && ek) 247280304Sjkim OPENSSL_free(ek); 248238405Sjkim 249280304Sjkim return ret; 250280304Sjkim} 251238405Sjkim 25255714SkrisBIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) 253280304Sjkim{ 254280304Sjkim int i; 255280304Sjkim BIO *out = NULL, *btmp = NULL; 256280304Sjkim X509_ALGOR *xa = NULL; 257280304Sjkim const EVP_CIPHER *evp_cipher = NULL; 258280304Sjkim STACK_OF(X509_ALGOR) *md_sk = NULL; 259280304Sjkim STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; 260280304Sjkim X509_ALGOR *xalg = NULL; 261280304Sjkim PKCS7_RECIP_INFO *ri = NULL; 262280304Sjkim ASN1_OCTET_STRING *os = NULL; 26355714Skris 264280304Sjkim if (p7 == NULL) { 265280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER); 266280304Sjkim return NULL; 267280304Sjkim } 268280304Sjkim /* 269280304Sjkim * The content field in the PKCS7 ContentInfo is optional, but that really 270280304Sjkim * only applies to inner content (precisely, detached signatures). 271280304Sjkim * 272280304Sjkim * When reading content, missing outer content is therefore treated as an 273280304Sjkim * error. 274280304Sjkim * 275280304Sjkim * When creating content, PKCS7_content_new() must be called before 276280304Sjkim * calling this method, so a NULL p7->d is always an error. 277280304Sjkim */ 278280304Sjkim if (p7->d.ptr == NULL) { 279280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT); 280280304Sjkim return NULL; 281280304Sjkim } 282280266Sdelphij 283280304Sjkim i = OBJ_obj2nid(p7->type); 284280304Sjkim p7->state = PKCS7_S_HEADER; 28555714Skris 286280304Sjkim switch (i) { 287280304Sjkim case NID_pkcs7_signed: 288280304Sjkim md_sk = p7->d.sign->md_algs; 289280304Sjkim os = PKCS7_get_octet_string(p7->d.sign->contents); 290280304Sjkim break; 291280304Sjkim case NID_pkcs7_signedAndEnveloped: 292280304Sjkim rsk = p7->d.signed_and_enveloped->recipientinfo; 293280304Sjkim md_sk = p7->d.signed_and_enveloped->md_algs; 294280304Sjkim xalg = p7->d.signed_and_enveloped->enc_data->algorithm; 295280304Sjkim evp_cipher = p7->d.signed_and_enveloped->enc_data->cipher; 296280304Sjkim if (evp_cipher == NULL) { 297280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); 298280304Sjkim goto err; 299280304Sjkim } 300280304Sjkim break; 301280304Sjkim case NID_pkcs7_enveloped: 302280304Sjkim rsk = p7->d.enveloped->recipientinfo; 303280304Sjkim xalg = p7->d.enveloped->enc_data->algorithm; 304280304Sjkim evp_cipher = p7->d.enveloped->enc_data->cipher; 305280304Sjkim if (evp_cipher == NULL) { 306280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); 307280304Sjkim goto err; 308280304Sjkim } 309280304Sjkim break; 310280304Sjkim case NID_pkcs7_digest: 311280304Sjkim xa = p7->d.digest->md; 312280304Sjkim os = PKCS7_get_octet_string(p7->d.digest->contents); 313280304Sjkim break; 314280304Sjkim case NID_pkcs7_data: 315280304Sjkim break; 316280304Sjkim default: 317280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 318280304Sjkim goto err; 319280304Sjkim } 32055714Skris 321280304Sjkim for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) 322280304Sjkim if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i))) 323280304Sjkim goto err; 32455714Skris 325280304Sjkim if (xa && !PKCS7_bio_add_digest(&out, xa)) 326280304Sjkim goto err; 32755714Skris 328280304Sjkim if (evp_cipher != NULL) { 329280304Sjkim unsigned char key[EVP_MAX_KEY_LENGTH]; 330280304Sjkim unsigned char iv[EVP_MAX_IV_LENGTH]; 331280304Sjkim int keylen, ivlen; 332280304Sjkim EVP_CIPHER_CTX *ctx; 33355714Skris 334280304Sjkim if ((btmp = BIO_new(BIO_f_cipher())) == NULL) { 335280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAINIT, ERR_R_BIO_LIB); 336280304Sjkim goto err; 337280304Sjkim } 338280304Sjkim BIO_get_cipher_ctx(btmp, &ctx); 339280304Sjkim keylen = EVP_CIPHER_key_length(evp_cipher); 340280304Sjkim ivlen = EVP_CIPHER_iv_length(evp_cipher); 341280304Sjkim xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); 342280304Sjkim if (ivlen > 0) 343306196Sjkim if (RAND_bytes(iv, ivlen) <= 0) 344280304Sjkim goto err; 345280304Sjkim if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1) <= 0) 346280304Sjkim goto err; 347280304Sjkim if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0) 348280304Sjkim goto err; 349280304Sjkim if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0) 350280304Sjkim goto err; 35155714Skris 352280304Sjkim if (ivlen > 0) { 353280304Sjkim if (xalg->parameter == NULL) { 354280304Sjkim xalg->parameter = ASN1_TYPE_new(); 355280304Sjkim if (xalg->parameter == NULL) 356280304Sjkim goto err; 357280304Sjkim } 358280304Sjkim if (EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0) 359280304Sjkim goto err; 360280304Sjkim } 36155714Skris 362280304Sjkim /* Lets do the pub key stuff :-) */ 363280304Sjkim for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { 364280304Sjkim ri = sk_PKCS7_RECIP_INFO_value(rsk, i); 365280304Sjkim if (pkcs7_encode_rinfo(ri, key, keylen) <= 0) 366280304Sjkim goto err; 367280304Sjkim } 368280304Sjkim OPENSSL_cleanse(key, keylen); 36955714Skris 370280304Sjkim if (out == NULL) 371280304Sjkim out = btmp; 372280304Sjkim else 373280304Sjkim BIO_push(out, btmp); 374280304Sjkim btmp = NULL; 375280304Sjkim } 37655714Skris 377280304Sjkim if (bio == NULL) { 378280304Sjkim if (PKCS7_is_detached(p7)) 379280304Sjkim bio = BIO_new(BIO_s_null()); 380280304Sjkim else if (os && os->length > 0) 381280304Sjkim bio = BIO_new_mem_buf(os->data, os->length); 382280304Sjkim if (bio == NULL) { 383280304Sjkim bio = BIO_new(BIO_s_mem()); 384280304Sjkim if (bio == NULL) 385280304Sjkim goto err; 386280304Sjkim BIO_set_mem_eof_return(bio, 0); 387280304Sjkim } 388280304Sjkim } 389280304Sjkim if (out) 390280304Sjkim BIO_push(out, bio); 391280304Sjkim else 392280304Sjkim out = bio; 393280304Sjkim bio = NULL; 394280304Sjkim if (0) { 395280304Sjkim err: 396280304Sjkim if (out != NULL) 397280304Sjkim BIO_free_all(out); 398280304Sjkim if (btmp != NULL) 399280304Sjkim BIO_free_all(btmp); 400280304Sjkim out = NULL; 401280304Sjkim } 402280304Sjkim return (out); 403280304Sjkim} 40455714Skris 405160814Ssimonstatic int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert) 406280304Sjkim{ 407280304Sjkim int ret; 408280304Sjkim ret = X509_NAME_cmp(ri->issuer_and_serial->issuer, 409280304Sjkim pcert->cert_info->issuer); 410280304Sjkim if (ret) 411280304Sjkim return ret; 412280304Sjkim return M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber, 413280304Sjkim ri->issuer_and_serial->serial); 414280304Sjkim} 415160814Ssimon 41655714Skris/* int */ 41755714SkrisBIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) 418280304Sjkim{ 419280304Sjkim int i, j; 420280304Sjkim BIO *out = NULL, *btmp = NULL, *etmp = NULL, *bio = NULL; 421280304Sjkim X509_ALGOR *xa; 422280304Sjkim ASN1_OCTET_STRING *data_body = NULL; 423280304Sjkim const EVP_MD *evp_md; 424280304Sjkim const EVP_CIPHER *evp_cipher = NULL; 425280304Sjkim EVP_CIPHER_CTX *evp_ctx = NULL; 426280304Sjkim X509_ALGOR *enc_alg = NULL; 427280304Sjkim STACK_OF(X509_ALGOR) *md_sk = NULL; 428280304Sjkim STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; 429280304Sjkim PKCS7_RECIP_INFO *ri = NULL; 430280304Sjkim unsigned char *ek = NULL, *tkey = NULL; 431280304Sjkim int eklen = 0, tkeylen = 0; 43255714Skris 433280304Sjkim if (p7 == NULL) { 434280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER); 435280304Sjkim return NULL; 436280304Sjkim } 437280266Sdelphij 438280304Sjkim if (p7->d.ptr == NULL) { 439280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); 440280304Sjkim return NULL; 441280304Sjkim } 442280266Sdelphij 443280304Sjkim i = OBJ_obj2nid(p7->type); 444280304Sjkim p7->state = PKCS7_S_HEADER; 44555714Skris 446280304Sjkim switch (i) { 447280304Sjkim case NID_pkcs7_signed: 448284285Sjkim /* 449284285Sjkim * p7->d.sign->contents is a PKCS7 structure consisting of a contentType 450284285Sjkim * field and optional content. 451284285Sjkim * data_body is NULL if that structure has no (=detached) content 452284285Sjkim * or if the contentType is wrong (i.e., not "data"). 453284285Sjkim */ 454280304Sjkim data_body = PKCS7_get_octet_string(p7->d.sign->contents); 455280304Sjkim if (!PKCS7_is_detached(p7) && data_body == NULL) { 456280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, 457280304Sjkim PKCS7_R_INVALID_SIGNED_DATA_TYPE); 458280304Sjkim goto err; 459280304Sjkim } 460280304Sjkim md_sk = p7->d.sign->md_algs; 461280304Sjkim break; 462280304Sjkim case NID_pkcs7_signedAndEnveloped: 463280304Sjkim rsk = p7->d.signed_and_enveloped->recipientinfo; 464280304Sjkim md_sk = p7->d.signed_and_enveloped->md_algs; 465284285Sjkim /* data_body is NULL if the optional EncryptedContent is missing. */ 466280304Sjkim data_body = p7->d.signed_and_enveloped->enc_data->enc_data; 467280304Sjkim enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm; 468280304Sjkim evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); 469280304Sjkim if (evp_cipher == NULL) { 470280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, 471280304Sjkim PKCS7_R_UNSUPPORTED_CIPHER_TYPE); 472280304Sjkim goto err; 473280304Sjkim } 474280304Sjkim break; 475280304Sjkim case NID_pkcs7_enveloped: 476280304Sjkim rsk = p7->d.enveloped->recipientinfo; 477280304Sjkim enc_alg = p7->d.enveloped->enc_data->algorithm; 478284285Sjkim /* data_body is NULL if the optional EncryptedContent is missing. */ 479280304Sjkim data_body = p7->d.enveloped->enc_data->enc_data; 480280304Sjkim evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); 481280304Sjkim if (evp_cipher == NULL) { 482280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, 483280304Sjkim PKCS7_R_UNSUPPORTED_CIPHER_TYPE); 484280304Sjkim goto err; 485280304Sjkim } 486280304Sjkim break; 487280304Sjkim default: 488280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 489280304Sjkim goto err; 490280304Sjkim } 49155714Skris 492284285Sjkim /* Detached content must be supplied via in_bio instead. */ 493284285Sjkim if (data_body == NULL && in_bio == NULL) { 494284285Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); 495284285Sjkim goto err; 496284285Sjkim } 497284285Sjkim 498280304Sjkim /* We will be checking the signature */ 499280304Sjkim if (md_sk != NULL) { 500280304Sjkim for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) { 501280304Sjkim xa = sk_X509_ALGOR_value(md_sk, i); 502280304Sjkim if ((btmp = BIO_new(BIO_f_md())) == NULL) { 503280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_BIO_LIB); 504280304Sjkim goto err; 505280304Sjkim } 50655714Skris 507280304Sjkim j = OBJ_obj2nid(xa->algorithm); 508280304Sjkim evp_md = EVP_get_digestbynid(j); 509280304Sjkim if (evp_md == NULL) { 510280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, 511280304Sjkim PKCS7_R_UNKNOWN_DIGEST_TYPE); 512280304Sjkim goto err; 513280304Sjkim } 51455714Skris 515280304Sjkim BIO_set_md(btmp, evp_md); 516280304Sjkim if (out == NULL) 517280304Sjkim out = btmp; 518280304Sjkim else 519280304Sjkim BIO_push(out, btmp); 520280304Sjkim btmp = NULL; 521280304Sjkim } 522280304Sjkim } 52355714Skris 524280304Sjkim if (evp_cipher != NULL) { 52555714Skris#if 0 526280304Sjkim unsigned char key[EVP_MAX_KEY_LENGTH]; 527280304Sjkim unsigned char iv[EVP_MAX_IV_LENGTH]; 528280304Sjkim unsigned char *p; 529280304Sjkim int keylen, ivlen; 530280304Sjkim int max; 531280304Sjkim X509_OBJECT ret; 53255714Skris#endif 53355714Skris 534280304Sjkim if ((etmp = BIO_new(BIO_f_cipher())) == NULL) { 535280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_BIO_LIB); 536280304Sjkim goto err; 537280304Sjkim } 53855714Skris 539280304Sjkim /* 540280304Sjkim * It was encrypted, we need to decrypt the secret key with the 541280304Sjkim * private key 542280304Sjkim */ 54355714Skris 544280304Sjkim /* 545280304Sjkim * Find the recipientInfo which matches the passed certificate (if 546280304Sjkim * any) 547280304Sjkim */ 54855714Skris 549280304Sjkim if (pcert) { 550280304Sjkim for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { 551280304Sjkim ri = sk_PKCS7_RECIP_INFO_value(rsk, i); 552280304Sjkim if (!pkcs7_cmp_ri(ri, pcert)) 553280304Sjkim break; 554280304Sjkim ri = NULL; 555280304Sjkim } 556280304Sjkim if (ri == NULL) { 557280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATADECODE, 558280304Sjkim PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); 559280304Sjkim goto err; 560280304Sjkim } 561280304Sjkim } 56255714Skris 563280304Sjkim /* If we haven't got a certificate try each ri in turn */ 564280304Sjkim if (pcert == NULL) { 565280304Sjkim /* 566280304Sjkim * Always attempt to decrypt all rinfo even after sucess as a 567280304Sjkim * defence against MMA timing attacks. 568280304Sjkim */ 569280304Sjkim for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { 570280304Sjkim ri = sk_PKCS7_RECIP_INFO_value(rsk, i); 57155714Skris 572280304Sjkim if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0) 573280304Sjkim goto err; 574280304Sjkim ERR_clear_error(); 575280304Sjkim } 576280304Sjkim } else { 577280304Sjkim /* Only exit on fatal errors, not decrypt failure */ 578280304Sjkim if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0) 579280304Sjkim goto err; 580280304Sjkim ERR_clear_error(); 581280304Sjkim } 58255714Skris 583280304Sjkim evp_ctx = NULL; 584280304Sjkim BIO_get_cipher_ctx(etmp, &evp_ctx); 585280304Sjkim if (EVP_CipherInit_ex(evp_ctx, evp_cipher, NULL, NULL, NULL, 0) <= 0) 586280304Sjkim goto err; 587280304Sjkim if (EVP_CIPHER_asn1_to_param(evp_ctx, enc_alg->parameter) < 0) 588280304Sjkim goto err; 589280304Sjkim /* Generate random key as MMA defence */ 590280304Sjkim tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx); 591280304Sjkim tkey = OPENSSL_malloc(tkeylen); 592280304Sjkim if (!tkey) 593280304Sjkim goto err; 594280304Sjkim if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0) 595280304Sjkim goto err; 596280304Sjkim if (ek == NULL) { 597280304Sjkim ek = tkey; 598280304Sjkim eklen = tkeylen; 599280304Sjkim tkey = NULL; 600280304Sjkim } 60155714Skris 602280304Sjkim if (eklen != EVP_CIPHER_CTX_key_length(evp_ctx)) { 603280304Sjkim /* 604280304Sjkim * Some S/MIME clients don't use the same key and effective key 605280304Sjkim * length. The key length is determined by the size of the 606280304Sjkim * decrypted RSA key. 607280304Sjkim */ 608280304Sjkim if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen)) { 609280304Sjkim /* Use random key as MMA defence */ 610280304Sjkim OPENSSL_cleanse(ek, eklen); 611280304Sjkim OPENSSL_free(ek); 612280304Sjkim ek = tkey; 613280304Sjkim eklen = tkeylen; 614280304Sjkim tkey = NULL; 615280304Sjkim } 616280304Sjkim } 617280304Sjkim /* Clear errors so we don't leak information useful in MMA */ 618280304Sjkim ERR_clear_error(); 619280304Sjkim if (EVP_CipherInit_ex(evp_ctx, NULL, NULL, ek, NULL, 0) <= 0) 620280304Sjkim goto err; 621234954Sbz 622280304Sjkim if (ek) { 623280304Sjkim OPENSSL_cleanse(ek, eklen); 624280304Sjkim OPENSSL_free(ek); 625280304Sjkim ek = NULL; 626280304Sjkim } 627280304Sjkim if (tkey) { 628280304Sjkim OPENSSL_cleanse(tkey, tkeylen); 629280304Sjkim OPENSSL_free(tkey); 630280304Sjkim tkey = NULL; 631280304Sjkim } 63255714Skris 633280304Sjkim if (out == NULL) 634280304Sjkim out = etmp; 635280304Sjkim else 636280304Sjkim BIO_push(out, etmp); 637280304Sjkim etmp = NULL; 638280304Sjkim } 63955714Skris#if 1 640284285Sjkim if (in_bio != NULL) { 641280304Sjkim bio = in_bio; 642280304Sjkim } else { 643280304Sjkim# if 0 644280304Sjkim bio = BIO_new(BIO_s_mem()); 645280304Sjkim /* 646280304Sjkim * We need to set this so that when we have read all the data, the 647280304Sjkim * encrypt BIO, if present, will read EOF and encode the last few 648280304Sjkim * bytes 649280304Sjkim */ 650280304Sjkim BIO_set_mem_eof_return(bio, 0); 65155714Skris 652280304Sjkim if (data_body->length > 0) 653280304Sjkim BIO_write(bio, (char *)data_body->data, data_body->length); 654280304Sjkim# else 655280304Sjkim if (data_body->length > 0) 656280304Sjkim bio = BIO_new_mem_buf(data_body->data, data_body->length); 657280304Sjkim else { 658280304Sjkim bio = BIO_new(BIO_s_mem()); 659291721Sjkim if (bio == NULL) 660291721Sjkim goto err; 661280304Sjkim BIO_set_mem_eof_return(bio, 0); 662280304Sjkim } 663280304Sjkim if (bio == NULL) 664280304Sjkim goto err; 665280304Sjkim# endif 666280304Sjkim } 667280304Sjkim BIO_push(out, bio); 668280304Sjkim bio = NULL; 66959191Skris#endif 670280304Sjkim if (0) { 671280304Sjkim err: 672280304Sjkim if (ek) { 673280304Sjkim OPENSSL_cleanse(ek, eklen); 674280304Sjkim OPENSSL_free(ek); 675280304Sjkim } 676280304Sjkim if (tkey) { 677280304Sjkim OPENSSL_cleanse(tkey, tkeylen); 678280304Sjkim OPENSSL_free(tkey); 679280304Sjkim } 680280304Sjkim if (out != NULL) 681280304Sjkim BIO_free_all(out); 682280304Sjkim if (btmp != NULL) 683280304Sjkim BIO_free_all(btmp); 684280304Sjkim if (etmp != NULL) 685280304Sjkim BIO_free_all(etmp); 686280304Sjkim if (bio != NULL) 687280304Sjkim BIO_free_all(bio); 688280304Sjkim out = NULL; 689280304Sjkim } 690280304Sjkim return (out); 691280304Sjkim} 69255714Skris 693160814Ssimonstatic BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid) 694280304Sjkim{ 695280304Sjkim for (;;) { 696280304Sjkim bio = BIO_find_type(bio, BIO_TYPE_MD); 697280304Sjkim if (bio == NULL) { 698280304Sjkim PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST, 699280304Sjkim PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 700280304Sjkim return NULL; 701280304Sjkim } 702280304Sjkim BIO_get_md_ctx(bio, pmd); 703280304Sjkim if (*pmd == NULL) { 704280304Sjkim PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST, ERR_R_INTERNAL_ERROR); 705280304Sjkim return NULL; 706280304Sjkim } 707280304Sjkim if (EVP_MD_CTX_type(*pmd) == nid) 708280304Sjkim return bio; 709280304Sjkim bio = BIO_next(bio); 710280304Sjkim } 711280304Sjkim return NULL; 712280304Sjkim} 713160814Ssimon 714238405Sjkimstatic int do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx) 715280304Sjkim{ 716280304Sjkim unsigned char md_data[EVP_MAX_MD_SIZE]; 717280304Sjkim unsigned int md_len; 718238405Sjkim 719280304Sjkim /* Add signing time if not already present */ 720280304Sjkim if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) { 721280304Sjkim if (!PKCS7_add0_attrib_signing_time(si, NULL)) { 722280304Sjkim PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE); 723280304Sjkim return 0; 724280304Sjkim } 725280304Sjkim } 726238405Sjkim 727280304Sjkim /* Add digest */ 728280304Sjkim if (!EVP_DigestFinal_ex(mctx, md_data, &md_len)) { 729280304Sjkim PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_EVP_LIB); 730280304Sjkim return 0; 731280304Sjkim } 732280304Sjkim if (!PKCS7_add1_attrib_digest(si, md_data, md_len)) { 733280304Sjkim PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE); 734280304Sjkim return 0; 735280304Sjkim } 736238405Sjkim 737280304Sjkim /* Now sign the attributes */ 738280304Sjkim if (!PKCS7_SIGNER_INFO_sign(si)) 739280304Sjkim return 0; 740238405Sjkim 741280304Sjkim return 1; 742280304Sjkim} 743280304Sjkim 74455714Skrisint PKCS7_dataFinal(PKCS7 *p7, BIO *bio) 745280304Sjkim{ 746280304Sjkim int ret = 0; 747280304Sjkim int i, j; 748280304Sjkim BIO *btmp; 749280304Sjkim PKCS7_SIGNER_INFO *si; 750280304Sjkim EVP_MD_CTX *mdc, ctx_tmp; 751280304Sjkim STACK_OF(X509_ATTRIBUTE) *sk; 752280304Sjkim STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL; 753280304Sjkim ASN1_OCTET_STRING *os = NULL; 75455714Skris 755280304Sjkim if (p7 == NULL) { 756280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER); 757280304Sjkim return 0; 758280304Sjkim } 759280266Sdelphij 760280304Sjkim if (p7->d.ptr == NULL) { 761280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT); 762280304Sjkim return 0; 763280304Sjkim } 764280266Sdelphij 765280304Sjkim EVP_MD_CTX_init(&ctx_tmp); 766280304Sjkim i = OBJ_obj2nid(p7->type); 767280304Sjkim p7->state = PKCS7_S_HEADER; 76855714Skris 769280304Sjkim switch (i) { 770280304Sjkim case NID_pkcs7_data: 771280304Sjkim os = p7->d.data; 772280304Sjkim break; 773280304Sjkim case NID_pkcs7_signedAndEnveloped: 774280304Sjkim /* XXXXXXXXXXXXXXXX */ 775280304Sjkim si_sk = p7->d.signed_and_enveloped->signer_info; 776280304Sjkim os = p7->d.signed_and_enveloped->enc_data->enc_data; 777280304Sjkim if (!os) { 778280304Sjkim os = M_ASN1_OCTET_STRING_new(); 779280304Sjkim if (!os) { 780280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); 781280304Sjkim goto err; 782280304Sjkim } 783280304Sjkim p7->d.signed_and_enveloped->enc_data->enc_data = os; 784280304Sjkim } 785280304Sjkim break; 786280304Sjkim case NID_pkcs7_enveloped: 787280304Sjkim /* XXXXXXXXXXXXXXXX */ 788280304Sjkim os = p7->d.enveloped->enc_data->enc_data; 789280304Sjkim if (!os) { 790280304Sjkim os = M_ASN1_OCTET_STRING_new(); 791280304Sjkim if (!os) { 792280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); 793280304Sjkim goto err; 794280304Sjkim } 795280304Sjkim p7->d.enveloped->enc_data->enc_data = os; 796280304Sjkim } 797280304Sjkim break; 798280304Sjkim case NID_pkcs7_signed: 799280304Sjkim si_sk = p7->d.sign->signer_info; 800280304Sjkim os = PKCS7_get_octet_string(p7->d.sign->contents); 801280304Sjkim /* If detached data then the content is excluded */ 802280304Sjkim if (PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) { 803280304Sjkim M_ASN1_OCTET_STRING_free(os); 804280304Sjkim os = NULL; 805280304Sjkim p7->d.sign->contents->d.data = NULL; 806280304Sjkim } 807280304Sjkim break; 808160814Ssimon 809280304Sjkim case NID_pkcs7_digest: 810280304Sjkim os = PKCS7_get_octet_string(p7->d.digest->contents); 811280304Sjkim /* If detached data then the content is excluded */ 812280304Sjkim if (PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) { 813280304Sjkim M_ASN1_OCTET_STRING_free(os); 814280304Sjkim os = NULL; 815280304Sjkim p7->d.digest->contents->d.data = NULL; 816280304Sjkim } 817280304Sjkim break; 818160814Ssimon 819280304Sjkim default: 820280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 821280304Sjkim goto err; 822280304Sjkim } 82355714Skris 824280304Sjkim if (si_sk != NULL) { 825280304Sjkim for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(si_sk); i++) { 826280304Sjkim si = sk_PKCS7_SIGNER_INFO_value(si_sk, i); 827280304Sjkim if (si->pkey == NULL) 828280304Sjkim continue; 82955714Skris 830280304Sjkim j = OBJ_obj2nid(si->digest_alg->algorithm); 83155714Skris 832280304Sjkim btmp = bio; 833160814Ssimon 834280304Sjkim btmp = PKCS7_find_digest(&mdc, btmp, j); 835160814Ssimon 836280304Sjkim if (btmp == NULL) 837280304Sjkim goto err; 838160814Ssimon 839280304Sjkim /* 840280304Sjkim * We now have the EVP_MD_CTX, lets do the signing. 841280304Sjkim */ 842280304Sjkim if (!EVP_MD_CTX_copy_ex(&ctx_tmp, mdc)) 843280304Sjkim goto err; 84455714Skris 845280304Sjkim sk = si->auth_attr; 84655714Skris 847280304Sjkim /* 848280304Sjkim * If there are attributes, we add the digest attribute and only 849280304Sjkim * sign the attributes 850280304Sjkim */ 851280304Sjkim if (sk_X509_ATTRIBUTE_num(sk) > 0) { 852280304Sjkim if (!do_pkcs7_signed_attrib(si, &ctx_tmp)) 853280304Sjkim goto err; 854280304Sjkim } else { 855280304Sjkim unsigned char *abuf = NULL; 856280304Sjkim unsigned int abuflen; 857280304Sjkim abuflen = EVP_PKEY_size(si->pkey); 858280304Sjkim abuf = OPENSSL_malloc(abuflen); 859280304Sjkim if (!abuf) 860280304Sjkim goto err; 86155714Skris 862280304Sjkim if (!EVP_SignFinal(&ctx_tmp, abuf, &abuflen, si->pkey)) { 863280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_EVP_LIB); 864280304Sjkim goto err; 865280304Sjkim } 866280304Sjkim ASN1_STRING_set0(si->enc_digest, abuf, abuflen); 867280304Sjkim } 868280304Sjkim } 869280304Sjkim } else if (i == NID_pkcs7_digest) { 870280304Sjkim unsigned char md_data[EVP_MAX_MD_SIZE]; 871280304Sjkim unsigned int md_len; 872280304Sjkim if (!PKCS7_find_digest(&mdc, bio, 873280304Sjkim OBJ_obj2nid(p7->d.digest->md->algorithm))) 874280304Sjkim goto err; 875280304Sjkim if (!EVP_DigestFinal_ex(mdc, md_data, &md_len)) 876280304Sjkim goto err; 877280304Sjkim M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len); 878280304Sjkim } 87955714Skris 880280304Sjkim if (!PKCS7_is_detached(p7)) { 881280304Sjkim /* 882280304Sjkim * NOTE(emilia): I think we only reach os == NULL here because detached 883280304Sjkim * digested data support is broken. 884280304Sjkim */ 885280304Sjkim if (os == NULL) 886280304Sjkim goto err; 887280304Sjkim if (!(os->flags & ASN1_STRING_FLAG_NDEF)) { 888280304Sjkim char *cont; 889280304Sjkim long contlen; 890280304Sjkim btmp = BIO_find_type(bio, BIO_TYPE_MEM); 891280304Sjkim if (btmp == NULL) { 892280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNABLE_TO_FIND_MEM_BIO); 893280304Sjkim goto err; 894280304Sjkim } 895280304Sjkim contlen = BIO_get_mem_data(btmp, &cont); 896280304Sjkim /* 897280304Sjkim * Mark the BIO read only then we can use its copy of the data 898280304Sjkim * instead of making an extra copy. 899280304Sjkim */ 900280304Sjkim BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); 901280304Sjkim BIO_set_mem_eof_return(btmp, 0); 902280304Sjkim ASN1_STRING_set0(os, (unsigned char *)cont, contlen); 903280304Sjkim } 904280304Sjkim } 905280304Sjkim ret = 1; 906280304Sjkim err: 907280304Sjkim EVP_MD_CTX_cleanup(&ctx_tmp); 908280304Sjkim return (ret); 909280304Sjkim} 91055714Skris 911238405Sjkimint PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) 912280304Sjkim{ 913280304Sjkim EVP_MD_CTX mctx; 914280304Sjkim EVP_PKEY_CTX *pctx; 915280304Sjkim unsigned char *abuf = NULL; 916280304Sjkim int alen; 917280304Sjkim size_t siglen; 918280304Sjkim const EVP_MD *md = NULL; 919238405Sjkim 920280304Sjkim md = EVP_get_digestbyobj(si->digest_alg->algorithm); 921280304Sjkim if (md == NULL) 922280304Sjkim return 0; 923238405Sjkim 924280304Sjkim EVP_MD_CTX_init(&mctx); 925280304Sjkim if (EVP_DigestSignInit(&mctx, &pctx, md, NULL, si->pkey) <= 0) 926280304Sjkim goto err; 927238405Sjkim 928280304Sjkim if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, 929280304Sjkim EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0) { 930280304Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); 931280304Sjkim goto err; 932280304Sjkim } 933238405Sjkim 934280304Sjkim alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr, &abuf, 935280304Sjkim ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); 936280304Sjkim if (!abuf) 937280304Sjkim goto err; 938280304Sjkim if (EVP_DigestSignUpdate(&mctx, abuf, alen) <= 0) 939280304Sjkim goto err; 940280304Sjkim OPENSSL_free(abuf); 941280304Sjkim abuf = NULL; 942280304Sjkim if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0) 943280304Sjkim goto err; 944280304Sjkim abuf = OPENSSL_malloc(siglen); 945280304Sjkim if (!abuf) 946280304Sjkim goto err; 947280304Sjkim if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0) 948280304Sjkim goto err; 949238405Sjkim 950280304Sjkim if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, 951280304Sjkim EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0) { 952280304Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); 953280304Sjkim goto err; 954280304Sjkim } 955238405Sjkim 956280304Sjkim EVP_MD_CTX_cleanup(&mctx); 957238405Sjkim 958280304Sjkim ASN1_STRING_set0(si->enc_digest, abuf, siglen); 959238405Sjkim 960280304Sjkim return 1; 961238405Sjkim 962280304Sjkim err: 963280304Sjkim if (abuf) 964280304Sjkim OPENSSL_free(abuf); 965280304Sjkim EVP_MD_CTX_cleanup(&mctx); 966280304Sjkim return 0; 967238405Sjkim 968280304Sjkim} 969238405Sjkim 97055714Skrisint PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, 971280304Sjkim PKCS7 *p7, PKCS7_SIGNER_INFO *si) 972280304Sjkim{ 973280304Sjkim PKCS7_ISSUER_AND_SERIAL *ias; 974280304Sjkim int ret = 0, i; 975280304Sjkim STACK_OF(X509) *cert; 976280304Sjkim X509 *x509; 97755714Skris 978280304Sjkim if (p7 == NULL) { 979280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_INVALID_NULL_POINTER); 980280304Sjkim return 0; 981280304Sjkim } 982280266Sdelphij 983280304Sjkim if (p7->d.ptr == NULL) { 984280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_NO_CONTENT); 985280304Sjkim return 0; 986280304Sjkim } 987280266Sdelphij 988280304Sjkim if (PKCS7_type_is_signed(p7)) { 989280304Sjkim cert = p7->d.sign->cert; 990280304Sjkim } else if (PKCS7_type_is_signedAndEnveloped(p7)) { 991280304Sjkim cert = p7->d.signed_and_enveloped->cert; 992280304Sjkim } else { 993280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); 994280304Sjkim goto err; 995280304Sjkim } 996280304Sjkim /* XXXXXXXXXXXXXXXXXXXXXXX */ 997280304Sjkim ias = si->issuer_and_serial; 99855714Skris 999280304Sjkim x509 = X509_find_by_issuer_and_serial(cert, ias->issuer, ias->serial); 100055714Skris 1001280304Sjkim /* were we able to find the cert in passed to us */ 1002280304Sjkim if (x509 == NULL) { 1003280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, 1004280304Sjkim PKCS7_R_UNABLE_TO_FIND_CERTIFICATE); 1005280304Sjkim goto err; 1006280304Sjkim } 100755714Skris 1008280304Sjkim /* Lets verify */ 1009280304Sjkim if (!X509_STORE_CTX_init(ctx, cert_store, x509, cert)) { 1010280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, ERR_R_X509_LIB); 1011280304Sjkim goto err; 1012280304Sjkim } 1013280304Sjkim X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN); 1014280304Sjkim i = X509_verify_cert(ctx); 1015280304Sjkim if (i <= 0) { 1016280304Sjkim PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, ERR_R_X509_LIB); 1017280304Sjkim X509_STORE_CTX_cleanup(ctx); 1018280304Sjkim goto err; 1019280304Sjkim } 1020280304Sjkim X509_STORE_CTX_cleanup(ctx); 102155714Skris 1022280304Sjkim return PKCS7_signatureVerify(bio, p7, si, x509); 1023280304Sjkim err: 1024280304Sjkim return ret; 1025280304Sjkim} 102655714Skris 102755714Skrisint PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, 1028280304Sjkim X509 *x509) 1029280304Sjkim{ 1030280304Sjkim ASN1_OCTET_STRING *os; 1031280304Sjkim EVP_MD_CTX mdc_tmp, *mdc; 1032280304Sjkim int ret = 0, i; 1033280304Sjkim int md_type; 1034280304Sjkim STACK_OF(X509_ATTRIBUTE) *sk; 1035280304Sjkim BIO *btmp; 1036280304Sjkim EVP_PKEY *pkey; 103755714Skris 1038280304Sjkim EVP_MD_CTX_init(&mdc_tmp); 1039109998Smarkm 1040280304Sjkim if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { 1041280304Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); 1042280304Sjkim goto err; 1043280304Sjkim } 104455714Skris 1045280304Sjkim md_type = OBJ_obj2nid(si->digest_alg->algorithm); 104655714Skris 1047280304Sjkim btmp = bio; 1048280304Sjkim for (;;) { 1049280304Sjkim if ((btmp == NULL) || 1050280304Sjkim ((btmp = BIO_find_type(btmp, BIO_TYPE_MD)) == NULL)) { 1051280304Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1052280304Sjkim PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 1053280304Sjkim goto err; 1054280304Sjkim } 1055280304Sjkim BIO_get_md_ctx(btmp, &mdc); 1056280304Sjkim if (mdc == NULL) { 1057280304Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_INTERNAL_ERROR); 1058280304Sjkim goto err; 1059280304Sjkim } 1060280304Sjkim if (EVP_MD_CTX_type(mdc) == md_type) 1061280304Sjkim break; 1062280304Sjkim /* 1063280304Sjkim * Workaround for some broken clients that put the signature OID 1064280304Sjkim * instead of the digest OID in digest_alg->algorithm 1065280304Sjkim */ 1066280304Sjkim if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type) 1067280304Sjkim break; 1068280304Sjkim btmp = BIO_next(btmp); 1069280304Sjkim } 107055714Skris 1071280304Sjkim /* 1072280304Sjkim * mdc is the digest ctx that we want, unless there are attributes, in 1073280304Sjkim * which case the digest is the signed attributes 1074280304Sjkim */ 1075280304Sjkim if (!EVP_MD_CTX_copy_ex(&mdc_tmp, mdc)) 1076280304Sjkim goto err; 107755714Skris 1078280304Sjkim sk = si->auth_attr; 1079280304Sjkim if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { 1080280304Sjkim unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; 1081280304Sjkim unsigned int md_len; 1082280304Sjkim int alen; 1083280304Sjkim ASN1_OCTET_STRING *message_digest; 108455714Skris 1085280304Sjkim if (!EVP_DigestFinal_ex(&mdc_tmp, md_dat, &md_len)) 1086280304Sjkim goto err; 1087280304Sjkim message_digest = PKCS7_digest_from_attributes(sk); 1088280304Sjkim if (!message_digest) { 1089280304Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1090280304Sjkim PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 1091280304Sjkim goto err; 1092280304Sjkim } 1093280304Sjkim if ((message_digest->length != (int)md_len) || 1094280304Sjkim (memcmp(message_digest->data, md_dat, md_len))) { 109555714Skris#if 0 1096280304Sjkim { 1097280304Sjkim int ii; 1098280304Sjkim for (ii = 0; ii < message_digest->length; ii++) 1099280304Sjkim printf("%02X", message_digest->data[ii]); 1100280304Sjkim printf(" sent\n"); 1101280304Sjkim for (ii = 0; ii < md_len; ii++) 1102280304Sjkim printf("%02X", md_dat[ii]); 1103280304Sjkim printf(" calc\n"); 1104280304Sjkim } 110555714Skris#endif 1106280304Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_DIGEST_FAILURE); 1107280304Sjkim ret = -1; 1108280304Sjkim goto err; 1109280304Sjkim } 111055714Skris 1111280304Sjkim if (!EVP_VerifyInit_ex(&mdc_tmp, EVP_get_digestbynid(md_type), NULL)) 1112280304Sjkim goto err; 111355714Skris 1114280304Sjkim alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, 1115280304Sjkim ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); 1116280304Sjkim if (alen <= 0) { 1117280304Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_ASN1_LIB); 1118280304Sjkim ret = -1; 1119280304Sjkim goto err; 1120280304Sjkim } 1121280304Sjkim if (!EVP_VerifyUpdate(&mdc_tmp, abuf, alen)) 1122280304Sjkim goto err; 1123109998Smarkm 1124280304Sjkim OPENSSL_free(abuf); 1125280304Sjkim } 112655714Skris 1127280304Sjkim os = si->enc_digest; 1128280304Sjkim pkey = X509_get_pubkey(x509); 1129280304Sjkim if (!pkey) { 1130280304Sjkim ret = -1; 1131280304Sjkim goto err; 1132280304Sjkim } 113355714Skris 1134280304Sjkim i = EVP_VerifyFinal(&mdc_tmp, os->data, os->length, pkey); 1135280304Sjkim EVP_PKEY_free(pkey); 1136280304Sjkim if (i <= 0) { 1137280304Sjkim PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); 1138280304Sjkim ret = -1; 1139280304Sjkim goto err; 1140280304Sjkim } else 1141280304Sjkim ret = 1; 1142280304Sjkim err: 1143280304Sjkim EVP_MD_CTX_cleanup(&mdc_tmp); 1144280304Sjkim return (ret); 1145280304Sjkim} 114655714Skris 114755714SkrisPKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx) 1148280304Sjkim{ 1149280304Sjkim STACK_OF(PKCS7_RECIP_INFO) *rsk; 1150280304Sjkim PKCS7_RECIP_INFO *ri; 1151280304Sjkim int i; 115255714Skris 1153280304Sjkim i = OBJ_obj2nid(p7->type); 1154280304Sjkim if (i != NID_pkcs7_signedAndEnveloped) 1155280304Sjkim return NULL; 1156280304Sjkim if (p7->d.signed_and_enveloped == NULL) 1157280304Sjkim return NULL; 1158280304Sjkim rsk = p7->d.signed_and_enveloped->recipientinfo; 1159280304Sjkim if (rsk == NULL) 1160280304Sjkim return NULL; 1161280304Sjkim if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) 1162280304Sjkim return (NULL); 1163280304Sjkim ri = sk_PKCS7_RECIP_INFO_value(rsk, idx); 1164280304Sjkim return (ri->issuer_and_serial); 1165280304Sjkim} 116655714Skris 116755714SkrisASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid) 1168280304Sjkim{ 1169280304Sjkim return (get_attribute(si->auth_attr, nid)); 1170280304Sjkim} 117155714Skris 117255714SkrisASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid) 1173280304Sjkim{ 1174280304Sjkim return (get_attribute(si->unauth_attr, nid)); 1175280304Sjkim} 117655714Skris 117755714Skrisstatic ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid) 1178280304Sjkim{ 1179280304Sjkim int i; 1180280304Sjkim X509_ATTRIBUTE *xa; 1181280304Sjkim ASN1_OBJECT *o; 118255714Skris 1183280304Sjkim o = OBJ_nid2obj(nid); 1184280304Sjkim if (!o || !sk) 1185280304Sjkim return (NULL); 1186280304Sjkim for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { 1187280304Sjkim xa = sk_X509_ATTRIBUTE_value(sk, i); 1188280304Sjkim if (OBJ_cmp(xa->object, o) == 0) { 1189280304Sjkim if (!xa->single && sk_ASN1_TYPE_num(xa->value.set)) 1190280304Sjkim return (sk_ASN1_TYPE_value(xa->value.set, 0)); 1191280304Sjkim else 1192280304Sjkim return (NULL); 1193280304Sjkim } 1194280304Sjkim } 1195280304Sjkim return (NULL); 1196280304Sjkim} 119755714Skris 119855714SkrisASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk) 119955714Skris{ 1200280304Sjkim ASN1_TYPE *astype; 1201280304Sjkim if (!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) 1202280304Sjkim return NULL; 1203280304Sjkim return astype->value.octet_string; 120455714Skris} 120555714Skris 120655714Skrisint PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, 1207280304Sjkim STACK_OF(X509_ATTRIBUTE) *sk) 1208280304Sjkim{ 1209280304Sjkim int i; 121055714Skris 1211280304Sjkim if (p7si->auth_attr != NULL) 1212280304Sjkim sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr, X509_ATTRIBUTE_free); 1213280304Sjkim p7si->auth_attr = sk_X509_ATTRIBUTE_dup(sk); 1214280304Sjkim if (p7si->auth_attr == NULL) 1215280304Sjkim return 0; 1216280304Sjkim for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { 1217280304Sjkim if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr, i, 1218280304Sjkim X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value 1219280304Sjkim (sk, i)))) 1220280304Sjkim == NULL) 1221280304Sjkim return (0); 1222280304Sjkim } 1223280304Sjkim return (1); 1224280304Sjkim} 122555714Skris 1226280304Sjkimint PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, 1227280304Sjkim STACK_OF(X509_ATTRIBUTE) *sk) 1228280304Sjkim{ 1229280304Sjkim int i; 123055714Skris 1231280304Sjkim if (p7si->unauth_attr != NULL) 1232280304Sjkim sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr, X509_ATTRIBUTE_free); 1233280304Sjkim p7si->unauth_attr = sk_X509_ATTRIBUTE_dup(sk); 1234280304Sjkim if (p7si->unauth_attr == NULL) 1235280304Sjkim return 0; 1236280304Sjkim for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { 1237280304Sjkim if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr, i, 1238280304Sjkim X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value 1239280304Sjkim (sk, i)))) 1240280304Sjkim == NULL) 1241280304Sjkim return (0); 1242280304Sjkim } 1243280304Sjkim return (1); 1244280304Sjkim} 124555714Skris 124655714Skrisint PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, 1247280304Sjkim void *value) 1248280304Sjkim{ 1249280304Sjkim return (add_attribute(&(p7si->auth_attr), nid, atrtype, value)); 1250280304Sjkim} 125155714Skris 125255714Skrisint PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, 1253280304Sjkim void *value) 1254280304Sjkim{ 1255280304Sjkim return (add_attribute(&(p7si->unauth_attr), nid, atrtype, value)); 1256280304Sjkim} 125755714Skris 125855714Skrisstatic int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, 1259280304Sjkim void *value) 1260280304Sjkim{ 1261280304Sjkim X509_ATTRIBUTE *attr = NULL; 126255714Skris 1263280304Sjkim if (*sk == NULL) { 1264280304Sjkim *sk = sk_X509_ATTRIBUTE_new_null(); 1265280304Sjkim if (*sk == NULL) 1266280304Sjkim return 0; 1267280304Sjkim new_attrib: 1268280304Sjkim if (!(attr = X509_ATTRIBUTE_create(nid, atrtype, value))) 1269280304Sjkim return 0; 1270280304Sjkim if (!sk_X509_ATTRIBUTE_push(*sk, attr)) { 1271280304Sjkim X509_ATTRIBUTE_free(attr); 1272280304Sjkim return 0; 1273280304Sjkim } 1274280304Sjkim } else { 1275280304Sjkim int i; 127655714Skris 1277280304Sjkim for (i = 0; i < sk_X509_ATTRIBUTE_num(*sk); i++) { 1278280304Sjkim attr = sk_X509_ATTRIBUTE_value(*sk, i); 1279280304Sjkim if (OBJ_obj2nid(attr->object) == nid) { 1280280304Sjkim X509_ATTRIBUTE_free(attr); 1281280304Sjkim attr = X509_ATTRIBUTE_create(nid, atrtype, value); 1282280304Sjkim if (attr == NULL) 1283280304Sjkim return 0; 1284280304Sjkim if (!sk_X509_ATTRIBUTE_set(*sk, i, attr)) { 1285280304Sjkim X509_ATTRIBUTE_free(attr); 1286280304Sjkim return 0; 1287280304Sjkim } 1288280304Sjkim goto end; 1289280304Sjkim } 1290280304Sjkim } 1291280304Sjkim goto new_attrib; 1292280304Sjkim } 1293280304Sjkim end: 1294280304Sjkim return (1); 1295280304Sjkim} 1296