]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libstrongswan/crypto/pkcs7.c
be4076f32a26a91f12e9df62085d9b8e758099d0
[thirdparty/strongswan.git] / src / libstrongswan / crypto / pkcs7.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Copyright (C) 2002-2008 Andreas Steffen
4 * Copyright (C) 2005 Jan Hutter, Martin Willi
5 * Hochschule fuer Technik Rapperswil, Switzerland
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include <stdlib.h>
19 #include <string.h>
20 #include <time.h>
21
22 #include <library.h>
23 #include <debug.h>
24
25 #include <asn1/oid.h>
26 #include <asn1/asn1.h>
27 #include <asn1/asn1_parser.h>
28 #include <credentials/certificates/x509.h>
29 #include <credentials/keys/public_key.h>
30 #include <crypto/pkcs9.h>
31 #include <crypto/hashers/hasher.h>
32 #include <crypto/crypters/crypter.h>
33 #include <utils/linked_list.h>
34
35 #include "pkcs7.h"
36
37 typedef struct private_pkcs7_t private_pkcs7_t;
38
39 /**
40 * Private data of a pkcs7_t object.
41 */
42 struct private_pkcs7_t {
43 /**
44 * Public interface for this certificate.
45 */
46 pkcs7_t public;
47
48 /**
49 * contentInfo type
50 */
51 int type;
52
53 /**
54 * ASN.1 encoded content
55 */
56 chunk_t content;
57
58 /**
59 * ASN.1 parsing start level
60 */
61 u_int level;
62
63 /**
64 * retrieved data
65 */
66 chunk_t data;
67
68 /**
69 * ASN.1 encoded attributes
70 */
71 pkcs9_t *attributes;
72
73 /**
74 * Linked list of X.509 certificates
75 */
76 linked_list_t *certs;
77 };
78
79 METHOD(pkcs7_t, is_data, bool,
80 private_pkcs7_t *this)
81 {
82 return this->type == OID_PKCS7_DATA;
83 }
84
85 METHOD(pkcs7_t, is_signedData, bool,
86 private_pkcs7_t *this)
87 {
88 return this->type == OID_PKCS7_SIGNED_DATA;
89 }
90
91 METHOD(pkcs7_t, is_envelopedData, bool,
92 private_pkcs7_t *this)
93 {
94 return this->type == OID_PKCS7_ENVELOPED_DATA;
95 }
96
97 /**
98 * ASN.1 definition of the PKCS#7 ContentInfo type
99 */
100 static const asn1Object_t contentInfoObjects[] = {
101 { 0, "contentInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
102 { 1, "contentType", ASN1_OID, ASN1_BODY }, /* 1 */
103 { 1, "content", ASN1_CONTEXT_C_0, ASN1_OPT |
104 ASN1_BODY }, /* 2 */
105 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
106 { 0, "exit", ASN1_EOC, ASN1_EXIT }
107 };
108 #define PKCS7_INFO_TYPE 1
109 #define PKCS7_INFO_CONTENT 2
110
111 /**
112 * Parse PKCS#7 contentInfo object
113 */
114 static bool parse_contentInfo(private_pkcs7_t *this)
115 {
116 asn1_parser_t *parser;
117 chunk_t object;
118 int objectID;
119 bool success = FALSE;
120
121 if (!this->data.ptr)
122 {
123 return FALSE;
124 }
125
126 parser = asn1_parser_create(contentInfoObjects, this->data);
127 parser->set_top_level(parser, this->level);
128
129 while (parser->iterate(parser, &objectID, &object))
130 {
131 if (objectID == PKCS7_INFO_TYPE)
132 {
133 this->type = asn1_known_oid(object);
134 if (this->type < OID_PKCS7_DATA ||
135 this->type > OID_PKCS7_ENCRYPTED_DATA)
136 {
137 DBG1(DBG_LIB, "unknown pkcs7 content type");
138 goto end;
139 }
140 }
141 else if (objectID == PKCS7_INFO_CONTENT && object.len > 0)
142 {
143 chunk_free(&this->content);
144 this->content = chunk_clone(object);
145 }
146 }
147 success = parser->success(parser);
148
149 if (success)
150 {
151 this->level += 2;
152 chunk_free(&this->data);
153 }
154
155 end:
156 parser->destroy(parser);
157 return success;
158 }
159
160 /**
161 * Check whether to abort the requested parsing
162 */
163 static bool abort_parsing(private_pkcs7_t *this, int type)
164 {
165 if (this->type != type)
166 {
167 DBG1(DBG_LIB, "pkcs7 content to be parsed is not of type '%s'",
168 oid_names[type].name);
169 return TRUE;
170 }
171 return FALSE;
172 }
173
174 METHOD(pkcs7_t, parse_data, bool,
175 private_pkcs7_t *this)
176 {
177 chunk_t data;
178
179 if (!parse_contentInfo(this) ||
180 abort_parsing(this, OID_PKCS7_DATA))
181 {
182 return FALSE;
183 }
184 data = this->content;
185 if (data.len == 0)
186 {
187 this->data = chunk_empty;
188 return TRUE;
189 }
190 if (asn1_parse_simple_object(&data, ASN1_OCTET_STRING,
191 this->level, "data"))
192 {
193 this->data = chunk_clone(data);
194 return TRUE;
195 }
196 return FALSE;
197 }
198
199 /**
200 * ASN.1 definition of the PKCS#7 signedData type
201 */
202 static const asn1Object_t signedDataObjects[] = {
203 { 0, "signedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
204 { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
205 { 1, "digestAlgorithms", ASN1_SET, ASN1_LOOP }, /* 2 */
206 { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 3 */
207 { 1, "end loop", ASN1_EOC, ASN1_END }, /* 4 */
208 { 1, "contentInfo", ASN1_EOC, ASN1_RAW }, /* 5 */
209 { 1, "certificates", ASN1_CONTEXT_C_0, ASN1_OPT |
210 ASN1_LOOP }, /* 6 */
211 { 2, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 7 */
212 { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 8 */
213 { 1, "crls", ASN1_CONTEXT_C_1, ASN1_OPT |
214 ASN1_LOOP }, /* 9 */
215 { 2, "crl", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */
216 { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 11 */
217 { 1, "signerInfos", ASN1_SET, ASN1_LOOP }, /* 12 */
218 { 2, "signerInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */
219 { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 14 */
220 { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 15 */
221 { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 16 */
222 { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 17 */
223 { 3, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 18 */
224 { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0, ASN1_OPT |
225 ASN1_OBJ }, /* 19 */
226 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
227 { 3, "digestEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */
228 { 3, "encryptedDigest", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */
229 { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 23 */
230 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 24 */
231 { 1, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
232 { 0, "exit", ASN1_EOC, ASN1_EXIT }
233 };
234 #define PKCS7_SIGNED_VERSION 1
235 #define PKCS7_DIGEST_ALG 3
236 #define PKCS7_SIGNED_CONTENT_INFO 5
237 #define PKCS7_SIGNED_CERT 7
238 #define PKCS7_SIGNER_INFO 13
239 #define PKCS7_SIGNER_INFO_VERSION 14
240 #define PKCS7_SIGNED_ISSUER 16
241 #define PKCS7_SIGNED_SERIAL_NUMBER 17
242 #define PKCS7_DIGEST_ALGORITHM 18
243 #define PKCS7_AUTH_ATTRIBUTES 19
244 #define PKCS7_DIGEST_ENC_ALGORITHM 21
245 #define PKCS7_ENCRYPTED_DIGEST 22
246
247 METHOD(pkcs7_t, parse_signedData, bool,
248 private_pkcs7_t *this, certificate_t *cacert)
249 {
250 asn1_parser_t *parser;
251 chunk_t object;
252 int objectID, version;
253 int digest_alg = OID_UNKNOWN;
254 int enc_alg = OID_UNKNOWN;
255 int signerInfos = 0;
256 bool success = FALSE;
257
258 chunk_t encrypted_digest = chunk_empty;
259
260 if (!parse_contentInfo(this) ||
261 abort_parsing(this, OID_PKCS7_SIGNED_DATA))
262 {
263 return FALSE;
264 }
265
266 parser = asn1_parser_create(signedDataObjects, this->content);
267 parser->set_top_level(parser, this->level);
268
269 while (parser->iterate(parser, &objectID, &object))
270 {
271 u_int level = parser->get_level(parser);
272
273 switch (objectID)
274 {
275 case PKCS7_SIGNED_VERSION:
276 version = object.len ? (int)*object.ptr : 0;
277 DBG2(DBG_LIB, " v%d", version);
278 break;
279 case PKCS7_DIGEST_ALG:
280 digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
281 break;
282 case PKCS7_SIGNED_CONTENT_INFO:
283 {
284 pkcs7_t *data = pkcs7_create_from_chunk(object, level+1);
285
286 if (!data || !data->parse_data(data))
287 {
288 DESTROY_IF(data);
289 goto end;
290 }
291 this->data = chunk_clone(data->get_data(data));
292 data->destroy(data);
293 break;
294 }
295 case PKCS7_SIGNED_CERT:
296 {
297 certificate_t *cert;
298
299 DBG2(DBG_LIB, " parsing pkcs7-wrapped certificate");
300 cert = lib->creds->create(lib->creds,
301 CRED_CERTIFICATE, CERT_X509,
302 BUILD_BLOB_ASN1_DER, object,
303 BUILD_END);
304 if (cert)
305 {
306 this->certs->insert_last(this->certs, cert);
307 }
308 break;
309 }
310 case PKCS7_SIGNER_INFO:
311 signerInfos++;
312 DBG2(DBG_LIB, " signer #%d", signerInfos);
313 break;
314 case PKCS7_SIGNER_INFO_VERSION:
315 version = object.len ? (int)*object.ptr : 0;
316 DBG2(DBG_LIB, " v%d", version);
317 break;
318 case PKCS7_SIGNED_ISSUER:
319 {
320 identification_t *issuer;
321
322 issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
323 DBG2(DBG_LIB, " '%Y'", issuer);
324 issuer->destroy(issuer);
325 break;
326 }
327 case PKCS7_AUTH_ATTRIBUTES:
328 *object.ptr = ASN1_SET;
329 this->attributes = pkcs9_create_from_chunk(object, level+1);
330 *object.ptr = ASN1_CONTEXT_C_0;
331 break;
332 case PKCS7_DIGEST_ALGORITHM:
333 digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
334 break;
335 case PKCS7_DIGEST_ENC_ALGORITHM:
336 enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
337 break;
338 case PKCS7_ENCRYPTED_DIGEST:
339 encrypted_digest = object;
340 }
341 }
342 success = parser->success(parser);
343
344 end:
345 parser->destroy(parser);
346 if (!success)
347 {
348 return FALSE;
349 }
350
351 /* check the signature only if a cacert is available */
352 if (cacert != NULL)
353 {
354 signature_scheme_t scheme;
355 public_key_t *key;
356
357 scheme = signature_scheme_from_oid(digest_alg);
358 if (scheme == SIGN_UNKNOWN)
359 {
360 DBG1(DBG_LIB, "unsupported signature scheme");
361 return FALSE;
362 }
363 if (signerInfos == 0)
364 {
365 DBG1(DBG_LIB, "no signerInfo object found");
366 return FALSE;
367 }
368 else if (signerInfos > 1)
369 {
370 DBG1(DBG_LIB, "more than one signerInfo object found");
371 return FALSE;
372 }
373 if (this->attributes == NULL)
374 {
375 DBG1(DBG_LIB, "no authenticatedAttributes object found");
376 return FALSE;
377 }
378 if (enc_alg != OID_RSA_ENCRYPTION)
379 {
380 DBG1(DBG_LIB, "only RSA digest encryption supported");
381 return FALSE;
382 }
383
384 /* verify the signature */
385 key = cacert->get_public_key(cacert);
386 if (key == NULL)
387 {
388 DBG1(DBG_LIB, "no public key found in CA certificate");
389 return FALSE;
390 }
391 if (key->verify(key, scheme,
392 this->attributes->get_encoding(this->attributes), encrypted_digest))
393 {
394 DBG2(DBG_LIB, "signature is valid");
395 }
396 else
397 {
398 DBG1(DBG_LIB, "invalid signature");
399 key->destroy(key);
400 return FALSE;
401 }
402 key->destroy(key);
403
404 if (this->data.ptr != NULL)
405 {
406 chunk_t messageDigest;
407
408 messageDigest = this->attributes->get_attribute(this->attributes,
409 OID_PKCS9_MESSAGE_DIGEST);
410 if (messageDigest.ptr == NULL)
411 {
412 DBG1(DBG_LIB, "messageDigest attribute not found");
413 return FALSE;
414 }
415 else
416 {
417 hash_algorithm_t algorithm;
418 hasher_t *hasher;
419 chunk_t hash;
420 bool valid;
421
422 algorithm = hasher_algorithm_from_oid(digest_alg);
423 hasher = lib->crypto->create_hasher(lib->crypto, algorithm);
424 if (hasher == NULL)
425 {
426 DBG1(DBG_LIB, "hash algorithm %N not supported",
427 hash_algorithm_names, algorithm);
428 return FALSE;
429 }
430 hasher->allocate_hash(hasher, this->data, &hash);
431 hasher->destroy(hasher);
432 DBG3(DBG_LIB, "hash: %B", &hash);
433
434 valid = chunk_equals(messageDigest, hash);
435 free(hash.ptr);
436 if (valid)
437 {
438 DBG2(DBG_LIB, "messageDigest is valid");
439 }
440 else
441 {
442 DBG1(DBG_LIB, "invalid messageDigest");
443 return FALSE;
444 }
445 }
446 }
447 }
448 return TRUE;
449 }
450
451 /**
452 * ASN.1 definition of the PKCS#7 envelopedData type
453 */
454 static const asn1Object_t envelopedDataObjects[] = {
455 { 0, "envelopedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
456 { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
457 { 1, "recipientInfos", ASN1_SET, ASN1_LOOP }, /* 2 */
458 { 2, "recipientInfo", ASN1_SEQUENCE, ASN1_BODY }, /* 3 */
459 { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 4 */
460 { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */
461 { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */
462 { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 7 */
463 { 3, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 8 */
464 { 3, "encryptedKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */
465 { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */
466 { 1, "encryptedContentInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
467 { 2, "contentType", ASN1_OID, ASN1_BODY }, /* 12 */
468 { 2, "contentEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 13 */
469 { 2, "encryptedContent", ASN1_CONTEXT_S_0, ASN1_BODY }, /* 14 */
470 { 0, "exit", ASN1_EOC, ASN1_EXIT }
471 };
472 #define PKCS7_ENVELOPED_VERSION 1
473 #define PKCS7_RECIPIENT_INFO_VERSION 4
474 #define PKCS7_ISSUER 6
475 #define PKCS7_SERIAL_NUMBER 7
476 #define PKCS7_ENCRYPTION_ALG 8
477 #define PKCS7_ENCRYPTED_KEY 9
478 #define PKCS7_CONTENT_TYPE 12
479 #define PKCS7_CONTENT_ENC_ALGORITHM 13
480 #define PKCS7_ENCRYPTED_CONTENT 14
481
482 METHOD(pkcs7_t, parse_envelopedData, bool,
483 private_pkcs7_t *this, chunk_t serialNumber, private_key_t *key)
484 {
485 asn1_parser_t *parser;
486 chunk_t object;
487 int objectID, version;
488 bool success = FALSE;
489
490 chunk_t iv = chunk_empty;
491 chunk_t symmetric_key = chunk_empty;
492 chunk_t encrypted_content = chunk_empty;
493
494 crypter_t *crypter = NULL;
495
496 if (!parse_contentInfo(this) ||
497 abort_parsing(this, OID_PKCS7_ENVELOPED_DATA))
498 {
499 return FALSE;
500 }
501
502 parser = asn1_parser_create(envelopedDataObjects, this->content);
503 parser->set_top_level(parser, this->level);
504
505 while (parser->iterate(parser, &objectID, &object))
506 {
507 u_int level = parser->get_level(parser);
508
509 switch (objectID)
510 {
511 case PKCS7_ENVELOPED_VERSION:
512 {
513 version = object.len ? (int)*object.ptr : 0;
514 DBG2(DBG_LIB, " v%d", version);
515 if (version != 0)
516 {
517 DBG1(DBG_LIB, "envelopedData version is not 0");
518 goto end;
519 }
520 break;
521 }
522 case PKCS7_RECIPIENT_INFO_VERSION:
523 {
524 version = object.len ? (int)*object.ptr : 0;
525 DBG2(DBG_LIB, " v%d", version);
526 if (version != 0)
527 {
528 DBG1(DBG_LIB, "recipient info version is not 0");
529 goto end;
530 }
531 break;
532 }
533 case PKCS7_ISSUER:
534 {
535 identification_t *issuer;
536
537 issuer = identification_create_from_encoding(ID_DER_ASN1_DN,
538 object);
539 DBG2(DBG_LIB, " '%Y'", issuer);
540 issuer->destroy(issuer);
541 break;
542 }
543 case PKCS7_SERIAL_NUMBER:
544 {
545 if (!chunk_equals(serialNumber, object))
546 {
547 DBG1(DBG_LIB, "serial numbers do not match");
548 goto end;
549 }
550 break;
551 }
552 case PKCS7_ENCRYPTION_ALG:
553 {
554 int alg;
555
556 alg = asn1_parse_algorithmIdentifier(object, level, NULL);
557 if (alg != OID_RSA_ENCRYPTION)
558 {
559 DBG1(DBG_LIB, "only rsa encryption supported");
560 goto end;
561 }
562 break;
563 }
564 case PKCS7_ENCRYPTED_KEY:
565 {
566 if (!key->decrypt(key, ENCRYPT_RSA_PKCS1, object, &symmetric_key))
567 {
568 DBG1(DBG_LIB, "symmetric key could not be decrypted with rsa");
569 goto end;
570 }
571 DBG4(DBG_LIB, "symmetric key %B", &symmetric_key);
572 break;
573 }
574 case PKCS7_CONTENT_TYPE:
575 {
576 if (asn1_known_oid(object) != OID_PKCS7_DATA)
577 {
578 DBG1(DBG_LIB, "encrypted content not of type pkcs7 data");
579 goto end;
580 }
581 break;
582 }
583 case PKCS7_CONTENT_ENC_ALGORITHM:
584 {
585 encryption_algorithm_t enc_alg;
586 size_t key_size;
587 int alg;
588
589 alg = asn1_parse_algorithmIdentifier(object, level, &iv);
590 enc_alg = encryption_algorithm_from_oid(alg, &key_size);
591 if (enc_alg == ENCR_UNDEFINED)
592 {
593 DBG1(DBG_LIB, "unsupported content encryption algorithm");
594 goto end;
595 }
596 crypter = lib->crypto->create_crypter(lib->crypto, enc_alg,
597 key_size);
598 if (crypter == NULL)
599 {
600 DBG1(DBG_LIB, "crypter %N not available",
601 encryption_algorithm_names, enc_alg);
602 goto end;
603 }
604 if (symmetric_key.len != crypter->get_key_size(crypter))
605 {
606 DBG1(DBG_LIB, "symmetric key length %d is wrong",
607 symmetric_key.len);
608 goto end;
609 }
610 if (!asn1_parse_simple_object(&iv, ASN1_OCTET_STRING,
611 level + 1, "IV"))
612 {
613 DBG1(DBG_LIB, "IV could not be parsed");
614 goto end;
615 }
616 if (iv.len != crypter->get_iv_size(crypter))
617 {
618 DBG1(DBG_LIB, "IV length %d is wrong", iv.len);
619 goto end;
620 }
621 break;
622 }
623 case PKCS7_ENCRYPTED_CONTENT:
624 {
625 encrypted_content = object;
626 break;
627 }
628 }
629 }
630 success = parser->success(parser);
631
632 end:
633 parser->destroy(parser);
634 if (!success)
635 {
636 goto failed;
637 }
638 success = FALSE;
639
640 /* decrypt the content */
641 crypter->set_key(crypter, symmetric_key);
642 crypter->decrypt(crypter, encrypted_content, iv, &this->data);
643 DBG4(DBG_LIB, "decrypted content with padding: %B", &this->data);
644
645 /* remove the padding */
646 {
647 u_char *pos = this->data.ptr + this->data.len - 1;
648 u_char pattern = *pos;
649 size_t padding = pattern;
650
651 if (padding > this->data.len)
652 {
653 DBG1(DBG_LIB, "padding greater than data length");
654 goto failed;
655 }
656 this->data.len -= padding;
657
658 while (padding-- > 0)
659 {
660 if (*pos-- != pattern)
661 {
662 DBG1(DBG_LIB, "wrong padding pattern");
663 goto failed;
664 }
665 }
666 }
667 success = TRUE;
668
669 failed:
670 DESTROY_IF(crypter);
671 chunk_clear(&symmetric_key);
672 if (!success)
673 {
674 chunk_free(&this->data);
675 }
676 return success;
677 }
678
679 METHOD(pkcs7_t, get_data, chunk_t,
680 private_pkcs7_t *this)
681 {
682 return this->data;
683 }
684
685 METHOD(pkcs7_t, get_contentInfo, chunk_t,
686 private_pkcs7_t *this)
687 {
688 chunk_t content_type;
689
690 /* create DER-encoded OID for pkcs7_contentInfo type */
691 switch(this->type)
692 {
693 case OID_PKCS7_DATA:
694 case OID_PKCS7_SIGNED_DATA:
695 case OID_PKCS7_ENVELOPED_DATA:
696 case OID_PKCS7_SIGNED_ENVELOPED_DATA:
697 case OID_PKCS7_DIGESTED_DATA:
698 case OID_PKCS7_ENCRYPTED_DATA:
699 content_type = asn1_build_known_oid(this->type);
700 break;
701 case OID_UNKNOWN:
702 default:
703 DBG1(DBG_LIB, "invalid pkcs7 contentInfo type");
704 return chunk_empty;
705 }
706
707 return this->content.ptr == NULL
708 ? asn1_wrap(ASN1_SEQUENCE, "m", content_type)
709 : asn1_wrap(ASN1_SEQUENCE, "mm", content_type,
710 asn1_simple_object(ASN1_CONTEXT_C_0, this->content));
711 }
712
713 METHOD(pkcs7_t, create_certificate_enumerator, enumerator_t*,
714 private_pkcs7_t *this)
715 {
716 return this->certs->create_enumerator(this->certs);
717 }
718
719 METHOD(pkcs7_t, set_certificate, void,
720 private_pkcs7_t *this, certificate_t *cert)
721 {
722 if (cert)
723 {
724 this->certs->insert_last(this->certs, cert);
725 }
726 }
727
728 METHOD(pkcs7_t, set_attributes, void,
729 private_pkcs7_t *this, pkcs9_t *attributes)
730 {
731 this->attributes = attributes;
732 }
733
734 METHOD(pkcs7_t, get_attributes, pkcs9_t*,
735 private_pkcs7_t *this)
736 {
737 return this->attributes;
738 }
739
740 /**
741 * build a DER-encoded issuerAndSerialNumber object
742 */
743 chunk_t pkcs7_build_issuerAndSerialNumber(certificate_t *cert)
744 {
745 identification_t *issuer = cert->get_issuer(cert);
746 chunk_t serial = chunk_empty;
747
748 if (cert->get_type(cert) == CERT_X509)
749 {
750 x509_t *x509 = (x509_t*)cert;
751 serial = x509->get_serial(x509);
752 }
753
754 return asn1_wrap(ASN1_SEQUENCE, "cm",
755 issuer->get_encoding(issuer),
756 asn1_integer("c", serial));
757 }
758
759 METHOD(pkcs7_t, build_envelopedData, bool,
760 private_pkcs7_t *this, certificate_t *cert, encryption_algorithm_t alg,
761 size_t key_size)
762 {
763 chunk_t iv, symmetricKey, protectedKey, in, out;
764 crypter_t *crypter;
765 int alg_oid;
766
767 /* select OID of symmetric encryption algorithm */
768 alg_oid = encryption_algorithm_to_oid(alg, key_size);
769 if (alg_oid == OID_UNKNOWN)
770 {
771 DBG1(DBG_LIB, " encryption algorithm %N not supported",
772 encryption_algorithm_names, alg);
773 return FALSE;
774 }
775 crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
776 if (crypter == NULL)
777 {
778 DBG1(DBG_LIB, " could not create crypter for algorithm %N",
779 encryption_algorithm_names, alg);
780 return FALSE;
781 }
782
783 /* generate a true random symmetric encryption key
784 * and a pseudo-random iv
785 */
786 {
787 rng_t *rng;
788
789 rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
790 if (!rng || !rng->allocate_bytes(rng, crypter->get_key_size(crypter),
791 &symmetricKey))
792 {
793 DBG1(DBG_LIB, " failed to allocate symmetric encryption key");
794 DESTROY_IF(rng);
795 return FALSE;
796 }
797 DBG4(DBG_LIB, " symmetric encryption key: %B", &symmetricKey);
798 rng->destroy(rng);
799
800 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
801 if (!rng || !rng->allocate_bytes(rng, crypter->get_iv_size(crypter),
802 &iv))
803 {
804 DBG1(DBG_LIB, " failed to allocate initialization vector");
805 DESTROY_IF(rng);
806 return FALSE;
807 }
808 DBG4(DBG_LIB, " initialization vector: %B", &iv);
809 rng->destroy(rng);
810 }
811
812 /* pad the data so that the total length becomes
813 * a multiple of the block size
814 */
815 {
816 size_t block_size = crypter->get_block_size(crypter);
817 size_t padding = block_size - this->data.len % block_size;
818
819 in.len = this->data.len + padding;
820 in.ptr = malloc(in.len);
821
822 DBG2(DBG_LIB, " padding %d bytes of data to multiple block size of %d bytes",
823 (int)this->data.len, (int)in.len);
824
825 /* copy data */
826 memcpy(in.ptr, this->data.ptr, this->data.len);
827 /* append padding */
828 memset(in.ptr + this->data.len, padding, padding);
829 }
830 DBG3(DBG_LIB, " padded unencrypted data: %B", &in);
831
832 /* symmetric encryption of data object */
833 crypter->set_key(crypter, symmetricKey);
834 if (!crypter->encrypt(crypter, in, iv, &out))
835 {
836 crypter->destroy(crypter);
837 chunk_clear(&in);
838 chunk_clear(&symmetricKey);
839 chunk_free(&iv);
840 return FALSE;
841 }
842 crypter->destroy(crypter);
843 chunk_clear(&in);
844 DBG3(DBG_LIB, " encrypted data: %B", &out);
845
846 /* protect symmetric key by public key encryption */
847 {
848 public_key_t *key = cert->get_public_key(cert);
849
850 if (key == NULL)
851 {
852 DBG1(DBG_LIB, " public key not found in encryption certificate");
853 chunk_clear(&symmetricKey);
854 chunk_free(&iv);
855 chunk_free(&out);
856 return FALSE;
857 }
858 key->encrypt(key, ENCRYPT_RSA_PKCS1, symmetricKey, &protectedKey);
859 key->destroy(key);
860 chunk_clear(&symmetricKey);
861 }
862
863 /* build pkcs7 enveloped data object */
864 {
865 chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "mm",
866 asn1_build_known_oid(alg_oid),
867 asn1_wrap(ASN1_OCTET_STRING, "m", iv));
868
869 chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "mmm",
870 asn1_build_known_oid(OID_PKCS7_DATA),
871 contentEncryptionAlgorithm,
872 asn1_wrap(ASN1_CONTEXT_S_0, "m", out));
873
874 chunk_t encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m", protectedKey);
875
876 chunk_t recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmmm",
877 ASN1_INTEGER_0,
878 pkcs7_build_issuerAndSerialNumber(cert),
879 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
880 encryptedKey);
881
882 this->content = asn1_wrap(ASN1_SEQUENCE, "cmm",
883 ASN1_INTEGER_0,
884 asn1_wrap(ASN1_SET, "m", recipientInfo),
885 encryptedContentInfo);
886 chunk_free(&this->data);
887 this->type = OID_PKCS7_ENVELOPED_DATA;
888 this->data = get_contentInfo(this);
889 }
890 return TRUE;
891 }
892
893 METHOD(pkcs7_t, build_signedData, bool,
894 private_pkcs7_t *this, private_key_t *private_key, hash_algorithm_t alg)
895 {
896 chunk_t authenticatedAttributes = chunk_empty;
897 chunk_t encryptedDigest = chunk_empty;
898 chunk_t signerInfo, encoding = chunk_empty;
899 signature_scheme_t scheme;
900 int digest_oid;
901 certificate_t *cert;
902
903 if (this->certs->get_first(this->certs, (void**)&cert) != SUCCESS)
904 {
905 DBG1(DBG_LIB, " no pkcs7 signer certificate found");
906 return FALSE;
907 }
908 digest_oid = hasher_algorithm_to_oid(alg);
909 scheme = signature_scheme_from_oid(digest_oid);
910
911 if (this->attributes != NULL)
912 {
913 if (this->data.ptr != NULL)
914 {
915 chunk_t messageDigest, signingTime, attributes;
916 hasher_t *hasher;
917 time_t now;
918
919 hasher = lib->crypto->create_hasher(lib->crypto, alg);
920 if (hasher == NULL)
921 {
922 DBG1(DBG_LIB, " hash algorithm %N not support",
923 hash_algorithm_names, alg);
924 return FALSE;
925 }
926 hasher->allocate_hash(hasher, this->data, &messageDigest);
927 hasher->destroy(hasher);
928 this->attributes->set_attribute(this->attributes,
929 OID_PKCS9_MESSAGE_DIGEST,
930 messageDigest);
931 free(messageDigest.ptr);
932
933 /* take the current time as signingTime */
934 now = time(NULL);
935 signingTime = asn1_from_time(&now, ASN1_UTCTIME);
936 this->attributes->set_attribute_raw(this->attributes,
937 OID_PKCS9_SIGNING_TIME, signingTime);
938 this->attributes->set_attribute_raw(this->attributes,
939 OID_PKCS9_CONTENT_TYPE,
940 asn1_build_known_oid(OID_PKCS7_DATA));
941
942 attributes = this->attributes->get_encoding(this->attributes);
943
944 private_key->sign(private_key, scheme, attributes, &encryptedDigest);
945 authenticatedAttributes = chunk_clone(attributes);
946 *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
947 }
948 }
949 else if (this->data.ptr != NULL)
950 {
951 private_key->sign(private_key, scheme, this->data, &encryptedDigest);
952 }
953 if (encryptedDigest.ptr)
954 {
955 encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", encryptedDigest);
956 }
957 signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmmmmm",
958 ASN1_INTEGER_1,
959 pkcs7_build_issuerAndSerialNumber(cert),
960 asn1_algorithmIdentifier(digest_oid),
961 authenticatedAttributes,
962 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
963 encryptedDigest);
964
965 if (this->data.ptr != NULL)
966 {
967 chunk_free(&this->content);
968 this->content = asn1_simple_object(ASN1_OCTET_STRING, this->data);
969 chunk_free(&this->data);
970 }
971 this->type = OID_PKCS7_DATA;
972 this->data = get_contentInfo(this);
973 chunk_free(&this->content);
974
975 cert->get_encoding(cert, CERT_ASN1_DER, &encoding);
976
977 this->content = asn1_wrap(ASN1_SEQUENCE, "cmcmm",
978 ASN1_INTEGER_1,
979 asn1_wrap(ASN1_SET, "m", asn1_algorithmIdentifier(digest_oid)),
980 this->data,
981 asn1_wrap(ASN1_CONTEXT_C_0, "m", encoding),
982 asn1_wrap(ASN1_SET, "m", signerInfo));
983 chunk_free(&this->data);
984 this->type = OID_PKCS7_SIGNED_DATA;
985 this->data = get_contentInfo(this);
986
987 return TRUE;
988 }
989
990 METHOD(pkcs7_t, destroy, void,
991 private_pkcs7_t *this)
992 {
993 DESTROY_IF(this->attributes);
994 this->certs->destroy_offset(this->certs, offsetof(certificate_t, destroy));
995 free(this->content.ptr);
996 free(this->data.ptr);
997 free(this);
998 }
999
1000 /**
1001 * Generic private constructor
1002 */
1003 static private_pkcs7_t *pkcs7_create_empty(void)
1004 {
1005 private_pkcs7_t *this;
1006
1007 INIT(this,
1008 .public = {
1009 .is_data = _is_data,
1010 .is_signedData = _is_signedData,
1011 .is_envelopedData = _is_envelopedData,
1012 .parse_data = _parse_data,
1013 .parse_signedData = _parse_signedData,
1014 .parse_envelopedData = _parse_envelopedData,
1015 .get_data = _get_data,
1016 .get_contentInfo = _get_contentInfo,
1017 .create_certificate_enumerator = _create_certificate_enumerator,
1018 .set_certificate = _set_certificate,
1019 .set_attributes = _set_attributes,
1020 .get_attributes = _get_attributes,
1021 .build_envelopedData = _build_envelopedData,
1022 .build_signedData = _build_signedData,
1023 .destroy = _destroy,
1024 },
1025 .type = OID_UNKNOWN,
1026 .certs = linked_list_create(),
1027 );
1028
1029 return this;
1030 }
1031
1032 /*
1033 * Described in header.
1034 */
1035 pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level)
1036 {
1037 private_pkcs7_t *this = pkcs7_create_empty();
1038
1039 this->level = level;
1040 this->data = chunk_clone(chunk);
1041
1042 return &this->public;
1043 }
1044
1045 /*
1046 * Described in header.
1047 */
1048 pkcs7_t *pkcs7_create_from_data(chunk_t data)
1049 {
1050 private_pkcs7_t *this = pkcs7_create_empty();
1051
1052 this->data = chunk_clone(data);
1053
1054 return &this->public;
1055 }
1056