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