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