]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/cms/cms_smime.c
TS and CMS CAdES-BES: Refactor check_signing_certs() funcs into common ESS func
[thirdparty/openssl.git] / crypto / cms / cms_smime.c
CommitLineData
0f113f3e 1/*
4333b89f 2 * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
8931b30d 3 *
08ddd302 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
b1322259
RS
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
8931b30d
DSH
8 */
9
b39fc560 10#include "internal/cryptlib.h"
8931b30d
DSH
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>
706457b7 16#include "cms_local.h"
25f2138b 17#include "crypto/asn1.h"
8931b30d 18
cd30f03a 19static BIO *cms_get_text_bio(BIO *out, unsigned int flags)
0f113f3e
MC
20{
21 BIO *rbio;
c1669f41 22
0f113f3e
MC
23 if (out == NULL)
24 rbio = BIO_new(BIO_s_null());
25 else if (flags & CMS_TEXT) {
26 rbio = BIO_new(BIO_s_mem());
27 BIO_set_mem_eof_return(rbio, 0);
28 } else
29 rbio = out;
30 return rbio;
31}
cd30f03a
DSH
32
33static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
0f113f3e
MC
34{
35 unsigned char buf[4096];
36 int r = 0, i;
37 BIO *tmpout;
38
39 tmpout = cms_get_text_bio(out, flags);
40
90945fa3 41 if (tmpout == NULL) {
9311d0c4 42 ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
0f113f3e
MC
43 goto err;
44 }
45
46 /* Read all content through chain to process digest, decrypt etc */
47 for (;;) {
48 i = BIO_read(in, buf, sizeof(buf));
49 if (i <= 0) {
50 if (BIO_method_type(in) == BIO_TYPE_CIPHER) {
51 if (!BIO_get_cipher_status(in))
52 goto err;
53 }
54 if (i < 0)
55 goto err;
56 break;
57 }
58
c1669f41 59 if (tmpout != NULL && (BIO_write(tmpout, buf, i) != i))
0f113f3e
MC
60 goto err;
61 }
62
63 if (flags & CMS_TEXT) {
64 if (!SMIME_text(tmpout, out)) {
9311d0c4 65 ERR_raise(ERR_LIB_CMS, CMS_R_SMIME_TEXT_ERROR);
0f113f3e
MC
66 goto err;
67 }
68 }
69
70 r = 1;
0f113f3e 71 err:
ca3a82c3 72 if (tmpout != out)
0f113f3e
MC
73 BIO_free(tmpout);
74 return r;
75
76}
8931b30d 77
4f1aa191 78static int check_content(CMS_ContentInfo *cms)
0f113f3e
MC
79{
80 ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
12a765a5
RS
81
82 if (pos == NULL || *pos == NULL) {
9311d0c4 83 ERR_raise(ERR_LIB_CMS, CMS_R_NO_CONTENT);
0f113f3e
MC
84 return 0;
85 }
86 return 1;
87}
4f1aa191 88
852bd350 89static void do_free_upto(BIO *f, BIO *upto)
0f113f3e 90{
12a765a5 91 if (upto != NULL) {
0f113f3e 92 BIO *tbio;
c1669f41 93
0f113f3e
MC
94 do {
95 tbio = BIO_pop(f);
96 BIO_free(f);
97 f = tbio;
12a765a5 98 } while (f != NULL && f != upto);
c1669f41 99 } else {
0f113f3e 100 BIO_free_all(f);
c1669f41 101 }
0f113f3e 102}
852bd350 103
8931b30d 104int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags)
0f113f3e
MC
105{
106 BIO *cont;
107 int r;
c1669f41 108
0f113f3e 109 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data) {
9311d0c4 110 ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_DATA);
0f113f3e
MC
111 return 0;
112 }
113 cont = CMS_dataInit(cms, NULL);
c1669f41 114 if (cont == NULL)
0f113f3e
MC
115 return 0;
116 r = cms_copy_content(out, cont, flags);
117 BIO_free_all(cont);
118 return r;
119}
8931b30d 120
d8652be0 121CMS_ContentInfo *CMS_data_create_ex(BIO *in, unsigned int flags,
b4250010 122 OSSL_LIB_CTX *libctx, const char *propq)
0f113f3e 123{
53155f1c 124 CMS_ContentInfo *cms = ossl_cms_Data_create(libctx, propq);
c1669f41
SL
125
126 if (cms == NULL)
0f113f3e 127 return NULL;
8931b30d 128
0f113f3e
MC
129 if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
130 return cms;
8931b30d 131
0f113f3e 132 CMS_ContentInfo_free(cms);
0f113f3e
MC
133 return NULL;
134}
8931b30d 135
c1669f41
SL
136CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags)
137{
d8652be0 138 return CMS_data_create_ex(in, flags, NULL, NULL);
c1669f41
SL
139}
140
8931b30d 141int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
0f113f3e
MC
142 unsigned int flags)
143{
144 BIO *cont;
145 int r;
c1669f41 146
0f113f3e 147 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest) {
9311d0c4 148 ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_DIGESTED_DATA);
0f113f3e
MC
149 return 0;
150 }
151
c1669f41 152 if (dcont == NULL && !check_content(cms))
0f113f3e
MC
153 return 0;
154
155 cont = CMS_dataInit(cms, dcont);
c1669f41 156 if (cont == NULL)
0f113f3e 157 return 0;
c1669f41 158
0f113f3e
MC
159 r = cms_copy_content(out, cont, flags);
160 if (r)
53155f1c 161 r = ossl_cms_DigestedData_do_final(cms, cont, 1);
0f113f3e
MC
162 do_free_upto(cont, dcont);
163 return r;
164}
8931b30d 165
d8652be0 166CMS_ContentInfo *CMS_digest_create_ex(BIO *in, const EVP_MD *md,
b4250010 167 unsigned int flags, OSSL_LIB_CTX *ctx,
d8652be0 168 const char *propq)
0f113f3e
MC
169{
170 CMS_ContentInfo *cms;
c1669f41
SL
171
172 if (md == NULL)
0f113f3e 173 md = EVP_sha1();
53155f1c 174 cms = ossl_cms_DigestedData_create(md, ctx, propq);
c1669f41 175 if (cms == NULL)
0f113f3e 176 return NULL;
8931b30d 177
0f113f3e
MC
178 if (!(flags & CMS_DETACHED))
179 CMS_set_detached(cms, 0);
8931b30d 180
0f113f3e
MC
181 if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
182 return cms;
8931b30d 183
0f113f3e
MC
184 CMS_ContentInfo_free(cms);
185 return NULL;
186}
8931b30d 187
c1669f41
SL
188CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
189 unsigned int flags)
190{
d8652be0 191 return CMS_digest_create_ex(in, md, flags, NULL, NULL);
c1669f41
SL
192}
193
b820455c 194int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
0f113f3e
MC
195 const unsigned char *key, size_t keylen,
196 BIO *dcont, BIO *out, unsigned int flags)
197{
198 BIO *cont;
199 int r;
c1669f41 200
0f113f3e 201 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted) {
9311d0c4 202 ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_ENCRYPTED_DATA);
0f113f3e
MC
203 return 0;
204 }
205
c1669f41 206 if (dcont == NULL && !check_content(cms))
0f113f3e
MC
207 return 0;
208
209 if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
210 return 0;
211 cont = CMS_dataInit(cms, dcont);
c1669f41 212 if (cont == NULL)
0f113f3e
MC
213 return 0;
214 r = cms_copy_content(out, cont, flags);
215 do_free_upto(cont, dcont);
216 return r;
217}
b820455c 218
d8652be0
MC
219CMS_ContentInfo *CMS_EncryptedData_encrypt_ex(BIO *in, const EVP_CIPHER *cipher,
220 const unsigned char *key,
221 size_t keylen, unsigned int flags,
b4250010 222 OSSL_LIB_CTX *libctx,
d8652be0 223 const char *propq)
0f113f3e
MC
224{
225 CMS_ContentInfo *cms;
c1669f41
SL
226
227 if (cipher == NULL) {
9311d0c4 228 ERR_raise(ERR_LIB_CMS, CMS_R_NO_CIPHER);
0f113f3e
MC
229 return NULL;
230 }
d8652be0 231 cms = CMS_ContentInfo_new_ex(libctx, propq);
90945fa3 232 if (cms == NULL)
0f113f3e
MC
233 return NULL;
234 if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
235 return NULL;
236
237 if (!(flags & CMS_DETACHED))
238 CMS_set_detached(cms, 0);
239
240 if ((flags & (CMS_STREAM | CMS_PARTIAL))
241 || CMS_final(cms, in, NULL, flags))
242 return cms;
243
244 CMS_ContentInfo_free(cms);
245 return NULL;
246}
320bfc1b 247
c1669f41
SL
248CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
249 const unsigned char *key,
250 size_t keylen, unsigned int flags)
251{
d8652be0
MC
252 return CMS_EncryptedData_encrypt_ex(in, cipher, key, keylen, flags, NULL,
253 NULL);
c1669f41
SL
254}
255
8931b30d 256static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
0f113f3e
MC
257 X509_STORE *store,
258 STACK_OF(X509) *certs,
9e3c510b 259 STACK_OF(X509_CRL) *crls,
c1669f41
SL
260 STACK_OF(X509) **chain,
261 const CMS_CTX *cms_ctx)
0f113f3e 262{
c1669f41 263 X509_STORE_CTX *ctx;
0f113f3e
MC
264 X509 *signer;
265 int i, j, r = 0;
f0e0fd51 266
53155f1c
SL
267 ctx = X509_STORE_CTX_new_ex(ossl_cms_ctx_get0_libctx(cms_ctx),
268 ossl_cms_ctx_get0_propq(cms_ctx));
f0e0fd51 269 if (ctx == NULL) {
9311d0c4 270 ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
f0e0fd51
RS
271 goto err;
272 }
0f113f3e 273 CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
f0e0fd51 274 if (!X509_STORE_CTX_init(ctx, store, signer, certs)) {
9311d0c4 275 ERR_raise(ERR_LIB_CMS, CMS_R_STORE_INIT_ERROR);
0f113f3e
MC
276 goto err;
277 }
f0e0fd51 278 X509_STORE_CTX_set_default(ctx, "smime_sign");
c1669f41 279 if (crls != NULL)
f0e0fd51 280 X509_STORE_CTX_set0_crls(ctx, crls);
0f113f3e 281
f0e0fd51 282 i = X509_verify_cert(ctx);
0f113f3e 283 if (i <= 0) {
f0e0fd51 284 j = X509_STORE_CTX_get_error(ctx);
a150f8e1
RL
285 ERR_raise_data(ERR_LIB_CMS, CMS_R_CERTIFICATE_VERIFY_ERROR,
286 "Verify error: %s", X509_verify_cert_error_string(j));
0f113f3e
MC
287 goto err;
288 }
289 r = 1;
9e3c510b
F
290
291 /* also send back the trust chain when required */
292 if (chain != NULL)
293 *chain = X509_STORE_CTX_get1_chain(ctx);
0f113f3e 294 err:
f0e0fd51 295 X509_STORE_CTX_free(ctx);
0f113f3e
MC
296 return r;
297
298}
8931b30d
DSH
299
300int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
0f113f3e
MC
301 X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags)
302{
303 CMS_SignerInfo *si;
304 STACK_OF(CMS_SignerInfo) *sinfos;
305 STACK_OF(X509) *cms_certs = NULL;
306 STACK_OF(X509_CRL) *crls = NULL;
9e3c510b 307 STACK_OF(X509) **si_chains = NULL;
0f113f3e
MC
308 X509 *signer;
309 int i, scount = 0, ret = 0;
310 BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL;
9e3c510b 311 int cadesVerify = (flags & CMS_CADES) != 0;
53155f1c 312 const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
0f113f3e 313
c1669f41 314 if (dcont == NULL && !check_content(cms))
0f113f3e 315 return 0;
c1669f41 316 if (dcont != NULL && !(flags & CMS_BINARY)) {
0f113f3e 317 const ASN1_OBJECT *coid = CMS_get0_eContentType(cms);
c1669f41 318
0f113f3e
MC
319 if (OBJ_obj2nid(coid) == NID_id_ct_asciiTextWithCRLF)
320 flags |= CMS_ASCIICRLF;
321 }
322
323 /* Attempt to find all signer certificates */
324
325 sinfos = CMS_get0_SignerInfos(cms);
326
327 if (sk_CMS_SignerInfo_num(sinfos) <= 0) {
9311d0c4 328 ERR_raise(ERR_LIB_CMS, CMS_R_NO_SIGNERS);
0f113f3e
MC
329 goto err;
330 }
331
332 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
333 si = sk_CMS_SignerInfo_value(sinfos, i);
334 CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
335 if (signer)
336 scount++;
337 }
338
339 if (scount != sk_CMS_SignerInfo_num(sinfos))
340 scount += CMS_set1_signers_certs(cms, certs, flags);
341
342 if (scount != sk_CMS_SignerInfo_num(sinfos)) {
9311d0c4 343 ERR_raise(ERR_LIB_CMS, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
0f113f3e
MC
344 goto err;
345 }
346
347 /* Attempt to verify all signers certs */
9e3c510b
F
348 /* at this point scount == sk_CMS_SignerInfo_num(sinfos) */
349
350 if ((flags & CMS_NO_SIGNER_CERT_VERIFY) == 0 || cadesVerify) {
351 if (cadesVerify) {
352 /* Certificate trust chain is required to check CAdES signature */
353 si_chains = OPENSSL_zalloc(scount * sizeof(si_chains[0]));
354 if (si_chains == NULL) {
9311d0c4 355 ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
9e3c510b
F
356 goto err;
357 }
358 }
0f113f3e
MC
359 cms_certs = CMS_get1_certs(cms);
360 if (!(flags & CMS_NOCRL))
361 crls = CMS_get1_crls(cms);
9e3c510b 362 for (i = 0; i < scount; i++) {
0f113f3e 363 si = sk_CMS_SignerInfo_value(sinfos, i);
9e3c510b
F
364
365 if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls,
c1669f41
SL
366 si_chains ? &si_chains[i] : NULL,
367 ctx))
0f113f3e
MC
368 goto err;
369 }
370 }
371
372 /* Attempt to verify all SignerInfo signed attribute signatures */
373
9e3c510b
F
374 if ((flags & CMS_NO_ATTR_VERIFY) == 0 || cadesVerify) {
375 for (i = 0; i < scount; i++) {
0f113f3e
MC
376 si = sk_CMS_SignerInfo_value(sinfos, i);
377 if (CMS_signed_get_attr_count(si) < 0)
378 continue;
379 if (CMS_SignerInfo_verify(si) <= 0)
380 goto err;
9e3c510b
F
381 if (cadesVerify) {
382 STACK_OF(X509) *si_chain = si_chains ? si_chains[i] : NULL;
383
63b64f19 384 if (ossl_cms_check_signing_certs(si, si_chain) <= 0)
9e3c510b
F
385 goto err;
386 }
0f113f3e
MC
387 }
388 }
389
390 /*
391 * Performance optimization: if the content is a memory BIO then store
392 * its contents in a temporary read only memory BIO. This avoids
393 * potentially large numbers of slow copies of data which will occur when
394 * reading from a read write memory BIO when signatures are calculated.
395 */
396
c1669f41 397 if (dcont != NULL && (BIO_method_type(dcont) == BIO_TYPE_MEM)) {
0f113f3e
MC
398 char *ptr;
399 long len;
c1669f41 400
0f113f3e 401 len = BIO_get_mem_data(dcont, &ptr);
13c5ec56 402 tmpin = (len == 0) ? dcont : BIO_new_mem_buf(ptr, len);
0f113f3e 403 if (tmpin == NULL) {
9311d0c4 404 ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
7fba8407 405 goto err2;
0f113f3e 406 }
c1669f41 407 } else {
0f113f3e 408 tmpin = dcont;
c1669f41 409 }
0f113f3e
MC
410 /*
411 * If not binary mode and detached generate digests by *writing* through
412 * the BIO. That makes it possible to canonicalise the input.
413 */
414 if (!(flags & SMIME_BINARY) && dcont) {
415 /*
416 * Create output BIO so we can either handle text or to ensure
417 * included content doesn't override detached content.
418 */
419 tmpout = cms_get_text_bio(out, flags);
c1669f41 420 if (tmpout == NULL) {
9311d0c4 421 ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
0f113f3e
MC
422 goto err;
423 }
424 cmsbio = CMS_dataInit(cms, tmpout);
c1669f41 425 if (cmsbio == NULL)
0f113f3e
MC
426 goto err;
427 /*
428 * Don't use SMIME_TEXT for verify: it adds headers and we want to
429 * remove them.
430 */
431 SMIME_crlf_copy(dcont, cmsbio, flags & ~SMIME_TEXT);
432
433 if (flags & CMS_TEXT) {
434 if (!SMIME_text(tmpout, out)) {
9311d0c4 435 ERR_raise(ERR_LIB_CMS, CMS_R_SMIME_TEXT_ERROR);
0f113f3e
MC
436 goto err;
437 }
438 }
439 } else {
440 cmsbio = CMS_dataInit(cms, tmpin);
c1669f41 441 if (cmsbio == NULL)
0f113f3e
MC
442 goto err;
443
444 if (!cms_copy_content(out, cmsbio, flags))
445 goto err;
446
447 }
448 if (!(flags & CMS_NO_CONTENT_VERIFY)) {
449 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
450 si = sk_CMS_SignerInfo_value(sinfos, i);
451 if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0) {
9311d0c4 452 ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_VERIFY_ERROR);
0f113f3e
MC
453 goto err;
454 }
455 }
456 }
457
458 ret = 1;
0f113f3e
MC
459 err:
460 if (!(flags & SMIME_BINARY) && dcont) {
461 do_free_upto(cmsbio, tmpout);
462 if (tmpin != dcont)
463 BIO_free(tmpin);
464 } else {
0f113f3e
MC
465 if (dcont && (tmpin == dcont))
466 do_free_upto(cmsbio, dcont);
467 else
468 BIO_free_all(cmsbio);
469 }
470
ca3a82c3 471 if (out != tmpout)
0f113f3e
MC
472 BIO_free_all(tmpout);
473
7fba8407 474 err2:
9e3c510b
F
475 if (si_chains != NULL) {
476 for (i = 0; i < scount; ++i)
477 sk_X509_pop_free(si_chains[i], X509_free);
478 OPENSSL_free(si_chains);
479 }
222561fe
RS
480 sk_X509_pop_free(cms_certs, X509_free);
481 sk_X509_CRL_pop_free(crls, X509_CRL_free);
0f113f3e
MC
482
483 return ret;
484}
8931b30d 485
eb9d8d8c 486int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
0f113f3e
MC
487 STACK_OF(X509) *certs,
488 X509_STORE *store, unsigned int flags)
489{
490 int r;
c1669f41 491
0f113f3e
MC
492 flags &= ~(CMS_DETACHED | CMS_TEXT);
493 r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
494 if (r <= 0)
495 return r;
53155f1c 496 return ossl_cms_Receipt_verify(rcms, ocms);
0f113f3e
MC
497}
498
d8652be0
MC
499CMS_ContentInfo *CMS_sign_ex(X509 *signcert, EVP_PKEY *pkey,
500 STACK_OF(X509) *certs, BIO *data,
b4250010 501 unsigned int flags, OSSL_LIB_CTX *libctx,
d8652be0 502 const char *propq)
0f113f3e
MC
503{
504 CMS_ContentInfo *cms;
505 int i;
506
d8652be0 507 cms = CMS_ContentInfo_new_ex(libctx, propq);
90945fa3 508 if (cms == NULL || !CMS_SignedData_init(cms))
0f113f3e
MC
509 goto merr;
510 if (flags & CMS_ASCIICRLF
511 && !CMS_set1_eContentType(cms,
512 OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF)))
513 goto err;
514
c1669f41 515 if (pkey != NULL && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) {
9311d0c4 516 ERR_raise(ERR_LIB_CMS, CMS_R_ADD_SIGNER_ERROR);
0f113f3e
MC
517 goto err;
518 }
519
520 for (i = 0; i < sk_X509_num(certs); i++) {
521 X509 *x = sk_X509_value(certs, i);
c1669f41 522
0f113f3e
MC
523 if (!CMS_add1_cert(cms, x))
524 goto merr;
525 }
526
527 if (!(flags & CMS_DETACHED))
528 CMS_set_detached(cms, 0);
529
530 if ((flags & (CMS_STREAM | CMS_PARTIAL))
531 || CMS_final(cms, data, NULL, flags))
532 return cms;
533 else
534 goto err;
535
536 merr:
9311d0c4 537 ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
0f113f3e
MC
538
539 err:
25aaa98a 540 CMS_ContentInfo_free(cms);
0f113f3e
MC
541 return NULL;
542}
8931b30d 543
c1669f41
SL
544CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
545 BIO *data, unsigned int flags)
546{
d8652be0 547 return CMS_sign_ex(signcert, pkey, certs, data, flags, NULL, NULL);
c1669f41
SL
548}
549
36309aa2 550CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
0f113f3e
MC
551 X509 *signcert, EVP_PKEY *pkey,
552 STACK_OF(X509) *certs, unsigned int flags)
553{
554 CMS_SignerInfo *rct_si;
555 CMS_ContentInfo *cms = NULL;
556 ASN1_OCTET_STRING **pos, *os;
557 BIO *rct_cont = NULL;
558 int r = 0;
c1669f41 559 const CMS_CTX *ctx = si->cms_ctx;
0f113f3e
MC
560
561 flags &= ~(CMS_STREAM | CMS_TEXT);
562 /* Not really detached but avoids content being allocated */
563 flags |= CMS_PARTIAL | CMS_BINARY | CMS_DETACHED;
12a765a5 564 if (pkey == NULL || signcert == NULL) {
9311d0c4 565 ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY_OR_CERT);
0f113f3e
MC
566 return NULL;
567 }
568
569 /* Initialize signed data */
570
53155f1c
SL
571 cms = CMS_sign_ex(NULL, NULL, certs, NULL, flags,
572 ossl_cms_ctx_get0_libctx(ctx),
573 ossl_cms_ctx_get0_propq(ctx));
c1669f41 574 if (cms == NULL)
0f113f3e
MC
575 goto err;
576
577 /* Set inner content type to signed receipt */
578 if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
579 goto err;
580
581 rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
582 if (!rct_si) {
9311d0c4 583 ERR_raise(ERR_LIB_CMS, CMS_R_ADD_SIGNER_ERROR);
0f113f3e
MC
584 goto err;
585 }
586
53155f1c 587 os = ossl_cms_encode_Receipt(si);
c1669f41 588 if (os == NULL)
0f113f3e
MC
589 goto err;
590
591 /* Set content to digest */
592 rct_cont = BIO_new_mem_buf(os->data, os->length);
c1669f41 593 if (rct_cont == NULL)
0f113f3e
MC
594 goto err;
595
596 /* Add msgSigDigest attribute */
597
53155f1c 598 if (!ossl_cms_msgSigDigest_add1(rct_si, si))
0f113f3e
MC
599 goto err;
600
601 /* Finalize structure */
602 if (!CMS_final(cms, rct_cont, NULL, flags))
603 goto err;
604
605 /* Set embedded content */
606 pos = CMS_get0_content(cms);
607 *pos = os;
608
609 r = 1;
610
611 err:
ca3a82c3 612 BIO_free(rct_cont);
0f113f3e
MC
613 if (r)
614 return cms;
615 CMS_ContentInfo_free(cms);
616 return NULL;
617
618}
36309aa2 619
d8652be0
MC
620CMS_ContentInfo *CMS_encrypt_ex(STACK_OF(X509) *certs, BIO *data,
621 const EVP_CIPHER *cipher, unsigned int flags,
b4250010 622 OSSL_LIB_CTX *libctx, const char *propq)
0f113f3e
MC
623{
624 CMS_ContentInfo *cms;
625 int i;
626 X509 *recip;
c1669f41 627
924663c3
JZ
628
629 cms = (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)
d8652be0
MC
630 ? CMS_AuthEnvelopedData_create_ex(cipher, libctx, propq)
631 : CMS_EnvelopedData_create_ex(cipher, libctx, propq);
c1669f41 632 if (cms == NULL)
0f113f3e
MC
633 goto merr;
634 for (i = 0; i < sk_X509_num(certs); i++) {
635 recip = sk_X509_value(certs, i);
636 if (!CMS_add1_recipient_cert(cms, recip, flags)) {
9311d0c4 637 ERR_raise(ERR_LIB_CMS, CMS_R_RECIPIENT_ERROR);
0f113f3e
MC
638 goto err;
639 }
640 }
641
642 if (!(flags & CMS_DETACHED))
643 CMS_set_detached(cms, 0);
644
645 if ((flags & (CMS_STREAM | CMS_PARTIAL))
646 || CMS_final(cms, data, NULL, flags))
647 return cms;
648 else
649 goto err;
650
651 merr:
9311d0c4 652 ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
0f113f3e 653 err:
25aaa98a 654 CMS_ContentInfo_free(cms);
0f113f3e
MC
655 return NULL;
656}
eeb9cdfc 657
c1669f41
SL
658CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
659 const EVP_CIPHER *cipher, unsigned int flags)
660{
d8652be0 661 return CMS_encrypt_ex(certs, data, cipher, flags, NULL, NULL);
c1669f41
SL
662}
663
664static int cms_kari_set1_pkey_and_peer(CMS_ContentInfo *cms,
665 CMS_RecipientInfo *ri,
71434aed 666 EVP_PKEY *pk, X509 *cert, X509 *peer)
0f113f3e
MC
667{
668 int i;
669 STACK_OF(CMS_RecipientEncryptedKey) *reks;
670 CMS_RecipientEncryptedKey *rek;
71434aed 671
0f113f3e 672 reks = CMS_RecipientInfo_kari_get0_reks(ri);
0f113f3e
MC
673 for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
674 int rv;
c1669f41 675
0f113f3e 676 rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
3f1d1704 677 if (cert != NULL && CMS_RecipientEncryptedKey_cert_cmp(rek, cert))
0f113f3e 678 continue;
71434aed 679 CMS_RecipientInfo_kari_set0_pkey_and_peer(ri, pk, peer);
0f113f3e
MC
680 rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek);
681 CMS_RecipientInfo_kari_set0_pkey(ri, NULL);
682 if (rv > 0)
683 return 1;
3f1d1704 684 return cert == NULL ? 0 : -1;
0f113f3e
MC
685 }
686 return 0;
687}
17c2764d 688
eeb9cdfc 689int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
71434aed
DB
690{
691 return CMS_decrypt_set1_pkey_and_peer(cms, pk, cert, NULL);
692}
693
c1669f41
SL
694int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk,
695 X509 *cert, X509 *peer)
0f113f3e
MC
696{
697 STACK_OF(CMS_RecipientInfo) *ris;
698 CMS_RecipientInfo *ri;
71434aed 699 int i, r, cms_pkey_ri_type;
0f113f3e 700 int debug = 0, match_ri = 0;
c1669f41 701
0f113f3e 702 ris = CMS_get0_RecipientInfos(cms);
c1669f41 703 if (ris != NULL)
53155f1c 704 debug = ossl_cms_get0_env_enc_content(cms)->debug;
71434aed 705
53155f1c 706 cms_pkey_ri_type = ossl_cms_pkey_get_ri_type(pk);
71434aed 707 if (cms_pkey_ri_type == CMS_RECIPINFO_NONE) {
9311d0c4 708 ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
71434aed 709 return 0;
0f113f3e
MC
710 }
711
712 for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
71434aed
DB
713 int ri_type;
714
0f113f3e 715 ri = sk_CMS_RecipientInfo_value(ris, i);
71434aed 716 ri_type = CMS_RecipientInfo_type(ri);
53155f1c 717 if (!ossl_cms_pkey_is_ri_type_supported(pk, ri_type))
0f113f3e
MC
718 continue;
719 match_ri = 1;
720 if (ri_type == CMS_RECIPINFO_AGREE) {
71434aed 721 r = cms_kari_set1_pkey_and_peer(cms, ri, pk, cert, peer);
0f113f3e
MC
722 if (r > 0)
723 return 1;
724 if (r < 0)
725 return 0;
726 }
727 /*
728 * If we have a cert try matching RecipientInfo otherwise try them
729 * all.
730 */
c1669f41 731 else if (cert == NULL|| !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
3d551b20 732 EVP_PKEY_up_ref(pk);
0f113f3e
MC
733 CMS_RecipientInfo_set0_pkey(ri, pk);
734 r = CMS_RecipientInfo_decrypt(cms, ri);
735 CMS_RecipientInfo_set0_pkey(ri, NULL);
c1669f41 736 if (cert != NULL) {
0f113f3e
MC
737 /*
738 * If not debugging clear any error and return success to
739 * avoid leaking of information useful to MMA
740 */
741 if (!debug) {
742 ERR_clear_error();
743 return 1;
744 }
745 if (r > 0)
746 return 1;
9311d0c4 747 ERR_raise(ERR_LIB_CMS, CMS_R_DECRYPT_ERROR);
0f113f3e
MC
748 return 0;
749 }
750 /*
751 * If no cert and not debugging don't leave loop after first
752 * successful decrypt. Always attempt to decrypt all recipients
753 * to avoid leaking timing of a successful decrypt.
754 */
71434aed 755 else if (r > 0 && (debug || cms_pkey_ri_type != CMS_RECIPINFO_TRANS))
0f113f3e
MC
756 return 1;
757 }
758 }
3f1d1704 759 /* If no cert, key transport and not debugging always return success */
c1669f41
SL
760 if (cert == NULL
761 && cms_pkey_ri_type == CMS_RECIPINFO_TRANS
762 && match_ri
763 && !debug) {
0f113f3e
MC
764 ERR_clear_error();
765 return 1;
766 }
767
9311d0c4 768 ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
0f113f3e
MC
769 return 0;
770
771}
772
773int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
774 unsigned char *key, size_t keylen,
c17dd597 775 const unsigned char *id, size_t idlen)
0f113f3e
MC
776{
777 STACK_OF(CMS_RecipientInfo) *ris;
778 CMS_RecipientInfo *ri;
779 int i, r;
c1669f41 780
0f113f3e
MC
781 ris = CMS_get0_RecipientInfos(cms);
782 for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
783 ri = sk_CMS_RecipientInfo_value(ris, i);
784 if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
785 continue;
786
787 /*
788 * If we have an id try matching RecipientInfo otherwise try them
789 * all.
790 */
c1669f41 791 if (id == NULL || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
0f113f3e
MC
792 CMS_RecipientInfo_set0_key(ri, key, keylen);
793 r = CMS_RecipientInfo_decrypt(cms, ri);
794 CMS_RecipientInfo_set0_key(ri, NULL, 0);
795 if (r > 0)
796 return 1;
c1669f41 797 if (id != NULL) {
9311d0c4 798 ERR_raise(ERR_LIB_CMS, CMS_R_DECRYPT_ERROR);
0f113f3e
MC
799 return 0;
800 }
801 ERR_clear_error();
802 }
803 }
804
9311d0c4 805 ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
0f113f3e
MC
806 return 0;
807
808}
809
810int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
811 unsigned char *pass, ossl_ssize_t passlen)
812{
813 STACK_OF(CMS_RecipientInfo) *ris;
814 CMS_RecipientInfo *ri;
815 int i, r;
c1669f41 816
0f113f3e
MC
817 ris = CMS_get0_RecipientInfos(cms);
818 for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
819 ri = sk_CMS_RecipientInfo_value(ris, i);
820 if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS)
821 continue;
822 CMS_RecipientInfo_set0_password(ri, pass, passlen);
823 r = CMS_RecipientInfo_decrypt(cms, ri);
824 CMS_RecipientInfo_set0_password(ri, NULL, 0);
825 if (r > 0)
826 return 1;
827 }
828
9311d0c4 829 ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
0f113f3e
MC
830 return 0;
831
832}
833
4f1aa191 834int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
0f113f3e
MC
835 BIO *dcont, BIO *out, unsigned int flags)
836{
837 int r;
838 BIO *cont;
12a765a5 839
924663c3
JZ
840 int nid = OBJ_obj2nid(CMS_get0_type(cms));
841
842 if (nid != NID_pkcs7_enveloped
843 && nid != NID_id_smime_ct_authEnvelopedData) {
9311d0c4 844 ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_ENVELOPED_DATA);
0f113f3e
MC
845 return 0;
846 }
c1669f41 847 if (dcont == NULL && !check_content(cms))
0f113f3e
MC
848 return 0;
849 if (flags & CMS_DEBUG_DECRYPT)
53155f1c 850 ossl_cms_get0_env_enc_content(cms)->debug = 1;
0f113f3e 851 else
53155f1c 852 ossl_cms_get0_env_enc_content(cms)->debug = 0;
c1669f41 853 if (cert == NULL)
53155f1c 854 ossl_cms_get0_env_enc_content(cms)->havenocert = 1;
5840ed0c 855 else
53155f1c 856 ossl_cms_get0_env_enc_content(cms)->havenocert = 0;
12a765a5 857 if (pk == NULL && cert == NULL && dcont == NULL && out == NULL)
0f113f3e 858 return 1;
12a765a5 859 if (pk != NULL && !CMS_decrypt_set1_pkey(cms, pk, cert))
0f113f3e
MC
860 return 0;
861 cont = CMS_dataInit(cms, dcont);
12a765a5 862 if (cont == NULL)
0f113f3e
MC
863 return 0;
864 r = cms_copy_content(out, cont, flags);
865 do_free_upto(cont, dcont);
866 return r;
867}
8931b30d 868
e0fbd073 869int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
0f113f3e
MC
870{
871 BIO *cmsbio;
872 int ret = 0;
75ebbd9a
RS
873
874 if ((cmsbio = CMS_dataInit(cms, dcont)) == NULL) {
9311d0c4 875 ERR_raise(ERR_LIB_CMS, CMS_R_CMS_LIB);
0f113f3e
MC
876 return 0;
877 }
8931b30d 878
c1669f41 879 ret = SMIME_crlf_copy(data, cmsbio, flags);
8931b30d 880
0f113f3e 881 (void)BIO_flush(cmsbio);
8931b30d 882
0f113f3e 883 if (!CMS_dataFinal(cms, cmsbio)) {
9311d0c4 884 ERR_raise(ERR_LIB_CMS, CMS_R_CMS_DATAFINAL_ERROR);
0f113f3e
MC
885 goto err;
886 }
c1669f41 887err:
0f113f3e 888 do_free_upto(cmsbio, dcont);
8931b30d 889
0f113f3e 890 return ret;
8931b30d 891
0f113f3e 892}
8931b30d
DSH
893
894#ifdef ZLIB
895
a5db50d0 896int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
0f113f3e
MC
897 unsigned int flags)
898{
899 BIO *cont;
900 int r;
c1669f41 901
0f113f3e 902 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData) {
9311d0c4 903 ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_COMPRESSED_DATA);
0f113f3e
MC
904 return 0;
905 }
906
c1669f41 907 if (dcont == NULL && !check_content(cms))
0f113f3e
MC
908 return 0;
909
910 cont = CMS_dataInit(cms, dcont);
c1669f41 911 if (cont == NULL)
0f113f3e
MC
912 return 0;
913 r = cms_copy_content(out, cont, flags);
914 do_free_upto(cont, dcont);
915 return r;
916}
8931b30d
DSH
917
918CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
0f113f3e
MC
919{
920 CMS_ContentInfo *cms;
c1669f41 921
0f113f3e
MC
922 if (comp_nid <= 0)
923 comp_nid = NID_zlib_compression;
53155f1c 924 cms = ossl_cms_CompressedData_create(comp_nid, NULL, NULL);
c1669f41 925 if (cms == NULL)
0f113f3e 926 return NULL;
8931b30d 927
0f113f3e
MC
928 if (!(flags & CMS_DETACHED))
929 CMS_set_detached(cms, 0);
8931b30d 930
0f113f3e
MC
931 if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
932 return cms;
8931b30d 933
0f113f3e
MC
934 CMS_ContentInfo_free(cms);
935 return NULL;
936}
8931b30d
DSH
937
938#else
939
940int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
0f113f3e
MC
941 unsigned int flags)
942{
9311d0c4 943 ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
0f113f3e
MC
944 return 0;
945}
8931b30d
DSH
946
947CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
0f113f3e 948{
9311d0c4 949 ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
0f113f3e
MC
950 return NULL;
951}
8931b30d
DSH
952
953#endif