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