]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/cms/cms_lib.c
Run util/openssl-format-source -v -c .
[thirdparty/openssl.git] / crypto / cms / cms_lib.c
CommitLineData
94b2c29f 1/* crypto/cms/cms_lib.c */
40720ce3
MC
2/*
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
94b2c29f
DSH
4 * project.
5 */
6/* ====================================================================
7 * Copyright (c) 2008 The OpenSSL Project. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
40720ce3 14 * notice, this list of conditions and the following disclaimer.
94b2c29f
DSH
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 * software must display the following acknowledgment:
23 * "This product includes software developed by the OpenSSL Project
24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 * endorse or promote products derived from this software without
28 * prior written permission. For written permission, please contact
29 * licensing@OpenSSL.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 * nor may "OpenSSL" appear in their names without prior written
33 * permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 * acknowledgment:
37 * "This product includes software developed by the OpenSSL Project
38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 */
54
55#include <openssl/asn1t.h>
56#include <openssl/x509.h>
57#include <openssl/err.h>
58#include <openssl/pem.h>
59#include <openssl/bio.h>
60#include <openssl/asn1.h>
61#include "cms.h"
62#include "cms_lcl.h"
63
64IMPLEMENT_ASN1_FUNCTIONS_const(CMS_ContentInfo)
65
66DECLARE_ASN1_ITEM(CMS_CertificateChoices)
67DECLARE_ASN1_ITEM(CMS_RevocationInfoChoice)
68DECLARE_STACK_OF(CMS_CertificateChoices)
69DECLARE_STACK_OF(CMS_RevocationInfoChoice)
70
71const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms)
40720ce3
MC
72{
73 return cms->contentType;
74}
94b2c29f
DSH
75
76CMS_ContentInfo *cms_Data_create(void)
40720ce3
MC
77{
78 CMS_ContentInfo *cms;
79 cms = CMS_ContentInfo_new();
80 if (cms) {
81 cms->contentType = OBJ_nid2obj(NID_pkcs7_data);
82 /* Never detached */
83 CMS_set_detached(cms, 0);
84 }
85 return cms;
86}
94b2c29f
DSH
87
88BIO *cms_content_bio(CMS_ContentInfo *cms)
40720ce3
MC
89{
90 ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
91 if (!pos)
92 return NULL;
93 /* If content detached data goes nowhere: create NULL BIO */
94 if (!*pos)
95 return BIO_new(BIO_s_null());
96 /*
97 * If content not detached and created return memory BIO
98 */
99 if (!*pos || ((*pos)->flags == ASN1_STRING_FLAG_CONT))
100 return BIO_new(BIO_s_mem());
101 /* Else content was read in: return read only BIO for it */
102 return BIO_new_mem_buf((*pos)->data, (*pos)->length);
103}
94b2c29f
DSH
104
105BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
40720ce3
MC
106{
107 BIO *cmsbio, *cont;
108 if (icont)
109 cont = icont;
110 else
111 cont = cms_content_bio(cms);
112 if (!cont) {
113 CMSerr(CMS_F_CMS_DATAINIT, CMS_R_NO_CONTENT);
114 return NULL;
115 }
116 switch (OBJ_obj2nid(cms->contentType)) {
117
118 case NID_pkcs7_data:
119 return cont;
120
121 case NID_pkcs7_signed:
122 cmsbio = cms_SignedData_init_bio(cms);
123 break;
124
125 case NID_pkcs7_digest:
126 cmsbio = cms_DigestedData_init_bio(cms);
127 break;
94b2c29f 128#ifdef ZLIB
40720ce3
MC
129 case NID_id_smime_ct_compressedData:
130 cmsbio = cms_CompressedData_init_bio(cms);
131 break;
94b2c29f
DSH
132#endif
133
40720ce3
MC
134 case NID_pkcs7_encrypted:
135 cmsbio = cms_EncryptedData_init_bio(cms);
136 break;
94b2c29f 137
40720ce3
MC
138 case NID_pkcs7_enveloped:
139 cmsbio = cms_EnvelopedData_init_bio(cms);
140 break;
94b2c29f 141
40720ce3
MC
142 default:
143 CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE);
144 return NULL;
145 }
94b2c29f 146
40720ce3
MC
147 if (cmsbio)
148 return BIO_push(cmsbio, cont);
94b2c29f 149
40720ce3
MC
150 if (!icont)
151 BIO_free(cont);
152 return NULL;
94b2c29f 153
40720ce3 154}
94b2c29f
DSH
155
156int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
40720ce3
MC
157{
158 ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
159 if (!pos)
160 return 0;
161 /* If ebmedded content find memory BIO and set content */
162 if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) {
163 BIO *mbio;
164 unsigned char *cont;
165 long contlen;
166 mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM);
167 if (!mbio) {
168 CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_CONTENT_NOT_FOUND);
169 return 0;
170 }
171 contlen = BIO_get_mem_data(mbio, &cont);
172 /* Set bio as read only so its content can't be clobbered */
173 BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY);
174 BIO_set_mem_eof_return(mbio, 0);
175 ASN1_STRING_set0(*pos, cont, contlen);
176 (*pos)->flags &= ~ASN1_STRING_FLAG_CONT;
177 }
178
179 switch (OBJ_obj2nid(cms->contentType)) {
180
181 case NID_pkcs7_data:
182 case NID_pkcs7_enveloped:
183 case NID_pkcs7_encrypted:
184 case NID_id_smime_ct_compressedData:
185 /* Nothing to do */
186 return 1;
187
188 case NID_pkcs7_signed:
189 return cms_SignedData_final(cms, cmsbio);
190
191 case NID_pkcs7_digest:
192 return cms_DigestedData_do_final(cms, cmsbio, 0);
193
194 default:
195 CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_UNSUPPORTED_TYPE);
196 return 0;
197 }
198}
199
200/*
201 * Return an OCTET STRING pointer to content. This allows it to be accessed
202 * or set later.
94b2c29f
DSH
203 */
204
205ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms)
40720ce3
MC
206{
207 switch (OBJ_obj2nid(cms->contentType)) {
94b2c29f 208
40720ce3
MC
209 case NID_pkcs7_data:
210 return &cms->d.data;
94b2c29f 211
40720ce3
MC
212 case NID_pkcs7_signed:
213 return &cms->d.signedData->encapContentInfo->eContent;
94b2c29f 214
40720ce3
MC
215 case NID_pkcs7_enveloped:
216 return &cms->d.envelopedData->encryptedContentInfo->encryptedContent;
94b2c29f 217
40720ce3
MC
218 case NID_pkcs7_digest:
219 return &cms->d.digestedData->encapContentInfo->eContent;
94b2c29f 220
40720ce3
MC
221 case NID_pkcs7_encrypted:
222 return &cms->d.encryptedData->encryptedContentInfo->encryptedContent;
94b2c29f 223
40720ce3
MC
224 case NID_id_smime_ct_authData:
225 return &cms->d.authenticatedData->encapContentInfo->eContent;
94b2c29f 226
40720ce3
MC
227 case NID_id_smime_ct_compressedData:
228 return &cms->d.compressedData->encapContentInfo->eContent;
94b2c29f 229
40720ce3
MC
230 default:
231 if (cms->d.other->type == V_ASN1_OCTET_STRING)
232 return &cms->d.other->value.octet_string;
233 CMSerr(CMS_F_CMS_GET0_CONTENT, CMS_R_UNSUPPORTED_CONTENT_TYPE);
234 return NULL;
94b2c29f 235
40720ce3
MC
236 }
237}
94b2c29f 238
40720ce3
MC
239/*
240 * Return an ASN1_OBJECT pointer to content type. This allows it to be
241 * accessed or set later.
94b2c29f
DSH
242 */
243
244static ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms)
40720ce3
MC
245{
246 switch (OBJ_obj2nid(cms->contentType)) {
94b2c29f 247
40720ce3
MC
248 case NID_pkcs7_signed:
249 return &cms->d.signedData->encapContentInfo->eContentType;
94b2c29f 250
40720ce3
MC
251 case NID_pkcs7_enveloped:
252 return &cms->d.envelopedData->encryptedContentInfo->contentType;
94b2c29f 253
40720ce3
MC
254 case NID_pkcs7_digest:
255 return &cms->d.digestedData->encapContentInfo->eContentType;
94b2c29f 256
40720ce3
MC
257 case NID_pkcs7_encrypted:
258 return &cms->d.encryptedData->encryptedContentInfo->contentType;
94b2c29f 259
40720ce3
MC
260 case NID_id_smime_ct_authData:
261 return &cms->d.authenticatedData->encapContentInfo->eContentType;
94b2c29f 262
40720ce3
MC
263 case NID_id_smime_ct_compressedData:
264 return &cms->d.compressedData->encapContentInfo->eContentType;
94b2c29f 265
40720ce3
MC
266 default:
267 CMSerr(CMS_F_CMS_GET0_ECONTENT_TYPE, CMS_R_UNSUPPORTED_CONTENT_TYPE);
268 return NULL;
94b2c29f 269
40720ce3
MC
270 }
271}
94b2c29f
DSH
272
273const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms)
40720ce3
MC
274{
275 ASN1_OBJECT **petype;
276 petype = cms_get0_econtent_type(cms);
277 if (petype)
278 return *petype;
279 return NULL;
280}
94b2c29f
DSH
281
282int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid)
40720ce3
MC
283{
284 ASN1_OBJECT **petype, *etype;
285 petype = cms_get0_econtent_type(cms);
286 if (!petype)
287 return 0;
288 if (!oid)
289 return 1;
290 etype = OBJ_dup(oid);
291 if (!etype)
292 return 0;
293 ASN1_OBJECT_free(*petype);
294 *petype = etype;
295 return 1;
296}
94b2c29f
DSH
297
298int CMS_is_detached(CMS_ContentInfo *cms)
40720ce3
MC
299{
300 ASN1_OCTET_STRING **pos;
301 pos = CMS_get0_content(cms);
302 if (!pos)
303 return -1;
304 if (*pos)
305 return 0;
306 return 1;
307}
94b2c29f
DSH
308
309int CMS_set_detached(CMS_ContentInfo *cms, int detached)
40720ce3
MC
310{
311 ASN1_OCTET_STRING **pos;
312 pos = CMS_get0_content(cms);
313 if (!pos)
314 return 0;
315 if (detached) {
316 if (*pos) {
317 ASN1_OCTET_STRING_free(*pos);
318 *pos = NULL;
319 }
320 return 1;
321 }
322 if (!*pos)
323 *pos = ASN1_OCTET_STRING_new();
324 if (*pos) {
325 /*
326 * NB: special flag to show content is created and not read in.
327 */
328 (*pos)->flags |= ASN1_STRING_FLAG_CONT;
329 return 1;
330 }
331 CMSerr(CMS_F_CMS_SET_DETACHED, ERR_R_MALLOC_FAILURE);
332 return 0;
333}
94b2c29f
DSH
334
335/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */
336
337void cms_DigestAlgorithm_set(X509_ALGOR *alg, const EVP_MD *md)
40720ce3
MC
338{
339 int param_type;
340
341 switch (EVP_MD_type(md)) {
342 case NID_sha1:
343 case NID_sha224:
344 case NID_sha256:
345 case NID_sha384:
346 case NID_sha512:
347 param_type = V_ASN1_UNDEF;
348 break;
349
350 default:
351 param_type = V_ASN1_NULL;
352 break;
353 }
354
355 X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
356
357}
94b2c29f
DSH
358
359/* Create a digest BIO from an X509_ALGOR structure */
360
361BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm)
40720ce3
MC
362{
363 BIO *mdbio = NULL;
364 ASN1_OBJECT *digestoid;
365 const EVP_MD *digest;
366 X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
367 digest = EVP_get_digestbyobj(digestoid);
368 if (!digest) {
369 CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO,
370 CMS_R_UNKNOWN_DIGEST_ALGORIHM);
371 goto err;
372 }
373 mdbio = BIO_new(BIO_f_md());
374 if (!mdbio || !BIO_set_md(mdbio, digest)) {
375 CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, CMS_R_MD_BIO_INIT_ERROR);
376 goto err;
377 }
378 return mdbio;
379 err:
380 if (mdbio)
381 BIO_free(mdbio);
382 return NULL;
383}
94b2c29f
DSH
384
385/* Locate a message digest content from a BIO chain based on SignerInfo */
386
387int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
40720ce3
MC
388 X509_ALGOR *mdalg)
389{
390 int nid;
391 ASN1_OBJECT *mdoid;
392 X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg);
393 nid = OBJ_obj2nid(mdoid);
394 /* Look for digest type to match signature */
395 for (;;) {
396 EVP_MD_CTX *mtmp;
397 chain = BIO_find_type(chain, BIO_TYPE_MD);
398 if (chain == NULL) {
399 CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX,
400 CMS_R_NO_MATCHING_DIGEST);
401 return 0;
402 }
403 BIO_get_md_ctx(chain, &mtmp);
404 if (EVP_MD_CTX_type(mtmp) == nid
405 /*
406 * Workaround for broken implementations that use signature
407 * algorithm OID instead of digest.
408 */
409 || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid) {
410 EVP_MD_CTX_copy_ex(mctx, mtmp);
411 return 1;
412 }
413 chain = BIO_next(chain);
414 }
415}
416
417static STACK_OF(CMS_CertificateChoices)
418**cms_get0_certificate_choices(CMS_ContentInfo *cms)
419{
420 switch (OBJ_obj2nid(cms->contentType)) {
421
422 case NID_pkcs7_signed:
423 return &cms->d.signedData->certificates;
424
425 case NID_pkcs7_enveloped:
426 return &cms->d.envelopedData->originatorInfo->certificates;
427
428 default:
429 CMSerr(CMS_F_CMS_GET0_CERTIFICATE_CHOICES,
430 CMS_R_UNSUPPORTED_CONTENT_TYPE);
431 return NULL;
432
433 }
434}
94b2c29f
DSH
435
436CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms)
40720ce3
MC
437{
438 STACK_OF(CMS_CertificateChoices) **pcerts;
439 CMS_CertificateChoices *cch;
440 pcerts = cms_get0_certificate_choices(cms);
441 if (!pcerts)
442 return NULL;
443 if (!*pcerts)
444 *pcerts = sk_CMS_CertificateChoices_new_null();
445 if (!*pcerts)
446 return NULL;
447 cch = M_ASN1_new_of(CMS_CertificateChoices);
448 if (!cch)
449 return NULL;
450 if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) {
451 M_ASN1_free_of(cch, CMS_CertificateChoices);
452 return NULL;
453 }
454 return cch;
455}
94b2c29f
DSH
456
457int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert)
40720ce3
MC
458{
459 CMS_CertificateChoices *cch;
460 STACK_OF(CMS_CertificateChoices) **pcerts;
461 int i;
462 pcerts = cms_get0_certificate_choices(cms);
463 if (!pcerts)
464 return 0;
465 for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
466 cch = sk_CMS_CertificateChoices_value(*pcerts, i);
467 if (cch->type == CMS_CERTCHOICE_CERT) {
468 if (!X509_cmp(cch->d.certificate, cert)) {
469 CMSerr(CMS_F_CMS_ADD0_CERT,
470 CMS_R_CERTIFICATE_ALREADY_PRESENT);
471 return 0;
472 }
473 }
474 }
475 cch = CMS_add0_CertificateChoices(cms);
476 if (!cch)
477 return 0;
478 cch->type = CMS_CERTCHOICE_CERT;
479 cch->d.certificate = cert;
480 return 1;
481}
94b2c29f
DSH
482
483int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert)
40720ce3
MC
484{
485 int r;
486 r = CMS_add0_cert(cms, cert);
487 if (r > 0)
488 CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509);
489 return r;
490}
94b2c29f 491
40720ce3
MC
492static STACK_OF(CMS_RevocationInfoChoice)
493**cms_get0_revocation_choices(CMS_ContentInfo *cms)
494{
495 switch (OBJ_obj2nid(cms->contentType)) {
94b2c29f 496
40720ce3
MC
497 case NID_pkcs7_signed:
498 return &cms->d.signedData->crls;
94b2c29f 499
40720ce3
MC
500 case NID_pkcs7_enveloped:
501 return &cms->d.envelopedData->originatorInfo->crls;
94b2c29f 502
40720ce3
MC
503 default:
504 CMSerr(CMS_F_CMS_GET0_REVOCATION_CHOICES,
505 CMS_R_UNSUPPORTED_CONTENT_TYPE);
506 return NULL;
94b2c29f 507
40720ce3
MC
508 }
509}
94b2c29f
DSH
510
511CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms)
40720ce3
MC
512{
513 STACK_OF(CMS_RevocationInfoChoice) **pcrls;
514 CMS_RevocationInfoChoice *rch;
515 pcrls = cms_get0_revocation_choices(cms);
516 if (!pcrls)
517 return NULL;
518 if (!*pcrls)
519 *pcrls = sk_CMS_RevocationInfoChoice_new_null();
520 if (!*pcrls)
521 return NULL;
522 rch = M_ASN1_new_of(CMS_RevocationInfoChoice);
523 if (!rch)
524 return NULL;
525 if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) {
526 M_ASN1_free_of(rch, CMS_RevocationInfoChoice);
527 return NULL;
528 }
529 return rch;
530}
94b2c29f
DSH
531
532int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl)
40720ce3
MC
533{
534 CMS_RevocationInfoChoice *rch;
535 rch = CMS_add0_RevocationInfoChoice(cms);
536 if (!rch)
537 return 0;
538 rch->type = CMS_REVCHOICE_CRL;
539 rch->d.crl = crl;
540 return 1;
541}
94b2c29f
DSH
542
543STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms)
40720ce3
MC
544{
545 STACK_OF(X509) *certs = NULL;
546 CMS_CertificateChoices *cch;
547 STACK_OF(CMS_CertificateChoices) **pcerts;
548 int i;
549 pcerts = cms_get0_certificate_choices(cms);
550 if (!pcerts)
551 return NULL;
552 for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
553 cch = sk_CMS_CertificateChoices_value(*pcerts, i);
554 if (cch->type == 0) {
555 if (!certs) {
556 certs = sk_X509_new_null();
557 if (!certs)
558 return NULL;
559 }
560 if (!sk_X509_push(certs, cch->d.certificate)) {
561 sk_X509_pop_free(certs, X509_free);
562 return NULL;
563 }
564 CRYPTO_add(&cch->d.certificate->references, 1, CRYPTO_LOCK_X509);
565 }
566 }
567 return certs;
568
569}
94b2c29f
DSH
570
571STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms)
40720ce3
MC
572{
573 STACK_OF(X509_CRL) *crls = NULL;
574 STACK_OF(CMS_RevocationInfoChoice) **pcrls;
575 CMS_RevocationInfoChoice *rch;
576 int i;
577 pcrls = cms_get0_revocation_choices(cms);
578 if (!pcrls)
579 return NULL;
580 for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) {
581 rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i);
582 if (rch->type == 0) {
583 if (!crls) {
584 crls = sk_X509_CRL_new_null();
585 if (!crls)
586 return NULL;
587 }
588 if (!sk_X509_CRL_push(crls, rch->d.crl)) {
589 sk_X509_CRL_pop_free(crls, X509_CRL_free);
590 return NULL;
591 }
592 CRYPTO_add(&rch->d.crl->references, 1, CRYPTO_LOCK_X509_CRL);
593 }
594 }
595 return crls;
596}