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