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