]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/cms/cms_smime.c
Ensure ossl_cms_EncryptedContent_init_bio() reports an error on no OID
[thirdparty/openssl.git] / crypto / cms / cms_smime.c
CommitLineData
0f113f3e 1/*
fecb3aae 2 * Copyright 2008-2022 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) {
e077455e 42 ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB);
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) {
48b571fe 51 if (BIO_get_cipher_status(in) <= 0)
0f113f3e
MC
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 171
27344bb8
P
172 /*
173 * Because the EVP_MD is cached and can be a legacy algorithm, we
174 * cannot fetch the algorithm if it isn't supplied.
175 */
c1669f41 176 if (md == NULL)
0f113f3e 177 md = EVP_sha1();
53155f1c 178 cms = ossl_cms_DigestedData_create(md, ctx, propq);
c1669f41 179 if (cms == NULL)
0f113f3e 180 return NULL;
8931b30d 181
0f113f3e
MC
182 if (!(flags & CMS_DETACHED))
183 CMS_set_detached(cms, 0);
8931b30d 184
0f113f3e
MC
185 if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
186 return cms;
8931b30d 187
0f113f3e
MC
188 CMS_ContentInfo_free(cms);
189 return NULL;
190}
8931b30d 191
c1669f41
SL
192CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
193 unsigned int flags)
194{
d8652be0 195 return CMS_digest_create_ex(in, md, flags, NULL, NULL);
c1669f41
SL
196}
197
b820455c 198int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
0f113f3e
MC
199 const unsigned char *key, size_t keylen,
200 BIO *dcont, BIO *out, unsigned int flags)
201{
202 BIO *cont;
203 int r;
c1669f41 204
0f113f3e 205 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted) {
9311d0c4 206 ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_ENCRYPTED_DATA);
0f113f3e
MC
207 return 0;
208 }
209
c1669f41 210 if (dcont == NULL && !check_content(cms))
0f113f3e
MC
211 return 0;
212
213 if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
214 return 0;
215 cont = CMS_dataInit(cms, dcont);
c1669f41 216 if (cont == NULL)
0f113f3e
MC
217 return 0;
218 r = cms_copy_content(out, cont, flags);
219 do_free_upto(cont, dcont);
220 return r;
221}
b820455c 222
d8652be0
MC
223CMS_ContentInfo *CMS_EncryptedData_encrypt_ex(BIO *in, const EVP_CIPHER *cipher,
224 const unsigned char *key,
225 size_t keylen, unsigned int flags,
b4250010 226 OSSL_LIB_CTX *libctx,
d8652be0 227 const char *propq)
0f113f3e
MC
228{
229 CMS_ContentInfo *cms;
c1669f41
SL
230
231 if (cipher == NULL) {
9311d0c4 232 ERR_raise(ERR_LIB_CMS, CMS_R_NO_CIPHER);
0f113f3e
MC
233 return NULL;
234 }
d8652be0 235 cms = CMS_ContentInfo_new_ex(libctx, propq);
90945fa3 236 if (cms == NULL)
0f113f3e
MC
237 return NULL;
238 if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
239 return NULL;
240
241 if (!(flags & CMS_DETACHED))
242 CMS_set_detached(cms, 0);
243
244 if ((flags & (CMS_STREAM | CMS_PARTIAL))
245 || CMS_final(cms, in, NULL, flags))
246 return cms;
247
248 CMS_ContentInfo_free(cms);
249 return NULL;
250}
320bfc1b 251
c1669f41
SL
252CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
253 const unsigned char *key,
254 size_t keylen, unsigned int flags)
255{
d8652be0
MC
256 return CMS_EncryptedData_encrypt_ex(in, cipher, key, keylen, flags, NULL,
257 NULL);
c1669f41
SL
258}
259
8931b30d 260static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
0f113f3e 261 X509_STORE *store,
f69ec4b4 262 STACK_OF(X509) *untrusted,
9e3c510b 263 STACK_OF(X509_CRL) *crls,
c1669f41
SL
264 STACK_OF(X509) **chain,
265 const CMS_CTX *cms_ctx)
0f113f3e 266{
c1669f41 267 X509_STORE_CTX *ctx;
0f113f3e
MC
268 X509 *signer;
269 int i, j, r = 0;
f0e0fd51 270
53155f1c
SL
271 ctx = X509_STORE_CTX_new_ex(ossl_cms_ctx_get0_libctx(cms_ctx),
272 ossl_cms_ctx_get0_propq(cms_ctx));
f0e0fd51 273 if (ctx == NULL) {
e077455e 274 ERR_raise(ERR_LIB_CMS, ERR_R_X509_LIB);
f0e0fd51
RS
275 goto err;
276 }
0f113f3e 277 CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
f69ec4b4 278 if (!X509_STORE_CTX_init(ctx, store, signer, untrusted)) {
9311d0c4 279 ERR_raise(ERR_LIB_CMS, CMS_R_STORE_INIT_ERROR);
0f113f3e
MC
280 goto err;
281 }
f0e0fd51 282 X509_STORE_CTX_set_default(ctx, "smime_sign");
c1669f41 283 if (crls != NULL)
f0e0fd51 284 X509_STORE_CTX_set0_crls(ctx, crls);
0f113f3e 285
f0e0fd51 286 i = X509_verify_cert(ctx);
0f113f3e 287 if (i <= 0) {
f0e0fd51 288 j = X509_STORE_CTX_get_error(ctx);
a150f8e1
RL
289 ERR_raise_data(ERR_LIB_CMS, CMS_R_CERTIFICATE_VERIFY_ERROR,
290 "Verify error: %s", X509_verify_cert_error_string(j));
0f113f3e
MC
291 goto err;
292 }
293 r = 1;
9e3c510b
F
294
295 /* also send back the trust chain when required */
296 if (chain != NULL)
297 *chain = X509_STORE_CTX_get1_chain(ctx);
0f113f3e 298 err:
f0e0fd51 299 X509_STORE_CTX_free(ctx);
0f113f3e
MC
300 return r;
301
302}
8931b30d 303
f69ec4b4 304/* This strongly overlaps with PKCS7_verify() */
8931b30d 305int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
0f113f3e
MC
306 X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags)
307{
308 CMS_SignerInfo *si;
309 STACK_OF(CMS_SignerInfo) *sinfos;
310 STACK_OF(X509) *cms_certs = NULL;
311 STACK_OF(X509_CRL) *crls = NULL;
9e3c510b 312 STACK_OF(X509) **si_chains = NULL;
0f113f3e
MC
313 X509 *signer;
314 int i, scount = 0, ret = 0;
315 BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL;
9e3c510b 316 int cadesVerify = (flags & CMS_CADES) != 0;
53155f1c 317 const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
0f113f3e 318
c1669f41 319 if (dcont == NULL && !check_content(cms))
0f113f3e 320 return 0;
c1669f41 321 if (dcont != NULL && !(flags & CMS_BINARY)) {
0f113f3e 322 const ASN1_OBJECT *coid = CMS_get0_eContentType(cms);
c1669f41 323
0f113f3e
MC
324 if (OBJ_obj2nid(coid) == NID_id_ct_asciiTextWithCRLF)
325 flags |= CMS_ASCIICRLF;
326 }
327
328 /* Attempt to find all signer certificates */
329
330 sinfos = CMS_get0_SignerInfos(cms);
331
332 if (sk_CMS_SignerInfo_num(sinfos) <= 0) {
9311d0c4 333 ERR_raise(ERR_LIB_CMS, CMS_R_NO_SIGNERS);
0f113f3e
MC
334 goto err;
335 }
336
337 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
338 si = sk_CMS_SignerInfo_value(sinfos, i);
339 CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
f69ec4b4 340 if (signer != NULL)
0f113f3e
MC
341 scount++;
342 }
343
344 if (scount != sk_CMS_SignerInfo_num(sinfos))
345 scount += CMS_set1_signers_certs(cms, certs, flags);
346
347 if (scount != sk_CMS_SignerInfo_num(sinfos)) {
9311d0c4 348 ERR_raise(ERR_LIB_CMS, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
0f113f3e
MC
349 goto err;
350 }
351
352 /* Attempt to verify all signers certs */
9e3c510b
F
353 /* at this point scount == sk_CMS_SignerInfo_num(sinfos) */
354
355 if ((flags & CMS_NO_SIGNER_CERT_VERIFY) == 0 || cadesVerify) {
356 if (cadesVerify) {
357 /* Certificate trust chain is required to check CAdES signature */
358 si_chains = OPENSSL_zalloc(scount * sizeof(si_chains[0]));
e077455e 359 if (si_chains == NULL)
9e3c510b 360 goto err;
9e3c510b 361 }
0f113f3e
MC
362 cms_certs = CMS_get1_certs(cms);
363 if (!(flags & CMS_NOCRL))
364 crls = CMS_get1_crls(cms);
9e3c510b 365 for (i = 0; i < scount; i++) {
0f113f3e 366 si = sk_CMS_SignerInfo_value(sinfos, i);
9e3c510b
F
367
368 if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls,
c1669f41
SL
369 si_chains ? &si_chains[i] : NULL,
370 ctx))
0f113f3e
MC
371 goto err;
372 }
373 }
374
375 /* Attempt to verify all SignerInfo signed attribute signatures */
376
9e3c510b
F
377 if ((flags & CMS_NO_ATTR_VERIFY) == 0 || cadesVerify) {
378 for (i = 0; i < scount; i++) {
0f113f3e
MC
379 si = sk_CMS_SignerInfo_value(sinfos, i);
380 if (CMS_signed_get_attr_count(si) < 0)
381 continue;
382 if (CMS_SignerInfo_verify(si) <= 0)
383 goto err;
9e3c510b
F
384 if (cadesVerify) {
385 STACK_OF(X509) *si_chain = si_chains ? si_chains[i] : NULL;
386
63b64f19 387 if (ossl_cms_check_signing_certs(si, si_chain) <= 0)
9e3c510b
F
388 goto err;
389 }
0f113f3e
MC
390 }
391 }
392
393 /*
394 * Performance optimization: if the content is a memory BIO then store
395 * its contents in a temporary read only memory BIO. This avoids
396 * potentially large numbers of slow copies of data which will occur when
397 * reading from a read write memory BIO when signatures are calculated.
398 */
399
c1669f41 400 if (dcont != NULL && (BIO_method_type(dcont) == BIO_TYPE_MEM)) {
0f113f3e
MC
401 char *ptr;
402 long len;
c1669f41 403
0f113f3e 404 len = BIO_get_mem_data(dcont, &ptr);
13c5ec56 405 tmpin = (len == 0) ? dcont : BIO_new_mem_buf(ptr, len);
0f113f3e 406 if (tmpin == NULL) {
e077455e 407 ERR_raise(ERR_LIB_CMS, ERR_R_BIO_LIB);
7fba8407 408 goto err2;
0f113f3e 409 }
c1669f41 410 } else {
0f113f3e 411 tmpin = dcont;
c1669f41 412 }
0f113f3e
MC
413 /*
414 * If not binary mode and detached generate digests by *writing* through
415 * the BIO. That makes it possible to canonicalise the input.
416 */
417 if (!(flags & SMIME_BINARY) && dcont) {
418 /*
419 * Create output BIO so we can either handle text or to ensure
420 * included content doesn't override detached content.
421 */
422 tmpout = cms_get_text_bio(out, flags);
c1669f41 423 if (tmpout == NULL) {
e077455e 424 ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB);
0f113f3e
MC
425 goto err;
426 }
427 cmsbio = CMS_dataInit(cms, tmpout);
c1669f41 428 if (cmsbio == NULL)
0f113f3e
MC
429 goto err;
430 /*
431 * Don't use SMIME_TEXT for verify: it adds headers and we want to
432 * remove them.
433 */
67c0460b
ABL
434 if (!SMIME_crlf_copy(dcont, cmsbio, flags & ~SMIME_TEXT))
435 goto err;
0f113f3e
MC
436
437 if (flags & CMS_TEXT) {
438 if (!SMIME_text(tmpout, out)) {
9311d0c4 439 ERR_raise(ERR_LIB_CMS, CMS_R_SMIME_TEXT_ERROR);
0f113f3e
MC
440 goto err;
441 }
442 }
443 } else {
444 cmsbio = CMS_dataInit(cms, tmpin);
c1669f41 445 if (cmsbio == NULL)
0f113f3e
MC
446 goto err;
447
448 if (!cms_copy_content(out, cmsbio, flags))
449 goto err;
450
451 }
452 if (!(flags & CMS_NO_CONTENT_VERIFY)) {
453 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
454 si = sk_CMS_SignerInfo_value(sinfos, i);
455 if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0) {
9311d0c4 456 ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_VERIFY_ERROR);
0f113f3e
MC
457 goto err;
458 }
459 }
460 }
461
462 ret = 1;
0f113f3e
MC
463 err:
464 if (!(flags & SMIME_BINARY) && dcont) {
465 do_free_upto(cmsbio, tmpout);
466 if (tmpin != dcont)
467 BIO_free(tmpin);
468 } else {
0f113f3e
MC
469 if (dcont && (tmpin == dcont))
470 do_free_upto(cmsbio, dcont);
471 else
472 BIO_free_all(cmsbio);
473 }
474
ca3a82c3 475 if (out != tmpout)
0f113f3e
MC
476 BIO_free_all(tmpout);
477
7fba8407 478 err2:
9e3c510b
F
479 if (si_chains != NULL) {
480 for (i = 0; i < scount; ++i)
79b2a2f2 481 OSSL_STACK_OF_X509_free(si_chains[i]);
9e3c510b
F
482 OPENSSL_free(si_chains);
483 }
79b2a2f2 484 OSSL_STACK_OF_X509_free(cms_certs);
222561fe 485 sk_X509_CRL_pop_free(crls, X509_CRL_free);
0f113f3e
MC
486
487 return ret;
488}
8931b30d 489
eb9d8d8c 490int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
0f113f3e
MC
491 STACK_OF(X509) *certs,
492 X509_STORE *store, unsigned int flags)
493{
494 int r;
c1669f41 495
0f113f3e
MC
496 flags &= ~(CMS_DETACHED | CMS_TEXT);
497 r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
498 if (r <= 0)
499 return r;
53155f1c 500 return ossl_cms_Receipt_verify(rcms, ocms);
0f113f3e
MC
501}
502
d8652be0
MC
503CMS_ContentInfo *CMS_sign_ex(X509 *signcert, EVP_PKEY *pkey,
504 STACK_OF(X509) *certs, BIO *data,
b4250010 505 unsigned int flags, OSSL_LIB_CTX *libctx,
d8652be0 506 const char *propq)
0f113f3e
MC
507{
508 CMS_ContentInfo *cms;
509 int i;
510
d8652be0 511 cms = CMS_ContentInfo_new_ex(libctx, propq);
e077455e
RL
512 if (cms == NULL || !CMS_SignedData_init(cms)) {
513 ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB);
514 goto err;
515 }
0f113f3e
MC
516 if (flags & CMS_ASCIICRLF
517 && !CMS_set1_eContentType(cms,
e077455e
RL
518 OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF))) {
519 ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB);
0f113f3e 520 goto err;
e077455e 521 }
0f113f3e 522
c1669f41 523 if (pkey != NULL && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) {
9311d0c4 524 ERR_raise(ERR_LIB_CMS, CMS_R_ADD_SIGNER_ERROR);
0f113f3e
MC
525 goto err;
526 }
527
528 for (i = 0; i < sk_X509_num(certs); i++) {
529 X509 *x = sk_X509_value(certs, i);
c1669f41 530
e077455e
RL
531 if (!CMS_add1_cert(cms, x)) {
532 ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB);
533 goto err;
534 }
0f113f3e
MC
535 }
536
537 if (!(flags & CMS_DETACHED))
538 CMS_set_detached(cms, 0);
539
540 if ((flags & (CMS_STREAM | CMS_PARTIAL))
541 || CMS_final(cms, data, NULL, flags))
542 return cms;
543 else
544 goto err;
545
0f113f3e 546 err:
25aaa98a 547 CMS_ContentInfo_free(cms);
0f113f3e
MC
548 return NULL;
549}
8931b30d 550
c1669f41
SL
551CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
552 BIO *data, unsigned int flags)
553{
d8652be0 554 return CMS_sign_ex(signcert, pkey, certs, data, flags, NULL, NULL);
c1669f41
SL
555}
556
36309aa2 557CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
0f113f3e
MC
558 X509 *signcert, EVP_PKEY *pkey,
559 STACK_OF(X509) *certs, unsigned int flags)
560{
561 CMS_SignerInfo *rct_si;
562 CMS_ContentInfo *cms = NULL;
563 ASN1_OCTET_STRING **pos, *os;
564 BIO *rct_cont = NULL;
565 int r = 0;
c1669f41 566 const CMS_CTX *ctx = si->cms_ctx;
0f113f3e
MC
567
568 flags &= ~(CMS_STREAM | CMS_TEXT);
569 /* Not really detached but avoids content being allocated */
570 flags |= CMS_PARTIAL | CMS_BINARY | CMS_DETACHED;
12a765a5 571 if (pkey == NULL || signcert == NULL) {
9311d0c4 572 ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY_OR_CERT);
0f113f3e
MC
573 return NULL;
574 }
575
576 /* Initialize signed data */
577
53155f1c
SL
578 cms = CMS_sign_ex(NULL, NULL, certs, NULL, flags,
579 ossl_cms_ctx_get0_libctx(ctx),
580 ossl_cms_ctx_get0_propq(ctx));
c1669f41 581 if (cms == NULL)
0f113f3e
MC
582 goto err;
583
584 /* Set inner content type to signed receipt */
585 if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
586 goto err;
587
588 rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
589 if (!rct_si) {
9311d0c4 590 ERR_raise(ERR_LIB_CMS, CMS_R_ADD_SIGNER_ERROR);
0f113f3e
MC
591 goto err;
592 }
593
53155f1c 594 os = ossl_cms_encode_Receipt(si);
c1669f41 595 if (os == NULL)
0f113f3e
MC
596 goto err;
597
598 /* Set content to digest */
599 rct_cont = BIO_new_mem_buf(os->data, os->length);
c1669f41 600 if (rct_cont == NULL)
0f113f3e
MC
601 goto err;
602
603 /* Add msgSigDigest attribute */
604
53155f1c 605 if (!ossl_cms_msgSigDigest_add1(rct_si, si))
0f113f3e
MC
606 goto err;
607
608 /* Finalize structure */
609 if (!CMS_final(cms, rct_cont, NULL, flags))
610 goto err;
611
612 /* Set embedded content */
613 pos = CMS_get0_content(cms);
ed5b26ce
P
614 if (pos == NULL)
615 goto err;
0f113f3e
MC
616 *pos = os;
617
618 r = 1;
619
620 err:
ca3a82c3 621 BIO_free(rct_cont);
0f113f3e
MC
622 if (r)
623 return cms;
624 CMS_ContentInfo_free(cms);
625 return NULL;
626
627}
36309aa2 628
d8652be0
MC
629CMS_ContentInfo *CMS_encrypt_ex(STACK_OF(X509) *certs, BIO *data,
630 const EVP_CIPHER *cipher, unsigned int flags,
b4250010 631 OSSL_LIB_CTX *libctx, const char *propq)
0f113f3e
MC
632{
633 CMS_ContentInfo *cms;
634 int i;
635 X509 *recip;
c1669f41 636
924663c3 637
ed576acd 638 cms = (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)
d8652be0
MC
639 ? CMS_AuthEnvelopedData_create_ex(cipher, libctx, propq)
640 : CMS_EnvelopedData_create_ex(cipher, libctx, propq);
e077455e
RL
641 if (cms == NULL) {
642 ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB);
643 goto err;
644 }
0f113f3e
MC
645 for (i = 0; i < sk_X509_num(certs); i++) {
646 recip = sk_X509_value(certs, i);
647 if (!CMS_add1_recipient_cert(cms, recip, flags)) {
9311d0c4 648 ERR_raise(ERR_LIB_CMS, CMS_R_RECIPIENT_ERROR);
0f113f3e
MC
649 goto err;
650 }
651 }
652
653 if (!(flags & CMS_DETACHED))
654 CMS_set_detached(cms, 0);
655
656 if ((flags & (CMS_STREAM | CMS_PARTIAL))
657 || CMS_final(cms, data, NULL, flags))
658 return cms;
659 else
e077455e 660 ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB);
0f113f3e 661
0f113f3e 662 err:
25aaa98a 663 CMS_ContentInfo_free(cms);
0f113f3e
MC
664 return NULL;
665}
eeb9cdfc 666
c1669f41
SL
667CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
668 const EVP_CIPHER *cipher, unsigned int flags)
669{
d8652be0 670 return CMS_encrypt_ex(certs, data, cipher, flags, NULL, NULL);
c1669f41
SL
671}
672
673static int cms_kari_set1_pkey_and_peer(CMS_ContentInfo *cms,
674 CMS_RecipientInfo *ri,
71434aed 675 EVP_PKEY *pk, X509 *cert, X509 *peer)
0f113f3e
MC
676{
677 int i;
678 STACK_OF(CMS_RecipientEncryptedKey) *reks;
679 CMS_RecipientEncryptedKey *rek;
71434aed 680
0f113f3e 681 reks = CMS_RecipientInfo_kari_get0_reks(ri);
0f113f3e
MC
682 for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
683 int rv;
c1669f41 684
0f113f3e 685 rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
3f1d1704 686 if (cert != NULL && CMS_RecipientEncryptedKey_cert_cmp(rek, cert))
0f113f3e 687 continue;
71434aed 688 CMS_RecipientInfo_kari_set0_pkey_and_peer(ri, pk, peer);
0f113f3e
MC
689 rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek);
690 CMS_RecipientInfo_kari_set0_pkey(ri, NULL);
691 if (rv > 0)
692 return 1;
3f1d1704 693 return cert == NULL ? 0 : -1;
0f113f3e
MC
694 }
695 return 0;
696}
17c2764d 697
eeb9cdfc 698int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
71434aed
DB
699{
700 return CMS_decrypt_set1_pkey_and_peer(cms, pk, cert, NULL);
701}
702
c1669f41
SL
703int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk,
704 X509 *cert, X509 *peer)
0f113f3e 705{
911045af 706 STACK_OF(CMS_RecipientInfo) *ris = CMS_get0_RecipientInfos(cms);
0f113f3e 707 CMS_RecipientInfo *ri;
71434aed 708 int i, r, cms_pkey_ri_type;
0f113f3e 709 int debug = 0, match_ri = 0;
25dd7804
DDO
710 CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cms);
711
712 /* Prevent mem leak on earlier CMS_decrypt_set1_{pkey_and_peer,password} */
713 OPENSSL_clear_free(ec->key, ec->keylen);
714 ec->key = NULL;
715 ec->keylen = 0;
c1669f41 716
c1669f41 717 if (ris != NULL)
25dd7804 718 debug = ec->debug;
71434aed 719
53155f1c 720 cms_pkey_ri_type = ossl_cms_pkey_get_ri_type(pk);
71434aed 721 if (cms_pkey_ri_type == CMS_RECIPINFO_NONE) {
9311d0c4 722 ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
71434aed 723 return 0;
0f113f3e
MC
724 }
725
726 for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
71434aed
DB
727 int ri_type;
728
0f113f3e 729 ri = sk_CMS_RecipientInfo_value(ris, i);
71434aed 730 ri_type = CMS_RecipientInfo_type(ri);
53155f1c 731 if (!ossl_cms_pkey_is_ri_type_supported(pk, ri_type))
0f113f3e
MC
732 continue;
733 match_ri = 1;
734 if (ri_type == CMS_RECIPINFO_AGREE) {
71434aed 735 r = cms_kari_set1_pkey_and_peer(cms, ri, pk, cert, peer);
0f113f3e
MC
736 if (r > 0)
737 return 1;
738 if (r < 0)
739 return 0;
740 }
60ea150b
DDO
741 /* If we have a cert, try matching RecipientInfo, else try them all */
742 else if (cert == NULL || !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
3d551b20 743 EVP_PKEY_up_ref(pk);
0f113f3e
MC
744 CMS_RecipientInfo_set0_pkey(ri, pk);
745 r = CMS_RecipientInfo_decrypt(cms, ri);
746 CMS_RecipientInfo_set0_pkey(ri, NULL);
c1669f41 747 if (cert != NULL) {
0f113f3e
MC
748 /*
749 * If not debugging clear any error and return success to
750 * avoid leaking of information useful to MMA
751 */
752 if (!debug) {
753 ERR_clear_error();
754 return 1;
755 }
756 if (r > 0)
757 return 1;
9311d0c4 758 ERR_raise(ERR_LIB_CMS, CMS_R_DECRYPT_ERROR);
0f113f3e
MC
759 return 0;
760 }
761 /*
762 * If no cert and not debugging don't leave loop after first
763 * successful decrypt. Always attempt to decrypt all recipients
764 * to avoid leaking timing of a successful decrypt.
765 */
71434aed 766 else if (r > 0 && (debug || cms_pkey_ri_type != CMS_RECIPINFO_TRANS))
0f113f3e
MC
767 return 1;
768 }
769 }
3f1d1704 770 /* If no cert, key transport and not debugging always return success */
c1669f41
SL
771 if (cert == NULL
772 && cms_pkey_ri_type == CMS_RECIPINFO_TRANS
773 && match_ri
774 && !debug) {
0f113f3e
MC
775 ERR_clear_error();
776 return 1;
777 }
778
60ea150b
DDO
779 if (!match_ri)
780 ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
0f113f3e
MC
781 return 0;
782
783}
784
785int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
786 unsigned char *key, size_t keylen,
c17dd597 787 const unsigned char *id, size_t idlen)
0f113f3e
MC
788{
789 STACK_OF(CMS_RecipientInfo) *ris;
790 CMS_RecipientInfo *ri;
60ea150b 791 int i, r, match_ri = 0;
c1669f41 792
0f113f3e
MC
793 ris = CMS_get0_RecipientInfos(cms);
794 for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
795 ri = sk_CMS_RecipientInfo_value(ris, i);
796 if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
797 continue;
798
60ea150b
DDO
799 /* If we have an id, try matching RecipientInfo, else try them all */
800 if (id == NULL
801 || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
802 match_ri = 1;
0f113f3e
MC
803 CMS_RecipientInfo_set0_key(ri, key, keylen);
804 r = CMS_RecipientInfo_decrypt(cms, ri);
805 CMS_RecipientInfo_set0_key(ri, NULL, 0);
806 if (r > 0)
807 return 1;
c1669f41 808 if (id != NULL) {
9311d0c4 809 ERR_raise(ERR_LIB_CMS, CMS_R_DECRYPT_ERROR);
0f113f3e
MC
810 return 0;
811 }
812 ERR_clear_error();
813 }
814 }
815
60ea150b
DDO
816 if (!match_ri)
817 ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
0f113f3e
MC
818 return 0;
819
820}
821
822int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
823 unsigned char *pass, ossl_ssize_t passlen)
824{
911045af 825 STACK_OF(CMS_RecipientInfo) *ris = CMS_get0_RecipientInfos(cms);
0f113f3e 826 CMS_RecipientInfo *ri;
60ea150b 827 int i, r, match_ri = 0;
911045af
DDO
828 CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cms);
829
830 /* Prevent mem leak on earlier CMS_decrypt_set1_{pkey_and_peer,password} */
831 OPENSSL_clear_free(ec->key, ec->keylen);
832 ec->key = NULL;
833 ec->keylen = 0;
c1669f41 834
0f113f3e
MC
835 for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
836 ri = sk_CMS_RecipientInfo_value(ris, i);
837 if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS)
838 continue;
60ea150b
DDO
839
840 /* Must try each PasswordRecipientInfo */
841 match_ri = 1;
0f113f3e
MC
842 CMS_RecipientInfo_set0_password(ri, pass, passlen);
843 r = CMS_RecipientInfo_decrypt(cms, ri);
844 CMS_RecipientInfo_set0_password(ri, NULL, 0);
845 if (r > 0)
846 return 1;
847 }
848
60ea150b
DDO
849 if (!match_ri)
850 ERR_raise(ERR_LIB_CMS, CMS_R_NO_MATCHING_RECIPIENT);
0f113f3e
MC
851 return 0;
852
853}
854
4f1aa191 855int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
0f113f3e
MC
856 BIO *dcont, BIO *out, unsigned int flags)
857{
858 int r;
859 BIO *cont;
25dd7804 860 CMS_EncryptedContentInfo *ec;
924663c3
JZ
861 int nid = OBJ_obj2nid(CMS_get0_type(cms));
862
863 if (nid != NID_pkcs7_enveloped
864 && nid != NID_id_smime_ct_authEnvelopedData) {
9311d0c4 865 ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_ENVELOPED_DATA);
0f113f3e
MC
866 return 0;
867 }
c1669f41 868 if (dcont == NULL && !check_content(cms))
0f113f3e 869 return 0;
25dd7804
DDO
870 ec = ossl_cms_get0_env_enc_content(cms);
871 ec->debug = (flags & CMS_DEBUG_DECRYPT) != 0;
872 ec->havenocert = cert == NULL;
12a765a5 873 if (pk == NULL && cert == NULL && dcont == NULL && out == NULL)
0f113f3e 874 return 1;
12a765a5 875 if (pk != NULL && !CMS_decrypt_set1_pkey(cms, pk, cert))
0f113f3e
MC
876 return 0;
877 cont = CMS_dataInit(cms, dcont);
12a765a5 878 if (cont == NULL)
0f113f3e
MC
879 return 0;
880 r = cms_copy_content(out, cont, flags);
881 do_free_upto(cont, dcont);
882 return r;
883}
8931b30d 884
e0fbd073 885int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
0f113f3e
MC
886{
887 BIO *cmsbio;
888 int ret = 0;
75ebbd9a
RS
889
890 if ((cmsbio = CMS_dataInit(cms, dcont)) == NULL) {
9311d0c4 891 ERR_raise(ERR_LIB_CMS, CMS_R_CMS_LIB);
0f113f3e
MC
892 return 0;
893 }
8931b30d 894
67c0460b
ABL
895 if (!SMIME_crlf_copy(data, cmsbio, flags)) {
896 goto err;
897 }
8931b30d 898
0f113f3e 899 (void)BIO_flush(cmsbio);
8931b30d 900
0f113f3e 901 if (!CMS_dataFinal(cms, cmsbio)) {
9311d0c4 902 ERR_raise(ERR_LIB_CMS, CMS_R_CMS_DATAFINAL_ERROR);
0f113f3e
MC
903 goto err;
904 }
b0375613
ABL
905
906 ret = 1;
907
c1669f41 908err:
0f113f3e 909 do_free_upto(cmsbio, dcont);
8931b30d 910
0f113f3e 911 return ret;
8931b30d 912
0f113f3e 913}
8931b30d 914
07342bad
VS
915int CMS_final_digest(CMS_ContentInfo *cms,
916 const unsigned char *md, unsigned int mdlen,
917 BIO *dcont, unsigned int flags)
918{
919 BIO *cmsbio;
920 int ret = 0;
921
922 if ((cmsbio = CMS_dataInit(cms, dcont)) == NULL) {
923 ERR_raise(ERR_LIB_CMS, CMS_R_CMS_LIB);
924 return 0;
925 }
926
927 (void)BIO_flush(cmsbio);
928
929 if (!ossl_cms_DataFinal(cms, cmsbio, md, mdlen)) {
930 ERR_raise(ERR_LIB_CMS, CMS_R_CMS_DATAFINAL_ERROR);
931 goto err;
932 }
933 ret = 1;
934
935err:
936 do_free_upto(cmsbio, dcont);
937 return ret;
938}
939
59d21298 940#ifndef OPENSSL_NO_ZLIB
8931b30d 941
a5db50d0 942int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
0f113f3e
MC
943 unsigned int flags)
944{
945 BIO *cont;
946 int r;
c1669f41 947
0f113f3e 948 if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData) {
9311d0c4 949 ERR_raise(ERR_LIB_CMS, CMS_R_TYPE_NOT_COMPRESSED_DATA);
0f113f3e
MC
950 return 0;
951 }
952
c1669f41 953 if (dcont == NULL && !check_content(cms))
0f113f3e
MC
954 return 0;
955
956 cont = CMS_dataInit(cms, dcont);
c1669f41 957 if (cont == NULL)
0f113f3e
MC
958 return 0;
959 r = cms_copy_content(out, cont, flags);
960 do_free_upto(cont, dcont);
961 return r;
962}
8931b30d
DSH
963
964CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
0f113f3e
MC
965{
966 CMS_ContentInfo *cms;
c1669f41 967
0f113f3e
MC
968 if (comp_nid <= 0)
969 comp_nid = NID_zlib_compression;
53155f1c 970 cms = ossl_cms_CompressedData_create(comp_nid, NULL, NULL);
c1669f41 971 if (cms == NULL)
0f113f3e 972 return NULL;
8931b30d 973
0f113f3e
MC
974 if (!(flags & CMS_DETACHED))
975 CMS_set_detached(cms, 0);
8931b30d 976
0f113f3e
MC
977 if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
978 return cms;
8931b30d 979
0f113f3e
MC
980 CMS_ContentInfo_free(cms);
981 return NULL;
982}
8931b30d
DSH
983
984#else
985
986int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
0f113f3e
MC
987 unsigned int flags)
988{
9311d0c4 989 ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
0f113f3e
MC
990 return 0;
991}
8931b30d
DSH
992
993CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
0f113f3e 994{
9311d0c4 995 ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
0f113f3e
MC
996 return NULL;
997}
8931b30d
DSH
998
999#endif