663397e59637246fe12daf8ac6b222dfa01f66d5
[strongswan.git] / src / libstrongswan / plugins / openssl / openssl_pkcs7.c
1 /*
2 * Copyright (C) 2012 Martin Willi
3 * Copyright (C) 2012 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <openssl/opensslconf.h>
17
18 #ifndef OPENSSL_NO_CMS
19
20 #include "openssl_pkcs7.h"
21 #include "openssl_util.h"
22
23 #include <library.h>
24 #include <utils/debug.h>
25 #include <asn1/oid.h>
26 #include <credentials/sets/mem_cred.h>
27
28 #include <openssl/cms.h>
29
30 typedef struct private_openssl_pkcs7_t private_openssl_pkcs7_t;
31
32 /**
33 * Private data of an openssl_pkcs7_t object.
34 */
35 struct private_openssl_pkcs7_t {
36
37 /**
38 * Public pkcs7_t interface.
39 */
40 pkcs7_t public;
41
42 /**
43 * Type of this container
44 */
45 container_type_t type;
46
47 /**
48 * OpenSSL CMS structure
49 */
50 CMS_ContentInfo *cms;
51 };
52
53 /**
54 * OpenSSL does not allow us to read the signature to verify it with our own
55 * crypto API. We define the internal CMS_SignerInfo structure here to get it.
56 */
57 struct CMS_SignerInfo_st {
58 long version;
59 void *sid;
60 X509_ALGOR *digestAlgorithm;
61 STACK_OF(X509_ATTRIBUTE) *signedAttrs;
62 X509_ALGOR *signatureAlgorithm;
63 ASN1_OCTET_STRING *signature;
64 /* and more... */
65 };
66
67 /**
68 * And we also need access to the wrappend CMS_KeyTransRecipientInfo to
69 * read the encrypted key
70 */
71 struct CMS_KeyTransRecipientInfo_st {
72 long version;
73 void *rid;
74 X509_ALGOR *keyEncryptionAlgorithm;
75 ASN1_OCTET_STRING *encryptedKey;
76 };
77
78 struct CMS_RecipientInfo_st {
79 int type;
80 struct CMS_KeyTransRecipientInfo_st *ktri;
81 /* and more in union... */
82 };
83
84 struct CMS_EncryptedContentInfo_st {
85 ASN1_OBJECT *contentType;
86 X509_ALGOR *contentEncryptionAlgorithm;
87 ASN1_OCTET_STRING *encryptedContent;
88 /* and more... */
89 };
90
91 struct CMS_EnvelopedData_st {
92 long version;
93 void *originatorInfo;
94 STACK_OF(CMS_RecipientInfo) *recipientInfos;
95 struct CMS_EncryptedContentInfo_st *encryptedContentInfo;
96 /* and more... */
97 };
98
99 struct CMS_ContentInfo_st {
100 ASN1_OBJECT *contentType;
101 struct CMS_EnvelopedData_st *envelopedData;
102 /* and more in union... */
103 };
104
105 /**
106 * We can't include asn1.h, declare function prototypes directly
107 */
108 chunk_t asn1_wrap(int, const char *mode, ...);
109 int asn1_unwrap(chunk_t*, chunk_t*);
110
111 /**
112 * Enumerator over certificates
113 */
114 typedef struct {
115 /** implements enumerator_t */
116 enumerator_t public;
117 /** Stack of X509 certificates */
118 STACK_OF(X509) *certs;
119 /** current enumerator position in certificates */
120 int i;
121 /** currently enumerating certificate_t */
122 certificate_t *cert;
123 } cert_enumerator_t;
124
125 METHOD(enumerator_t, cert_destroy, void,
126 cert_enumerator_t *this)
127 {
128 DESTROY_IF(this->cert);
129 free(this);
130 }
131
132 METHOD(enumerator_t, cert_enumerate, bool,
133 cert_enumerator_t *this, certificate_t **out)
134 {
135 if (!this->certs)
136 {
137 return FALSE;
138 }
139 while (this->i < sk_X509_num(this->certs))
140 {
141 chunk_t encoding;
142 X509 *x509;
143
144 /* clean up previous round */
145 DESTROY_IF(this->cert);
146 this->cert = NULL;
147
148 x509 = sk_X509_value(this->certs, this->i++);
149 encoding = openssl_i2chunk(X509, x509);
150 this->cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
151 BUILD_BLOB_ASN1_DER, encoding,
152 BUILD_END);
153 free(encoding.ptr);
154 if (!this->cert)
155 {
156 continue;
157 }
158 *out = this->cert;
159 return TRUE;
160 }
161 return FALSE;
162 }
163
164 METHOD(pkcs7_t, create_cert_enumerator, enumerator_t*,
165 private_openssl_pkcs7_t *this)
166 {
167 cert_enumerator_t *enumerator;
168
169 if (this->type == CONTAINER_PKCS7_SIGNED_DATA)
170 {
171 INIT(enumerator,
172 .public = {
173 .enumerate = (void*)_cert_enumerate,
174 .destroy = _cert_destroy,
175 },
176 .certs = CMS_get1_certs(this->cms),
177 );
178 return &enumerator->public;
179 }
180 return enumerator_create_empty();
181 }
182
183 /**
184 * Enumerator for signatures
185 */
186 typedef struct {
187 /** implements enumerator_t */
188 enumerator_t public;
189 /** Stack of signerinfos */
190 STACK_OF(CMS_SignerInfo) *signers;
191 /** current enumerator position in signers */
192 int i;
193 /** currently enumerating auth config */
194 auth_cfg_t *auth;
195 /** full CMS */
196 CMS_ContentInfo *cms;
197 /** credential set containing wrapped certificates */
198 mem_cred_t *creds;
199 } signature_enumerator_t;
200
201 /**
202 * Verify signerInfo signature
203 */
204 static auth_cfg_t *verify_signature(CMS_SignerInfo *si, int hash_oid)
205 {
206 enumerator_t *enumerator;
207 public_key_t *key;
208 certificate_t *cert;
209 auth_cfg_t *auth, *found = NULL;
210 identification_t *issuer, *serial;
211 chunk_t attrs = chunk_empty, sig, attr;
212 X509_NAME *name;
213 ASN1_INTEGER *snr;
214 int i;
215
216 if (CMS_SignerInfo_get0_signer_id(si, NULL, &name, &snr) != 1)
217 {
218 return NULL;
219 }
220 issuer = openssl_x509_name2id(name);
221 if (!issuer)
222 {
223 return NULL;
224 }
225 serial = identification_create_from_encoding(
226 ID_KEY_ID, openssl_asn1_str2chunk(snr));
227
228 /* reconstruct DER encoded attributes to verify signature */
229 for (i = 0; i < CMS_signed_get_attr_count(si); i++)
230 {
231 attr = openssl_i2chunk(X509_ATTRIBUTE, CMS_signed_get_attr(si, i));
232 attrs = chunk_cat("mm", attrs, attr);
233 }
234 /* wrap in a ASN1_SET */
235 attrs = asn1_wrap(0x31, "m", attrs);
236
237 /* TODO: find a better way to access and verify the signature */
238 sig = openssl_asn1_str2chunk(si->signature);
239 enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr,
240 KEY_RSA, serial, FALSE);
241 while (enumerator->enumerate(enumerator, &cert, &auth))
242 {
243 if (issuer->equals(issuer, cert->get_issuer(cert)))
244 {
245 key = cert->get_public_key(cert);
246 if (key)
247 {
248 if (key->verify(key, signature_scheme_from_oid(hash_oid),
249 attrs, sig))
250 {
251 found = auth->clone(auth);
252 key->destroy(key);
253 break;
254 }
255 key->destroy(key);
256 }
257 }
258 }
259 enumerator->destroy(enumerator);
260 issuer->destroy(issuer);
261 serial->destroy(serial);
262 free(attrs.ptr);
263
264 return found;
265 }
266
267 /**
268 * Verify the message digest in the signerInfo attributes
269 */
270 static bool verify_digest(CMS_ContentInfo *cms, CMS_SignerInfo *si, int hash_oid)
271 {
272 ASN1_OCTET_STRING *os, **osp;
273 hash_algorithm_t hash_alg;
274 chunk_t digest, content, hash;
275 hasher_t *hasher;
276
277 os = CMS_signed_get0_data_by_OBJ(si,
278 OBJ_nid2obj(NID_pkcs9_messageDigest), -3, V_ASN1_OCTET_STRING);
279 if (!os)
280 {
281 return FALSE;
282 }
283 digest = openssl_asn1_str2chunk(os);
284 osp = CMS_get0_content(cms);
285 if (!osp)
286 {
287 return FALSE;
288 }
289 content = openssl_asn1_str2chunk(*osp);
290
291 hash_alg = hasher_algorithm_from_oid(hash_oid);
292 hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
293 if (!hasher)
294 {
295 DBG1(DBG_LIB, "hash algorithm %N not supported",
296 hash_algorithm_names, hash_alg);
297 return FALSE;
298 }
299 if (!hasher->allocate_hash(hasher, content, &hash))
300 {
301 hasher->destroy(hasher);
302 return FALSE;
303 }
304 hasher->destroy(hasher);
305
306 if (!chunk_equals(digest, hash))
307 {
308 free(hash.ptr);
309 DBG1(DBG_LIB, "invalid messageDigest");
310 return FALSE;
311 }
312 free(hash.ptr);
313 return TRUE;
314 }
315
316 METHOD(enumerator_t, signature_enumerate, bool,
317 signature_enumerator_t *this, auth_cfg_t **out)
318 {
319 if (!this->signers)
320 {
321 return FALSE;
322 }
323 while (this->i < sk_CMS_SignerInfo_num(this->signers))
324 {
325 CMS_SignerInfo *si;
326 X509_ALGOR *digest, *sig;
327 int hash_oid;
328
329 /* clean up previous round */
330 DESTROY_IF(this->auth);
331 this->auth = NULL;
332
333 si = sk_CMS_SignerInfo_value(this->signers, this->i++);
334
335 CMS_SignerInfo_get0_algs(si, NULL, NULL, &digest, &sig);
336 hash_oid = openssl_asn1_known_oid(digest->algorithm);
337 if (openssl_asn1_known_oid(sig->algorithm) != OID_RSA_ENCRYPTION)
338 {
339 DBG1(DBG_LIB, "only RSA digest encryption supported");
340 continue;
341 }
342 this->auth = verify_signature(si, hash_oid);
343 if (!this->auth)
344 {
345 DBG1(DBG_LIB, "unable to verify pkcs7 attributes signature");
346 continue;
347 }
348 if (!verify_digest(this->cms, si, hash_oid))
349 {
350 continue;
351 }
352 *out = this->auth;
353 return TRUE;
354 }
355 return FALSE;
356 }
357
358 METHOD(enumerator_t, signature_destroy, void,
359 signature_enumerator_t *this)
360 {
361 lib->credmgr->remove_local_set(lib->credmgr, &this->creds->set);
362 this->creds->destroy(this->creds);
363 DESTROY_IF(this->auth);
364 free(this);
365 }
366
367 METHOD(container_t, create_signature_enumerator, enumerator_t*,
368 private_openssl_pkcs7_t *this)
369 {
370 signature_enumerator_t *enumerator;
371
372 if (this->type == CONTAINER_PKCS7_SIGNED_DATA)
373 {
374 enumerator_t *certs;
375 certificate_t *cert;
376
377 INIT(enumerator,
378 .public = {
379 .enumerate = (void*)_signature_enumerate,
380 .destroy = _signature_destroy,
381 },
382 .cms = this->cms,
383 .signers = CMS_get0_SignerInfos(this->cms),
384 .creds = mem_cred_create(),
385 );
386
387 /* make available wrapped certs during signature checking */
388 certs = create_cert_enumerator(this);
389 while (certs->enumerate(certs, &cert))
390 {
391 enumerator->creds->add_cert(enumerator->creds, FALSE,
392 cert->get_ref(cert));
393 }
394 certs->destroy(certs);
395
396 lib->credmgr->add_local_set(lib->credmgr, &enumerator->creds->set,
397 FALSE);
398
399 return &enumerator->public;
400 }
401 return enumerator_create_empty();
402 }
403
404
405 METHOD(container_t, get_type, container_type_t,
406 private_openssl_pkcs7_t *this)
407 {
408 return this->type;
409 }
410
411 METHOD(pkcs7_t, get_attribute, bool,
412 private_openssl_pkcs7_t *this, int oid,
413 enumerator_t *enumerator, chunk_t *value)
414 {
415 signature_enumerator_t *e;
416 CMS_SignerInfo *si;
417 X509_ATTRIBUTE *attr;
418 ASN1_TYPE *type;
419 chunk_t chunk, wrapped;
420 int i;
421
422 e = (signature_enumerator_t*)enumerator;
423 if (e->i <= 0)
424 {
425 return FALSE;
426 }
427
428 /* "i" gets incremeneted after enumerate(), hence read from previous */
429 si = sk_CMS_SignerInfo_value(e->signers, e->i - 1);
430 for (i = 0; i < CMS_signed_get_attr_count(si); i++)
431 {
432 attr = CMS_signed_get_attr(si, i);
433 if (!attr->single && sk_ASN1_TYPE_num(attr->value.set) == 1 &&
434 openssl_asn1_known_oid(attr->object) == oid)
435 {
436 /* get first value in SET */
437 type = sk_ASN1_TYPE_value(attr->value.set, 0);
438 chunk = wrapped = openssl_i2chunk(ASN1_TYPE, type);
439 if (asn1_unwrap(&chunk, &chunk) != 0x100 /* ASN1_INVALID */)
440 {
441 *value = chunk_clone(chunk);
442 free(wrapped.ptr);
443 return TRUE;
444 }
445 free(wrapped.ptr);
446 }
447 }
448 return FALSE;
449 }
450
451 /**
452 * Find a private key for issuerAndSerialNumber
453 */
454 static private_key_t *find_private(identification_t *issuer,
455 identification_t *serial)
456 {
457 enumerator_t *enumerator;
458 certificate_t *cert;
459 public_key_t *public;
460 private_key_t *private = NULL;
461 identification_t *id;
462 chunk_t fp;
463
464 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
465 CERT_X509, KEY_RSA, serial, FALSE);
466 while (enumerator->enumerate(enumerator, &cert))
467 {
468 if (issuer->equals(issuer, cert->get_issuer(cert)))
469 {
470 public = cert->get_public_key(cert);
471 if (public)
472 {
473 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &fp))
474 {
475 id = identification_create_from_encoding(ID_KEY_ID, fp);
476 private = lib->credmgr->get_private(lib->credmgr,
477 KEY_ANY, id, NULL);
478 id->destroy(id);
479 }
480 public->destroy(public);
481 }
482 }
483 if (private)
484 {
485 break;
486 }
487 }
488 enumerator->destroy(enumerator);
489 return private;
490 }
491
492 /**
493 * Decrypt enveloped-data with a decrypted symmetric key
494 */
495 static bool decrypt_symmetric(private_openssl_pkcs7_t *this, chunk_t key,
496 chunk_t encrypted, chunk_t *plain)
497 {
498 encryption_algorithm_t encr;
499 X509_ALGOR *alg;
500 crypter_t *crypter;
501 chunk_t iv;
502 size_t key_size;
503
504 /* read encryption algorithm from interal structures; TODO fixup */
505 alg = this->cms->envelopedData->encryptedContentInfo->
506 contentEncryptionAlgorithm;
507 encr = encryption_algorithm_from_oid(openssl_asn1_known_oid(alg->algorithm),
508 &key_size);
509 if (alg->parameter->type != V_ASN1_OCTET_STRING)
510 {
511 return FALSE;
512 }
513 iv = openssl_asn1_str2chunk(alg->parameter->value.octet_string);
514
515 crypter = lib->crypto->create_crypter(lib->crypto, encr, key_size / 8);
516 if (!crypter)
517 {
518 DBG1(DBG_LIB, "crypter %N-%d not available",
519 encryption_algorithm_names, alg, key_size);
520 return FALSE;
521 }
522 if (key.len != crypter->get_key_size(crypter))
523 {
524 DBG1(DBG_LIB, "symmetric key length is wrong");
525 crypter->destroy(crypter);
526 return FALSE;
527 }
528 if (iv.len != crypter->get_iv_size(crypter))
529 {
530 DBG1(DBG_LIB, "IV length is wrong");
531 crypter->destroy(crypter);
532 return FALSE;
533 }
534 if (!crypter->set_key(crypter, key) ||
535 !crypter->decrypt(crypter, encrypted, iv, plain))
536 {
537 crypter->destroy(crypter);
538 return FALSE;
539 }
540 crypter->destroy(crypter);
541 return TRUE;
542 }
543
544 /**
545 * Remove enveloped-data PKCS#7 padding from plain data
546 */
547 static bool remove_padding(chunk_t *data)
548 {
549 u_char *pos;
550 u_char pattern;
551 size_t padding;
552
553 if (!data->len)
554 {
555 return FALSE;
556 }
557 pos = data->ptr + data->len - 1;
558 padding = pattern = *pos;
559
560 if (padding > data->len)
561 {
562 DBG1(DBG_LIB, "padding greater than data length");
563 return FALSE;
564 }
565 data->len -= padding;
566
567 while (padding-- > 0)
568 {
569 if (*pos-- != pattern)
570 {
571 DBG1(DBG_LIB, "wrong padding pattern");
572 return FALSE;
573 }
574 }
575 return TRUE;
576 }
577
578 /**
579 * Decrypt PKCS#7 enveloped-data
580 */
581 static bool decrypt(private_openssl_pkcs7_t *this,
582 chunk_t encrypted, chunk_t *plain)
583 {
584 STACK_OF(CMS_RecipientInfo) *ris;
585 CMS_RecipientInfo *ri;
586 chunk_t chunk, key = chunk_empty;
587 int i;
588
589 ris = CMS_get0_RecipientInfos(this->cms);
590 for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
591 {
592 ri = sk_CMS_RecipientInfo_value(ris, i);
593 if (CMS_RecipientInfo_type(ri) == CMS_RECIPINFO_TRANS)
594 {
595 identification_t *serial, *issuer;
596 private_key_t *private;
597 X509_ALGOR *alg;
598 X509_NAME *name;
599 ASN1_INTEGER *sn;
600 u_char zero = 0;
601 int oid;
602
603 if (CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &alg) == 1 &&
604 CMS_RecipientInfo_ktri_get0_signer_id(ri, NULL, &name, &sn) == 1)
605 {
606 oid = openssl_asn1_known_oid(alg->algorithm);
607 if (oid != OID_RSA_ENCRYPTION)
608 {
609 DBG1(DBG_LIB, "only RSA encryption supported in PKCS#7");
610 continue;
611 }
612 issuer = openssl_x509_name2id(name);
613 if (!issuer)
614 {
615 continue;
616 }
617 chunk = openssl_asn1_str2chunk(sn);
618 if (chunk.len && chunk.ptr[0] | 0x80)
619 { /* if MSB is set, append a zero to make it non-negative */
620 chunk = chunk_cata("cc", chunk_from_thing(zero), chunk);
621 }
622 serial = identification_create_from_encoding(ID_KEY_ID, chunk);
623 private = find_private(issuer, serial);
624 issuer->destroy(issuer);
625 serial->destroy(serial);
626
627 if (private)
628 {
629 /* get encryptedKey from internal structure; TODO fixup */
630 chunk = openssl_asn1_str2chunk(ri->ktri->encryptedKey);
631 if (private->decrypt(private, ENCRYPT_RSA_PKCS1,
632 chunk, &key))
633 {
634 private->destroy(private);
635 break;
636 }
637 private->destroy(private);
638 }
639 }
640 }
641 }
642 if (!key.len)
643 {
644 DBG1(DBG_LIB, "no private key found to decrypt PKCS#7");
645 return FALSE;
646 }
647 if (!decrypt_symmetric(this, key, encrypted, plain))
648 {
649 chunk_clear(&key);
650 return FALSE;
651 }
652 chunk_clear(&key);
653 if (!remove_padding(plain))
654 {
655 free(plain->ptr);
656 return FALSE;
657 }
658 return TRUE;
659 }
660
661 METHOD(container_t, get_data, bool,
662 private_openssl_pkcs7_t *this, chunk_t *data)
663 {
664 ASN1_OCTET_STRING **os;
665 chunk_t chunk;
666
667 os = CMS_get0_content(this->cms);
668 if (os)
669 {
670 chunk = openssl_asn1_str2chunk(*os);
671 switch (this->type)
672 {
673 case CONTAINER_PKCS7_DATA:
674 case CONTAINER_PKCS7_SIGNED_DATA:
675 *data = chunk_clone(chunk);
676 return TRUE;
677 case CONTAINER_PKCS7_ENVELOPED_DATA:
678 return decrypt(this, chunk, data);
679 default:
680 break;
681 }
682 }
683 return FALSE;
684 }
685
686 METHOD(container_t, get_encoding, bool,
687 private_openssl_pkcs7_t *this, chunk_t *data)
688 {
689 return FALSE;
690 }
691
692 METHOD(container_t, destroy, void,
693 private_openssl_pkcs7_t *this)
694 {
695 CMS_ContentInfo_free(this->cms);
696 free(this);
697 }
698
699 /**
700 * Generic constructor
701 */
702 static private_openssl_pkcs7_t* create_empty()
703 {
704 private_openssl_pkcs7_t *this;
705
706 INIT(this,
707 .public = {
708 .container = {
709 .get_type = _get_type,
710 .create_signature_enumerator = _create_signature_enumerator,
711 .get_data = _get_data,
712 .get_encoding = _get_encoding,
713 .destroy = _destroy,
714 },
715 .get_attribute = _get_attribute,
716 .create_cert_enumerator = _create_cert_enumerator,
717 },
718 );
719
720 return this;
721 }
722
723 /**
724 * Parse a PKCS#7 container
725 */
726 static bool parse(private_openssl_pkcs7_t *this, chunk_t blob)
727 {
728 BIO *bio;
729
730 bio = BIO_new_mem_buf(blob.ptr, blob.len);
731 this->cms = d2i_CMS_bio(bio, NULL);
732 BIO_free(bio);
733
734 if (!this->cms)
735 {
736 return FALSE;
737 }
738 switch (openssl_asn1_known_oid((ASN1_OBJECT*)CMS_get0_type(this->cms)))
739 {
740 case OID_PKCS7_DATA:
741 this->type = CONTAINER_PKCS7_DATA;
742 break;
743 case OID_PKCS7_SIGNED_DATA:
744 this->type = CONTAINER_PKCS7_SIGNED_DATA;
745 break;
746 case OID_PKCS7_ENVELOPED_DATA:
747 this->type = CONTAINER_PKCS7_ENVELOPED_DATA;
748 break;
749 default:
750 return FALSE;
751 }
752
753 return TRUE;
754 }
755
756 /**
757 * See header
758 */
759 pkcs7_t *openssl_pkcs7_load(container_type_t type, va_list args)
760 {
761 chunk_t blob = chunk_empty;
762 private_openssl_pkcs7_t *this;
763
764 while (TRUE)
765 {
766 switch (va_arg(args, builder_part_t))
767 {
768 case BUILD_BLOB_ASN1_DER:
769 blob = va_arg(args, chunk_t);
770 continue;
771 case BUILD_END:
772 break;
773 default:
774 return NULL;
775 }
776 break;
777 }
778 if (blob.len)
779 {
780 this = create_empty();
781 if (parse(this, blob))
782 {
783 return &this->public;
784 }
785 destroy(this);
786 }
787 return NULL;
788 }
789
790 #endif /* OPENSSL_NO_CMS */