xref: /openbsd-src/lib/libcrypto/pkcs7/pk7_doit.c (revision fc405d53b73a2d73393cb97f684863d17b583e38)
1 /* $OpenBSD: pk7_doit.c,v 1.52 2023/03/09 18:20:10 tb Exp $ */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 
63 #include <openssl/err.h>
64 #include <openssl/objects.h>
65 #include <openssl/x509.h>
66 #include <openssl/x509v3.h>
67 
68 #include "evp_local.h"
69 #include "x509_local.h"
70 
71 static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
72     void *value);
73 static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid);
74 
75 static int
76 PKCS7_type_is_other(PKCS7* p7)
77 {
78 	int isOther = 1;
79 
80 	int nid = OBJ_obj2nid(p7->type);
81 
82 	switch (nid ) {
83 	case NID_pkcs7_data:
84 	case NID_pkcs7_signed:
85 	case NID_pkcs7_enveloped:
86 	case NID_pkcs7_signedAndEnveloped:
87 	case NID_pkcs7_digest:
88 	case NID_pkcs7_encrypted:
89 		isOther = 0;
90 		break;
91 	default:
92 		isOther = 1;
93 	}
94 
95 	return isOther;
96 
97 }
98 
99 static ASN1_OCTET_STRING *
100 PKCS7_get_octet_string(PKCS7 *p7)
101 {
102 	if (PKCS7_type_is_data(p7))
103 		return p7->d.data;
104 	if (PKCS7_type_is_other(p7) && p7->d.other &&
105 	    (p7->d.other->type == V_ASN1_OCTET_STRING))
106 		return p7->d.other->value.octet_string;
107 	return NULL;
108 }
109 
110 static int
111 PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg)
112 {
113 	BIO *btmp;
114 	const EVP_MD *md;
115 
116 	if ((btmp = BIO_new(BIO_f_md())) == NULL) {
117 		PKCS7error(ERR_R_BIO_LIB);
118 		goto err;
119 	}
120 
121 	md = EVP_get_digestbyobj(alg->algorithm);
122 	if (md == NULL) {
123 		PKCS7error(PKCS7_R_UNKNOWN_DIGEST_TYPE);
124 		goto err;
125 	}
126 
127 	if (BIO_set_md(btmp, md) <= 0) {
128 		PKCS7error(ERR_R_BIO_LIB);
129 		goto err;
130 	}
131 
132 	if (*pbio == NULL)
133 		*pbio = btmp;
134 	else if (!BIO_push(*pbio, btmp)) {
135 		PKCS7error(ERR_R_BIO_LIB);
136 		goto err;
137 	}
138 	btmp = NULL;
139 
140 	return 1;
141 
142 err:
143 	BIO_free(btmp);
144 	return 0;
145 
146 }
147 
148 static int
149 pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, unsigned char *key, int keylen)
150 {
151 	EVP_PKEY_CTX *pctx = NULL;
152 	EVP_PKEY *pkey = NULL;
153 	unsigned char *ek = NULL;
154 	int ret = 0;
155 	size_t eklen;
156 
157 	pkey = X509_get_pubkey(ri->cert);
158 	if (!pkey)
159 		return 0;
160 
161 	pctx = EVP_PKEY_CTX_new(pkey, NULL);
162 	if (!pctx)
163 		return 0;
164 
165 	if (EVP_PKEY_encrypt_init(pctx) <= 0)
166 		goto err;
167 
168 	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT,
169 	    EVP_PKEY_CTRL_PKCS7_ENCRYPT, 0, ri) <= 0) {
170 		PKCS7error(PKCS7_R_CTRL_ERROR);
171 		goto err;
172 	}
173 
174 	if (EVP_PKEY_encrypt(pctx, NULL, &eklen, key, keylen) <= 0)
175 		goto err;
176 
177 	ek = malloc(eklen);
178 
179 	if (ek == NULL) {
180 		PKCS7error(ERR_R_MALLOC_FAILURE);
181 		goto err;
182 	}
183 
184 	if (EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen) <= 0)
185 		goto err;
186 
187 	ASN1_STRING_set0(ri->enc_key, ek, eklen);
188 	ek = NULL;
189 
190 	ret = 1;
191 
192 err:
193 	EVP_PKEY_free(pkey);
194 	EVP_PKEY_CTX_free(pctx);
195 	free(ek);
196 	return ret;
197 }
198 
199 
200 static int
201 pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, PKCS7_RECIP_INFO *ri,
202     EVP_PKEY *pkey, size_t fixlen)
203 {
204 	EVP_PKEY_CTX *pctx = NULL;
205 	unsigned char *ek = NULL;
206 	size_t eklen;
207 
208 	int ret = -1;
209 
210 	pctx = EVP_PKEY_CTX_new(pkey, NULL);
211 	if (!pctx)
212 		return -1;
213 
214 	if (EVP_PKEY_decrypt_init(pctx) <= 0)
215 		goto err;
216 
217 	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT,
218 	    EVP_PKEY_CTRL_PKCS7_DECRYPT, 0, ri) <= 0) {
219 		PKCS7error(PKCS7_R_CTRL_ERROR);
220 		goto err;
221 	}
222 
223 	if (EVP_PKEY_decrypt(pctx, NULL, &eklen,
224 	    ri->enc_key->data, ri->enc_key->length) <= 0)
225 		goto err;
226 
227 	ek = malloc(eklen);
228 	if (ek == NULL) {
229 		PKCS7error(ERR_R_MALLOC_FAILURE);
230 		goto err;
231 	}
232 
233 	if (EVP_PKEY_decrypt(pctx, ek, &eklen, ri->enc_key->data,
234 	    ri->enc_key->length) <= 0 || eklen == 0 ||
235 	    (fixlen != 0 && eklen != fixlen)) {
236 		ret = 0;
237 		PKCS7error(ERR_R_EVP_LIB);
238 		goto err;
239 	}
240 
241 	ret = 1;
242 
243 	freezero(*pek, *peklen);
244 
245 	*pek = ek;
246 	*peklen = eklen;
247 
248 err:
249 	EVP_PKEY_CTX_free(pctx);
250 	if (!ret && ek)
251 		free(ek);
252 
253 	return ret;
254 }
255 
256 BIO *
257 PKCS7_dataInit(PKCS7 *p7, BIO *bio)
258 {
259 	int i;
260 	BIO *out = NULL, *btmp = NULL;
261 	X509_ALGOR *xa = NULL;
262 	const EVP_CIPHER *evp_cipher = NULL;
263 	STACK_OF(X509_ALGOR) *md_sk = NULL;
264 	STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL;
265 	X509_ALGOR *xalg = NULL;
266 	PKCS7_RECIP_INFO *ri = NULL;
267 	ASN1_OCTET_STRING *os = NULL;
268 
269 	if (p7 == NULL) {
270 		PKCS7error(PKCS7_R_INVALID_NULL_POINTER);
271 		return NULL;
272 	}
273 
274 	/*
275 	 * The content field in the PKCS7 ContentInfo is optional,
276 	 * but that really only applies to inner content (precisely,
277 	 * detached signatures).
278 	 *
279 	 * When reading content, missing outer content is therefore
280 	 * treated as an error.
281 	 *
282 	 * When creating content, PKCS7_content_new() must be called
283 	 * before calling this method, so a NULL p7->d is always
284 	 * an error.
285 	 */
286 	if (p7->d.ptr == NULL) {
287 		PKCS7error(PKCS7_R_NO_CONTENT);
288 		return NULL;
289 	}
290 
291 	i = OBJ_obj2nid(p7->type);
292 	p7->state = PKCS7_S_HEADER;
293 
294 	switch (i) {
295 	case NID_pkcs7_signed:
296 		md_sk = p7->d.sign->md_algs;
297 		os = PKCS7_get_octet_string(p7->d.sign->contents);
298 		break;
299 	case NID_pkcs7_signedAndEnveloped:
300 		rsk = p7->d.signed_and_enveloped->recipientinfo;
301 		md_sk = p7->d.signed_and_enveloped->md_algs;
302 		xalg = p7->d.signed_and_enveloped->enc_data->algorithm;
303 		evp_cipher = p7->d.signed_and_enveloped->enc_data->cipher;
304 		if (evp_cipher == NULL) {
305 			PKCS7error(PKCS7_R_CIPHER_NOT_INITIALIZED);
306 			goto err;
307 		}
308 		break;
309 	case NID_pkcs7_enveloped:
310 		rsk = p7->d.enveloped->recipientinfo;
311 		xalg = p7->d.enveloped->enc_data->algorithm;
312 		evp_cipher = p7->d.enveloped->enc_data->cipher;
313 		if (evp_cipher == NULL) {
314 			PKCS7error(PKCS7_R_CIPHER_NOT_INITIALIZED);
315 			goto err;
316 		}
317 		break;
318 	case NID_pkcs7_digest:
319 		xa = p7->d.digest->md;
320 		os = PKCS7_get_octet_string(p7->d.digest->contents);
321 		break;
322 	case NID_pkcs7_data:
323 		break;
324 	default:
325 		PKCS7error(PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
326 		goto err;
327 	}
328 
329 	for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++)
330 		if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i)))
331 			goto err;
332 
333 	if (xa && !PKCS7_bio_add_digest(&out, xa))
334 		goto err;
335 
336 	if (evp_cipher != NULL) {
337 		unsigned char key[EVP_MAX_KEY_LENGTH];
338 		unsigned char iv[EVP_MAX_IV_LENGTH];
339 		int keylen, ivlen;
340 		EVP_CIPHER_CTX *ctx;
341 
342 		if ((btmp = BIO_new(BIO_f_cipher())) == NULL) {
343 			PKCS7error(ERR_R_BIO_LIB);
344 			goto err;
345 		}
346 		BIO_get_cipher_ctx(btmp, &ctx);
347 		keylen = EVP_CIPHER_key_length(evp_cipher);
348 		ivlen = EVP_CIPHER_iv_length(evp_cipher);
349 		xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
350 		if (ivlen > 0)
351 			arc4random_buf(iv, ivlen);
352 		if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL,
353 		    NULL, 1) <= 0)
354 			goto err;
355 		if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
356 			goto err;
357 		if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
358 			goto err;
359 
360 		if (ivlen > 0) {
361 			if (xalg->parameter == NULL) {
362 				xalg->parameter = ASN1_TYPE_new();
363 				if (xalg->parameter == NULL)
364 					goto err;
365 			}
366 			if (EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
367 				goto err;
368 		}
369 
370 		/* Lets do the pub key stuff :-) */
371 		for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
372 			ri = sk_PKCS7_RECIP_INFO_value(rsk, i);
373 			if (pkcs7_encode_rinfo(ri, key, keylen) <= 0)
374 				goto err;
375 		}
376 		explicit_bzero(key, keylen);
377 
378 		if (out == NULL)
379 			out = btmp;
380 		else
381 			BIO_push(out, btmp);
382 		btmp = NULL;
383 	}
384 
385 	if (bio == NULL) {
386 		if (PKCS7_is_detached(p7))
387 			bio = BIO_new(BIO_s_null());
388 		else if (os && os->length > 0)
389 			bio = BIO_new_mem_buf(os->data, os->length);
390 		if (bio == NULL) {
391 			bio = BIO_new(BIO_s_mem());
392 			if (bio == NULL)
393 				goto err;
394 			BIO_set_mem_eof_return(bio, 0);
395 		}
396 	}
397 	if (out)
398 		BIO_push(out, bio);
399 	else
400 		out = bio;
401 	bio = NULL;
402 	if (0) {
403 err:
404 		if (out != NULL)
405 			BIO_free_all(out);
406 		if (btmp != NULL)
407 			BIO_free_all(btmp);
408 		out = NULL;
409 	}
410 	return (out);
411 }
412 LCRYPTO_ALIAS(PKCS7_dataInit);
413 
414 static int
415 pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert)
416 {
417 	int ret;
418 
419 	ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
420 	    pcert->cert_info->issuer);
421 	if (ret)
422 		return ret;
423 	return ASN1_INTEGER_cmp(pcert->cert_info->serialNumber,
424 	    ri->issuer_and_serial->serial);
425 }
426 
427 /* int */
428 BIO *
429 PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
430 {
431 	int i, j;
432 	BIO *out = NULL, *btmp = NULL, *etmp = NULL, *bio = NULL;
433 	X509_ALGOR *xa;
434 	ASN1_OCTET_STRING *data_body = NULL;
435 	const EVP_MD *evp_md;
436 	const EVP_CIPHER *evp_cipher = NULL;
437 	EVP_CIPHER_CTX *evp_ctx = NULL;
438 	X509_ALGOR *enc_alg = NULL;
439 	STACK_OF(X509_ALGOR) *md_sk = NULL;
440 	STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL;
441 	PKCS7_RECIP_INFO *ri = NULL;
442 	unsigned char *ek = NULL, *tkey = NULL;
443 	int eklen = 0, tkeylen = 0;
444 
445 	if (p7 == NULL) {
446 		PKCS7error(PKCS7_R_INVALID_NULL_POINTER);
447 		return NULL;
448 	}
449 
450 	if (p7->d.ptr == NULL) {
451 		PKCS7error(PKCS7_R_NO_CONTENT);
452 		return NULL;
453 	}
454 
455 	i = OBJ_obj2nid(p7->type);
456 	p7->state = PKCS7_S_HEADER;
457 
458 	switch (i) {
459 	case NID_pkcs7_signed:
460 		data_body = PKCS7_get_octet_string(p7->d.sign->contents);
461 		md_sk = p7->d.sign->md_algs;
462 		break;
463 	case NID_pkcs7_signedAndEnveloped:
464 		rsk = p7->d.signed_and_enveloped->recipientinfo;
465 		md_sk = p7->d.signed_and_enveloped->md_algs;
466 		data_body = p7->d.signed_and_enveloped->enc_data->enc_data;
467 		enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm;
468 		evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm);
469 		if (evp_cipher == NULL) {
470 			PKCS7error(PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
471 			goto err;
472 		}
473 		break;
474 	case NID_pkcs7_enveloped:
475 		rsk = p7->d.enveloped->recipientinfo;
476 		enc_alg = p7->d.enveloped->enc_data->algorithm;
477 		data_body = p7->d.enveloped->enc_data->enc_data;
478 		evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm);
479 		if (evp_cipher == NULL) {
480 			PKCS7error(PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
481 			goto err;
482 		}
483 		break;
484 	default:
485 		PKCS7error(PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
486 		goto err;
487 	}
488 
489 	/* We will be checking the signature */
490 	if (md_sk != NULL) {
491 		for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) {
492 			xa = sk_X509_ALGOR_value(md_sk, i);
493 			if ((btmp = BIO_new(BIO_f_md())) == NULL) {
494 				PKCS7error(ERR_R_BIO_LIB);
495 				goto err;
496 			}
497 
498 			j = OBJ_obj2nid(xa->algorithm);
499 			evp_md = EVP_get_digestbynid(j);
500 			if (evp_md == NULL) {
501 				PKCS7error(PKCS7_R_UNKNOWN_DIGEST_TYPE);
502 				goto err;
503 			}
504 
505 			if (BIO_set_md(btmp, evp_md) <= 0) {
506 				PKCS7error(ERR_R_BIO_LIB);
507 				goto err;
508 			}
509 			if (out == NULL)
510 				out = btmp;
511 			else
512 				BIO_push(out, btmp);
513 			btmp = NULL;
514 		}
515 	}
516 
517 	if (evp_cipher != NULL) {
518 		if ((etmp = BIO_new(BIO_f_cipher())) == NULL) {
519 			PKCS7error(ERR_R_BIO_LIB);
520 			goto err;
521 		}
522 
523 		/* It was encrypted, we need to decrypt the secret key
524 		 * with the private key */
525 
526 		/* Find the recipientInfo which matches the passed certificate
527 		 * (if any)
528 		 */
529 		if (pcert) {
530 			for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
531 				ri = sk_PKCS7_RECIP_INFO_value(rsk, i);
532 				if (!pkcs7_cmp_ri(ri, pcert))
533 					break;
534 				ri = NULL;
535 			}
536 			if (ri == NULL) {
537 				PKCS7error(PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
538 				goto err;
539 			}
540 		}
541 
542 		/* If we haven't got a certificate try each ri in turn */
543 		if (pcert == NULL) {
544 			/* Always attempt to decrypt all rinfo even
545 			 * after success as a defence against MMA timing
546 			 * attacks.
547 			 */
548 			for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
549 				ri = sk_PKCS7_RECIP_INFO_value(rsk, i);
550 
551 				if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey,
552 				    EVP_CIPHER_key_length(evp_cipher)) < 0)
553 					goto err;
554 				ERR_clear_error();
555 			}
556 		} else {
557 			/* Only exit on fatal errors, not decrypt failure */
558 			if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, 0) < 0)
559 				goto err;
560 			ERR_clear_error();
561 		}
562 
563 		evp_ctx = NULL;
564 		BIO_get_cipher_ctx(etmp, &evp_ctx);
565 		if (EVP_CipherInit_ex(evp_ctx, evp_cipher, NULL, NULL,
566 		    NULL, 0) <= 0)
567 			goto err;
568 		if (EVP_CIPHER_asn1_to_param(evp_ctx, enc_alg->parameter) < 0)
569 			goto err;
570 		/* Generate random key as MMA defence */
571 		tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx);
572 		tkey = malloc(tkeylen);
573 		if (!tkey)
574 			goto err;
575 		if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0)
576 			goto err;
577 		if (ek == NULL) {
578 			ek = tkey;
579 			eklen = tkeylen;
580 			tkey = NULL;
581 		}
582 
583 		if (eklen != EVP_CIPHER_CTX_key_length(evp_ctx)) {
584 			/* Some S/MIME clients don't use the same key
585 			 * and effective key length. The key length is
586 			 * determined by the size of the decrypted RSA key.
587 			 */
588 			if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen)) {
589 				/* Use random key as MMA defence */
590 				freezero(ek, eklen);
591 				ek = tkey;
592 				eklen = tkeylen;
593 				tkey = NULL;
594 			}
595 		}
596 		/* Clear errors so we don't leak information useful in MMA */
597 		ERR_clear_error();
598 		if (EVP_CipherInit_ex(evp_ctx, NULL, NULL, ek, NULL, 0) <= 0)
599 			goto err;
600 
601 		freezero(ek, eklen);
602 		ek = NULL;
603 		freezero(tkey, tkeylen);
604 		tkey = NULL;
605 
606 		if (out == NULL)
607 			out = etmp;
608 		else
609 			BIO_push(out, etmp);
610 		etmp = NULL;
611 	}
612 
613 	if (PKCS7_is_detached(p7) || (in_bio != NULL)) {
614 		bio = in_bio;
615 	} else {
616 		if (data_body != NULL && data_body->length > 0)
617 			bio = BIO_new_mem_buf(data_body->data, data_body->length);
618 		else {
619 			bio = BIO_new(BIO_s_mem());
620 			BIO_set_mem_eof_return(bio, 0);
621 		}
622 		if (bio == NULL)
623 			goto err;
624 	}
625 	BIO_push(out, bio);
626 
627 	if (0) {
628 err:
629 		freezero(ek, eklen);
630 		freezero(tkey, tkeylen);
631 		if (out != NULL)
632 			BIO_free_all(out);
633 		if (btmp != NULL)
634 			BIO_free_all(btmp);
635 		if (etmp != NULL)
636 			BIO_free_all(etmp);
637 		out = NULL;
638 	}
639 	return (out);
640 }
641 LCRYPTO_ALIAS(PKCS7_dataDecode);
642 
643 static BIO *
644 PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid)
645 {
646 	for (;;) {
647 		bio = BIO_find_type(bio, BIO_TYPE_MD);
648 		if (bio == NULL) {
649 			PKCS7error(PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
650 			return NULL;
651 		}
652 		BIO_get_md_ctx(bio, pmd);
653 		if (*pmd == NULL) {
654 			PKCS7error(ERR_R_INTERNAL_ERROR);
655 			return NULL;
656 		}
657 		if (EVP_MD_CTX_type(*pmd) == nid)
658 			return bio;
659 		bio = BIO_next(bio);
660 	}
661 	return NULL;
662 }
663 
664 static int
665 do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx)
666 {
667 	unsigned char md_data[EVP_MAX_MD_SIZE];
668 	unsigned int md_len;
669 
670 	/* Add signing time if not already present */
671 	if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) {
672 		if (!PKCS7_add0_attrib_signing_time(si, NULL)) {
673 			PKCS7error(ERR_R_MALLOC_FAILURE);
674 			return 0;
675 		}
676 	}
677 
678 	/* Add digest */
679 	if (!EVP_DigestFinal_ex(mctx, md_data, &md_len)) {
680 		PKCS7error(ERR_R_EVP_LIB);
681 		return 0;
682 	}
683 	if (!PKCS7_add1_attrib_digest(si, md_data, md_len)) {
684 		PKCS7error(ERR_R_MALLOC_FAILURE);
685 		return 0;
686 	}
687 
688 	/* Now sign the attributes */
689 	if (!PKCS7_SIGNER_INFO_sign(si))
690 		return 0;
691 
692 	return 1;
693 }
694 
695 
696 int
697 PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
698 {
699 	int ret = 0;
700 	int i, j;
701 	BIO *btmp;
702 	PKCS7_SIGNER_INFO *si;
703 	EVP_MD_CTX *mdc, ctx_tmp;
704 	STACK_OF(X509_ATTRIBUTE) *sk;
705 	STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL;
706 	ASN1_OCTET_STRING *os = NULL;
707 
708 	if (p7 == NULL) {
709 		PKCS7error(PKCS7_R_INVALID_NULL_POINTER);
710 		return 0;
711 	}
712 
713 	if (p7->d.ptr == NULL) {
714 		PKCS7error(PKCS7_R_NO_CONTENT);
715 		return 0;
716 	}
717 
718 	EVP_MD_CTX_init(&ctx_tmp);
719 	i = OBJ_obj2nid(p7->type);
720 	p7->state = PKCS7_S_HEADER;
721 
722 	switch (i) {
723 	case NID_pkcs7_data:
724 		os = p7->d.data;
725 		break;
726 	case NID_pkcs7_signedAndEnveloped:
727 		/* XXX */
728 		si_sk = p7->d.signed_and_enveloped->signer_info;
729 		os = p7->d.signed_and_enveloped->enc_data->enc_data;
730 		if (!os) {
731 			os = ASN1_OCTET_STRING_new();
732 			if (!os) {
733 				PKCS7error(ERR_R_MALLOC_FAILURE);
734 				goto err;
735 			}
736 			p7->d.signed_and_enveloped->enc_data->enc_data = os;
737 		}
738 		break;
739 	case NID_pkcs7_enveloped:
740 		/* XXX */
741 		os = p7->d.enveloped->enc_data->enc_data;
742 		if (!os) {
743 			os = ASN1_OCTET_STRING_new();
744 			if (!os) {
745 				PKCS7error(ERR_R_MALLOC_FAILURE);
746 				goto err;
747 			}
748 			p7->d.enveloped->enc_data->enc_data = os;
749 		}
750 		break;
751 	case NID_pkcs7_signed:
752 		si_sk = p7->d.sign->signer_info;
753 		os = PKCS7_get_octet_string(p7->d.sign->contents);
754 		if (!PKCS7_is_detached(p7) && os == NULL) {
755 			PKCS7error(PKCS7_R_DECODE_ERROR);
756 			goto err;
757 		}
758 		/* If detached data then the content is excluded */
759 		if (PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
760 			ASN1_OCTET_STRING_free(os);
761 			os = NULL;
762 			p7->d.sign->contents->d.data = NULL;
763 		}
764 		break;
765 
766 	case NID_pkcs7_digest:
767 		os = PKCS7_get_octet_string(p7->d.digest->contents);
768 		if (os == NULL) {
769 			PKCS7error(PKCS7_R_DECODE_ERROR);
770 			goto err;
771 		}
772 		/* If detached data then the content is excluded */
773 		if (PKCS7_type_is_data(p7->d.digest->contents) &&
774 		    p7->detached) {
775 			ASN1_OCTET_STRING_free(os);
776 			os = NULL;
777 			p7->d.digest->contents->d.data = NULL;
778 		}
779 		break;
780 
781 	default:
782 		PKCS7error(PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
783 		goto err;
784 	}
785 
786 	if (si_sk != NULL) {
787 		for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(si_sk); i++) {
788 			si = sk_PKCS7_SIGNER_INFO_value(si_sk, i);
789 			if (si->pkey == NULL)
790 				continue;
791 
792 			j = OBJ_obj2nid(si->digest_alg->algorithm);
793 
794 			if ((btmp = PKCS7_find_digest(&mdc, bio, j)) == NULL)
795 				goto err;
796 
797 			/* We now have the EVP_MD_CTX, lets do the
798 			 * signing. */
799 			if (!EVP_MD_CTX_copy_ex(&ctx_tmp, mdc))
800 				goto err;
801 
802 			sk = si->auth_attr;
803 
804 			/* If there are attributes, we add the digest
805 			 * attribute and only sign the attributes */
806 			if (sk_X509_ATTRIBUTE_num(sk) > 0) {
807 				if (!do_pkcs7_signed_attrib(si, &ctx_tmp))
808 					goto err;
809 			} else {
810 				unsigned char *abuf = NULL;
811 				unsigned int abuflen;
812 				abuflen = EVP_PKEY_size(si->pkey);
813 				abuf = malloc(abuflen);
814 				if (!abuf)
815 					goto err;
816 
817 				if (!EVP_SignFinal(&ctx_tmp, abuf, &abuflen,
818 				    si->pkey)) {
819 					PKCS7error(ERR_R_EVP_LIB);
820 					goto err;
821 				}
822 				ASN1_STRING_set0(si->enc_digest, abuf, abuflen);
823 			}
824 		}
825 	} else if (i == NID_pkcs7_digest) {
826 		unsigned char md_data[EVP_MAX_MD_SIZE];
827 		unsigned int md_len;
828 
829 		if (!PKCS7_find_digest(&mdc, bio,
830 		    OBJ_obj2nid(p7->d.digest->md->algorithm)))
831 			goto err;
832 		if (!EVP_DigestFinal_ex(mdc, md_data, &md_len))
833 			goto err;
834 		if (ASN1_STRING_set(p7->d.digest->digest, md_data,
835 		    md_len) == 0)
836 			goto err;
837 	}
838 
839 	if (!PKCS7_is_detached(p7)) {
840 		/*
841 		 * NOTE: only reach os == NULL here because detached
842 		 * digested data support is broken?
843 		 */
844 		if (os == NULL)
845 			goto err;
846 		if (!(os->flags & ASN1_STRING_FLAG_NDEF)) {
847 			char *cont;
848 			long contlen;
849 
850 			btmp = BIO_find_type(bio, BIO_TYPE_MEM);
851 			if (btmp == NULL) {
852 				PKCS7error(PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
853 				goto err;
854 			}
855 			contlen = BIO_get_mem_data(btmp, &cont);
856 			/*
857 			 * Mark the BIO read only then we can use its copy
858 			 * of the data instead of making an extra copy.
859 			 */
860 			BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
861 			BIO_set_mem_eof_return(btmp, 0);
862 			ASN1_STRING_set0(os, (unsigned char *)cont, contlen);
863 		}
864 	}
865 	ret = 1;
866 err:
867 	EVP_MD_CTX_cleanup(&ctx_tmp);
868 	return (ret);
869 }
870 LCRYPTO_ALIAS(PKCS7_dataFinal);
871 
872 int
873 PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
874 {
875 	EVP_MD_CTX mctx;
876 	EVP_PKEY_CTX *pctx;
877 	unsigned char *abuf = NULL;
878 	int alen;
879 	size_t siglen;
880 	const EVP_MD *md = NULL;
881 
882 	md = EVP_get_digestbyobj(si->digest_alg->algorithm);
883 	if (md == NULL)
884 		return 0;
885 
886 	EVP_MD_CTX_init(&mctx);
887 	if (EVP_DigestSignInit(&mctx, &pctx, md, NULL, si->pkey) <= 0)
888 		goto err;
889 
890 	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
891 	    EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0) {
892 		PKCS7error(PKCS7_R_CTRL_ERROR);
893 		goto err;
894 	}
895 
896 	alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr, &abuf,
897 	    &PKCS7_ATTR_SIGN_it);
898 	if (!abuf)
899 		goto err;
900 	if (EVP_DigestSignUpdate(&mctx, abuf, alen) <= 0)
901 		goto err;
902 	free(abuf);
903 	abuf = NULL;
904 	if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0)
905 		goto err;
906 	abuf = malloc(siglen);
907 	if (!abuf)
908 		goto err;
909 	if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0)
910 		goto err;
911 
912 	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
913 	    EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0) {
914 		PKCS7error(PKCS7_R_CTRL_ERROR);
915 		goto err;
916 	}
917 
918 	EVP_MD_CTX_cleanup(&mctx);
919 
920 	ASN1_STRING_set0(si->enc_digest, abuf, siglen);
921 
922 	return 1;
923 
924 err:
925 	free(abuf);
926 	EVP_MD_CTX_cleanup(&mctx);
927 	return 0;
928 }
929 LCRYPTO_ALIAS(PKCS7_SIGNER_INFO_sign);
930 
931 int
932 PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
933     PKCS7 *p7, PKCS7_SIGNER_INFO *si)
934 {
935 	PKCS7_ISSUER_AND_SERIAL *ias;
936 	int ret = 0, i;
937 	STACK_OF(X509) *cert;
938 	X509 *x509;
939 
940 	if (p7 == NULL) {
941 		PKCS7error(PKCS7_R_INVALID_NULL_POINTER);
942 		return 0;
943 	}
944 
945 	if (p7->d.ptr == NULL) {
946 		PKCS7error(PKCS7_R_NO_CONTENT);
947 		return 0;
948 	}
949 
950 	if (PKCS7_type_is_signed(p7)) {
951 		cert = p7->d.sign->cert;
952 	} else if (PKCS7_type_is_signedAndEnveloped(p7)) {
953 		cert = p7->d.signed_and_enveloped->cert;
954 	} else {
955 		PKCS7error(PKCS7_R_WRONG_PKCS7_TYPE);
956 		goto err;
957 	}
958 	/* XXXX */
959 	ias = si->issuer_and_serial;
960 
961 	x509 = X509_find_by_issuer_and_serial(cert, ias->issuer, ias->serial);
962 
963 	/* were we able to find the cert in passed to us */
964 	if (x509 == NULL) {
965 		PKCS7error(PKCS7_R_UNABLE_TO_FIND_CERTIFICATE);
966 		goto err;
967 	}
968 
969 	/* Lets verify */
970 	if (!X509_STORE_CTX_init(ctx, cert_store, x509, cert)) {
971 		PKCS7error(ERR_R_X509_LIB);
972 		goto err;
973 	}
974 	if (X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN) == 0) {
975 		X509_STORE_CTX_cleanup(ctx);
976 		goto err;
977 	}
978 	i = X509_verify_cert(ctx);
979 	if (i <= 0) {
980 		PKCS7error(ERR_R_X509_LIB);
981 		X509_STORE_CTX_cleanup(ctx);
982 		goto err;
983 	}
984 	X509_STORE_CTX_cleanup(ctx);
985 
986 	return PKCS7_signatureVerify(bio, p7, si, x509);
987 err:
988 
989 	return ret;
990 }
991 LCRYPTO_ALIAS(PKCS7_dataVerify);
992 
993 int
994 PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, X509 *x509)
995 {
996 	ASN1_OCTET_STRING *os;
997 	EVP_MD_CTX mdc_tmp, *mdc;
998 	int ret = 0, i;
999 	int md_type;
1000 	STACK_OF(X509_ATTRIBUTE) *sk;
1001 	BIO *btmp;
1002 	EVP_PKEY *pkey;
1003 
1004 	EVP_MD_CTX_init(&mdc_tmp);
1005 
1006 	if (!PKCS7_type_is_signed(p7) &&
1007 	    !PKCS7_type_is_signedAndEnveloped(p7)) {
1008 		PKCS7error(PKCS7_R_WRONG_PKCS7_TYPE);
1009 		goto err;
1010 	}
1011 
1012 	md_type = OBJ_obj2nid(si->digest_alg->algorithm);
1013 
1014 	btmp = bio;
1015 	for (;;) {
1016 		if ((btmp == NULL) ||
1017 		    ((btmp = BIO_find_type(btmp, BIO_TYPE_MD)) == NULL)) {
1018 			PKCS7error(PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
1019 			goto err;
1020 		}
1021 		BIO_get_md_ctx(btmp, &mdc);
1022 		if (mdc == NULL) {
1023 			PKCS7error(ERR_R_INTERNAL_ERROR);
1024 			goto err;
1025 		}
1026 		if (EVP_MD_CTX_type(mdc) == md_type)
1027 			break;
1028 		/* Workaround for some broken clients that put the signature
1029 		 * OID instead of the digest OID in digest_alg->algorithm
1030 		 */
1031 		if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type)
1032 			break;
1033 		btmp = BIO_next(btmp);
1034 	}
1035 
1036 	/* mdc is the digest ctx that we want, unless there are attributes,
1037 	 * in which case the digest is the signed attributes */
1038 	if (!EVP_MD_CTX_copy_ex(&mdc_tmp, mdc))
1039 		goto err;
1040 
1041 	sk = si->auth_attr;
1042 	if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) {
1043 		unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL;
1044 		unsigned int md_len;
1045 		int alen;
1046 		ASN1_OCTET_STRING *message_digest;
1047 
1048 		if (!EVP_DigestFinal_ex(&mdc_tmp, md_dat, &md_len))
1049 			goto err;
1050 		message_digest = PKCS7_digest_from_attributes(sk);
1051 		if (!message_digest) {
1052 			PKCS7error(PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
1053 			goto err;
1054 		}
1055 		if ((message_digest->length != (int)md_len) ||
1056 		    (memcmp(message_digest->data, md_dat, md_len))) {
1057 			PKCS7error(PKCS7_R_DIGEST_FAILURE);
1058 			ret = -1;
1059 			goto err;
1060 		}
1061 
1062 		if (!EVP_VerifyInit_ex(&mdc_tmp, EVP_get_digestbynid(md_type),
1063 		    NULL))
1064 			goto err;
1065 
1066 		alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf,
1067 		    &PKCS7_ATTR_VERIFY_it);
1068 		if (alen <= 0) {
1069 			PKCS7error(ERR_R_ASN1_LIB);
1070 			ret = -1;
1071 			goto err;
1072 		}
1073 		if (!EVP_VerifyUpdate(&mdc_tmp, abuf, alen))
1074 			goto err;
1075 
1076 		free(abuf);
1077 	}
1078 
1079 	os = si->enc_digest;
1080 	pkey = X509_get_pubkey(x509);
1081 	if (!pkey) {
1082 		ret = -1;
1083 		goto err;
1084 	}
1085 
1086 	i = EVP_VerifyFinal(&mdc_tmp, os->data, os->length, pkey);
1087 	EVP_PKEY_free(pkey);
1088 	if (i <= 0) {
1089 		PKCS7error(PKCS7_R_SIGNATURE_FAILURE);
1090 		ret = -1;
1091 		goto err;
1092 	} else
1093 		ret = 1;
1094 err:
1095 	EVP_MD_CTX_cleanup(&mdc_tmp);
1096 	return (ret);
1097 }
1098 LCRYPTO_ALIAS(PKCS7_signatureVerify);
1099 
1100 PKCS7_ISSUER_AND_SERIAL *
1101 PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
1102 {
1103 	STACK_OF(PKCS7_RECIP_INFO) *rsk;
1104 	PKCS7_RECIP_INFO *ri;
1105 	int i;
1106 
1107 	i = OBJ_obj2nid(p7->type);
1108 	if (i != NID_pkcs7_signedAndEnveloped)
1109 		return NULL;
1110 	if (p7->d.signed_and_enveloped == NULL)
1111 		return NULL;
1112 	rsk = p7->d.signed_and_enveloped->recipientinfo;
1113 	if (rsk == NULL)
1114 		return NULL;
1115 	ri = sk_PKCS7_RECIP_INFO_value(rsk, 0);
1116 	if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx)
1117 		return (NULL);
1118 	ri = sk_PKCS7_RECIP_INFO_value(rsk, idx);
1119 	return (ri->issuer_and_serial);
1120 }
1121 LCRYPTO_ALIAS(PKCS7_get_issuer_and_serial);
1122 
1123 ASN1_TYPE *
1124 PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid)
1125 {
1126 	return (get_attribute(si->auth_attr, nid));
1127 }
1128 LCRYPTO_ALIAS(PKCS7_get_signed_attribute);
1129 
1130 ASN1_TYPE *
1131 PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid)
1132 {
1133 	return (get_attribute(si->unauth_attr, nid));
1134 }
1135 LCRYPTO_ALIAS(PKCS7_get_attribute);
1136 
1137 static ASN1_TYPE *
1138 get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid)
1139 {
1140 	int i;
1141 	X509_ATTRIBUTE *xa;
1142 	ASN1_OBJECT *o;
1143 
1144 	o = OBJ_nid2obj(nid);
1145 	if (!o || !sk)
1146 		return (NULL);
1147 	for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) {
1148 		xa = sk_X509_ATTRIBUTE_value(sk, i);
1149 		if (OBJ_cmp(xa->object, o) == 0)
1150 			return (sk_ASN1_TYPE_value(xa->set, 0));
1151 	}
1152 	return (NULL);
1153 }
1154 
1155 ASN1_OCTET_STRING *
1156 PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk)
1157 {
1158 	ASN1_TYPE *astype;
1159 
1160 	if (!(astype = get_attribute(sk, NID_pkcs9_messageDigest)))
1161 		return NULL;
1162 	if (astype->type != V_ASN1_OCTET_STRING)
1163 		return NULL;
1164 	return astype->value.octet_string;
1165 }
1166 LCRYPTO_ALIAS(PKCS7_digest_from_attributes);
1167 
1168 int
1169 PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
1170     STACK_OF(X509_ATTRIBUTE) *sk)
1171 {
1172 	int i;
1173 
1174 	if (p7si->auth_attr != NULL)
1175 		sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,
1176 		    X509_ATTRIBUTE_free);
1177 	p7si->auth_attr = sk_X509_ATTRIBUTE_dup(sk);
1178 	if (p7si->auth_attr == NULL)
1179 		return 0;
1180 	for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) {
1181 		if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr, i,
1182 		    X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk, i))))
1183 		    == NULL)
1184 			return (0);
1185 	}
1186 	return (1);
1187 }
1188 LCRYPTO_ALIAS(PKCS7_set_signed_attributes);
1189 
1190 int
1191 PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk)
1192 {
1193 	int i;
1194 
1195 	if (p7si->unauth_attr != NULL)
1196 		sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr,
1197 		    X509_ATTRIBUTE_free);
1198 	p7si->unauth_attr = sk_X509_ATTRIBUTE_dup(sk);
1199 	if (p7si->unauth_attr == NULL)
1200 		return 0;
1201 	for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) {
1202 		if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr, i,
1203 		    X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk, i))))
1204 		    == NULL)
1205 			return (0);
1206 	}
1207 	return (1);
1208 }
1209 LCRYPTO_ALIAS(PKCS7_set_attributes);
1210 
1211 int
1212 PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
1213     void *value)
1214 {
1215 	return (add_attribute(&(p7si->auth_attr), nid, atrtype, value));
1216 }
1217 LCRYPTO_ALIAS(PKCS7_add_signed_attribute);
1218 
1219 int
1220 PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, void *value)
1221 {
1222 	return (add_attribute(&(p7si->unauth_attr), nid, atrtype, value));
1223 }
1224 LCRYPTO_ALIAS(PKCS7_add_attribute);
1225 
1226 static int
1227 add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, void *value)
1228 {
1229 	X509_ATTRIBUTE *attr = NULL;
1230 
1231 	if (*sk == NULL) {
1232 		*sk = sk_X509_ATTRIBUTE_new_null();
1233 		if (*sk == NULL)
1234 			return 0;
1235 new_attrib:
1236 		if (!(attr = X509_ATTRIBUTE_create(nid, atrtype, value)))
1237 			return 0;
1238 		if (!sk_X509_ATTRIBUTE_push(*sk, attr)) {
1239 			X509_ATTRIBUTE_free(attr);
1240 			return 0;
1241 		}
1242 	} else {
1243 		int i;
1244 
1245 		for (i = 0; i < sk_X509_ATTRIBUTE_num(*sk); i++) {
1246 			attr = sk_X509_ATTRIBUTE_value(*sk, i);
1247 			if (OBJ_obj2nid(attr->object) == nid) {
1248 				X509_ATTRIBUTE_free(attr);
1249 				attr = X509_ATTRIBUTE_create(nid, atrtype,
1250 				    value);
1251 				if (attr == NULL)
1252 					return 0;
1253 				if (!sk_X509_ATTRIBUTE_set(*sk, i, attr)) {
1254 					X509_ATTRIBUTE_free(attr);
1255 					return 0;
1256 				}
1257 				goto end;
1258 			}
1259 		}
1260 		goto new_attrib;
1261 	}
1262 end:
1263 	return (1);
1264 }
1265