Branch data Line data Source code
1 : : /* crypto/cms/cms_smime.c */
2 : : /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 : : * project.
4 : : */
5 : : /* ====================================================================
6 : : * Copyright (c) 2008 The OpenSSL Project. All rights reserved.
7 : : *
8 : : * Redistribution and use in source and binary forms, with or without
9 : : * modification, are permitted provided that the following conditions
10 : : * are met:
11 : : *
12 : : * 1. Redistributions of source code must retain the above copyright
13 : : * notice, this list of conditions and the following disclaimer.
14 : : *
15 : : * 2. Redistributions in binary form must reproduce the above copyright
16 : : * notice, this list of conditions and the following disclaimer in
17 : : * the documentation and/or other materials provided with the
18 : : * distribution.
19 : : *
20 : : * 3. All advertising materials mentioning features or use of this
21 : : * software must display the following acknowledgment:
22 : : * "This product includes software developed by the OpenSSL Project
23 : : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 : : *
25 : : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 : : * endorse or promote products derived from this software without
27 : : * prior written permission. For written permission, please contact
28 : : * licensing@OpenSSL.org.
29 : : *
30 : : * 5. Products derived from this software may not be called "OpenSSL"
31 : : * nor may "OpenSSL" appear in their names without prior written
32 : : * permission of the OpenSSL Project.
33 : : *
34 : : * 6. Redistributions of any form whatsoever must retain the following
35 : : * acknowledgment:
36 : : * "This product includes software developed by the OpenSSL Project
37 : : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 : : *
39 : : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 : : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 : : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 : : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 : : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 : : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 : : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 : : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 : : * OF THE POSSIBILITY OF SUCH DAMAGE.
51 : : * ====================================================================
52 : : */
53 : :
54 : : #include "cryptlib.h"
55 : : #include <openssl/asn1t.h>
56 : : #include <openssl/x509.h>
57 : : #include <openssl/x509v3.h>
58 : : #include <openssl/err.h>
59 : : #include <openssl/cms.h>
60 : : #include "cms_lcl.h"
61 : : #include "asn1_locl.h"
62 : :
63 : 51 : static BIO *cms_get_text_bio(BIO *out, unsigned int flags)
64 : : {
65 : : BIO *rbio;
66 [ + + ]: 51 : if (out == NULL)
67 : 1 : rbio = BIO_new(BIO_s_null());
68 [ - + ]: 50 : else if (flags & CMS_TEXT)
69 : : {
70 : 0 : rbio = BIO_new(BIO_s_mem());
71 : 0 : BIO_set_mem_eof_return(rbio, 0);
72 : : }
73 : : else
74 : : rbio = out;
75 : 51 : return rbio;
76 : : }
77 : :
78 : 43 : static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
79 : : {
80 : : unsigned char buf[4096];
81 : 43 : int r = 0, i;
82 : : BIO *tmpout;
83 : :
84 : 43 : tmpout = cms_get_text_bio(out, flags);
85 : :
86 [ - + ]: 43 : if(!tmpout)
87 : : {
88 : 0 : CMSerr(CMS_F_CMS_COPY_CONTENT,ERR_R_MALLOC_FAILURE);
89 : 86 : goto err;
90 : : }
91 : :
92 : : /* Read all content through chain to process digest, decrypt etc */
93 : : for (;;)
94 : : {
95 : 86 : i=BIO_read(in,buf,sizeof(buf));
96 [ + + ]: 86 : if (i <= 0)
97 : : {
98 [ + + ]: 43 : if (BIO_method_type(in) == BIO_TYPE_CIPHER)
99 : : {
100 [ + - ]: 21 : if (!BIO_get_cipher_status(in))
101 : : goto err;
102 : : }
103 [ + - ]: 43 : if (i < 0)
104 : : goto err;
105 : : break;
106 : : }
107 : :
108 [ - + ][ + - ]: 43 : if (tmpout && (BIO_write(tmpout, buf, i) != i))
109 : : goto err;
110 : : }
111 : :
112 [ - + ]: 43 : if(flags & CMS_TEXT)
113 : : {
114 [ # # ]: 0 : if(!SMIME_text(tmpout, out))
115 : : {
116 : 0 : CMSerr(CMS_F_CMS_COPY_CONTENT,CMS_R_SMIME_TEXT_ERROR);
117 : 0 : goto err;
118 : : }
119 : : }
120 : :
121 : : r = 1;
122 : :
123 : : err:
124 [ + + ]: 43 : if (tmpout && (tmpout != out))
125 : 1 : BIO_free(tmpout);
126 : 43 : return r;
127 : :
128 : : }
129 : :
130 : 42 : static int check_content(CMS_ContentInfo *cms)
131 : : {
132 : 42 : ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
133 [ + - ][ - + ]: 42 : if (!pos || !*pos)
134 : : {
135 : 0 : CMSerr(CMS_F_CHECK_CONTENT, CMS_R_NO_CONTENT);
136 : 0 : return 0;
137 : : }
138 : : return 1;
139 : : }
140 : :
141 : 42 : static void do_free_upto(BIO *f, BIO *upto)
142 : : {
143 [ + + ]: 42 : if (upto)
144 : : {
145 : : BIO *tbio;
146 : : do
147 : : {
148 : 8 : tbio = BIO_pop(f);
149 : 8 : BIO_free(f);
150 : 8 : f = tbio;
151 : : }
152 [ - + ]: 8 : while (f && f != upto);
153 : : }
154 : : else
155 : 34 : BIO_free_all(f);
156 : 42 : }
157 : :
158 : 1 : int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags)
159 : : {
160 : : BIO *cont;
161 : : int r;
162 [ - + ]: 1 : if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data)
163 : : {
164 : 0 : CMSerr(CMS_F_CMS_DATA, CMS_R_TYPE_NOT_DATA);
165 : 0 : return 0;
166 : : }
167 : 1 : cont = CMS_dataInit(cms, NULL);
168 [ + - ]: 1 : if (!cont)
169 : : return 0;
170 : 1 : r = cms_copy_content(out, cont, flags);
171 : 1 : BIO_free_all(cont);
172 : 1 : return r;
173 : : }
174 : :
175 : 1 : CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags)
176 : : {
177 : : CMS_ContentInfo *cms;
178 : 1 : cms = cms_Data_create();
179 [ + - ]: 1 : if (!cms)
180 : : return NULL;
181 : :
182 [ - + ][ # # ]: 1 : if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
183 : 1 : return cms;
184 : :
185 : 0 : CMS_ContentInfo_free(cms);
186 : :
187 : 0 : return NULL;
188 : : }
189 : :
190 : 0 : int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
191 : : unsigned int flags)
192 : : {
193 : : BIO *cont;
194 : : int r;
195 [ # # ]: 0 : if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest)
196 : : {
197 : 0 : CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_TYPE_NOT_DIGESTED_DATA);
198 : 0 : return 0;
199 : : }
200 : :
201 [ # # ][ # # ]: 0 : if (!dcont && !check_content(cms))
202 : : return 0;
203 : :
204 : 0 : cont = CMS_dataInit(cms, dcont);
205 [ # # ]: 0 : if (!cont)
206 : : return 0;
207 : 0 : r = cms_copy_content(out, cont, flags);
208 [ # # ]: 0 : if (r)
209 : 0 : r = cms_DigestedData_do_final(cms, cont, 1);
210 : 0 : do_free_upto(cont, dcont);
211 : 0 : return r;
212 : : }
213 : :
214 : 0 : CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
215 : : unsigned int flags)
216 : : {
217 : : CMS_ContentInfo *cms;
218 [ # # ]: 0 : if (!md)
219 : 0 : md = EVP_sha1();
220 : 0 : cms = cms_DigestedData_create(md);
221 [ # # ]: 0 : if (!cms)
222 : : return NULL;
223 : :
224 [ # # ]: 0 : if(!(flags & CMS_DETACHED))
225 : 0 : CMS_set_detached(cms, 0);
226 : :
227 [ # # ][ # # ]: 0 : if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
228 : 0 : return cms;
229 : :
230 : 0 : CMS_ContentInfo_free(cms);
231 : 0 : return NULL;
232 : : }
233 : :
234 : 4 : int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
235 : : const unsigned char *key, size_t keylen,
236 : : BIO *dcont, BIO *out, unsigned int flags)
237 : : {
238 : : BIO *cont;
239 : : int r;
240 [ - + ]: 4 : if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted)
241 : : {
242 : 0 : CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT,
243 : : CMS_R_TYPE_NOT_ENCRYPTED_DATA);
244 : 0 : return 0;
245 : : }
246 : :
247 [ + - ][ + - ]: 4 : if (!dcont && !check_content(cms))
248 : : return 0;
249 : :
250 [ + - ]: 4 : if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
251 : : return 0;
252 : 4 : cont = CMS_dataInit(cms, dcont);
253 [ + - ]: 4 : if (!cont)
254 : : return 0;
255 : 4 : r = cms_copy_content(out, cont, flags);
256 : 4 : do_free_upto(cont, dcont);
257 : 4 : return r;
258 : : }
259 : :
260 : 4 : CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
261 : : const unsigned char *key, size_t keylen,
262 : : unsigned int flags)
263 : : {
264 : : CMS_ContentInfo *cms;
265 [ - + ]: 4 : if (!cipher)
266 : : {
267 : 0 : CMSerr(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, CMS_R_NO_CIPHER);
268 : 0 : return NULL;
269 : : }
270 : 4 : cms = CMS_ContentInfo_new();
271 [ + - ]: 4 : if (!cms)
272 : : return NULL;
273 [ + - ]: 4 : if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
274 : : return NULL;
275 : :
276 [ + - ]: 4 : if(!(flags & CMS_DETACHED))
277 : 4 : CMS_set_detached(cms, 0);
278 : :
279 [ - + ]: 4 : if ((flags & (CMS_STREAM|CMS_PARTIAL))
280 [ # # ]: 0 : || CMS_final(cms, in, NULL, flags))
281 : 4 : return cms;
282 : :
283 : 0 : CMS_ContentInfo_free(cms);
284 : 0 : return NULL;
285 : : }
286 : :
287 : 122 : static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
288 : : X509_STORE *store,
289 : : STACK_OF(X509) *certs,
290 : : STACK_OF(X509_CRL) *crls,
291 : : unsigned int flags)
292 : : {
293 : : X509_STORE_CTX ctx;
294 : : X509 *signer;
295 : 61 : int i, j, r = 0;
296 : 61 : CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
297 [ - + ]: 61 : if (!X509_STORE_CTX_init(&ctx, store, signer, certs))
298 : : {
299 : 0 : CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT,
300 : : CMS_R_STORE_INIT_ERROR);
301 : : goto err;
302 : : }
303 : 61 : X509_STORE_CTX_set_default(&ctx, "smime_sign");
304 [ - + ]: 61 : if (crls)
305 : 0 : X509_STORE_CTX_set0_crls(&ctx, crls);
306 : :
307 : 61 : i = X509_verify_cert(&ctx);
308 [ - + ]: 61 : if (i <= 0)
309 : : {
310 : 0 : j = X509_STORE_CTX_get_error(&ctx);
311 : 0 : CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT,
312 : : CMS_R_CERTIFICATE_VERIFY_ERROR);
313 : 0 : ERR_add_error_data(2, "Verify error:",
314 : : X509_verify_cert_error_string(j));
315 : : goto err;
316 : : }
317 : : r = 1;
318 : : err:
319 : 61 : X509_STORE_CTX_cleanup(&ctx);
320 : 61 : return r;
321 : :
322 : : }
323 : :
324 : 29 : int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
325 : : X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags)
326 : : {
327 : : CMS_SignerInfo *si;
328 : : STACK_OF(CMS_SignerInfo) *sinfos;
329 : 29 : STACK_OF(X509) *cms_certs = NULL;
330 : 29 : STACK_OF(X509_CRL) *crls = NULL;
331 : : X509 *signer;
332 : 29 : int i, scount = 0, ret = 0;
333 : 29 : BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL;
334 : :
335 [ + + ][ + - ]: 29 : if (!dcont && !check_content(cms))
336 : : return 0;
337 [ + + ][ + - ]: 29 : if (dcont && !(flags & CMS_BINARY))
338 : : {
339 : 8 : const ASN1_OBJECT *coid = CMS_get0_eContentType(cms);
340 [ - + ]: 8 : if (OBJ_obj2nid(coid) == NID_id_ct_asciiTextWithCRLF)
341 : 0 : flags |= CMS_ASCIICRLF;
342 : : }
343 : :
344 : : /* Attempt to find all signer certificates */
345 : :
346 : 29 : sinfos = CMS_get0_SignerInfos(cms);
347 : :
348 [ + - ]: 29 : if (sk_CMS_SignerInfo_num(sinfos) <= 0)
349 : : {
350 : 0 : CMSerr(CMS_F_CMS_VERIFY, CMS_R_NO_SIGNERS);
351 : 0 : goto err;
352 : : }
353 : :
354 [ + + ]: 90 : for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
355 : : {
356 : 61 : si = sk_CMS_SignerInfo_value(sinfos, i);
357 : 61 : CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
358 [ - + ]: 61 : if (signer)
359 : 0 : scount++;
360 : : }
361 : :
362 [ + - ]: 29 : if (scount != sk_CMS_SignerInfo_num(sinfos))
363 : 29 : scount += CMS_set1_signers_certs(cms, certs, flags);
364 : :
365 [ - + ]: 29 : if (scount != sk_CMS_SignerInfo_num(sinfos))
366 : : {
367 : 0 : CMSerr(CMS_F_CMS_VERIFY, CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
368 : 0 : goto err;
369 : : }
370 : :
371 : : /* Attempt to verify all signers certs */
372 : :
373 [ + - ]: 29 : if (!(flags & CMS_NO_SIGNER_CERT_VERIFY))
374 : : {
375 : 29 : cms_certs = CMS_get1_certs(cms);
376 [ + - ]: 29 : if (!(flags & CMS_NOCRL))
377 : 29 : crls = CMS_get1_crls(cms);
378 [ + + ]: 90 : for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
379 : : {
380 : 61 : si = sk_CMS_SignerInfo_value(sinfos, i);
381 [ + - ]: 61 : if (!cms_signerinfo_verify_cert(si, store,
382 : : cms_certs, crls, flags))
383 : : goto err;
384 : : }
385 : : }
386 : :
387 : : /* Attempt to verify all SignerInfo signed attribute signatures */
388 : :
389 [ + - ]: 29 : if (!(flags & CMS_NO_ATTR_VERIFY))
390 : : {
391 [ + + ]: 90 : for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
392 : : {
393 : 61 : si = sk_CMS_SignerInfo_value(sinfos, i);
394 [ + + ]: 61 : if (CMS_signed_get_attr_count(si) < 0)
395 : 9 : continue;
396 [ + - ]: 52 : if (CMS_SignerInfo_verify(si) <= 0)
397 : : goto err;
398 : : }
399 : : }
400 : :
401 : : /* Performance optimization: if the content is a memory BIO then
402 : : * store its contents in a temporary read only memory BIO. This
403 : : * avoids potentially large numbers of slow copies of data which will
404 : : * occur when reading from a read write memory BIO when signatures
405 : : * are calculated.
406 : : */
407 : :
408 [ + + ][ + + ]: 29 : if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM))
409 : 2 : {
410 : : char *ptr;
411 : : long len;
412 : 2 : len = BIO_get_mem_data(dcont, &ptr);
413 : 2 : tmpin = BIO_new_mem_buf(ptr, len);
414 [ - + ]: 2 : if (tmpin == NULL)
415 : : {
416 : 0 : CMSerr(CMS_F_CMS_VERIFY,ERR_R_MALLOC_FAILURE);
417 : 0 : return 0;
418 : : }
419 : : }
420 : : else
421 : 27 : tmpin = dcont;
422 : : /* If not binary mode and detached generate digests by *writing*
423 : : * through the BIO. That makes it possible to canonicalise the
424 : : * input.
425 : : */
426 [ + - ][ + + ]: 29 : if (!(flags & SMIME_BINARY) && dcont)
427 : : {
428 : : /* Create output BIO so we can either handle text or to
429 : : * ensure included content doesn't override detached content.
430 : : */
431 : 8 : tmpout = cms_get_text_bio(out, flags);
432 [ - + ]: 8 : if(!tmpout)
433 : : {
434 : 0 : CMSerr(CMS_F_CMS_VERIFY,ERR_R_MALLOC_FAILURE);
435 : 0 : goto err;
436 : : }
437 : 8 : cmsbio = CMS_dataInit(cms, tmpout);
438 [ + - ]: 8 : if (!cmsbio)
439 : : goto err;
440 : : /* Don't use SMIME_TEXT for verify: it adds headers and
441 : : * we want to remove them.
442 : : */
443 : 8 : SMIME_crlf_copy(dcont, cmsbio, flags & ~SMIME_TEXT);
444 : :
445 [ - + ]: 8 : if(flags & CMS_TEXT)
446 : : {
447 [ # # ]: 0 : if (!SMIME_text(tmpout, out))
448 : : {
449 : 0 : CMSerr(CMS_F_CMS_VERIFY,CMS_R_SMIME_TEXT_ERROR);
450 : 0 : goto err;
451 : : }
452 : : }
453 : : }
454 : : else
455 : : {
456 : 21 : cmsbio=CMS_dataInit(cms, tmpin);
457 [ + - ]: 21 : if (!cmsbio)
458 : : goto err;
459 : :
460 [ + - ]: 21 : if (!cms_copy_content(out, cmsbio, flags))
461 : : goto err;
462 : :
463 : : }
464 [ + - ]: 29 : if (!(flags & CMS_NO_CONTENT_VERIFY))
465 : : {
466 [ + + ]: 90 : for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++)
467 : : {
468 : 61 : si = sk_CMS_SignerInfo_value(sinfos, i);
469 [ - + ]: 61 : if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0)
470 : : {
471 : 0 : CMSerr(CMS_F_CMS_VERIFY,
472 : : CMS_R_CONTENT_VERIFY_ERROR);
473 : 0 : goto err;
474 : : }
475 : : }
476 : : }
477 : :
478 : : ret = 1;
479 : :
480 : : err:
481 [ + - ][ + + ]: 29 : if (!(flags & SMIME_BINARY) && dcont)
482 : : {
483 : 8 : do_free_upto(cmsbio, tmpout);
484 [ + + ]: 8 : if (tmpin != dcont)
485 : 2 : BIO_free(tmpin);
486 : : }
487 : : else
488 : : {
489 : :
490 [ - + ]: 21 : if (dcont && (tmpin == dcont))
491 : 0 : do_free_upto(cmsbio, dcont);
492 : : else
493 : 21 : BIO_free_all(cmsbio);
494 : : }
495 : :
496 [ - + ]: 29 : if (tmpout && out != tmpout)
497 : 0 : BIO_free_all(tmpout);
498 : :
499 [ + - ]: 29 : if (cms_certs)
500 : 29 : sk_X509_pop_free(cms_certs, X509_free);
501 [ - + ]: 29 : if (crls)
502 : 0 : sk_X509_CRL_pop_free(crls, X509_CRL_free);
503 : :
504 : 29 : return ret;
505 : : }
506 : :
507 : 1 : int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
508 : : STACK_OF(X509) *certs,
509 : : X509_STORE *store, unsigned int flags)
510 : : {
511 : : int r;
512 : 1 : flags &= ~(CMS_DETACHED|CMS_TEXT);
513 : 1 : r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
514 [ + - ]: 1 : if (r <= 0)
515 : : return r;
516 : 1 : return cms_Receipt_verify(rcms, ocms);
517 : : }
518 : :
519 : 27 : CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
520 : : BIO *data, unsigned int flags)
521 : : {
522 : : CMS_ContentInfo *cms;
523 : : int i;
524 : :
525 : 27 : cms = CMS_ContentInfo_new();
526 [ + - ][ + - ]: 27 : if (!cms || !CMS_SignedData_init(cms))
527 : : goto merr;
528 [ - + ][ # # ]: 27 : if (flags & CMS_ASCIICRLF && !CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF)))
529 : : goto err;
530 : :
531 [ - + ][ # # ]: 27 : if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags))
532 : : {
533 : 0 : CMSerr(CMS_F_CMS_SIGN, CMS_R_ADD_SIGNER_ERROR);
534 : 0 : goto err;
535 : : }
536 : :
537 [ + + ]: 29 : for (i = 0; i < sk_X509_num(certs); i++)
538 : : {
539 : 2 : X509 *x = sk_X509_value(certs, i);
540 [ + - ]: 2 : if (!CMS_add1_cert(cms, x))
541 : : goto merr;
542 : : }
543 : :
544 [ + + ]: 27 : if(!(flags & CMS_DETACHED))
545 : 20 : CMS_set_detached(cms, 0);
546 : :
547 [ - + ]: 27 : if ((flags & (CMS_STREAM|CMS_PARTIAL))
548 [ # # ]: 0 : || CMS_final(cms, data, NULL, flags))
549 : 27 : return cms;
550 : : else
551 : : goto err;
552 : :
553 : : merr:
554 : 0 : CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE);
555 : :
556 : : err:
557 [ # # ]: 0 : if (cms)
558 : 0 : CMS_ContentInfo_free(cms);
559 : : return NULL;
560 : : }
561 : :
562 : 1 : CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
563 : : X509 *signcert, EVP_PKEY *pkey,
564 : : STACK_OF(X509) *certs,
565 : : unsigned int flags)
566 : : {
567 : : CMS_SignerInfo *rct_si;
568 : 1 : CMS_ContentInfo *cms = NULL;
569 : : ASN1_OCTET_STRING **pos, *os;
570 : 1 : BIO *rct_cont = NULL;
571 : 1 : int r = 0;
572 : :
573 : 1 : flags &= ~(CMS_STREAM|CMS_TEXT);
574 : : /* Not really detached but avoids content being allocated */
575 : 1 : flags |= CMS_PARTIAL|CMS_BINARY|CMS_DETACHED;
576 [ - + ]: 1 : if (!pkey || !signcert)
577 : : {
578 : 0 : CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_NO_KEY_OR_CERT);
579 : 0 : return NULL;
580 : : }
581 : :
582 : : /* Initialize signed data */
583 : :
584 : 1 : cms = CMS_sign(NULL, NULL, certs, NULL, flags);
585 [ + - ]: 1 : if (!cms)
586 : : goto err;
587 : :
588 : : /* Set inner content type to signed receipt */
589 [ + - ]: 1 : if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
590 : : goto err;
591 : :
592 : 1 : rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
593 [ - + ]: 1 : if (!rct_si)
594 : : {
595 : 0 : CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_ADD_SIGNER_ERROR);
596 : 0 : goto err;
597 : : }
598 : :
599 : 1 : os = cms_encode_Receipt(si);
600 : :
601 [ + - ]: 1 : if (!os)
602 : : goto err;
603 : :
604 : : /* Set content to digest */
605 : 1 : rct_cont = BIO_new_mem_buf(os->data, os->length);
606 [ + - ]: 1 : if (!rct_cont)
607 : : goto err;
608 : :
609 : : /* Add msgSigDigest attribute */
610 : :
611 [ + - ]: 1 : if (!cms_msgSigDigest_add1(rct_si, si))
612 : : goto err;
613 : :
614 : : /* Finalize structure */
615 [ + - ]: 1 : if (!CMS_final(cms, rct_cont, NULL, flags))
616 : : goto err;
617 : :
618 : : /* Set embedded content */
619 : 1 : pos = CMS_get0_content(cms);
620 : 1 : *pos = os;
621 : :
622 : 1 : r = 1;
623 : :
624 : : err:
625 [ + - ]: 1 : if (rct_cont)
626 : 1 : BIO_free(rct_cont);
627 [ - + ]: 1 : if (r)
628 : : return cms;
629 : 0 : CMS_ContentInfo_free(cms);
630 : 0 : return NULL;
631 : :
632 : : }
633 : :
634 : 17 : CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
635 : : const EVP_CIPHER *cipher, unsigned int flags)
636 : : {
637 : : CMS_ContentInfo *cms;
638 : : int i;
639 : : X509 *recip;
640 : 17 : cms = CMS_EnvelopedData_create(cipher);
641 [ + - ]: 17 : if (!cms)
642 : : goto merr;
643 [ - + ]: 17 : for (i = 0; i < sk_X509_num(certs); i++)
644 : : {
645 : 0 : recip = sk_X509_value(certs, i);
646 [ # # ]: 0 : if (!CMS_add1_recipient_cert(cms, recip, flags))
647 : : {
648 : 0 : CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR);
649 : 0 : goto err;
650 : : }
651 : : }
652 : :
653 [ + - ]: 17 : if(!(flags & CMS_DETACHED))
654 : 17 : CMS_set_detached(cms, 0);
655 : :
656 [ - + ]: 17 : if ((flags & (CMS_STREAM|CMS_PARTIAL))
657 [ # # ]: 0 : || CMS_final(cms, data, NULL, flags))
658 : 17 : return cms;
659 : : else
660 : : goto err;
661 : :
662 : : merr:
663 : 0 : CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE);
664 : : err:
665 [ # # ]: 0 : if (cms)
666 : 0 : CMS_ContentInfo_free(cms);
667 : : return NULL;
668 : : }
669 : :
670 : 4 : static int cms_kari_set1_pkey(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
671 : : EVP_PKEY *pk, X509 *cert)
672 : : {
673 : : int i;
674 : : STACK_OF(CMS_RecipientEncryptedKey) *reks;
675 : : CMS_RecipientEncryptedKey *rek;
676 : 4 : reks = CMS_RecipientInfo_kari_get0_reks(ri);
677 [ + - ]: 4 : if (!cert)
678 : : return 0;
679 [ + - ]: 4 : for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++)
680 : : {
681 : : int rv;
682 : 4 : rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
683 [ - + ]: 4 : if (CMS_RecipientEncryptedKey_cert_cmp(rek, cert))
684 : 0 : continue;
685 : 4 : CMS_RecipientInfo_kari_set0_pkey(ri, pk);
686 : 4 : rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek);
687 : 4 : CMS_RecipientInfo_kari_set0_pkey(ri, NULL);
688 [ - + ]: 4 : if (rv > 0)
689 : : return 1;
690 : 0 : return -1;
691 : : }
692 : : return 0;
693 : : }
694 : :
695 : 15 : int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
696 : : {
697 : : STACK_OF(CMS_RecipientInfo) *ris;
698 : : CMS_RecipientInfo *ri;
699 : : int i, r, ri_type;
700 : 15 : int debug = 0, match_ri = 0;
701 : 15 : ris = CMS_get0_RecipientInfos(cms);
702 [ + - ]: 15 : if (ris)
703 : 15 : debug = cms->d.envelopedData->encryptedContentInfo->debug;
704 : 15 : ri_type = cms_pkey_get_ri_type(pk);
705 [ + - ]: 15 : if (ri_type == CMS_RECIPINFO_NONE)
706 : : {
707 : 0 : CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
708 : : CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
709 : 0 : return 0;
710 : : }
711 : :
712 [ + + ]: 26 : for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
713 : : {
714 : 24 : ri = sk_CMS_RecipientInfo_value(ris, i);
715 [ - + ]: 24 : if (CMS_RecipientInfo_type(ri) != ri_type)
716 : 0 : continue;
717 : 24 : match_ri = 1;
718 [ + + ]: 24 : if (ri_type == CMS_RECIPINFO_AGREE)
719 : : {
720 : 4 : r = cms_kari_set1_pkey(cms, ri, pk, cert);
721 [ - + ]: 4 : if (r > 0)
722 : : return 1;
723 [ # # ]: 0 : if (r < 0)
724 : : return 0;
725 : : }
726 : : /* If we have a cert try matching RecipientInfo
727 : : * otherwise try them all.
728 : : */
729 [ + + ][ + + ]: 20 : else if (!cert || !CMS_RecipientInfo_ktri_cert_cmp(ri, cert))
730 : : {
731 : 15 : CMS_RecipientInfo_set0_pkey(ri, pk);
732 : 15 : r = CMS_RecipientInfo_decrypt(cms, ri);
733 : 15 : CMS_RecipientInfo_set0_pkey(ri, NULL);
734 [ + + ]: 15 : if (cert)
735 : : {
736 : : /* If not debugging clear any error and
737 : : * return success to avoid leaking of
738 : : * information useful to MMA
739 : : */
740 [ + - ]: 9 : if (!debug)
741 : : {
742 : 9 : ERR_clear_error();
743 : 9 : return 1;
744 : : }
745 [ # # ]: 0 : if (r > 0)
746 : : return 1;
747 : 0 : CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
748 : : CMS_R_DECRYPT_ERROR);
749 : 0 : return 0;
750 : : }
751 : : /* If no cert and not debugging don't leave loop
752 : : * after first successful decrypt. Always attempt
753 : : * to decrypt all recipients to avoid leaking timing
754 : : * of a successful decrypt.
755 : : */
756 [ + - ]: 6 : else if (r > 0 && debug)
757 : : return 1;
758 : : }
759 : : }
760 : : /* If no cert and not debugging always return success */
761 [ + - ][ + - ]: 2 : if (match_ri && !cert && !debug)
762 : : {
763 : 2 : ERR_clear_error();
764 : 2 : return 1;
765 : : }
766 : :
767 : 0 : CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT);
768 : 0 : return 0;
769 : :
770 : : }
771 : :
772 : 2 : int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
773 : : unsigned char *key, size_t keylen,
774 : : unsigned char *id, size_t idlen)
775 : : {
776 : : STACK_OF(CMS_RecipientInfo) *ris;
777 : : CMS_RecipientInfo *ri;
778 : : int i, r;
779 : 2 : ris = CMS_get0_RecipientInfos(cms);
780 [ + - ]: 2 : for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
781 : : {
782 : 2 : ri = sk_CMS_RecipientInfo_value(ris, i);
783 [ - + ]: 2 : if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
784 : 0 : continue;
785 : :
786 : : /* If we have an id try matching RecipientInfo
787 : : * otherwise try them all.
788 : : */
789 [ + + ][ + - ]: 2 : if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0))
790 : : {
791 : 2 : CMS_RecipientInfo_set0_key(ri, key, keylen);
792 : 2 : r = CMS_RecipientInfo_decrypt(cms, ri);
793 : 2 : CMS_RecipientInfo_set0_key(ri, NULL, 0);
794 [ - + ]: 2 : if (r > 0)
795 : : return 1;
796 [ # # ]: 0 : if (id)
797 : : {
798 : 0 : CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY,
799 : : CMS_R_DECRYPT_ERROR);
800 : 0 : return 0;
801 : : }
802 : 0 : ERR_clear_error();
803 : : }
804 : : }
805 : :
806 : 0 : CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT);
807 : 0 : return 0;
808 : :
809 : : }
810 : :
811 : 0 : int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
812 : : unsigned char *pass, ossl_ssize_t passlen)
813 : : {
814 : : STACK_OF(CMS_RecipientInfo) *ris;
815 : : CMS_RecipientInfo *ri;
816 : : int i, r;
817 : 0 : ris = CMS_get0_RecipientInfos(cms);
818 [ # # ]: 0 : for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
819 : : {
820 : 0 : ri = sk_CMS_RecipientInfo_value(ris, i);
821 [ # # ]: 0 : if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS)
822 : 0 : continue;
823 : 0 : CMS_RecipientInfo_set0_password(ri, pass, passlen);
824 : 0 : r = CMS_RecipientInfo_decrypt(cms, ri);
825 : 0 : CMS_RecipientInfo_set0_password(ri, NULL, 0);
826 [ # # ]: 0 : if (r > 0)
827 : : return 1;
828 : : }
829 : :
830 : 0 : CMSerr(CMS_F_CMS_DECRYPT_SET1_PASSWORD, CMS_R_NO_MATCHING_RECIPIENT);
831 : 0 : return 0;
832 : :
833 : : }
834 : :
835 : 17 : int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
836 : : BIO *dcont, BIO *out,
837 : : unsigned int flags)
838 : : {
839 : : int r;
840 : : BIO *cont;
841 [ - + ]: 17 : if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped)
842 : : {
843 : 0 : CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA);
844 : 0 : return 0;
845 : : }
846 [ + - ][ + - ]: 17 : if (!dcont && !check_content(cms))
847 : : return 0;
848 [ - + ]: 17 : if (flags & CMS_DEBUG_DECRYPT)
849 : 0 : cms->d.envelopedData->encryptedContentInfo->debug = 1;
850 : : else
851 : 17 : cms->d.envelopedData->encryptedContentInfo->debug = 0;
852 [ + - ][ + - ]: 17 : if (!pk && !cert && !dcont && !out)
853 : : return 1;
854 [ - + ][ # # ]: 17 : if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
855 : : return 0;
856 : 17 : cont = CMS_dataInit(cms, dcont);
857 [ + - ]: 17 : if (!cont)
858 : : return 0;
859 : 17 : r = cms_copy_content(out, cont, flags);
860 : 17 : do_free_upto(cont, dcont);
861 : 17 : return r;
862 : : }
863 : :
864 : 13 : int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
865 : : {
866 : : BIO *cmsbio;
867 : 13 : int ret = 0;
868 [ - + ]: 13 : if (!(cmsbio = CMS_dataInit(cms, dcont)))
869 : : {
870 : 0 : CMSerr(CMS_F_CMS_FINAL,ERR_R_MALLOC_FAILURE);
871 : 0 : return 0;
872 : : }
873 : :
874 : 13 : SMIME_crlf_copy(data, cmsbio, flags);
875 : :
876 : 13 : (void)BIO_flush(cmsbio);
877 : :
878 : :
879 [ - + ]: 13 : if (!CMS_dataFinal(cms, cmsbio))
880 : : {
881 : 0 : CMSerr(CMS_F_CMS_FINAL,CMS_R_CMS_DATAFINAL_ERROR);
882 : 0 : goto err;
883 : : }
884 : :
885 : : ret = 1;
886 : :
887 : : err:
888 : 13 : do_free_upto(cmsbio, dcont);
889 : :
890 : 13 : return ret;
891 : :
892 : : }
893 : :
894 : : #ifdef ZLIB
895 : :
896 : : int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
897 : : unsigned int flags)
898 : : {
899 : : BIO *cont;
900 : : int r;
901 : : if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData)
902 : : {
903 : : CMSerr(CMS_F_CMS_UNCOMPRESS,
904 : : CMS_R_TYPE_NOT_COMPRESSED_DATA);
905 : : return 0;
906 : : }
907 : :
908 : : if (!dcont && !check_content(cms))
909 : : return 0;
910 : :
911 : : cont = CMS_dataInit(cms, dcont);
912 : : if (!cont)
913 : : return 0;
914 : : r = cms_copy_content(out, cont, flags);
915 : : do_free_upto(cont, dcont);
916 : : return r;
917 : : }
918 : :
919 : : CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
920 : : {
921 : : CMS_ContentInfo *cms;
922 : : if (comp_nid <= 0)
923 : : comp_nid = NID_zlib_compression;
924 : : cms = cms_CompressedData_create(comp_nid);
925 : : if (!cms)
926 : : return NULL;
927 : :
928 : : if(!(flags & CMS_DETACHED))
929 : : CMS_set_detached(cms, 0);
930 : :
931 : : if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
932 : : return cms;
933 : :
934 : : CMS_ContentInfo_free(cms);
935 : : return NULL;
936 : : }
937 : :
938 : : #else
939 : :
940 : 0 : int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
941 : : unsigned int flags)
942 : : {
943 : 0 : CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
944 : 0 : return 0;
945 : : }
946 : :
947 : 0 : CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
948 : : {
949 : 0 : CMSerr(CMS_F_CMS_COMPRESS, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
950 : 0 : return NULL;
951 : : }
952 : :
953 : : #endif
|