pk7_doit.c revision 306195
1130803Smarcel/* crypto/pkcs7/pk7_doit.c */ 2130803Smarcel/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3130803Smarcel * All rights reserved. 4130803Smarcel * 5130803Smarcel * This package is an SSL implementation written 6130803Smarcel * by Eric Young (eay@cryptsoft.com). 7130803Smarcel * The implementation was written so as to conform with Netscapes SSL. 8130803Smarcel * 9130803Smarcel * This library is free for commercial and non-commercial use as long as 10130803Smarcel * the following conditions are aheared to. The following conditions 11130803Smarcel * apply to all code found in this distribution, be it the RC4, RSA, 12130803Smarcel * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13130803Smarcel * included with this distribution is covered by the same copyright terms 14130803Smarcel * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15130803Smarcel * 16130803Smarcel * Copyright remains Eric Young's, and as such any Copyright notices in 17130803Smarcel * the code are not to be removed. 18130803Smarcel * If this package is used in a product, Eric Young should be given attribution 19130803Smarcel * as the author of the parts of the library used. 20130803Smarcel * This can be in the form of a textual message at program startup or 21130803Smarcel * in documentation (online or textual) provided with the package. 22130803Smarcel * 23130803Smarcel * Redistribution and use in source and binary forms, with or without 24130803Smarcel * modification, are permitted provided that the following conditions 25130803Smarcel * are met: 26130803Smarcel * 1. Redistributions of source code must retain the copyright 27130803Smarcel * notice, this list of conditions and the following disclaimer. 28130803Smarcel * 2. Redistributions in binary form must reproduce the above copyright 29130803Smarcel * notice, this list of conditions and the following disclaimer in the 30130803Smarcel * documentation and/or other materials provided with the distribution. 31130803Smarcel * 3. All advertising materials mentioning features or use of this software 32130803Smarcel * must display the following acknowledgement: 33130803Smarcel * "This product includes cryptographic software written by 34130803Smarcel * Eric Young (eay@cryptsoft.com)" 35130803Smarcel * The word 'cryptographic' can be left out if the rouines from the library 36130803Smarcel * being used are not cryptographic related :-). 37130803Smarcel * 4. If you include any Windows specific code (or a derivative thereof) from 38130803Smarcel * the apps directory (application code) you must include an acknowledgement: 39130803Smarcel * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40130803Smarcel * 41130803Smarcel * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42130803Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43130803Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44130803Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45130803Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46130803Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47130803Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48130803Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49130803Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50130803Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51130803Smarcel * SUCH DAMAGE. 52130803Smarcel * 53130803Smarcel * The licence and distribution terms for any publically available version or 54130803Smarcel * derivative of this code cannot be changed. i.e. this code cannot simply be 55130803Smarcel * copied and put under another distribution licence 56130803Smarcel * [including the GNU Public Licence.] 57130803Smarcel */ 58130803Smarcel 59130803Smarcel#include <stdio.h> 60130803Smarcel#include "cryptlib.h" 61130803Smarcel#include <openssl/rand.h> 62130803Smarcel#include <openssl/objects.h> 63130803Smarcel#include <openssl/x509.h> 64130803Smarcel#include <openssl/x509v3.h> 65130803Smarcel#include <openssl/err.h> 66130803Smarcel 67130803Smarcelstatic int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, 68130803Smarcel void *value); 69130803Smarcelstatic ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid); 70130803Smarcel 71130803Smarcelstatic int PKCS7_type_is_other(PKCS7 *p7) 72130803Smarcel{ 73130803Smarcel int isOther = 1; 74130803Smarcel 75130803Smarcel int nid = OBJ_obj2nid(p7->type); 76130803Smarcel 77130803Smarcel switch (nid) { 78130803Smarcel case NID_pkcs7_data: 79130803Smarcel case NID_pkcs7_signed: 80130803Smarcel case NID_pkcs7_enveloped: 81130803Smarcel case NID_pkcs7_signedAndEnveloped: 82130803Smarcel case NID_pkcs7_digest: 83130803Smarcel case NID_pkcs7_encrypted: 84130803Smarcel isOther = 0; 85130803Smarcel break; 86130803Smarcel default: 87130803Smarcel isOther = 1; 88130803Smarcel } 89130803Smarcel 90130803Smarcel return isOther; 91130803Smarcel 92130803Smarcel} 93130803Smarcel 94130803Smarcelstatic ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7) 95130803Smarcel{ 96130803Smarcel if (PKCS7_type_is_data(p7)) 97130803Smarcel return p7->d.data; 98130803Smarcel if (PKCS7_type_is_other(p7) && p7->d.other 99130803Smarcel && (p7->d.other->type == V_ASN1_OCTET_STRING)) 100130803Smarcel return p7->d.other->value.octet_string; 101130803Smarcel return NULL; 102130803Smarcel} 103130803Smarcel 104130803Smarcelstatic int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg) 105130803Smarcel{ 106130803Smarcel BIO *btmp; 107130803Smarcel const EVP_MD *md; 108130803Smarcel if ((btmp = BIO_new(BIO_f_md())) == NULL) { 109130803Smarcel PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, ERR_R_BIO_LIB); 110130803Smarcel goto err; 111130803Smarcel } 112130803Smarcel 113130803Smarcel md = EVP_get_digestbyobj(alg->algorithm); 114130803Smarcel if (md == NULL) { 115130803Smarcel PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, PKCS7_R_UNKNOWN_DIGEST_TYPE); 116130803Smarcel goto err; 117130803Smarcel } 118130803Smarcel 119130803Smarcel BIO_set_md(btmp, md); 120130803Smarcel if (*pbio == NULL) 121130803Smarcel *pbio = btmp; 122130803Smarcel else if (!BIO_push(*pbio, btmp)) { 123130803Smarcel PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, ERR_R_BIO_LIB); 124130803Smarcel goto err; 125130803Smarcel } 126130803Smarcel btmp = NULL; 127130803Smarcel 128130803Smarcel return 1; 129130803Smarcel 130130803Smarcel err: 131130803Smarcel if (btmp) 132130803Smarcel BIO_free(btmp); 133130803Smarcel return 0; 134130803Smarcel 135130803Smarcel} 136130803Smarcel 137130803Smarcelstatic int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, 138130803Smarcel unsigned char *key, int keylen) 139130803Smarcel{ 140130803Smarcel EVP_PKEY_CTX *pctx = NULL; 141130803Smarcel EVP_PKEY *pkey = NULL; 142130803Smarcel unsigned char *ek = NULL; 143130803Smarcel int ret = 0; 144130803Smarcel size_t eklen; 145130803Smarcel 146130803Smarcel pkey = X509_get_pubkey(ri->cert); 147130803Smarcel 148130803Smarcel if (!pkey) 149130803Smarcel return 0; 150130803Smarcel 151130803Smarcel pctx = EVP_PKEY_CTX_new(pkey, NULL); 152130803Smarcel if (!pctx) 153130803Smarcel return 0; 154130803Smarcel 155130803Smarcel if (EVP_PKEY_encrypt_init(pctx) <= 0) 156130803Smarcel goto err; 157130803Smarcel 158130803Smarcel if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT, 159130803Smarcel EVP_PKEY_CTRL_PKCS7_ENCRYPT, 0, ri) <= 0) { 160130803Smarcel PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, PKCS7_R_CTRL_ERROR); 161130803Smarcel goto err; 162130803Smarcel } 163130803Smarcel 164130803Smarcel if (EVP_PKEY_encrypt(pctx, NULL, &eklen, key, keylen) <= 0) 165130803Smarcel goto err; 166130803Smarcel 167130803Smarcel ek = OPENSSL_malloc(eklen); 168130803Smarcel 169130803Smarcel if (ek == NULL) { 170130803Smarcel PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, ERR_R_MALLOC_FAILURE); 171130803Smarcel goto err; 172130803Smarcel } 173130803Smarcel 174130803Smarcel if (EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen) <= 0) 175130803Smarcel goto err; 176130803Smarcel 177130803Smarcel ASN1_STRING_set0(ri->enc_key, ek, eklen); 178130803Smarcel ek = NULL; 179130803Smarcel 180130803Smarcel ret = 1; 181130803Smarcel 182130803Smarcel err: 183130803Smarcel if (pkey) 184130803Smarcel EVP_PKEY_free(pkey); 185130803Smarcel if (pctx) 186130803Smarcel EVP_PKEY_CTX_free(pctx); 187130803Smarcel if (ek) 188130803Smarcel OPENSSL_free(ek); 189130803Smarcel return ret; 190130803Smarcel 191130803Smarcel} 192130803Smarcel 193130803Smarcelstatic int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, 194130803Smarcel PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey) 195130803Smarcel{ 196130803Smarcel EVP_PKEY_CTX *pctx = NULL; 197130803Smarcel unsigned char *ek = NULL; 198130803Smarcel size_t eklen; 199130803Smarcel 200130803Smarcel int ret = -1; 201130803Smarcel 202130803Smarcel pctx = EVP_PKEY_CTX_new(pkey, NULL); 203130803Smarcel if (!pctx) 204130803Smarcel return -1; 205130803Smarcel 206130803Smarcel if (EVP_PKEY_decrypt_init(pctx) <= 0) 207130803Smarcel goto err; 208130803Smarcel 209130803Smarcel if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT, 210130803Smarcel EVP_PKEY_CTRL_PKCS7_DECRYPT, 0, ri) <= 0) { 211130803Smarcel PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, PKCS7_R_CTRL_ERROR); 212130803Smarcel goto err; 213130803Smarcel } 214130803Smarcel 215130803Smarcel if (EVP_PKEY_decrypt(pctx, NULL, &eklen, 216130803Smarcel ri->enc_key->data, ri->enc_key->length) <= 0) 217130803Smarcel goto err; 218130803Smarcel 219130803Smarcel ek = OPENSSL_malloc(eklen); 220130803Smarcel 221130803Smarcel if (ek == NULL) { 222130803Smarcel PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_MALLOC_FAILURE); 223130803Smarcel goto err; 224130803Smarcel } 225130803Smarcel 226130803Smarcel if (EVP_PKEY_decrypt(pctx, ek, &eklen, 227130803Smarcel ri->enc_key->data, ri->enc_key->length) <= 0) { 228130803Smarcel ret = 0; 229130803Smarcel PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB); 230130803Smarcel goto err; 231130803Smarcel } 232130803Smarcel 233130803Smarcel ret = 1; 234130803Smarcel 235130803Smarcel if (*pek) { 236130803Smarcel OPENSSL_cleanse(*pek, *peklen); 237130803Smarcel OPENSSL_free(*pek); 238130803Smarcel } 239130803Smarcel 240130803Smarcel *pek = ek; 241130803Smarcel *peklen = eklen; 242130803Smarcel 243130803Smarcel err: 244130803Smarcel if (pctx) 245130803Smarcel EVP_PKEY_CTX_free(pctx); 246130803Smarcel if (!ret && ek) 247130803Smarcel OPENSSL_free(ek); 248130803Smarcel 249130803Smarcel return ret; 250130803Smarcel} 251130803Smarcel 252130803SmarcelBIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) 253130803Smarcel{ 254130803Smarcel int i; 255130803Smarcel BIO *out = NULL, *btmp = NULL; 256130803Smarcel X509_ALGOR *xa = NULL; 257130803Smarcel const EVP_CIPHER *evp_cipher = NULL; 258130803Smarcel STACK_OF(X509_ALGOR) *md_sk = NULL; 259130803Smarcel STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; 260130803Smarcel X509_ALGOR *xalg = NULL; 261130803Smarcel PKCS7_RECIP_INFO *ri = NULL; 262130803Smarcel ASN1_OCTET_STRING *os = NULL; 263130803Smarcel 264130803Smarcel if (p7 == NULL) { 265130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER); 266130803Smarcel return NULL; 267130803Smarcel } 268130803Smarcel /* 269130803Smarcel * The content field in the PKCS7 ContentInfo is optional, but that really 270130803Smarcel * only applies to inner content (precisely, detached signatures). 271130803Smarcel * 272130803Smarcel * When reading content, missing outer content is therefore treated as an 273130803Smarcel * error. 274130803Smarcel * 275130803Smarcel * When creating content, PKCS7_content_new() must be called before 276130803Smarcel * calling this method, so a NULL p7->d is always an error. 277130803Smarcel */ 278130803Smarcel if (p7->d.ptr == NULL) { 279130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT); 280130803Smarcel return NULL; 281130803Smarcel } 282130803Smarcel 283130803Smarcel i = OBJ_obj2nid(p7->type); 284130803Smarcel p7->state = PKCS7_S_HEADER; 285130803Smarcel 286130803Smarcel switch (i) { 287130803Smarcel case NID_pkcs7_signed: 288130803Smarcel md_sk = p7->d.sign->md_algs; 289130803Smarcel os = PKCS7_get_octet_string(p7->d.sign->contents); 290130803Smarcel break; 291130803Smarcel case NID_pkcs7_signedAndEnveloped: 292130803Smarcel rsk = p7->d.signed_and_enveloped->recipientinfo; 293130803Smarcel md_sk = p7->d.signed_and_enveloped->md_algs; 294130803Smarcel xalg = p7->d.signed_and_enveloped->enc_data->algorithm; 295130803Smarcel evp_cipher = p7->d.signed_and_enveloped->enc_data->cipher; 296130803Smarcel if (evp_cipher == NULL) { 297130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); 298130803Smarcel goto err; 299130803Smarcel } 300130803Smarcel break; 301130803Smarcel case NID_pkcs7_enveloped: 302130803Smarcel rsk = p7->d.enveloped->recipientinfo; 303130803Smarcel xalg = p7->d.enveloped->enc_data->algorithm; 304130803Smarcel evp_cipher = p7->d.enveloped->enc_data->cipher; 305130803Smarcel if (evp_cipher == NULL) { 306130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); 307130803Smarcel goto err; 308130803Smarcel } 309130803Smarcel break; 310130803Smarcel case NID_pkcs7_digest: 311130803Smarcel xa = p7->d.digest->md; 312130803Smarcel os = PKCS7_get_octet_string(p7->d.digest->contents); 313130803Smarcel break; 314130803Smarcel case NID_pkcs7_data: 315130803Smarcel break; 316130803Smarcel default: 317130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 318130803Smarcel goto err; 319130803Smarcel } 320130803Smarcel 321130803Smarcel for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) 322130803Smarcel if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i))) 323130803Smarcel goto err; 324130803Smarcel 325130803Smarcel if (xa && !PKCS7_bio_add_digest(&out, xa)) 326130803Smarcel goto err; 327130803Smarcel 328130803Smarcel if (evp_cipher != NULL) { 329130803Smarcel unsigned char key[EVP_MAX_KEY_LENGTH]; 330130803Smarcel unsigned char iv[EVP_MAX_IV_LENGTH]; 331130803Smarcel int keylen, ivlen; 332130803Smarcel EVP_CIPHER_CTX *ctx; 333130803Smarcel 334130803Smarcel if ((btmp = BIO_new(BIO_f_cipher())) == NULL) { 335130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAINIT, ERR_R_BIO_LIB); 336130803Smarcel goto err; 337130803Smarcel } 338130803Smarcel BIO_get_cipher_ctx(btmp, &ctx); 339130803Smarcel keylen = EVP_CIPHER_key_length(evp_cipher); 340130803Smarcel ivlen = EVP_CIPHER_iv_length(evp_cipher); 341130803Smarcel xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); 342130803Smarcel if (ivlen > 0) 343130803Smarcel if (RAND_bytes(iv, ivlen) <= 0) 344130803Smarcel goto err; 345130803Smarcel if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1) <= 0) 346130803Smarcel goto err; 347130803Smarcel if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0) 348130803Smarcel goto err; 349130803Smarcel if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0) 350130803Smarcel goto err; 351130803Smarcel 352130803Smarcel if (ivlen > 0) { 353130803Smarcel if (xalg->parameter == NULL) { 354130803Smarcel xalg->parameter = ASN1_TYPE_new(); 355130803Smarcel if (xalg->parameter == NULL) 356130803Smarcel goto err; 357130803Smarcel } 358130803Smarcel if (EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0) 359130803Smarcel goto err; 360130803Smarcel } 361130803Smarcel 362130803Smarcel /* Lets do the pub key stuff :-) */ 363130803Smarcel for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { 364130803Smarcel ri = sk_PKCS7_RECIP_INFO_value(rsk, i); 365130803Smarcel if (pkcs7_encode_rinfo(ri, key, keylen) <= 0) 366130803Smarcel goto err; 367130803Smarcel } 368130803Smarcel OPENSSL_cleanse(key, keylen); 369130803Smarcel 370130803Smarcel if (out == NULL) 371130803Smarcel out = btmp; 372130803Smarcel else 373130803Smarcel BIO_push(out, btmp); 374130803Smarcel btmp = NULL; 375130803Smarcel } 376130803Smarcel 377130803Smarcel if (bio == NULL) { 378130803Smarcel if (PKCS7_is_detached(p7)) 379130803Smarcel bio = BIO_new(BIO_s_null()); 380130803Smarcel else if (os && os->length > 0) 381130803Smarcel bio = BIO_new_mem_buf(os->data, os->length); 382130803Smarcel if (bio == NULL) { 383130803Smarcel bio = BIO_new(BIO_s_mem()); 384130803Smarcel if (bio == NULL) 385130803Smarcel goto err; 386130803Smarcel BIO_set_mem_eof_return(bio, 0); 387130803Smarcel } 388130803Smarcel } 389130803Smarcel if (out) 390130803Smarcel BIO_push(out, bio); 391130803Smarcel else 392130803Smarcel out = bio; 393130803Smarcel bio = NULL; 394130803Smarcel if (0) { 395130803Smarcel err: 396130803Smarcel if (out != NULL) 397130803Smarcel BIO_free_all(out); 398130803Smarcel if (btmp != NULL) 399130803Smarcel BIO_free_all(btmp); 400130803Smarcel out = NULL; 401130803Smarcel } 402130803Smarcel return (out); 403130803Smarcel} 404130803Smarcel 405130803Smarcelstatic int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert) 406130803Smarcel{ 407130803Smarcel int ret; 408130803Smarcel ret = X509_NAME_cmp(ri->issuer_and_serial->issuer, 409130803Smarcel pcert->cert_info->issuer); 410130803Smarcel if (ret) 411130803Smarcel return ret; 412130803Smarcel return M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber, 413130803Smarcel ri->issuer_and_serial->serial); 414130803Smarcel} 415130803Smarcel 416130803Smarcel/* int */ 417130803SmarcelBIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) 418130803Smarcel{ 419130803Smarcel int i, j; 420130803Smarcel BIO *out = NULL, *btmp = NULL, *etmp = NULL, *bio = NULL; 421130803Smarcel X509_ALGOR *xa; 422130803Smarcel ASN1_OCTET_STRING *data_body = NULL; 423130803Smarcel const EVP_MD *evp_md; 424130803Smarcel const EVP_CIPHER *evp_cipher = NULL; 425130803Smarcel EVP_CIPHER_CTX *evp_ctx = NULL; 426130803Smarcel X509_ALGOR *enc_alg = NULL; 427130803Smarcel STACK_OF(X509_ALGOR) *md_sk = NULL; 428130803Smarcel STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; 429130803Smarcel PKCS7_RECIP_INFO *ri = NULL; 430130803Smarcel unsigned char *ek = NULL, *tkey = NULL; 431130803Smarcel int eklen = 0, tkeylen = 0; 432130803Smarcel 433130803Smarcel if (p7 == NULL) { 434130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER); 435130803Smarcel return NULL; 436130803Smarcel } 437130803Smarcel 438130803Smarcel if (p7->d.ptr == NULL) { 439130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); 440130803Smarcel return NULL; 441130803Smarcel } 442130803Smarcel 443130803Smarcel i = OBJ_obj2nid(p7->type); 444130803Smarcel p7->state = PKCS7_S_HEADER; 445130803Smarcel 446130803Smarcel switch (i) { 447130803Smarcel case NID_pkcs7_signed: 448130803Smarcel /* 449130803Smarcel * p7->d.sign->contents is a PKCS7 structure consisting of a contentType 450130803Smarcel * field and optional content. 451130803Smarcel * data_body is NULL if that structure has no (=detached) content 452130803Smarcel * or if the contentType is wrong (i.e., not "data"). 453130803Smarcel */ 454130803Smarcel data_body = PKCS7_get_octet_string(p7->d.sign->contents); 455130803Smarcel if (!PKCS7_is_detached(p7) && data_body == NULL) { 456130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATADECODE, 457130803Smarcel PKCS7_R_INVALID_SIGNED_DATA_TYPE); 458130803Smarcel goto err; 459130803Smarcel } 460130803Smarcel md_sk = p7->d.sign->md_algs; 461130803Smarcel break; 462130803Smarcel case NID_pkcs7_signedAndEnveloped: 463130803Smarcel rsk = p7->d.signed_and_enveloped->recipientinfo; 464130803Smarcel md_sk = p7->d.signed_and_enveloped->md_algs; 465130803Smarcel /* data_body is NULL if the optional EncryptedContent is missing. */ 466130803Smarcel data_body = p7->d.signed_and_enveloped->enc_data->enc_data; 467130803Smarcel enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm; 468130803Smarcel evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); 469130803Smarcel if (evp_cipher == NULL) { 470130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATADECODE, 471130803Smarcel PKCS7_R_UNSUPPORTED_CIPHER_TYPE); 472130803Smarcel goto err; 473130803Smarcel } 474130803Smarcel break; 475130803Smarcel case NID_pkcs7_enveloped: 476130803Smarcel rsk = p7->d.enveloped->recipientinfo; 477130803Smarcel enc_alg = p7->d.enveloped->enc_data->algorithm; 478130803Smarcel /* data_body is NULL if the optional EncryptedContent is missing. */ 479130803Smarcel data_body = p7->d.enveloped->enc_data->enc_data; 480130803Smarcel evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); 481130803Smarcel if (evp_cipher == NULL) { 482130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATADECODE, 483130803Smarcel PKCS7_R_UNSUPPORTED_CIPHER_TYPE); 484130803Smarcel goto err; 485130803Smarcel } 486130803Smarcel break; 487130803Smarcel default: 488130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 489130803Smarcel goto err; 490130803Smarcel } 491130803Smarcel 492130803Smarcel /* Detached content must be supplied via in_bio instead. */ 493130803Smarcel if (data_body == NULL && in_bio == NULL) { 494130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); 495130803Smarcel goto err; 496130803Smarcel } 497130803Smarcel 498130803Smarcel /* We will be checking the signature */ 499130803Smarcel if (md_sk != NULL) { 500130803Smarcel for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) { 501130803Smarcel xa = sk_X509_ALGOR_value(md_sk, i); 502130803Smarcel if ((btmp = BIO_new(BIO_f_md())) == NULL) { 503130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_BIO_LIB); 504130803Smarcel goto err; 505130803Smarcel } 506130803Smarcel 507130803Smarcel j = OBJ_obj2nid(xa->algorithm); 508130803Smarcel evp_md = EVP_get_digestbynid(j); 509130803Smarcel if (evp_md == NULL) { 510130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATADECODE, 511130803Smarcel PKCS7_R_UNKNOWN_DIGEST_TYPE); 512130803Smarcel goto err; 513130803Smarcel } 514130803Smarcel 515130803Smarcel BIO_set_md(btmp, evp_md); 516130803Smarcel if (out == NULL) 517130803Smarcel out = btmp; 518130803Smarcel else 519130803Smarcel BIO_push(out, btmp); 520130803Smarcel btmp = NULL; 521130803Smarcel } 522130803Smarcel } 523130803Smarcel 524130803Smarcel if (evp_cipher != NULL) { 525130803Smarcel#if 0 526130803Smarcel unsigned char key[EVP_MAX_KEY_LENGTH]; 527130803Smarcel unsigned char iv[EVP_MAX_IV_LENGTH]; 528130803Smarcel unsigned char *p; 529130803Smarcel int keylen, ivlen; 530130803Smarcel int max; 531130803Smarcel X509_OBJECT ret; 532130803Smarcel#endif 533130803Smarcel 534130803Smarcel if ((etmp = BIO_new(BIO_f_cipher())) == NULL) { 535130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_BIO_LIB); 536130803Smarcel goto err; 537130803Smarcel } 538130803Smarcel 539130803Smarcel /* 540130803Smarcel * It was encrypted, we need to decrypt the secret key with the 541130803Smarcel * private key 542130803Smarcel */ 543130803Smarcel 544130803Smarcel /* 545130803Smarcel * Find the recipientInfo which matches the passed certificate (if 546130803Smarcel * any) 547130803Smarcel */ 548130803Smarcel 549130803Smarcel if (pcert) { 550130803Smarcel for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { 551130803Smarcel ri = sk_PKCS7_RECIP_INFO_value(rsk, i); 552130803Smarcel if (!pkcs7_cmp_ri(ri, pcert)) 553130803Smarcel break; 554130803Smarcel ri = NULL; 555130803Smarcel } 556130803Smarcel if (ri == NULL) { 557130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATADECODE, 558130803Smarcel PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); 559130803Smarcel goto err; 560130803Smarcel } 561130803Smarcel } 562130803Smarcel 563130803Smarcel /* If we haven't got a certificate try each ri in turn */ 564130803Smarcel if (pcert == NULL) { 565130803Smarcel /* 566130803Smarcel * Always attempt to decrypt all rinfo even after sucess as a 567130803Smarcel * defence against MMA timing attacks. 568130803Smarcel */ 569130803Smarcel for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { 570130803Smarcel ri = sk_PKCS7_RECIP_INFO_value(rsk, i); 571130803Smarcel 572130803Smarcel if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0) 573130803Smarcel goto err; 574130803Smarcel ERR_clear_error(); 575130803Smarcel } 576130803Smarcel } else { 577130803Smarcel /* Only exit on fatal errors, not decrypt failure */ 578130803Smarcel if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0) 579130803Smarcel goto err; 580130803Smarcel ERR_clear_error(); 581130803Smarcel } 582130803Smarcel 583130803Smarcel evp_ctx = NULL; 584130803Smarcel BIO_get_cipher_ctx(etmp, &evp_ctx); 585130803Smarcel if (EVP_CipherInit_ex(evp_ctx, evp_cipher, NULL, NULL, NULL, 0) <= 0) 586130803Smarcel goto err; 587130803Smarcel if (EVP_CIPHER_asn1_to_param(evp_ctx, enc_alg->parameter) < 0) 588130803Smarcel goto err; 589130803Smarcel /* Generate random key as MMA defence */ 590130803Smarcel tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx); 591130803Smarcel tkey = OPENSSL_malloc(tkeylen); 592130803Smarcel if (!tkey) 593130803Smarcel goto err; 594130803Smarcel if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0) 595130803Smarcel goto err; 596130803Smarcel if (ek == NULL) { 597130803Smarcel ek = tkey; 598130803Smarcel eklen = tkeylen; 599130803Smarcel tkey = NULL; 600130803Smarcel } 601130803Smarcel 602130803Smarcel if (eklen != EVP_CIPHER_CTX_key_length(evp_ctx)) { 603130803Smarcel /* 604130803Smarcel * Some S/MIME clients don't use the same key and effective key 605130803Smarcel * length. The key length is determined by the size of the 606130803Smarcel * decrypted RSA key. 607130803Smarcel */ 608130803Smarcel if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen)) { 609130803Smarcel /* Use random key as MMA defence */ 610130803Smarcel OPENSSL_cleanse(ek, eklen); 611130803Smarcel OPENSSL_free(ek); 612130803Smarcel ek = tkey; 613130803Smarcel eklen = tkeylen; 614130803Smarcel tkey = NULL; 615130803Smarcel } 616130803Smarcel } 617130803Smarcel /* Clear errors so we don't leak information useful in MMA */ 618130803Smarcel ERR_clear_error(); 619130803Smarcel if (EVP_CipherInit_ex(evp_ctx, NULL, NULL, ek, NULL, 0) <= 0) 620130803Smarcel goto err; 621130803Smarcel 622130803Smarcel if (ek) { 623130803Smarcel OPENSSL_cleanse(ek, eklen); 624130803Smarcel OPENSSL_free(ek); 625130803Smarcel ek = NULL; 626130803Smarcel } 627130803Smarcel if (tkey) { 628130803Smarcel OPENSSL_cleanse(tkey, tkeylen); 629130803Smarcel OPENSSL_free(tkey); 630130803Smarcel tkey = NULL; 631130803Smarcel } 632130803Smarcel 633130803Smarcel if (out == NULL) 634130803Smarcel out = etmp; 635130803Smarcel else 636130803Smarcel BIO_push(out, etmp); 637130803Smarcel etmp = NULL; 638130803Smarcel } 639130803Smarcel#if 1 640130803Smarcel if (in_bio != NULL) { 641130803Smarcel bio = in_bio; 642130803Smarcel } else { 643130803Smarcel# if 0 644130803Smarcel bio = BIO_new(BIO_s_mem()); 645130803Smarcel if (bio == NULL) 646130803Smarcel goto err; 647130803Smarcel /* 648130803Smarcel * We need to set this so that when we have read all the data, the 649130803Smarcel * encrypt BIO, if present, will read EOF and encode the last few 650130803Smarcel * bytes 651130803Smarcel */ 652130803Smarcel BIO_set_mem_eof_return(bio, 0); 653130803Smarcel 654130803Smarcel if (data_body->length > 0) 655130803Smarcel BIO_write(bio, (char *)data_body->data, data_body->length); 656130803Smarcel# else 657130803Smarcel if (data_body->length > 0) 658130803Smarcel bio = BIO_new_mem_buf(data_body->data, data_body->length); 659130803Smarcel else { 660130803Smarcel bio = BIO_new(BIO_s_mem()); 661130803Smarcel if (bio == NULL) 662130803Smarcel goto err; 663130803Smarcel BIO_set_mem_eof_return(bio, 0); 664130803Smarcel } 665130803Smarcel if (bio == NULL) 666130803Smarcel goto err; 667130803Smarcel# endif 668130803Smarcel } 669130803Smarcel BIO_push(out, bio); 670130803Smarcel bio = NULL; 671130803Smarcel#endif 672130803Smarcel if (0) { 673130803Smarcel err: 674130803Smarcel if (ek) { 675130803Smarcel OPENSSL_cleanse(ek, eklen); 676130803Smarcel OPENSSL_free(ek); 677130803Smarcel } 678130803Smarcel if (tkey) { 679130803Smarcel OPENSSL_cleanse(tkey, tkeylen); 680130803Smarcel OPENSSL_free(tkey); 681130803Smarcel } 682130803Smarcel if (out != NULL) 683130803Smarcel BIO_free_all(out); 684130803Smarcel if (btmp != NULL) 685130803Smarcel BIO_free_all(btmp); 686130803Smarcel if (etmp != NULL) 687130803Smarcel BIO_free_all(etmp); 688130803Smarcel if (bio != NULL) 689130803Smarcel BIO_free_all(bio); 690130803Smarcel out = NULL; 691130803Smarcel } 692130803Smarcel return (out); 693130803Smarcel} 694130803Smarcel 695130803Smarcelstatic BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid) 696130803Smarcel{ 697130803Smarcel for (;;) { 698130803Smarcel bio = BIO_find_type(bio, BIO_TYPE_MD); 699130803Smarcel if (bio == NULL) { 700130803Smarcel PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST, 701130803Smarcel PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 702130803Smarcel return NULL; 703130803Smarcel } 704130803Smarcel BIO_get_md_ctx(bio, pmd); 705130803Smarcel if (*pmd == NULL) { 706130803Smarcel PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST, ERR_R_INTERNAL_ERROR); 707130803Smarcel return NULL; 708130803Smarcel } 709130803Smarcel if (EVP_MD_CTX_type(*pmd) == nid) 710130803Smarcel return bio; 711130803Smarcel bio = BIO_next(bio); 712130803Smarcel } 713130803Smarcel return NULL; 714130803Smarcel} 715130803Smarcel 716130803Smarcelstatic int do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx) 717130803Smarcel{ 718130803Smarcel unsigned char md_data[EVP_MAX_MD_SIZE]; 719130803Smarcel unsigned int md_len; 720130803Smarcel 721130803Smarcel /* Add signing time if not already present */ 722130803Smarcel if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) { 723130803Smarcel if (!PKCS7_add0_attrib_signing_time(si, NULL)) { 724130803Smarcel PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE); 725130803Smarcel return 0; 726130803Smarcel } 727130803Smarcel } 728130803Smarcel 729130803Smarcel /* Add digest */ 730130803Smarcel if (!EVP_DigestFinal_ex(mctx, md_data, &md_len)) { 731130803Smarcel PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_EVP_LIB); 732130803Smarcel return 0; 733130803Smarcel } 734130803Smarcel if (!PKCS7_add1_attrib_digest(si, md_data, md_len)) { 735130803Smarcel PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE); 736130803Smarcel return 0; 737130803Smarcel } 738130803Smarcel 739130803Smarcel /* Now sign the attributes */ 740130803Smarcel if (!PKCS7_SIGNER_INFO_sign(si)) 741130803Smarcel return 0; 742130803Smarcel 743130803Smarcel return 1; 744130803Smarcel} 745130803Smarcel 746130803Smarcelint PKCS7_dataFinal(PKCS7 *p7, BIO *bio) 747130803Smarcel{ 748130803Smarcel int ret = 0; 749130803Smarcel int i, j; 750130803Smarcel BIO *btmp; 751130803Smarcel PKCS7_SIGNER_INFO *si; 752130803Smarcel EVP_MD_CTX *mdc, ctx_tmp; 753130803Smarcel STACK_OF(X509_ATTRIBUTE) *sk; 754130803Smarcel STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL; 755130803Smarcel ASN1_OCTET_STRING *os = NULL; 756130803Smarcel 757130803Smarcel if (p7 == NULL) { 758130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER); 759130803Smarcel return 0; 760130803Smarcel } 761130803Smarcel 762130803Smarcel if (p7->d.ptr == NULL) { 763130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT); 764130803Smarcel return 0; 765130803Smarcel } 766130803Smarcel 767130803Smarcel EVP_MD_CTX_init(&ctx_tmp); 768130803Smarcel i = OBJ_obj2nid(p7->type); 769130803Smarcel p7->state = PKCS7_S_HEADER; 770130803Smarcel 771130803Smarcel switch (i) { 772130803Smarcel case NID_pkcs7_data: 773130803Smarcel os = p7->d.data; 774130803Smarcel break; 775130803Smarcel case NID_pkcs7_signedAndEnveloped: 776130803Smarcel /* XXXXXXXXXXXXXXXX */ 777130803Smarcel si_sk = p7->d.signed_and_enveloped->signer_info; 778130803Smarcel os = p7->d.signed_and_enveloped->enc_data->enc_data; 779130803Smarcel if (!os) { 780130803Smarcel os = M_ASN1_OCTET_STRING_new(); 781130803Smarcel if (!os) { 782130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); 783130803Smarcel goto err; 784130803Smarcel } 785130803Smarcel p7->d.signed_and_enveloped->enc_data->enc_data = os; 786130803Smarcel } 787130803Smarcel break; 788130803Smarcel case NID_pkcs7_enveloped: 789130803Smarcel /* XXXXXXXXXXXXXXXX */ 790130803Smarcel os = p7->d.enveloped->enc_data->enc_data; 791130803Smarcel if (!os) { 792130803Smarcel os = M_ASN1_OCTET_STRING_new(); 793130803Smarcel if (!os) { 794130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); 795130803Smarcel goto err; 796130803Smarcel } 797130803Smarcel p7->d.enveloped->enc_data->enc_data = os; 798130803Smarcel } 799130803Smarcel break; 800130803Smarcel case NID_pkcs7_signed: 801130803Smarcel si_sk = p7->d.sign->signer_info; 802130803Smarcel os = PKCS7_get_octet_string(p7->d.sign->contents); 803130803Smarcel /* If detached data then the content is excluded */ 804130803Smarcel if (PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) { 805130803Smarcel M_ASN1_OCTET_STRING_free(os); 806130803Smarcel os = NULL; 807130803Smarcel p7->d.sign->contents->d.data = NULL; 808130803Smarcel } 809130803Smarcel break; 810130803Smarcel 811130803Smarcel case NID_pkcs7_digest: 812130803Smarcel os = PKCS7_get_octet_string(p7->d.digest->contents); 813130803Smarcel /* If detached data then the content is excluded */ 814130803Smarcel if (PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) { 815130803Smarcel M_ASN1_OCTET_STRING_free(os); 816130803Smarcel os = NULL; 817130803Smarcel p7->d.digest->contents->d.data = NULL; 818130803Smarcel } 819130803Smarcel break; 820130803Smarcel 821130803Smarcel default: 822130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 823130803Smarcel goto err; 824130803Smarcel } 825130803Smarcel 826130803Smarcel if (si_sk != NULL) { 827130803Smarcel for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(si_sk); i++) { 828130803Smarcel si = sk_PKCS7_SIGNER_INFO_value(si_sk, i); 829130803Smarcel if (si->pkey == NULL) 830130803Smarcel continue; 831130803Smarcel 832130803Smarcel j = OBJ_obj2nid(si->digest_alg->algorithm); 833130803Smarcel 834130803Smarcel btmp = bio; 835130803Smarcel 836130803Smarcel btmp = PKCS7_find_digest(&mdc, btmp, j); 837130803Smarcel 838130803Smarcel if (btmp == NULL) 839130803Smarcel goto err; 840130803Smarcel 841130803Smarcel /* 842130803Smarcel * We now have the EVP_MD_CTX, lets do the signing. 843130803Smarcel */ 844130803Smarcel if (!EVP_MD_CTX_copy_ex(&ctx_tmp, mdc)) 845130803Smarcel goto err; 846130803Smarcel 847130803Smarcel sk = si->auth_attr; 848130803Smarcel 849130803Smarcel /* 850130803Smarcel * If there are attributes, we add the digest attribute and only 851130803Smarcel * sign the attributes 852130803Smarcel */ 853130803Smarcel if (sk_X509_ATTRIBUTE_num(sk) > 0) { 854130803Smarcel if (!do_pkcs7_signed_attrib(si, &ctx_tmp)) 855130803Smarcel goto err; 856130803Smarcel } else { 857130803Smarcel unsigned char *abuf = NULL; 858130803Smarcel unsigned int abuflen; 859130803Smarcel abuflen = EVP_PKEY_size(si->pkey); 860130803Smarcel abuf = OPENSSL_malloc(abuflen); 861130803Smarcel if (!abuf) 862130803Smarcel goto err; 863130803Smarcel 864130803Smarcel if (!EVP_SignFinal(&ctx_tmp, abuf, &abuflen, si->pkey)) { 865130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_EVP_LIB); 866130803Smarcel goto err; 867130803Smarcel } 868130803Smarcel ASN1_STRING_set0(si->enc_digest, abuf, abuflen); 869130803Smarcel } 870130803Smarcel } 871130803Smarcel } else if (i == NID_pkcs7_digest) { 872130803Smarcel unsigned char md_data[EVP_MAX_MD_SIZE]; 873130803Smarcel unsigned int md_len; 874130803Smarcel if (!PKCS7_find_digest(&mdc, bio, 875130803Smarcel OBJ_obj2nid(p7->d.digest->md->algorithm))) 876130803Smarcel goto err; 877130803Smarcel if (!EVP_DigestFinal_ex(mdc, md_data, &md_len)) 878130803Smarcel goto err; 879130803Smarcel M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len); 880130803Smarcel } 881130803Smarcel 882130803Smarcel if (!PKCS7_is_detached(p7)) { 883130803Smarcel /* 884130803Smarcel * NOTE(emilia): I think we only reach os == NULL here because detached 885130803Smarcel * digested data support is broken. 886130803Smarcel */ 887130803Smarcel if (os == NULL) 888130803Smarcel goto err; 889130803Smarcel if (!(os->flags & ASN1_STRING_FLAG_NDEF)) { 890130803Smarcel char *cont; 891130803Smarcel long contlen; 892130803Smarcel btmp = BIO_find_type(bio, BIO_TYPE_MEM); 893130803Smarcel if (btmp == NULL) { 894130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNABLE_TO_FIND_MEM_BIO); 895130803Smarcel goto err; 896130803Smarcel } 897130803Smarcel contlen = BIO_get_mem_data(btmp, &cont); 898130803Smarcel /* 899130803Smarcel * Mark the BIO read only then we can use its copy of the data 900130803Smarcel * instead of making an extra copy. 901130803Smarcel */ 902130803Smarcel BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); 903130803Smarcel BIO_set_mem_eof_return(btmp, 0); 904130803Smarcel ASN1_STRING_set0(os, (unsigned char *)cont, contlen); 905130803Smarcel } 906130803Smarcel } 907130803Smarcel ret = 1; 908130803Smarcel err: 909130803Smarcel EVP_MD_CTX_cleanup(&ctx_tmp); 910130803Smarcel return (ret); 911130803Smarcel} 912130803Smarcel 913130803Smarcelint PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) 914130803Smarcel{ 915130803Smarcel EVP_MD_CTX mctx; 916130803Smarcel EVP_PKEY_CTX *pctx; 917130803Smarcel unsigned char *abuf = NULL; 918130803Smarcel int alen; 919130803Smarcel size_t siglen; 920130803Smarcel const EVP_MD *md = NULL; 921130803Smarcel 922130803Smarcel md = EVP_get_digestbyobj(si->digest_alg->algorithm); 923130803Smarcel if (md == NULL) 924130803Smarcel return 0; 925130803Smarcel 926130803Smarcel EVP_MD_CTX_init(&mctx); 927130803Smarcel if (EVP_DigestSignInit(&mctx, &pctx, md, NULL, si->pkey) <= 0) 928130803Smarcel goto err; 929130803Smarcel 930130803Smarcel if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, 931130803Smarcel EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0) { 932130803Smarcel PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); 933130803Smarcel goto err; 934130803Smarcel } 935130803Smarcel 936130803Smarcel alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr, &abuf, 937130803Smarcel ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); 938130803Smarcel if (!abuf) 939130803Smarcel goto err; 940130803Smarcel if (EVP_DigestSignUpdate(&mctx, abuf, alen) <= 0) 941130803Smarcel goto err; 942130803Smarcel OPENSSL_free(abuf); 943130803Smarcel abuf = NULL; 944130803Smarcel if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0) 945130803Smarcel goto err; 946130803Smarcel abuf = OPENSSL_malloc(siglen); 947130803Smarcel if (!abuf) 948130803Smarcel goto err; 949130803Smarcel if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0) 950130803Smarcel goto err; 951130803Smarcel 952130803Smarcel if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, 953130803Smarcel EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0) { 954130803Smarcel PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); 955130803Smarcel goto err; 956130803Smarcel } 957130803Smarcel 958130803Smarcel EVP_MD_CTX_cleanup(&mctx); 959130803Smarcel 960130803Smarcel ASN1_STRING_set0(si->enc_digest, abuf, siglen); 961130803Smarcel 962130803Smarcel return 1; 963130803Smarcel 964130803Smarcel err: 965130803Smarcel if (abuf) 966130803Smarcel OPENSSL_free(abuf); 967130803Smarcel EVP_MD_CTX_cleanup(&mctx); 968130803Smarcel return 0; 969130803Smarcel 970130803Smarcel} 971130803Smarcel 972130803Smarcelint PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, 973130803Smarcel PKCS7 *p7, PKCS7_SIGNER_INFO *si) 974130803Smarcel{ 975130803Smarcel PKCS7_ISSUER_AND_SERIAL *ias; 976130803Smarcel int ret = 0, i; 977130803Smarcel STACK_OF(X509) *cert; 978130803Smarcel X509 *x509; 979130803Smarcel 980130803Smarcel if (p7 == NULL) { 981130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_INVALID_NULL_POINTER); 982130803Smarcel return 0; 983130803Smarcel } 984130803Smarcel 985130803Smarcel if (p7->d.ptr == NULL) { 986130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_NO_CONTENT); 987130803Smarcel return 0; 988130803Smarcel } 989130803Smarcel 990130803Smarcel if (PKCS7_type_is_signed(p7)) { 991130803Smarcel cert = p7->d.sign->cert; 992130803Smarcel } else if (PKCS7_type_is_signedAndEnveloped(p7)) { 993130803Smarcel cert = p7->d.signed_and_enveloped->cert; 994130803Smarcel } else { 995130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); 996130803Smarcel goto err; 997130803Smarcel } 998130803Smarcel /* XXXXXXXXXXXXXXXXXXXXXXX */ 999130803Smarcel ias = si->issuer_and_serial; 1000130803Smarcel 1001130803Smarcel x509 = X509_find_by_issuer_and_serial(cert, ias->issuer, ias->serial); 1002130803Smarcel 1003130803Smarcel /* were we able to find the cert in passed to us */ 1004130803Smarcel if (x509 == NULL) { 1005130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, 1006130803Smarcel PKCS7_R_UNABLE_TO_FIND_CERTIFICATE); 1007130803Smarcel goto err; 1008130803Smarcel } 1009130803Smarcel 1010130803Smarcel /* Lets verify */ 1011130803Smarcel if (!X509_STORE_CTX_init(ctx, cert_store, x509, cert)) { 1012130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, ERR_R_X509_LIB); 1013130803Smarcel goto err; 1014130803Smarcel } 1015130803Smarcel X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN); 1016130803Smarcel i = X509_verify_cert(ctx); 1017130803Smarcel if (i <= 0) { 1018130803Smarcel PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, ERR_R_X509_LIB); 1019130803Smarcel X509_STORE_CTX_cleanup(ctx); 1020130803Smarcel goto err; 1021130803Smarcel } 1022130803Smarcel X509_STORE_CTX_cleanup(ctx); 1023130803Smarcel 1024130803Smarcel return PKCS7_signatureVerify(bio, p7, si, x509); 1025130803Smarcel err: 1026130803Smarcel return ret; 1027130803Smarcel} 1028130803Smarcel 1029130803Smarcelint PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, 1030130803Smarcel X509 *x509) 1031130803Smarcel{ 1032130803Smarcel ASN1_OCTET_STRING *os; 1033130803Smarcel EVP_MD_CTX mdc_tmp, *mdc; 1034130803Smarcel int ret = 0, i; 1035130803Smarcel int md_type; 1036130803Smarcel STACK_OF(X509_ATTRIBUTE) *sk; 1037130803Smarcel BIO *btmp; 1038130803Smarcel EVP_PKEY *pkey; 1039130803Smarcel 1040130803Smarcel EVP_MD_CTX_init(&mdc_tmp); 1041130803Smarcel 1042130803Smarcel if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { 1043130803Smarcel PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); 1044130803Smarcel goto err; 1045130803Smarcel } 1046130803Smarcel 1047130803Smarcel md_type = OBJ_obj2nid(si->digest_alg->algorithm); 1048130803Smarcel 1049130803Smarcel btmp = bio; 1050130803Smarcel for (;;) { 1051130803Smarcel if ((btmp == NULL) || 1052130803Smarcel ((btmp = BIO_find_type(btmp, BIO_TYPE_MD)) == NULL)) { 1053130803Smarcel PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1054130803Smarcel PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 1055130803Smarcel goto err; 1056130803Smarcel } 1057130803Smarcel BIO_get_md_ctx(btmp, &mdc); 1058130803Smarcel if (mdc == NULL) { 1059130803Smarcel PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_INTERNAL_ERROR); 1060130803Smarcel goto err; 1061130803Smarcel } 1062130803Smarcel if (EVP_MD_CTX_type(mdc) == md_type) 1063130803Smarcel break; 1064130803Smarcel /* 1065130803Smarcel * Workaround for some broken clients that put the signature OID 1066130803Smarcel * instead of the digest OID in digest_alg->algorithm 1067130803Smarcel */ 1068130803Smarcel if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type) 1069130803Smarcel break; 1070130803Smarcel btmp = BIO_next(btmp); 1071130803Smarcel } 1072130803Smarcel 1073130803Smarcel /* 1074130803Smarcel * mdc is the digest ctx that we want, unless there are attributes, in 1075130803Smarcel * which case the digest is the signed attributes 1076130803Smarcel */ 1077130803Smarcel if (!EVP_MD_CTX_copy_ex(&mdc_tmp, mdc)) 1078130803Smarcel goto err; 1079130803Smarcel 1080130803Smarcel sk = si->auth_attr; 1081130803Smarcel if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { 1082130803Smarcel unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; 1083130803Smarcel unsigned int md_len; 1084130803Smarcel int alen; 1085130803Smarcel ASN1_OCTET_STRING *message_digest; 1086130803Smarcel 1087130803Smarcel if (!EVP_DigestFinal_ex(&mdc_tmp, md_dat, &md_len)) 1088130803Smarcel goto err; 1089130803Smarcel message_digest = PKCS7_digest_from_attributes(sk); 1090130803Smarcel if (!message_digest) { 1091130803Smarcel PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1092130803Smarcel PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 1093130803Smarcel goto err; 1094130803Smarcel } 1095130803Smarcel if ((message_digest->length != (int)md_len) || 1096130803Smarcel (memcmp(message_digest->data, md_dat, md_len))) { 1097130803Smarcel#if 0 1098130803Smarcel { 1099130803Smarcel int ii; 1100130803Smarcel for (ii = 0; ii < message_digest->length; ii++) 1101130803Smarcel printf("%02X", message_digest->data[ii]); 1102130803Smarcel printf(" sent\n"); 1103130803Smarcel for (ii = 0; ii < md_len; ii++) 1104130803Smarcel printf("%02X", md_dat[ii]); 1105130803Smarcel printf(" calc\n"); 1106130803Smarcel } 1107130803Smarcel#endif 1108130803Smarcel PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_DIGEST_FAILURE); 1109130803Smarcel ret = -1; 1110130803Smarcel goto err; 1111130803Smarcel } 1112130803Smarcel 1113130803Smarcel if (!EVP_VerifyInit_ex(&mdc_tmp, EVP_get_digestbynid(md_type), NULL)) 1114130803Smarcel goto err; 1115130803Smarcel 1116130803Smarcel alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, 1117130803Smarcel ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); 1118130803Smarcel if (alen <= 0) { 1119130803Smarcel PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_ASN1_LIB); 1120130803Smarcel ret = -1; 1121130803Smarcel goto err; 1122130803Smarcel } 1123130803Smarcel if (!EVP_VerifyUpdate(&mdc_tmp, abuf, alen)) 1124130803Smarcel goto err; 1125130803Smarcel 1126130803Smarcel OPENSSL_free(abuf); 1127130803Smarcel } 1128130803Smarcel 1129130803Smarcel os = si->enc_digest; 1130130803Smarcel pkey = X509_get_pubkey(x509); 1131130803Smarcel if (!pkey) { 1132130803Smarcel ret = -1; 1133130803Smarcel goto err; 1134130803Smarcel } 1135130803Smarcel 1136130803Smarcel i = EVP_VerifyFinal(&mdc_tmp, os->data, os->length, pkey); 1137130803Smarcel EVP_PKEY_free(pkey); 1138130803Smarcel if (i <= 0) { 1139130803Smarcel PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); 1140130803Smarcel ret = -1; 1141130803Smarcel goto err; 1142130803Smarcel } else 1143130803Smarcel ret = 1; 1144130803Smarcel err: 1145130803Smarcel EVP_MD_CTX_cleanup(&mdc_tmp); 1146130803Smarcel return (ret); 1147130803Smarcel} 1148130803Smarcel 1149130803SmarcelPKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx) 1150130803Smarcel{ 1151130803Smarcel STACK_OF(PKCS7_RECIP_INFO) *rsk; 1152130803Smarcel PKCS7_RECIP_INFO *ri; 1153130803Smarcel int i; 1154130803Smarcel 1155130803Smarcel i = OBJ_obj2nid(p7->type); 1156130803Smarcel if (i != NID_pkcs7_signedAndEnveloped) 1157130803Smarcel return NULL; 1158130803Smarcel if (p7->d.signed_and_enveloped == NULL) 1159130803Smarcel return NULL; 1160130803Smarcel rsk = p7->d.signed_and_enveloped->recipientinfo; 1161130803Smarcel if (rsk == NULL) 1162130803Smarcel return NULL; 1163130803Smarcel if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) 1164130803Smarcel return (NULL); 1165130803Smarcel ri = sk_PKCS7_RECIP_INFO_value(rsk, idx); 1166130803Smarcel return (ri->issuer_and_serial); 1167130803Smarcel} 1168130803Smarcel 1169130803SmarcelASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid) 1170130803Smarcel{ 1171130803Smarcel return (get_attribute(si->auth_attr, nid)); 1172130803Smarcel} 1173130803Smarcel 1174130803SmarcelASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid) 1175130803Smarcel{ 1176130803Smarcel return (get_attribute(si->unauth_attr, nid)); 1177130803Smarcel} 1178130803Smarcel 1179130803Smarcelstatic ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid) 1180130803Smarcel{ 1181130803Smarcel int i; 1182130803Smarcel X509_ATTRIBUTE *xa; 1183130803Smarcel ASN1_OBJECT *o; 1184130803Smarcel 1185130803Smarcel o = OBJ_nid2obj(nid); 1186130803Smarcel if (!o || !sk) 1187130803Smarcel return (NULL); 1188130803Smarcel for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { 1189130803Smarcel xa = sk_X509_ATTRIBUTE_value(sk, i); 1190130803Smarcel if (OBJ_cmp(xa->object, o) == 0) { 1191130803Smarcel if (!xa->single && sk_ASN1_TYPE_num(xa->value.set)) 1192130803Smarcel return (sk_ASN1_TYPE_value(xa->value.set, 0)); 1193130803Smarcel else 1194130803Smarcel return (NULL); 1195130803Smarcel } 1196130803Smarcel } 1197130803Smarcel return (NULL); 1198130803Smarcel} 1199130803Smarcel 1200130803SmarcelASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk) 1201130803Smarcel{ 1202130803Smarcel ASN1_TYPE *astype; 1203130803Smarcel if (!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) 1204130803Smarcel return NULL; 1205130803Smarcel return astype->value.octet_string; 1206130803Smarcel} 1207130803Smarcel 1208130803Smarcelint PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, 1209130803Smarcel STACK_OF(X509_ATTRIBUTE) *sk) 1210130803Smarcel{ 1211130803Smarcel int i; 1212130803Smarcel 1213130803Smarcel if (p7si->auth_attr != NULL) 1214130803Smarcel sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr, X509_ATTRIBUTE_free); 1215130803Smarcel p7si->auth_attr = sk_X509_ATTRIBUTE_dup(sk); 1216130803Smarcel if (p7si->auth_attr == NULL) 1217130803Smarcel return 0; 1218130803Smarcel for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { 1219130803Smarcel if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr, i, 1220130803Smarcel X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value 1221130803Smarcel (sk, i)))) 1222130803Smarcel == NULL) 1223130803Smarcel return (0); 1224130803Smarcel } 1225130803Smarcel return (1); 1226130803Smarcel} 1227130803Smarcel 1228130803Smarcelint PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, 1229130803Smarcel STACK_OF(X509_ATTRIBUTE) *sk) 1230130803Smarcel{ 1231130803Smarcel int i; 1232130803Smarcel 1233130803Smarcel if (p7si->unauth_attr != NULL) 1234130803Smarcel sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr, X509_ATTRIBUTE_free); 1235130803Smarcel p7si->unauth_attr = sk_X509_ATTRIBUTE_dup(sk); 1236130803Smarcel if (p7si->unauth_attr == NULL) 1237130803Smarcel return 0; 1238130803Smarcel for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { 1239130803Smarcel if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr, i, 1240130803Smarcel X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value 1241130803Smarcel (sk, i)))) 1242130803Smarcel == NULL) 1243130803Smarcel return (0); 1244130803Smarcel } 1245130803Smarcel return (1); 1246130803Smarcel} 1247130803Smarcel 1248130803Smarcelint PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, 1249130803Smarcel void *value) 1250130803Smarcel{ 1251130803Smarcel return (add_attribute(&(p7si->auth_attr), nid, atrtype, value)); 1252130803Smarcel} 1253130803Smarcel 1254130803Smarcelint PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, 1255130803Smarcel void *value) 1256130803Smarcel{ 1257130803Smarcel return (add_attribute(&(p7si->unauth_attr), nid, atrtype, value)); 1258130803Smarcel} 1259130803Smarcel 1260130803Smarcelstatic int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, 1261130803Smarcel void *value) 1262130803Smarcel{ 1263130803Smarcel X509_ATTRIBUTE *attr = NULL; 1264130803Smarcel 1265130803Smarcel if (*sk == NULL) { 1266130803Smarcel *sk = sk_X509_ATTRIBUTE_new_null(); 1267130803Smarcel if (*sk == NULL) 1268130803Smarcel return 0; 1269130803Smarcel new_attrib: 1270130803Smarcel if (!(attr = X509_ATTRIBUTE_create(nid, atrtype, value))) 1271130803Smarcel return 0; 1272130803Smarcel if (!sk_X509_ATTRIBUTE_push(*sk, attr)) { 1273130803Smarcel X509_ATTRIBUTE_free(attr); 1274130803Smarcel return 0; 1275130803Smarcel } 1276130803Smarcel } else { 1277130803Smarcel int i; 1278130803Smarcel 1279130803Smarcel for (i = 0; i < sk_X509_ATTRIBUTE_num(*sk); i++) { 1280130803Smarcel attr = sk_X509_ATTRIBUTE_value(*sk, i); 1281130803Smarcel if (OBJ_obj2nid(attr->object) == nid) { 1282130803Smarcel X509_ATTRIBUTE_free(attr); 1283130803Smarcel attr = X509_ATTRIBUTE_create(nid, atrtype, value); 1284130803Smarcel if (attr == NULL) 1285130803Smarcel return 0; 1286130803Smarcel if (!sk_X509_ATTRIBUTE_set(*sk, i, attr)) { 1287130803Smarcel X509_ATTRIBUTE_free(attr); 1288130803Smarcel return 0; 1289130803Smarcel } 1290130803Smarcel goto end; 1291130803Smarcel } 1292130803Smarcel } 1293130803Smarcel goto new_attrib; 1294130803Smarcel } 1295130803Smarcel end: 1296130803Smarcel return (1); 1297130803Smarcel} 1298130803Smarcel