diff options
author | jsing <> | 2019-08-10 15:55:20 +0000 |
---|---|---|
committer | jsing <> | 2019-08-10 15:55:20 +0000 |
commit | a0845ead6d459f388701fe3fe8fa27635f4885f1 (patch) | |
tree | cfa2d4e7280cbfe7b7007556c8dcab6691e87b83 /src/lib/libcrypto/cms/cms_lib.c | |
parent | 38e170324f2dafb68786e79022ddafab241aad3d (diff) | |
download | openbsd-a0845ead6d459f388701fe3fe8fa27635f4885f1.tar.gz openbsd-a0845ead6d459f388701fe3fe8fa27635f4885f1.tar.bz2 openbsd-a0845ead6d459f388701fe3fe8fa27635f4885f1.zip |
Work towards supporting Cryptographic Message Syntax (CMS) in libcrypto.
Cryptographic Message Syntax (CMS) is a standard for cryptographically
protecting messages, as defined in RFC 5652. It is derived from PKCS #7
version 1.5 and utilises various ASN.1 structures, making it complex and
fairly heavyweight. Various protocols - including RPKI (RFC 6480) - have
been built on top of it, which means it is necessary to support CMS, in
order to support RPKI.
This imports around 6,000 lines of code from OpenSSL 1.1.1, which is still
under the original OpenSSL license. Further work will occur in tree.
Requested by and discussed with many.
ok deraadt@ tb@
Diffstat (limited to 'src/lib/libcrypto/cms/cms_lib.c')
-rw-r--r-- | src/lib/libcrypto/cms/cms_lib.c | 587 |
1 files changed, 587 insertions, 0 deletions
diff --git a/src/lib/libcrypto/cms/cms_lib.c b/src/lib/libcrypto/cms/cms_lib.c new file mode 100644 index 0000000000..c2cac26010 --- /dev/null +++ b/src/lib/libcrypto/cms/cms_lib.c | |||
@@ -0,0 +1,587 @@ | |||
1 | /* | ||
2 | * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. | ||
3 | * | ||
4 | * Licensed under the OpenSSL license (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 <openssl/asn1t.h> | ||
11 | #include <openssl/x509v3.h> | ||
12 | #include <openssl/err.h> | ||
13 | #include <openssl/pem.h> | ||
14 | #include <openssl/bio.h> | ||
15 | #include <openssl/asn1.h> | ||
16 | #include <openssl/cms.h> | ||
17 | #include "cms_lcl.h" | ||
18 | |||
19 | IMPLEMENT_ASN1_FUNCTIONS(CMS_ContentInfo) | ||
20 | IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo) | ||
21 | |||
22 | const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms) | ||
23 | { | ||
24 | return cms->contentType; | ||
25 | } | ||
26 | |||
27 | CMS_ContentInfo *cms_Data_create(void) | ||
28 | { | ||
29 | CMS_ContentInfo *cms; | ||
30 | cms = CMS_ContentInfo_new(); | ||
31 | if (cms != NULL) { | ||
32 | cms->contentType = OBJ_nid2obj(NID_pkcs7_data); | ||
33 | /* Never detached */ | ||
34 | CMS_set_detached(cms, 0); | ||
35 | } | ||
36 | return cms; | ||
37 | } | ||
38 | |||
39 | BIO *cms_content_bio(CMS_ContentInfo *cms) | ||
40 | { | ||
41 | ASN1_OCTET_STRING **pos = CMS_get0_content(cms); | ||
42 | if (!pos) | ||
43 | return NULL; | ||
44 | /* If content detached data goes nowhere: create NULL BIO */ | ||
45 | if (!*pos) | ||
46 | return BIO_new(BIO_s_null()); | ||
47 | /* | ||
48 | * If content not detached and created return memory BIO | ||
49 | */ | ||
50 | if (!*pos || ((*pos)->flags == ASN1_STRING_FLAG_CONT)) | ||
51 | return BIO_new(BIO_s_mem()); | ||
52 | /* Else content was read in: return read only BIO for it */ | ||
53 | return BIO_new_mem_buf((*pos)->data, (*pos)->length); | ||
54 | } | ||
55 | |||
56 | BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont) | ||
57 | { | ||
58 | BIO *cmsbio, *cont; | ||
59 | if (icont) | ||
60 | cont = icont; | ||
61 | else | ||
62 | cont = cms_content_bio(cms); | ||
63 | if (!cont) { | ||
64 | CMSerr(CMS_F_CMS_DATAINIT, CMS_R_NO_CONTENT); | ||
65 | return NULL; | ||
66 | } | ||
67 | switch (OBJ_obj2nid(cms->contentType)) { | ||
68 | |||
69 | case NID_pkcs7_data: | ||
70 | return cont; | ||
71 | |||
72 | case NID_pkcs7_signed: | ||
73 | cmsbio = cms_SignedData_init_bio(cms); | ||
74 | break; | ||
75 | |||
76 | case NID_pkcs7_digest: | ||
77 | cmsbio = cms_DigestedData_init_bio(cms); | ||
78 | break; | ||
79 | #ifdef ZLIB | ||
80 | case NID_id_smime_ct_compressedData: | ||
81 | cmsbio = cms_CompressedData_init_bio(cms); | ||
82 | break; | ||
83 | #endif | ||
84 | |||
85 | case NID_pkcs7_encrypted: | ||
86 | cmsbio = cms_EncryptedData_init_bio(cms); | ||
87 | break; | ||
88 | |||
89 | case NID_pkcs7_enveloped: | ||
90 | cmsbio = cms_EnvelopedData_init_bio(cms); | ||
91 | break; | ||
92 | |||
93 | default: | ||
94 | CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE); | ||
95 | return NULL; | ||
96 | } | ||
97 | |||
98 | if (cmsbio) | ||
99 | return BIO_push(cmsbio, cont); | ||
100 | |||
101 | if (!icont) | ||
102 | BIO_free(cont); | ||
103 | return NULL; | ||
104 | |||
105 | } | ||
106 | |||
107 | int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) | ||
108 | { | ||
109 | ASN1_OCTET_STRING **pos = CMS_get0_content(cms); | ||
110 | if (!pos) | ||
111 | return 0; | ||
112 | /* If embedded content find memory BIO and set content */ | ||
113 | if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) { | ||
114 | BIO *mbio; | ||
115 | unsigned char *cont; | ||
116 | long contlen; | ||
117 | mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM); | ||
118 | if (!mbio) { | ||
119 | CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_CONTENT_NOT_FOUND); | ||
120 | return 0; | ||
121 | } | ||
122 | contlen = BIO_get_mem_data(mbio, &cont); | ||
123 | /* Set bio as read only so its content can't be clobbered */ | ||
124 | BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY); | ||
125 | BIO_set_mem_eof_return(mbio, 0); | ||
126 | ASN1_STRING_set0(*pos, cont, contlen); | ||
127 | (*pos)->flags &= ~ASN1_STRING_FLAG_CONT; | ||
128 | } | ||
129 | |||
130 | switch (OBJ_obj2nid(cms->contentType)) { | ||
131 | |||
132 | case NID_pkcs7_data: | ||
133 | case NID_pkcs7_enveloped: | ||
134 | case NID_pkcs7_encrypted: | ||
135 | case NID_id_smime_ct_compressedData: | ||
136 | /* Nothing to do */ | ||
137 | return 1; | ||
138 | |||
139 | case NID_pkcs7_signed: | ||
140 | return cms_SignedData_final(cms, cmsbio); | ||
141 | |||
142 | case NID_pkcs7_digest: | ||
143 | return cms_DigestedData_do_final(cms, cmsbio, 0); | ||
144 | |||
145 | default: | ||
146 | CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_UNSUPPORTED_TYPE); | ||
147 | return 0; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | /* | ||
152 | * Return an OCTET STRING pointer to content. This allows it to be accessed | ||
153 | * or set later. | ||
154 | */ | ||
155 | |||
156 | ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms) | ||
157 | { | ||
158 | switch (OBJ_obj2nid(cms->contentType)) { | ||
159 | |||
160 | case NID_pkcs7_data: | ||
161 | return &cms->d.data; | ||
162 | |||
163 | case NID_pkcs7_signed: | ||
164 | return &cms->d.signedData->encapContentInfo->eContent; | ||
165 | |||
166 | case NID_pkcs7_enveloped: | ||
167 | return &cms->d.envelopedData->encryptedContentInfo->encryptedContent; | ||
168 | |||
169 | case NID_pkcs7_digest: | ||
170 | return &cms->d.digestedData->encapContentInfo->eContent; | ||
171 | |||
172 | case NID_pkcs7_encrypted: | ||
173 | return &cms->d.encryptedData->encryptedContentInfo->encryptedContent; | ||
174 | |||
175 | case NID_id_smime_ct_authData: | ||
176 | return &cms->d.authenticatedData->encapContentInfo->eContent; | ||
177 | |||
178 | case NID_id_smime_ct_compressedData: | ||
179 | return &cms->d.compressedData->encapContentInfo->eContent; | ||
180 | |||
181 | default: | ||
182 | if (cms->d.other->type == V_ASN1_OCTET_STRING) | ||
183 | return &cms->d.other->value.octet_string; | ||
184 | CMSerr(CMS_F_CMS_GET0_CONTENT, CMS_R_UNSUPPORTED_CONTENT_TYPE); | ||
185 | return NULL; | ||
186 | |||
187 | } | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * Return an ASN1_OBJECT pointer to content type. This allows it to be | ||
192 | * accessed or set later. | ||
193 | */ | ||
194 | |||
195 | static ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms) | ||
196 | { | ||
197 | switch (OBJ_obj2nid(cms->contentType)) { | ||
198 | |||
199 | case NID_pkcs7_signed: | ||
200 | return &cms->d.signedData->encapContentInfo->eContentType; | ||
201 | |||
202 | case NID_pkcs7_enveloped: | ||
203 | return &cms->d.envelopedData->encryptedContentInfo->contentType; | ||
204 | |||
205 | case NID_pkcs7_digest: | ||
206 | return &cms->d.digestedData->encapContentInfo->eContentType; | ||
207 | |||
208 | case NID_pkcs7_encrypted: | ||
209 | return &cms->d.encryptedData->encryptedContentInfo->contentType; | ||
210 | |||
211 | case NID_id_smime_ct_authData: | ||
212 | return &cms->d.authenticatedData->encapContentInfo->eContentType; | ||
213 | |||
214 | case NID_id_smime_ct_compressedData: | ||
215 | return &cms->d.compressedData->encapContentInfo->eContentType; | ||
216 | |||
217 | default: | ||
218 | CMSerr(CMS_F_CMS_GET0_ECONTENT_TYPE, CMS_R_UNSUPPORTED_CONTENT_TYPE); | ||
219 | return NULL; | ||
220 | |||
221 | } | ||
222 | } | ||
223 | |||
224 | const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms) | ||
225 | { | ||
226 | ASN1_OBJECT **petype; | ||
227 | petype = cms_get0_econtent_type(cms); | ||
228 | if (petype) | ||
229 | return *petype; | ||
230 | return NULL; | ||
231 | } | ||
232 | |||
233 | int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid) | ||
234 | { | ||
235 | ASN1_OBJECT **petype, *etype; | ||
236 | petype = cms_get0_econtent_type(cms); | ||
237 | if (!petype) | ||
238 | return 0; | ||
239 | if (!oid) | ||
240 | return 1; | ||
241 | etype = OBJ_dup(oid); | ||
242 | if (!etype) | ||
243 | return 0; | ||
244 | ASN1_OBJECT_free(*petype); | ||
245 | *petype = etype; | ||
246 | return 1; | ||
247 | } | ||
248 | |||
249 | int CMS_is_detached(CMS_ContentInfo *cms) | ||
250 | { | ||
251 | ASN1_OCTET_STRING **pos; | ||
252 | pos = CMS_get0_content(cms); | ||
253 | if (!pos) | ||
254 | return -1; | ||
255 | if (*pos) | ||
256 | return 0; | ||
257 | return 1; | ||
258 | } | ||
259 | |||
260 | int CMS_set_detached(CMS_ContentInfo *cms, int detached) | ||
261 | { | ||
262 | ASN1_OCTET_STRING **pos; | ||
263 | pos = CMS_get0_content(cms); | ||
264 | if (!pos) | ||
265 | return 0; | ||
266 | if (detached) { | ||
267 | ASN1_OCTET_STRING_free(*pos); | ||
268 | *pos = NULL; | ||
269 | return 1; | ||
270 | } | ||
271 | if (*pos == NULL) | ||
272 | *pos = ASN1_OCTET_STRING_new(); | ||
273 | if (*pos != NULL) { | ||
274 | /* | ||
275 | * NB: special flag to show content is created and not read in. | ||
276 | */ | ||
277 | (*pos)->flags |= ASN1_STRING_FLAG_CONT; | ||
278 | return 1; | ||
279 | } | ||
280 | CMSerr(CMS_F_CMS_SET_DETACHED, ERR_R_MALLOC_FAILURE); | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | /* Create a digest BIO from an X509_ALGOR structure */ | ||
285 | |||
286 | BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm) | ||
287 | { | ||
288 | BIO *mdbio = NULL; | ||
289 | const ASN1_OBJECT *digestoid; | ||
290 | const EVP_MD *digest; | ||
291 | X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm); | ||
292 | digest = EVP_get_digestbyobj(digestoid); | ||
293 | if (!digest) { | ||
294 | CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, | ||
295 | CMS_R_UNKNOWN_DIGEST_ALGORITHM); | ||
296 | goto err; | ||
297 | } | ||
298 | mdbio = BIO_new(BIO_f_md()); | ||
299 | if (mdbio == NULL || !BIO_set_md(mdbio, digest)) { | ||
300 | CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, CMS_R_MD_BIO_INIT_ERROR); | ||
301 | goto err; | ||
302 | } | ||
303 | return mdbio; | ||
304 | err: | ||
305 | BIO_free(mdbio); | ||
306 | return NULL; | ||
307 | } | ||
308 | |||
309 | /* Locate a message digest content from a BIO chain based on SignerInfo */ | ||
310 | |||
311 | int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, | ||
312 | X509_ALGOR *mdalg) | ||
313 | { | ||
314 | int nid; | ||
315 | const ASN1_OBJECT *mdoid; | ||
316 | X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg); | ||
317 | nid = OBJ_obj2nid(mdoid); | ||
318 | /* Look for digest type to match signature */ | ||
319 | for (;;) { | ||
320 | EVP_MD_CTX *mtmp; | ||
321 | chain = BIO_find_type(chain, BIO_TYPE_MD); | ||
322 | if (chain == NULL) { | ||
323 | CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX, | ||
324 | CMS_R_NO_MATCHING_DIGEST); | ||
325 | return 0; | ||
326 | } | ||
327 | BIO_get_md_ctx(chain, &mtmp); | ||
328 | if (EVP_MD_CTX_type(mtmp) == nid | ||
329 | /* | ||
330 | * Workaround for broken implementations that use signature | ||
331 | * algorithm OID instead of digest. | ||
332 | */ | ||
333 | || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid) | ||
334 | return EVP_MD_CTX_copy_ex(mctx, mtmp); | ||
335 | chain = BIO_next(chain); | ||
336 | } | ||
337 | } | ||
338 | |||
339 | static STACK_OF(CMS_CertificateChoices) | ||
340 | **cms_get0_certificate_choices(CMS_ContentInfo *cms) | ||
341 | { | ||
342 | switch (OBJ_obj2nid(cms->contentType)) { | ||
343 | |||
344 | case NID_pkcs7_signed: | ||
345 | return &cms->d.signedData->certificates; | ||
346 | |||
347 | case NID_pkcs7_enveloped: | ||
348 | if (cms->d.envelopedData->originatorInfo == NULL) | ||
349 | return NULL; | ||
350 | return &cms->d.envelopedData->originatorInfo->certificates; | ||
351 | |||
352 | default: | ||
353 | CMSerr(CMS_F_CMS_GET0_CERTIFICATE_CHOICES, | ||
354 | CMS_R_UNSUPPORTED_CONTENT_TYPE); | ||
355 | return NULL; | ||
356 | |||
357 | } | ||
358 | } | ||
359 | |||
360 | CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms) | ||
361 | { | ||
362 | STACK_OF(CMS_CertificateChoices) **pcerts; | ||
363 | CMS_CertificateChoices *cch; | ||
364 | pcerts = cms_get0_certificate_choices(cms); | ||
365 | if (!pcerts) | ||
366 | return NULL; | ||
367 | if (!*pcerts) | ||
368 | *pcerts = sk_CMS_CertificateChoices_new_null(); | ||
369 | if (!*pcerts) | ||
370 | return NULL; | ||
371 | cch = M_ASN1_new_of(CMS_CertificateChoices); | ||
372 | if (!cch) | ||
373 | return NULL; | ||
374 | if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) { | ||
375 | M_ASN1_free_of(cch, CMS_CertificateChoices); | ||
376 | return NULL; | ||
377 | } | ||
378 | return cch; | ||
379 | } | ||
380 | |||
381 | int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) | ||
382 | { | ||
383 | CMS_CertificateChoices *cch; | ||
384 | STACK_OF(CMS_CertificateChoices) **pcerts; | ||
385 | int i; | ||
386 | pcerts = cms_get0_certificate_choices(cms); | ||
387 | if (!pcerts) | ||
388 | return 0; | ||
389 | for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { | ||
390 | cch = sk_CMS_CertificateChoices_value(*pcerts, i); | ||
391 | if (cch->type == CMS_CERTCHOICE_CERT) { | ||
392 | if (!X509_cmp(cch->d.certificate, cert)) { | ||
393 | CMSerr(CMS_F_CMS_ADD0_CERT, | ||
394 | CMS_R_CERTIFICATE_ALREADY_PRESENT); | ||
395 | return 0; | ||
396 | } | ||
397 | } | ||
398 | } | ||
399 | cch = CMS_add0_CertificateChoices(cms); | ||
400 | if (!cch) | ||
401 | return 0; | ||
402 | cch->type = CMS_CERTCHOICE_CERT; | ||
403 | cch->d.certificate = cert; | ||
404 | return 1; | ||
405 | } | ||
406 | |||
407 | int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert) | ||
408 | { | ||
409 | int r; | ||
410 | r = CMS_add0_cert(cms, cert); | ||
411 | if (r > 0) | ||
412 | X509_up_ref(cert); | ||
413 | return r; | ||
414 | } | ||
415 | |||
416 | static STACK_OF(CMS_RevocationInfoChoice) | ||
417 | **cms_get0_revocation_choices(CMS_ContentInfo *cms) | ||
418 | { | ||
419 | switch (OBJ_obj2nid(cms->contentType)) { | ||
420 | |||
421 | case NID_pkcs7_signed: | ||
422 | return &cms->d.signedData->crls; | ||
423 | |||
424 | case NID_pkcs7_enveloped: | ||
425 | if (cms->d.envelopedData->originatorInfo == NULL) | ||
426 | return NULL; | ||
427 | return &cms->d.envelopedData->originatorInfo->crls; | ||
428 | |||
429 | default: | ||
430 | CMSerr(CMS_F_CMS_GET0_REVOCATION_CHOICES, | ||
431 | CMS_R_UNSUPPORTED_CONTENT_TYPE); | ||
432 | return NULL; | ||
433 | |||
434 | } | ||
435 | } | ||
436 | |||
437 | CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms) | ||
438 | { | ||
439 | STACK_OF(CMS_RevocationInfoChoice) **pcrls; | ||
440 | CMS_RevocationInfoChoice *rch; | ||
441 | pcrls = cms_get0_revocation_choices(cms); | ||
442 | if (!pcrls) | ||
443 | return NULL; | ||
444 | if (!*pcrls) | ||
445 | *pcrls = sk_CMS_RevocationInfoChoice_new_null(); | ||
446 | if (!*pcrls) | ||
447 | return NULL; | ||
448 | rch = M_ASN1_new_of(CMS_RevocationInfoChoice); | ||
449 | if (!rch) | ||
450 | return NULL; | ||
451 | if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) { | ||
452 | M_ASN1_free_of(rch, CMS_RevocationInfoChoice); | ||
453 | return NULL; | ||
454 | } | ||
455 | return rch; | ||
456 | } | ||
457 | |||
458 | int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl) | ||
459 | { | ||
460 | CMS_RevocationInfoChoice *rch; | ||
461 | rch = CMS_add0_RevocationInfoChoice(cms); | ||
462 | if (!rch) | ||
463 | return 0; | ||
464 | rch->type = CMS_REVCHOICE_CRL; | ||
465 | rch->d.crl = crl; | ||
466 | return 1; | ||
467 | } | ||
468 | |||
469 | int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl) | ||
470 | { | ||
471 | int r; | ||
472 | r = CMS_add0_crl(cms, crl); | ||
473 | if (r > 0) | ||
474 | X509_CRL_up_ref(crl); | ||
475 | return r; | ||
476 | } | ||
477 | |||
478 | STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms) | ||
479 | { | ||
480 | STACK_OF(X509) *certs = NULL; | ||
481 | CMS_CertificateChoices *cch; | ||
482 | STACK_OF(CMS_CertificateChoices) **pcerts; | ||
483 | int i; | ||
484 | pcerts = cms_get0_certificate_choices(cms); | ||
485 | if (!pcerts) | ||
486 | return NULL; | ||
487 | for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { | ||
488 | cch = sk_CMS_CertificateChoices_value(*pcerts, i); | ||
489 | if (cch->type == 0) { | ||
490 | if (!certs) { | ||
491 | certs = sk_X509_new_null(); | ||
492 | if (!certs) | ||
493 | return NULL; | ||
494 | } | ||
495 | if (!sk_X509_push(certs, cch->d.certificate)) { | ||
496 | sk_X509_pop_free(certs, X509_free); | ||
497 | return NULL; | ||
498 | } | ||
499 | X509_up_ref(cch->d.certificate); | ||
500 | } | ||
501 | } | ||
502 | return certs; | ||
503 | |||
504 | } | ||
505 | |||
506 | STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms) | ||
507 | { | ||
508 | STACK_OF(X509_CRL) *crls = NULL; | ||
509 | STACK_OF(CMS_RevocationInfoChoice) **pcrls; | ||
510 | CMS_RevocationInfoChoice *rch; | ||
511 | int i; | ||
512 | pcrls = cms_get0_revocation_choices(cms); | ||
513 | if (!pcrls) | ||
514 | return NULL; | ||
515 | for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) { | ||
516 | rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i); | ||
517 | if (rch->type == 0) { | ||
518 | if (!crls) { | ||
519 | crls = sk_X509_CRL_new_null(); | ||
520 | if (!crls) | ||
521 | return NULL; | ||
522 | } | ||
523 | if (!sk_X509_CRL_push(crls, rch->d.crl)) { | ||
524 | sk_X509_CRL_pop_free(crls, X509_CRL_free); | ||
525 | return NULL; | ||
526 | } | ||
527 | X509_CRL_up_ref(rch->d.crl); | ||
528 | } | ||
529 | } | ||
530 | return crls; | ||
531 | } | ||
532 | |||
533 | int cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert) | ||
534 | { | ||
535 | int ret; | ||
536 | ret = X509_NAME_cmp(ias->issuer, X509_get_issuer_name(cert)); | ||
537 | if (ret) | ||
538 | return ret; | ||
539 | return ASN1_INTEGER_cmp(ias->serialNumber, X509_get_serialNumber(cert)); | ||
540 | } | ||
541 | |||
542 | int cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert) | ||
543 | { | ||
544 | const ASN1_OCTET_STRING *cert_keyid = X509_get0_subject_key_id(cert); | ||
545 | |||
546 | if (cert_keyid == NULL) | ||
547 | return -1; | ||
548 | return ASN1_OCTET_STRING_cmp(keyid, cert_keyid); | ||
549 | } | ||
550 | |||
551 | int cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert) | ||
552 | { | ||
553 | CMS_IssuerAndSerialNumber *ias; | ||
554 | ias = M_ASN1_new_of(CMS_IssuerAndSerialNumber); | ||
555 | if (!ias) | ||
556 | goto err; | ||
557 | if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert))) | ||
558 | goto err; | ||
559 | if (!ASN1_STRING_copy(ias->serialNumber, X509_get_serialNumber(cert))) | ||
560 | goto err; | ||
561 | M_ASN1_free_of(*pias, CMS_IssuerAndSerialNumber); | ||
562 | *pias = ias; | ||
563 | return 1; | ||
564 | err: | ||
565 | M_ASN1_free_of(ias, CMS_IssuerAndSerialNumber); | ||
566 | CMSerr(CMS_F_CMS_SET1_IAS, ERR_R_MALLOC_FAILURE); | ||
567 | return 0; | ||
568 | } | ||
569 | |||
570 | int cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert) | ||
571 | { | ||
572 | ASN1_OCTET_STRING *keyid = NULL; | ||
573 | const ASN1_OCTET_STRING *cert_keyid; | ||
574 | cert_keyid = X509_get0_subject_key_id(cert); | ||
575 | if (cert_keyid == NULL) { | ||
576 | CMSerr(CMS_F_CMS_SET1_KEYID, CMS_R_CERTIFICATE_HAS_NO_KEYID); | ||
577 | return 0; | ||
578 | } | ||
579 | keyid = ASN1_STRING_dup(cert_keyid); | ||
580 | if (!keyid) { | ||
581 | CMSerr(CMS_F_CMS_SET1_KEYID, ERR_R_MALLOC_FAILURE); | ||
582 | return 0; | ||
583 | } | ||
584 | ASN1_OCTET_STRING_free(*pkeyid); | ||
585 | *pkeyid = keyid; | ||
586 | return 1; | ||
587 | } | ||