summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/cms/cms_smime.c
diff options
context:
space:
mode:
authorjsing <>2019-08-10 15:55:20 +0000
committerjsing <>2019-08-10 15:55:20 +0000
commita0845ead6d459f388701fe3fe8fa27635f4885f1 (patch)
treecfa2d4e7280cbfe7b7007556c8dcab6691e87b83 /src/lib/libcrypto/cms/cms_smime.c
parent38e170324f2dafb68786e79022ddafab241aad3d (diff)
downloadopenbsd-a0845ead6d459f388701fe3fe8fa27635f4885f1.tar.gz
openbsd-a0845ead6d459f388701fe3fe8fa27635f4885f1.tar.bz2
openbsd-a0845ead6d459f388701fe3fe8fa27635f4885f1.zip
Work towards supporting Cryptographic Message Syntax (CMS) in libcrypto.
Cryptographic Message Syntax (CMS) is a standard for cryptographically protecting messages, as defined in RFC 5652. It is derived from PKCS #7 version 1.5 and utilises various ASN.1 structures, making it complex and fairly heavyweight. Various protocols - including RPKI (RFC 6480) - have been built on top of it, which means it is necessary to support CMS, in order to support RPKI. This imports around 6,000 lines of code from OpenSSL 1.1.1, which is still under the original OpenSSL license. Further work will occur in tree. Requested by and discussed with many. ok deraadt@ tb@
Diffstat (limited to 'src/lib/libcrypto/cms/cms_smime.c')
-rw-r--r--src/lib/libcrypto/cms/cms_smime.c843
1 files changed, 843 insertions, 0 deletions
diff --git a/src/lib/libcrypto/cms/cms_smime.c b/src/lib/libcrypto/cms/cms_smime.c
new file mode 100644
index 0000000000..5dcf803f4b
--- /dev/null
+++ b/src/lib/libcrypto/cms/cms_smime.c
@@ -0,0 +1,843 @@
1/*
2 * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (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 "internal/cryptlib.h"
11#include <openssl/asn1t.h>
12#include <openssl/x509.h>
13#include <openssl/x509v3.h>
14#include <openssl/err.h>
15#include <openssl/cms.h>
16#include "cms_lcl.h"
17#include "internal/asn1_int.h"
18
19static BIO *cms_get_text_bio(BIO *out, unsigned int flags)
20{
21 BIO *rbio;
22 if (out == NULL)
23 rbio = BIO_new(BIO_s_null());
24 else if (flags & CMS_TEXT) {
25 rbio = BIO_new(BIO_s_mem());
26 BIO_set_mem_eof_return(rbio, 0);
27 } else
28 rbio = out;
29 return rbio;
30}
31
32static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
33{
34 unsigned char buf[4096];
35 int r = 0, i;
36 BIO *tmpout;
37
38 tmpout = cms_get_text_bio(out, flags);
39
40 if (tmpout == NULL) {
41 CMSerr(CMS_F_CMS_COPY_CONTENT, ERR_R_MALLOC_FAILURE);
42 goto err;
43 }
44
45 /* Read all content through chain to process digest, decrypt etc */
46 for (;;) {
47 i = BIO_read(in, buf, sizeof(buf));
48 if (i <= 0) {
49 if (BIO_method_type(in) == BIO_TYPE_CIPHER) {
50 if (!BIO_get_cipher_status(in))
51 goto err;
52 }
53 if (i < 0)
54 goto err;
55 break;
56 }
57
58 if (tmpout && (BIO_write(tmpout, buf, i) != i))
59 goto err;
60 }
61
62 if (flags & CMS_TEXT) {
63 if (!SMIME_text(tmpout, out)) {
64 CMSerr(CMS_F_CMS_COPY_CONTENT, CMS_R_SMIME_TEXT_ERROR);
65 goto err;
66 }
67 }
68
69 r = 1;
70
71 err:
72 if (tmpout != out)
73 BIO_free(tmpout);
74 return r;
75
76}
77
78static int check_content(CMS_ContentInfo *cms)
79{
80 ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
81 if (!pos || !*pos) {
82 CMSerr(CMS_F_CHECK_CONTENT, CMS_R_NO_CONTENT);
83 return 0;
84 }
85 return 1;
86}
87
88static void do_free_upto(BIO *f, BIO *upto)
89{
90 if (upto) {
91 BIO *tbio;
92 do {
93 tbio = BIO_pop(f);
94 BIO_free(f);
95 f = tbio;
96 }
97 while (f && f != upto);
98 } else
99 BIO_free_all(f);
100}
101
102int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags)
103{
104 BIO *cont;
105 int r;
106 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data) {
107 CMSerr(CMS_F_CMS_DATA, CMS_R_TYPE_NOT_DATA);
108 return 0;
109 }
110 cont = CMS_dataInit(cms, NULL);
111 if (!cont)
112 return 0;
113 r = cms_copy_content(out, cont, flags);
114 BIO_free_all(cont);
115 return r;
116}
117
118CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags)
119{
120 CMS_ContentInfo *cms;
121 cms = cms_Data_create();
122 if (!cms)
123 return NULL;
124
125 if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
126 return cms;
127
128 CMS_ContentInfo_free(cms);
129
130 return NULL;
131}
132
133int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
134 unsigned int flags)
135{
136 BIO *cont;
137 int r;
138 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest) {
139 CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_TYPE_NOT_DIGESTED_DATA);
140 return 0;
141 }
142
143 if (!dcont && !check_content(cms))
144 return 0;
145
146 cont = CMS_dataInit(cms, dcont);
147 if (!cont)
148 return 0;
149 r = cms_copy_content(out, cont, flags);
150 if (r)
151 r = cms_DigestedData_do_final(cms, cont, 1);
152 do_free_upto(cont, dcont);
153 return r;
154}
155
156CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
157 unsigned int flags)
158{
159 CMS_ContentInfo *cms;
160 if (!md)
161 md = EVP_sha1();
162 cms = cms_DigestedData_create(md);
163 if (!cms)
164 return NULL;
165
166 if (!(flags & CMS_DETACHED))
167 CMS_set_detached(cms, 0);
168
169 if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
170 return cms;
171
172 CMS_ContentInfo_free(cms);
173 return NULL;
174}
175
176int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
177 const unsigned char *key, size_t keylen,
178 BIO *dcont, BIO *out, unsigned int flags)
179{
180 BIO *cont;
181 int r;
182 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted) {
183 CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT,
184 CMS_R_TYPE_NOT_ENCRYPTED_DATA);
185 return 0;
186 }
187
188 if (!dcont && !check_content(cms))
189 return 0;
190
191 if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
192 return 0;
193 cont = CMS_dataInit(cms, dcont);
194 if (!cont)
195 return 0;
196 r = cms_copy_content(out, cont, flags);
197 do_free_upto(cont, dcont);
198 return r;
199}
200
201CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
202 const unsigned char *key,
203 size_t keylen, unsigned int flags)
204{
205 CMS_ContentInfo *cms;
206 if (!cipher) {
207 CMSerr(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, CMS_R_NO_CIPHER);
208 return NULL;
209 }
210 cms = CMS_ContentInfo_new();
211 if (cms == NULL)
212 return NULL;
213 if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
214 return NULL;
215
216 if (!(flags & CMS_DETACHED))
217 CMS_set_detached(cms, 0);
218
219 if ((flags & (CMS_STREAM | CMS_PARTIAL))
220 || CMS_final(cms, in, NULL, flags))
221 return cms;
222
223 CMS_ContentInfo_free(cms);
224 return NULL;
225}
226
227static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
228 X509_STORE *store,
229 STACK_OF(X509) *certs,
230 STACK_OF(X509_CRL) *crls)
231{
232 X509_STORE_CTX *ctx = X509_STORE_CTX_new();
233 X509 *signer;
234 int i, j, r = 0;
235
236 if (ctx == NULL) {
237 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
238 goto err;
239 }
240 CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
241 if (!X509_STORE_CTX_init(ctx, store, signer, certs)) {
242 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, CMS_R_STORE_INIT_ERROR);
243 goto err;
244 }
245 X509_STORE_CTX_set_default(ctx, "smime_sign");
246 if (crls)
247 X509_STORE_CTX_set0_crls(ctx, crls);
248
249 i = X509_verify_cert(ctx);
250 if (i <= 0) {
251 j = X509_STORE_CTX_get_error(ctx);
252 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT,
253 CMS_R_CERTIFICATE_VERIFY_ERROR);
254 ERR_add_error_data(2, "Verify error:",
255 X509_verify_cert_error_string(j));
256 goto err;
257 }
258 r = 1;
259 err:
260 X509_STORE_CTX_free(ctx);
261 return r;
262
263}
264
265int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
266 X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags)
267{
268 CMS_SignerInfo *si;
269 STACK_OF(CMS_SignerInfo) *sinfos;
270 STACK_OF(X509) *cms_certs = NULL;
271 STACK_OF(X509_CRL) *crls = NULL;
272 X509 *signer;
273 int i, scount = 0, ret = 0;
274 BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL;
275
276 if (!dcont && !check_content(cms))
277 return 0;
278 if (dcont && !(flags & CMS_BINARY)) {
279 const ASN1_OBJECT *coid = CMS_get0_eContentType(cms);
280 if (OBJ_obj2nid(coid) == NID_id_ct_asciiTextWithCRLF)
281 flags |= CMS_ASCIICRLF;
282 }
283
284 /* Attempt to find all signer certificates */
285
286 sinfos = CMS_get0_SignerInfos(cms);
287
288 if (sk_CMS_SignerInfo_num(sinfos) <= 0) {
289 CMSerr(CMS_F_CMS_VERIFY, CMS_R_NO_SIGNERS);
290 goto err;
291 }
292
293 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
294 si = sk_CMS_SignerInfo_value(sinfos, i);
295 CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
296 if (signer)
297 scount++;
298 }
299
300 if (scount != sk_CMS_SignerInfo_num(sinfos))
301 scount += CMS_set1_signers_certs(cms, certs, flags);
302
303 if (scount != sk_CMS_SignerInfo_num(sinfos)) {
304 CMSerr(CMS_F_CMS_VERIFY, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
305 goto err;
306 }
307
308 /* Attempt to verify all signers certs */
309
310 if (!(flags & CMS_NO_SIGNER_CERT_VERIFY)) {
311 cms_certs = CMS_get1_certs(cms);
312 if (!(flags & CMS_NOCRL))
313 crls = CMS_get1_crls(cms);
314 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
315 si = sk_CMS_SignerInfo_value(sinfos, i);
316 if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls))
317 goto err;
318 }
319 }
320
321 /* Attempt to verify all SignerInfo signed attribute signatures */
322
323 if (!(flags & CMS_NO_ATTR_VERIFY)) {
324 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
325 si = sk_CMS_SignerInfo_value(sinfos, i);
326 if (CMS_signed_get_attr_count(si) < 0)
327 continue;
328 if (CMS_SignerInfo_verify(si) <= 0)
329 goto err;
330 }
331 }
332
333 /*
334 * Performance optimization: if the content is a memory BIO then store
335 * its contents in a temporary read only memory BIO. This avoids
336 * potentially large numbers of slow copies of data which will occur when
337 * reading from a read write memory BIO when signatures are calculated.
338 */
339
340 if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM)) {
341 char *ptr;
342 long len;
343 len = BIO_get_mem_data(dcont, &ptr);
344 tmpin = BIO_new_mem_buf(ptr, len);
345 if (tmpin == NULL) {
346 CMSerr(CMS_F_CMS_VERIFY, ERR_R_MALLOC_FAILURE);
347 goto err2;
348 }
349 } else
350 tmpin = dcont;
351 /*
352 * If not binary mode and detached generate digests by *writing* through
353 * the BIO. That makes it possible to canonicalise the input.
354 */
355 if (!(flags & SMIME_BINARY) && dcont) {
356 /*
357 * Create output BIO so we can either handle text or to ensure
358 * included content doesn't override detached content.
359 */
360 tmpout = cms_get_text_bio(out, flags);
361 if (!tmpout) {
362 CMSerr(CMS_F_CMS_VERIFY, ERR_R_MALLOC_FAILURE);
363 goto err;
364 }
365 cmsbio = CMS_dataInit(cms, tmpout);
366 if (!cmsbio)
367 goto err;
368 /*
369 * Don't use SMIME_TEXT for verify: it adds headers and we want to
370 * remove them.
371 */
372 SMIME_crlf_copy(dcont, cmsbio, flags & ~SMIME_TEXT);
373
374 if (flags & CMS_TEXT) {
375 if (!SMIME_text(tmpout, out)) {
376 CMSerr(CMS_F_CMS_VERIFY, CMS_R_SMIME_TEXT_ERROR);
377 goto err;
378 }
379 }
380 } else {
381 cmsbio = CMS_dataInit(cms, tmpin);
382 if (!cmsbio)
383 goto err;
384
385 if (!cms_copy_content(out, cmsbio, flags))
386 goto err;
387
388 }
389 if (!(flags & CMS_NO_CONTENT_VERIFY)) {
390 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
391 si = sk_CMS_SignerInfo_value(sinfos, i);
392 if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0) {
393 CMSerr(CMS_F_CMS_VERIFY, CMS_R_CONTENT_VERIFY_ERROR);
394 goto err;
395 }
396 }
397 }
398
399 ret = 1;
400
401 err:
402 if (!(flags & SMIME_BINARY) && dcont) {
403 do_free_upto(cmsbio, tmpout);
404 if (tmpin != dcont)
405 BIO_free(tmpin);
406 } else {
407 if (dcont && (tmpin == dcont))
408 do_free_upto(cmsbio, dcont);
409 else
410 BIO_free_all(cmsbio);
411 }
412
413 if (out != tmpout)
414 BIO_free_all(tmpout);
415
416 err2:
417 sk_X509_pop_free(cms_certs, X509_free);
418 sk_X509_CRL_pop_free(crls, X509_CRL_free);
419
420 return ret;
421}
422
423int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
424 STACK_OF(X509) *certs,
425 X509_STORE *store, unsigned int flags)
426{
427 int r;
428 flags &= ~(CMS_DETACHED | CMS_TEXT);
429 r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
430 if (r <= 0)
431 return r;
432 return cms_Receipt_verify(rcms, ocms);
433}
434
435CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
436 STACK_OF(X509) *certs, BIO *data,
437 unsigned int flags)
438{
439 CMS_ContentInfo *cms;
440 int i;
441
442 cms = CMS_ContentInfo_new();
443 if (cms == NULL || !CMS_SignedData_init(cms))
444 goto merr;
445 if (flags & CMS_ASCIICRLF
446 && !CMS_set1_eContentType(cms,
447 OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF)))
448 goto err;
449
450 if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) {
451 CMSerr(CMS_F_CMS_SIGN, CMS_R_ADD_SIGNER_ERROR);
452 goto err;
453 }
454
455 for (i = 0; i < sk_X509_num(certs); i++) {
456 X509 *x = sk_X509_value(certs, i);
457 if (!CMS_add1_cert(cms, x))
458 goto merr;
459 }
460
461 if (!(flags & CMS_DETACHED))
462 CMS_set_detached(cms, 0);
463
464 if ((flags & (CMS_STREAM | CMS_PARTIAL))
465 || CMS_final(cms, data, NULL, flags))
466 return cms;
467 else
468 goto err;
469
470 merr:
471 CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE);
472
473 err:
474 CMS_ContentInfo_free(cms);
475 return NULL;
476}
477
478CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
479 X509 *signcert, EVP_PKEY *pkey,
480 STACK_OF(X509) *certs, unsigned int flags)
481{
482 CMS_SignerInfo *rct_si;
483 CMS_ContentInfo *cms = NULL;
484 ASN1_OCTET_STRING **pos, *os;
485 BIO *rct_cont = NULL;
486 int r = 0;
487
488 flags &= ~(CMS_STREAM | CMS_TEXT);
489 /* Not really detached but avoids content being allocated */
490 flags |= CMS_PARTIAL | CMS_BINARY | CMS_DETACHED;
491 if (!pkey || !signcert) {
492 CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_NO_KEY_OR_CERT);
493 return NULL;
494 }
495
496 /* Initialize signed data */
497
498 cms = CMS_sign(NULL, NULL, certs, NULL, flags);
499 if (!cms)
500 goto err;
501
502 /* Set inner content type to signed receipt */
503 if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
504 goto err;
505
506 rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
507 if (!rct_si) {
508 CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_ADD_SIGNER_ERROR);
509 goto err;
510 }
511
512 os = cms_encode_Receipt(si);
513
514 if (!os)
515 goto err;
516
517 /* Set content to digest */
518 rct_cont = BIO_new_mem_buf(os->data, os->length);
519 if (!rct_cont)
520 goto err;
521
522 /* Add msgSigDigest attribute */
523
524 if (!cms_msgSigDigest_add1(rct_si, si))
525 goto err;
526
527 /* Finalize structure */
528 if (!CMS_final(cms, rct_cont, NULL, flags))
529 goto err;
530
531 /* Set embedded content */
532 pos = CMS_get0_content(cms);
533 *pos = os;
534
535 r = 1;
536
537 err:
538 BIO_free(rct_cont);
539 if (r)
540 return cms;
541 CMS_ContentInfo_free(cms);
542 return NULL;
543
544}
545
546CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
547 const EVP_CIPHER *cipher, unsigned int flags)
548{
549 CMS_ContentInfo *cms;
550 int i;
551 X509 *recip;
552 cms = CMS_EnvelopedData_create(cipher);
553 if (!cms)
554 goto merr;
555 for (i = 0; i < sk_X509_num(certs); i++) {
556 recip = sk_X509_value(certs, i);
557 if (!CMS_add1_recipient_cert(cms, recip, flags)) {
558 CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR);
559 goto err;
560 }
561 }
562
563 if (!(flags & CMS_DETACHED))
564 CMS_set_detached(cms, 0);
565
566 if ((flags & (CMS_STREAM | CMS_PARTIAL))
567 || CMS_final(cms, data, NULL, flags))
568 return cms;
569 else
570 goto err;
571
572 merr:
573 CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE);
574 err:
575 CMS_ContentInfo_free(cms);
576 return NULL;
577}
578
579static int cms_kari_set1_pkey(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
580 EVP_PKEY *pk, X509 *cert)
581{
582 int i;
583 STACK_OF(CMS_RecipientEncryptedKey) *reks;
584 CMS_RecipientEncryptedKey *rek;
585 reks = CMS_RecipientInfo_kari_get0_reks(ri);
586 for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
587 int rv;
588 rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
589 if (cert != NULL && CMS_RecipientEncryptedKey_cert_cmp(rek, cert))
590 continue;
591 CMS_RecipientInfo_kari_set0_pkey(ri, pk);
592 rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek);
593 CMS_RecipientInfo_kari_set0_pkey(ri, NULL);
594 if (rv > 0)
595 return 1;
596 return cert == NULL ? 0 : -1;
597 }
598 return 0;
599}
600
601int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
602{
603 STACK_OF(CMS_RecipientInfo) *ris;
604 CMS_RecipientInfo *ri;
605 int i, r, ri_type;
606 int debug = 0, match_ri = 0;
607 ris = CMS_get0_RecipientInfos(cms);
608 if (ris)
609 debug = cms->d.envelopedData->encryptedContentInfo->debug;
610 ri_type = cms_pkey_get_ri_type(pk);
611 if (ri_type == CMS_RECIPINFO_NONE) {
612 CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
613 CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
614 return 0;
615 }
616
617 for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
618 ri = sk_CMS_RecipientInfo_value(ris, i);
619 if (CMS_RecipientInfo_type(ri) != ri_type)
620 continue;
621 match_ri = 1;
622 if (ri_type == CMS_RECIPINFO_AGREE) {
623 r = cms_kari_set1_pkey(cms, ri, pk, cert);
624 if (r > 0)
625 return 1;
626 if (r < 0)
627 return 0;
628 }
629 /*
630 * If we have a cert try matching RecipientInfo otherwise try them
631 * all.
632 */
633 else if (!cert || !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
634 EVP_PKEY_up_ref(pk);
635 CMS_RecipientInfo_set0_pkey(ri, pk);
636 r = CMS_RecipientInfo_decrypt(cms, ri);
637 CMS_RecipientInfo_set0_pkey(ri, NULL);
638 if (cert) {
639 /*
640 * If not debugging clear any error and return success to
641 * avoid leaking of information useful to MMA
642 */
643 if (!debug) {
644 ERR_clear_error();
645 return 1;
646 }
647 if (r > 0)
648 return 1;
649 CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_DECRYPT_ERROR);
650 return 0;
651 }
652 /*
653 * If no cert and not debugging don't leave loop after first
654 * successful decrypt. Always attempt to decrypt all recipients
655 * to avoid leaking timing of a successful decrypt.
656 */
657 else if (r > 0 && debug)
658 return 1;
659 }
660 }
661 /* If no cert, key transport and not debugging always return success */
662 if (cert == NULL && ri_type == CMS_RECIPINFO_TRANS && match_ri && !debug) {
663 ERR_clear_error();
664 return 1;
665 }
666
667 CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT);
668 return 0;
669
670}
671
672int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
673 unsigned char *key, size_t keylen,
674 const unsigned char *id, size_t idlen)
675{
676 STACK_OF(CMS_RecipientInfo) *ris;
677 CMS_RecipientInfo *ri;
678 int i, r;
679 ris = CMS_get0_RecipientInfos(cms);
680 for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
681 ri = sk_CMS_RecipientInfo_value(ris, i);
682 if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
683 continue;
684
685 /*
686 * If we have an id try matching RecipientInfo otherwise try them
687 * all.
688 */
689 if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
690 CMS_RecipientInfo_set0_key(ri, key, keylen);
691 r = CMS_RecipientInfo_decrypt(cms, ri);
692 CMS_RecipientInfo_set0_key(ri, NULL, 0);
693 if (r > 0)
694 return 1;
695 if (id) {
696 CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_DECRYPT_ERROR);
697 return 0;
698 }
699 ERR_clear_error();
700 }
701 }
702
703 CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT);
704 return 0;
705
706}
707
708int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
709 unsigned char *pass, ossl_ssize_t passlen)
710{
711 STACK_OF(CMS_RecipientInfo) *ris;
712 CMS_RecipientInfo *ri;
713 int i, r;
714 ris = CMS_get0_RecipientInfos(cms);
715 for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
716 ri = sk_CMS_RecipientInfo_value(ris, i);
717 if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS)
718 continue;
719 CMS_RecipientInfo_set0_password(ri, pass, passlen);
720 r = CMS_RecipientInfo_decrypt(cms, ri);
721 CMS_RecipientInfo_set0_password(ri, NULL, 0);
722 if (r > 0)
723 return 1;
724 }
725
726 CMSerr(CMS_F_CMS_DECRYPT_SET1_PASSWORD, CMS_R_NO_MATCHING_RECIPIENT);
727 return 0;
728
729}
730
731int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
732 BIO *dcont, BIO *out, unsigned int flags)
733{
734 int r;
735 BIO *cont;
736 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped) {
737 CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA);
738 return 0;
739 }
740 if (!dcont && !check_content(cms))
741 return 0;
742 if (flags & CMS_DEBUG_DECRYPT)
743 cms->d.envelopedData->encryptedContentInfo->debug = 1;
744 else
745 cms->d.envelopedData->encryptedContentInfo->debug = 0;
746 if (!pk && !cert && !dcont && !out)
747 return 1;
748 if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
749 return 0;
750 cont = CMS_dataInit(cms, dcont);
751 if (!cont)
752 return 0;
753 r = cms_copy_content(out, cont, flags);
754 do_free_upto(cont, dcont);
755 return r;
756}
757
758int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
759{
760 BIO *cmsbio;
761 int ret = 0;
762
763 if ((cmsbio = CMS_dataInit(cms, dcont)) == NULL) {
764 CMSerr(CMS_F_CMS_FINAL, CMS_R_CMS_LIB);
765 return 0;
766 }
767
768 SMIME_crlf_copy(data, cmsbio, flags);
769
770 (void)BIO_flush(cmsbio);
771
772 if (!CMS_dataFinal(cms, cmsbio)) {
773 CMSerr(CMS_F_CMS_FINAL, CMS_R_CMS_DATAFINAL_ERROR);
774 goto err;
775 }
776
777 ret = 1;
778
779 err:
780 do_free_upto(cmsbio, dcont);
781
782 return ret;
783
784}
785
786#ifdef ZLIB
787
788int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
789 unsigned int flags)
790{
791 BIO *cont;
792 int r;
793 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData) {
794 CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_TYPE_NOT_COMPRESSED_DATA);
795 return 0;
796 }
797
798 if (!dcont && !check_content(cms))
799 return 0;
800
801 cont = CMS_dataInit(cms, dcont);
802 if (!cont)
803 return 0;
804 r = cms_copy_content(out, cont, flags);
805 do_free_upto(cont, dcont);
806 return r;
807}
808
809CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
810{
811 CMS_ContentInfo *cms;
812 if (comp_nid <= 0)
813 comp_nid = NID_zlib_compression;
814 cms = cms_CompressedData_create(comp_nid);
815 if (!cms)
816 return NULL;
817
818 if (!(flags & CMS_DETACHED))
819 CMS_set_detached(cms, 0);
820
821 if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
822 return cms;
823
824 CMS_ContentInfo_free(cms);
825 return NULL;
826}
827
828#else
829
830int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
831 unsigned int flags)
832{
833 CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
834 return 0;
835}
836
837CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
838{
839 CMSerr(CMS_F_CMS_COMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
840 return NULL;
841}
842
843#endif