VirtualBox

source: vbox/trunk/src/libs/openssl-3.1.2/crypto/pkcs7/pk7_doit.c@ 101021

Last change on this file since 101021 was 101021, checked in by vboxsync, 15 months ago

openssl-3.1.2: Applied and adjusted our OpenSSL changes to 3.1.0. bugref:10519

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette