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