build_signedData() now computes messageDigest attribute
[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 * Hochschule fuer Technik Rapperswil, Switzerland
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 *
23 * RCSID $Id$
24 */
25
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include <library.h>
30 #include "debug.h"
31
32 #include <asn1/asn1.h>
33 #include <asn1/oid.h>
34 #include <crypto/x509.h>
35 #include <crypto/pkcs9.h>
36 #include <crypto/hashers/hasher.h>
37 #include <crypto/crypters/crypter.h>
38 #include <crypto/rsa/rsa_public_key.h>
39 #include <utils/randomizer.h>
40 #include <utils/linked_list.h>
41
42 #include "pkcs7.h"
43
44 typedef struct private_pkcs7_t private_pkcs7_t;
45
46 /**
47 * Private data of a pkcs7_t object.
48 */
49 struct private_pkcs7_t {
50 /**
51 * Public interface for this certificate.
52 */
53 pkcs7_t public;
54
55 /**
56 * contentInfo type
57 */
58 int type;
59
60 /**
61 * ASN.1 encoded content
62 */
63 chunk_t content;
64
65 /**
66 * Has the content already been parsed?
67 */
68 bool parsed;
69
70 /**
71 * ASN.1 parsing start level
72 */
73 u_int level;
74
75 /**
76 * retrieved data
77 */
78 chunk_t data;
79
80 /**
81 * ASN.1 encoded attributes
82 */
83 pkcs9_t *attributes;
84
85 /**
86 * Linked list of X.509 certificates
87 */
88 linked_list_t *certs;
89 };
90
91 /**
92 * ASN.1 definition of the PKCS#7 ContentInfo type
93 */
94 static const asn1Object_t contentInfoObjects[] = {
95 { 0, "contentInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
96 { 1, "contentType", ASN1_OID, ASN1_BODY }, /* 1 */
97 { 1, "content", ASN1_CONTEXT_C_0, ASN1_OPT |
98 ASN1_BODY }, /* 2 */
99 { 1, "end opt", ASN1_EOC, ASN1_END } /* 3 */
100 };
101
102 #define PKCS7_INFO_TYPE 1
103 #define PKCS7_INFO_CONTENT 2
104 #define PKCS7_INFO_ROOF 4
105
106 /**
107 * ASN.1 definition of the PKCS#7 signedData type
108 */
109 static const asn1Object_t signedDataObjects[] = {
110 { 0, "signedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
111 { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
112 { 1, "digestAlgorithms", ASN1_SET, ASN1_LOOP }, /* 2 */
113 { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 3 */
114 { 1, "end loop", ASN1_EOC, ASN1_END }, /* 4 */
115 { 1, "contentInfo", ASN1_EOC, ASN1_RAW }, /* 5 */
116 { 1, "certificates", ASN1_CONTEXT_C_0, ASN1_OPT |
117 ASN1_LOOP }, /* 6 */
118 { 2, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 7 */
119 { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 8 */
120 { 1, "crls", ASN1_CONTEXT_C_1, ASN1_OPT |
121 ASN1_LOOP }, /* 9 */
122 { 2, "crl", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */
123 { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 11 */
124 { 1, "signerInfos", ASN1_SET, ASN1_LOOP }, /* 12 */
125 { 2, "signerInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */
126 { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 14 */
127 { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 15 */
128 { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 16 */
129 { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 17 */
130 { 3, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 18 */
131 { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0, ASN1_OPT |
132 ASN1_OBJ }, /* 19 */
133 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
134 { 3, "digestEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */
135 { 3, "encryptedDigest", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */
136 { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 23 */
137 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 24 */
138 { 1, "end loop", ASN1_EOC, ASN1_END } /* 25 */
139 };
140
141 #define PKCS7_DIGEST_ALG 3
142 #define PKCS7_SIGNED_CONTENT_INFO 5
143 #define PKCS7_SIGNED_CERT 7
144 #define PKCS7_SIGNER_INFO 13
145 #define PKCS7_SIGNED_ISSUER 16
146 #define PKCS7_SIGNED_SERIAL_NUMBER 17
147 #define PKCS7_DIGEST_ALGORITHM 18
148 #define PKCS7_AUTH_ATTRIBUTES 19
149 #define PKCS7_DIGEST_ENC_ALGORITHM 21
150 #define PKCS7_ENCRYPTED_DIGEST 22
151 #define PKCS7_SIGNED_ROOF 26
152
153 /**
154 * ASN.1 definition of the PKCS#7 envelopedData type
155 */
156 static const asn1Object_t envelopedDataObjects[] = {
157 { 0, "envelopedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
158 { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
159 { 1, "recipientInfos", ASN1_SET, ASN1_LOOP }, /* 2 */
160 { 2, "recipientInfo", ASN1_SEQUENCE, ASN1_BODY }, /* 3 */
161 { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 4 */
162 { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */
163 { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */
164 { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 7 */
165 { 3, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 8 */
166 { 3, "encryptedKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */
167 { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */
168 { 1, "encryptedContentInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
169 { 2, "contentType", ASN1_OID, ASN1_BODY }, /* 12 */
170 { 2, "contentEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 13 */
171 { 2, "encryptedContent", ASN1_CONTEXT_S_0, ASN1_BODY } /* 14 */
172 };
173
174 #define PKCS7_ENVELOPED_VERSION 1
175 #define PKCS7_RECIPIENT_INFO_VERSION 4
176 #define PKCS7_ISSUER 6
177 #define PKCS7_SERIAL_NUMBER 7
178 #define PKCS7_ENCRYPTION_ALG 8
179 #define PKCS7_ENCRYPTED_KEY 9
180 #define PKCS7_CONTENT_TYPE 12
181 #define PKCS7_CONTENT_ENC_ALGORITHM 13
182 #define PKCS7_ENCRYPTED_CONTENT 14
183 #define PKCS7_ENVELOPED_ROOF 15
184
185 /**
186 * PKCS7 contentInfo OIDs
187 */
188 static u_char ASN1_pkcs7_data_oid_str[] = {
189 0x06, 0x09,
190 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01
191 };
192
193 static u_char ASN1_pkcs7_signed_data_oid_str[] = {
194 0x06, 0x09,
195 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02
196 };
197
198 static u_char ASN1_pkcs7_enveloped_data_oid_str[] = {
199 0x06, 0x09,
200 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x03
201 };
202
203 static u_char ASN1_pkcs7_signed_enveloped_data_oid_str[] = {
204 0x06, 0x09,
205 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x04
206 };
207
208 static u_char ASN1_pkcs7_digested_data_oid_str[] = {
209 0x06, 0x09,
210 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x05
211 };
212
213 static char ASN1_pkcs7_encrypted_data_oid_str[] = {
214 0x06, 0x09,
215 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06
216 };
217
218 static const chunk_t ASN1_pkcs7_data_oid =
219 chunk_from_buf(ASN1_pkcs7_data_oid_str);
220 static const chunk_t ASN1_pkcs7_signed_data_oid =
221 chunk_from_buf(ASN1_pkcs7_signed_data_oid_str);
222 static const chunk_t ASN1_pkcs7_enveloped_data_oid =
223 chunk_from_buf(ASN1_pkcs7_enveloped_data_oid_str);
224 static const chunk_t ASN1_pkcs7_signed_enveloped_data_oid =
225 chunk_from_buf(ASN1_pkcs7_signed_enveloped_data_oid_str);
226 static const chunk_t ASN1_pkcs7_digested_data_oid =
227 chunk_from_buf(ASN1_pkcs7_digested_data_oid_str);
228 static const chunk_t ASN1_pkcs7_encrypted_data_oid =
229 chunk_from_buf(ASN1_pkcs7_encrypted_data_oid_str);
230
231 /**
232 * 3DES and DES encryption OIDs
233 */
234 static u_char ASN1_3des_ede_cbc_oid_str[] = {
235 0x06, 0x08,
236 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x07
237 };
238
239 static u_char ASN1_des_cbc_oid_str[] = {
240 0x06, 0x05,
241 0x2B, 0x0E, 0x03, 0x02, 0x07
242 };
243
244 static const chunk_t ASN1_3des_ede_cbc_oid =
245 chunk_from_buf(ASN1_3des_ede_cbc_oid_str);
246 static const chunk_t ASN1_des_cbc_oid =
247 chunk_from_buf(ASN1_des_cbc_oid_str);
248
249 /**
250 * Implements pkcs7_t.is_data.
251 */
252 static bool is_data(private_pkcs7_t *this)
253 {
254 return this->type == OID_PKCS7_DATA;
255 }
256
257 /**
258 * Implements pkcs7_t.is_signedData.
259 */
260 static bool is_signedData(private_pkcs7_t *this)
261 {
262 return this->type == OID_PKCS7_SIGNED_DATA;
263 }
264
265 /**
266 * Implements pkcs7_t.is_envelopedData.
267 */
268 static bool is_envelopedData(private_pkcs7_t *this)
269 {
270 return this->type == OID_PKCS7_ENVELOPED_DATA;
271 }
272
273 /**
274 * Check whether to abort the requested parsing
275 */
276 static bool abort_parsing(private_pkcs7_t *this, int type)
277 {
278 if (this->type != type)
279 {
280 DBG1("pkcs7 content to be parsed is not of type '%s'",
281 oid_names[type]);
282 return TRUE;
283 }
284 if (this->parsed)
285 {
286 DBG1("pkcs7 content has already been parsed");
287 return TRUE;
288 }
289 this->parsed = TRUE;
290 return FALSE;
291 }
292
293 /**
294 * Implements pkcs7_t.parse_data.
295 */
296 static bool parse_data(private_pkcs7_t *this)
297 {
298 chunk_t data = this->content;
299
300 if (abort_parsing(this, OID_PKCS7_DATA))
301 {
302 return FALSE;
303 }
304 if (parse_asn1_simple_object(&data, ASN1_OCTET_STRING, this->level, "data"))
305 {
306 this->data = chunk_clone(data);
307 return TRUE;
308 }
309 else
310 {
311 return FALSE;
312 }
313 }
314
315 /**
316 * Parse PKCS#7 signedData content
317 */
318 static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert)
319 {
320 asn1_ctx_t ctx;
321 chunk_t object;
322 u_int level;
323 int objectID = 0;
324
325 int digest_alg = OID_UNKNOWN;
326 int enc_alg = OID_UNKNOWN;
327 int signerInfos = 0;
328
329 chunk_t encrypted_digest = chunk_empty;
330
331 if (abort_parsing(this, OID_PKCS7_SIGNED_DATA))
332 {
333 return FALSE;
334 }
335
336 asn1_init(&ctx, this->content, this->level, FALSE, FALSE);
337
338 while (objectID < PKCS7_SIGNED_ROOF)
339 {
340 if (!extract_object(signedDataObjects, &objectID, &object, &level, &ctx))
341 {
342 return FALSE;
343 }
344
345 switch (objectID)
346 {
347 case PKCS7_DIGEST_ALG:
348 digest_alg = parse_algorithmIdentifier(object, level, NULL);
349 break;
350 case PKCS7_SIGNED_CONTENT_INFO:
351 {
352 pkcs7_t *data = pkcs7_create_from_chunk(object, level+1);
353
354 if (data == NULL)
355 {
356 return FALSE;
357 }
358 if (!data->parse_data(data))
359 {
360 data->destroy(data);
361 return FALSE;
362 }
363 this->data = chunk_clone(data->get_data(data));
364 data->destroy(data);
365 }
366 break;
367 case PKCS7_SIGNED_CERT:
368 {
369 x509_t *cert = x509_create_from_chunk(chunk_clone(object), level+1);
370
371 if (cert)
372 {
373 this->certs->insert_last(this->certs, (void*)cert);
374 }
375 }
376 break;
377 case PKCS7_SIGNER_INFO:
378 signerInfos++;
379 DBG2(" signer #%d", signerInfos);
380 break;
381 case PKCS7_SIGNED_ISSUER:
382 {
383 identification_t *issuer;
384
385 issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
386 DBG2(" '%D'", issuer);
387 issuer->destroy(issuer);
388 }
389 break;
390 case PKCS7_AUTH_ATTRIBUTES:
391 *object.ptr = ASN1_SET;
392 this->attributes = pkcs9_create_from_chunk(object, level+1);
393 *object.ptr = ASN1_CONTEXT_C_0;
394 break;
395 case PKCS7_DIGEST_ALGORITHM:
396 digest_alg = parse_algorithmIdentifier(object, level, NULL);
397 break;
398 case PKCS7_DIGEST_ENC_ALGORITHM:
399 enc_alg = parse_algorithmIdentifier(object, level, NULL);
400 break;
401 case PKCS7_ENCRYPTED_DIGEST:
402 encrypted_digest = object;
403 }
404 objectID++;
405 }
406
407 /* check the signature only if a cacert is available */
408 if (cacert != NULL)
409 {
410 hash_algorithm_t algorithm = hasher_algorithm_from_oid(digest_alg);
411 rsa_public_key_t *signer = cacert->get_public_key(cacert);
412
413 if (signerInfos == 0)
414 {
415 DBG1("no signerInfo object found");
416 return FALSE;
417 }
418 else if (signerInfos > 1)
419 {
420 DBG1("more than one signerInfo object found");
421 return FALSE;
422 }
423 if (this->attributes == NULL)
424 {
425 DBG1("no authenticatedAttributes object found");
426 return FALSE;
427 }
428 if (enc_alg != OID_RSA_ENCRYPTION)
429 {
430 DBG1("only RSA digest encryption supported");
431 return FALSE;
432 }
433 if (signer->verify_emsa_pkcs1_signature(signer, algorithm,
434 this->attributes->get_encoding(this->attributes), encrypted_digest) != SUCCESS)
435 {
436 DBG1("invalid digest signature");
437 return FALSE;
438 }
439 else
440 {
441 DBG2("digest signature is valid");
442 }
443 if (this->data.ptr != NULL)
444 {
445 chunk_t messageDigest = this->attributes->get_messageDigest(this->attributes);
446
447 if (messageDigest.ptr == NULL)
448 {
449 DBG1("messageDigest attribute not found");
450 return FALSE;
451 }
452 else
453 {
454 hasher_t *hasher = hasher_create(algorithm);
455 chunk_t hash;
456 bool valid;
457
458 hasher->allocate_hash(hasher, this->data, &hash);
459 hasher->destroy(hasher);
460 DBG3("hash: %B", &hash);
461
462 valid = chunk_equals(messageDigest, hash);
463 free(messageDigest.ptr);
464 free(hash.ptr);
465 if (valid)
466 {
467 DBG2("messageDigest is valid");
468 }
469 else
470 {
471 DBG1("invalid messageDigest");
472 return FALSE;
473 }
474 }
475 }
476 }
477 return TRUE;
478 }
479
480 /**
481 * Parse PKCS#7 envelopedData content
482 */
483 static bool parse_envelopedData(private_pkcs7_t *this, chunk_t serialNumber,
484 rsa_private_key_t *key)
485 {
486 asn1_ctx_t ctx;
487 chunk_t object;
488 u_int level;
489 int objectID = 0;
490
491 chunk_t iv = chunk_empty;
492 chunk_t symmetric_key = chunk_empty;
493 chunk_t encrypted_content = chunk_empty;
494
495 crypter_t *crypter = NULL;
496
497 if (abort_parsing(this, OID_PKCS7_ENVELOPED_DATA))
498 {
499 return FALSE;
500 }
501
502 asn1_init(&ctx, this->content, this->level, FALSE, FALSE);
503
504 while (objectID < PKCS7_ENVELOPED_ROOF)
505 {
506 if (!extract_object(envelopedDataObjects, &objectID, &object, &level, &ctx))
507 {
508 goto failed;
509 }
510
511 switch (objectID)
512 {
513 case PKCS7_ENVELOPED_VERSION:
514 if (*object.ptr != 0)
515 {
516 DBG1("envelopedData version is not 0");
517 goto failed;
518 }
519 break;
520 case PKCS7_RECIPIENT_INFO_VERSION:
521 if (*object.ptr != 0)
522 {
523 DBG1("recipient info version is not 0");
524 goto failed;
525 }
526 break;
527 case PKCS7_ISSUER:
528 {
529 identification_t *issuer;
530
531 issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
532 DBG2(" '%D'", issuer);
533 issuer->destroy(issuer);
534 }
535 break;
536 case PKCS7_SERIAL_NUMBER:
537 if (!chunk_equals(serialNumber, object))
538 {
539 DBG1("serial numbers do not match");
540 goto failed;
541 }
542 break;
543 case PKCS7_ENCRYPTION_ALG:
544 {
545 int alg = parse_algorithmIdentifier(object, level, NULL);
546
547 if (alg != OID_RSA_ENCRYPTION)
548 {
549 DBG1("only rsa encryption supported");
550 goto failed;
551 }
552 }
553 break;
554 case PKCS7_ENCRYPTED_KEY:
555 if (key->pkcs1_decrypt(key, object, &symmetric_key) != SUCCESS)
556 {
557 DBG1("symmetric key could not be decrypted with rsa");
558 goto failed;
559 }
560 DBG4("symmetric key : %B", &symmetric_key);
561 break;
562 case PKCS7_CONTENT_TYPE:
563 if (known_oid(object) != OID_PKCS7_DATA)
564 {
565 DBG1("encrypted content not of type pkcs7 data");
566 goto failed;
567 }
568 break;
569 case PKCS7_CONTENT_ENC_ALGORITHM:
570 {
571 int alg = parse_algorithmIdentifier(object, level, &iv);
572
573 switch (alg)
574 {
575 case OID_DES_CBC:
576 crypter = crypter_create(ENCR_DES, 0);
577 break;
578 case OID_3DES_EDE_CBC:
579 crypter = crypter_create(ENCR_3DES, 0);
580 break;
581 default:
582 DBG1("Only DES and 3DES supported for symmetric encryption");
583 goto failed;
584 }
585 if (symmetric_key.len != crypter->get_key_size(crypter))
586 {
587 DBG1("symmetric key has wrong length");
588 goto failed;
589 }
590 if (!parse_asn1_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV"))
591 {
592 DBG1("IV could not be parsed");
593 goto failed;
594 }
595 if (iv.len != crypter->get_block_size(crypter))
596 {
597 DBG1("IV has wrong length");
598 goto failed;
599 }
600 }
601 break;
602 case PKCS7_ENCRYPTED_CONTENT:
603 encrypted_content = object;
604 break;
605 }
606 objectID++;
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 randomizer_t *randomizer = randomizer_create();
774
775 randomizer->allocate_random_bytes(randomizer,
776 crypter->get_key_size(crypter), &symmetricKey);
777 DBG4(" symmetric encryption key: %B", &symmetricKey);
778
779 randomizer->allocate_pseudo_random_bytes(randomizer,
780 crypter->get_block_size(crypter), &iv);
781 DBG4(" initialization vector: %B", &iv);
782
783 randomizer->destroy(randomizer);
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_free_randomized(&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_free_randomized(&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 /* take the current time as signingTime */
871 time_t now = time(NULL);
872 chunk_t signingTime = timetoasn1(&now, ASN1_UTCTIME);
873
874 chunk_t messageDigest, attributes;
875 hasher_t *hasher = hasher_create(alg);
876
877 hasher->allocate_hash(hasher, this->data, &messageDigest);
878 hasher->destroy(hasher);
879 this->attributes->set_attribute(this->attributes,
880 OID_PKCS9_CONTENT_TYPE, ASN1_pkcs7_data_oid);
881 this->attributes->set_messageDigest(this->attributes,
882 messageDigest);
883 this->attributes->set_attribute(this->attributes,
884 OID_PKCS9_SIGNING_TIME, signingTime);
885 attributes = this->attributes->get_encoding(this->attributes);
886
887 free(messageDigest.ptr);
888 free(signingTime.ptr);
889
890 private_key->build_emsa_pkcs1_signature(private_key, alg,
891 attributes, &encryptedDigest);
892 authenticatedAttributes = chunk_clone(attributes);
893 *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
894 }
895 }
896 else if (this->data.ptr != NULL)
897 {
898 private_key->build_emsa_pkcs1_signature(private_key, alg,
899 this->data, &encryptedDigest);
900 }
901 if (encryptedDigest.ptr)
902 {
903 encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", encryptedDigest);
904 }
905
906 signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmcmcm",
907 ASN1_INTEGER_1,
908 pkcs7_build_issuerAndSerialNumber(cert),
909 asn1_algorithmIdentifier(signature_oid),
910 authenticatedAttributes,
911 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
912 encryptedDigest);
913
914 if (this->data.ptr != NULL)
915 {
916 this->content = asn1_simple_object(ASN1_OCTET_STRING, this->data);
917 chunk_free(&this->data);
918 }
919 this->type = OID_PKCS7_DATA;
920 this->data = get_contentInfo(this);
921 chunk_free(&this->content);
922
923 this->type = OID_PKCS7_SIGNED_DATA;
924
925 this->content = asn1_wrap(ASN1_SEQUENCE, "cmcmm",
926 ASN1_INTEGER_1,
927 asn1_simple_object(ASN1_SET, asn1_algorithmIdentifier(signature_oid)),
928 this->data,
929 asn1_simple_object(ASN1_CONTEXT_C_0, cert->get_certificate(cert)),
930 asn1_wrap(ASN1_SET, "m", signerInfo));
931
932 return TRUE;
933 }
934
935 /**
936 * Implements pkcs7_t.destroy
937 */
938 static void destroy(private_pkcs7_t *this)
939 {
940 DESTROY_IF(this->attributes);
941 this->certs->destroy_offset(this->certs, offsetof(x509_t, destroy));
942 free(this->content.ptr);
943 free(this->data.ptr);
944 free(this);
945 }
946
947 /**
948 * Parse PKCS#7 contentInfo object
949 */
950 static bool parse_contentInfo(chunk_t blob, u_int level0, private_pkcs7_t *cInfo)
951 {
952 asn1_ctx_t ctx;
953 chunk_t object;
954 u_int level;
955 int objectID = 0;
956
957 asn1_init(&ctx, blob, level0, FALSE, FALSE);
958
959 while (objectID < PKCS7_INFO_ROOF)
960 {
961 if (!extract_object(contentInfoObjects, &objectID, &object, &level, &ctx))
962 {
963 return FALSE;
964 }
965
966 if (objectID == PKCS7_INFO_TYPE)
967 {
968 cInfo->type = known_oid(object);
969 if (cInfo->type < OID_PKCS7_DATA
970 || cInfo->type > OID_PKCS7_ENCRYPTED_DATA)
971 {
972 DBG1("unknown pkcs7 content type");
973 return FALSE;
974 }
975 }
976 else if (objectID == PKCS7_INFO_CONTENT)
977 {
978 cInfo->content = chunk_clone(object);
979 }
980 objectID++;
981 }
982 return TRUE;
983 }
984
985 /**
986 * Generic private constructor
987 */
988 static private_pkcs7_t *pkcs7_create_empty(void)
989 {
990 private_pkcs7_t *this = malloc_thing(private_pkcs7_t);
991
992 /* initialize */
993 this->type = OID_UNKNOWN;
994 this->content = chunk_empty;
995 this->parsed = FALSE;
996 this->level = 0;
997 this->data = chunk_empty;
998 this->attributes = NULL;
999 this->certs = linked_list_create();
1000
1001 /*public functions */
1002 this->public.is_data = (bool (*) (pkcs7_t*))is_data;
1003 this->public.is_signedData = (bool (*) (pkcs7_t*))is_signedData;
1004 this->public.is_envelopedData = (bool (*) (pkcs7_t*))is_envelopedData;
1005 this->public.parse_data = (bool (*) (pkcs7_t*))parse_data;
1006 this->public.parse_signedData = (bool (*) (pkcs7_t*,x509_t*))parse_signedData;
1007 this->public.parse_envelopedData = (bool (*) (pkcs7_t*,chunk_t,rsa_private_key_t*))parse_envelopedData;
1008 this->public.get_data = (chunk_t (*) (pkcs7_t*))get_data;
1009 this->public.get_contentInfo = (chunk_t (*) (pkcs7_t*))get_contentInfo;
1010 this->public.create_certificate_iterator = (iterator_t* (*) (pkcs7_t*))create_certificate_iterator;
1011 this->public.set_certificate = (void (*) (pkcs7_t*,x509_t*))set_certificate;
1012 this->public.set_attributes = (void (*) (pkcs7_t*,pkcs9_t*))set_attributes;
1013 this->public.build_envelopedData = (bool (*) (pkcs7_t*,x509_t*,encryption_algorithm_t))build_envelopedData;
1014 this->public.build_signedData = (bool (*) (pkcs7_t*,rsa_private_key_t*,hash_algorithm_t))build_signedData;
1015 this->public.destroy = (void (*) (pkcs7_t*))destroy;
1016
1017 return this;
1018 }
1019
1020 /*
1021 * Described in header.
1022 */
1023 pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level)
1024 {
1025 private_pkcs7_t *this = pkcs7_create_empty();
1026
1027 this->level = level + 2;
1028 if (!parse_contentInfo(chunk, level, this))
1029 {
1030 destroy(this);
1031 return NULL;
1032 }
1033 return &this->public;
1034 }
1035
1036 /*
1037 * Described in header.
1038 */
1039 pkcs7_t *pkcs7_create_from_data(chunk_t data)
1040 {
1041 private_pkcs7_t *this = pkcs7_create_empty();
1042
1043 this->data = chunk_clone(data);
1044 this->parsed = TRUE;
1045
1046 return &this->public;
1047 }
1048
1049 /*
1050 * Described in header.
1051 */
1052 pkcs7_t *pkcs7_create_from_file(const char *filename, const char *label)
1053 {
1054 bool pgp = FALSE;
1055 chunk_t chunk = chunk_empty;
1056 char cert_label[BUF_LEN];
1057 pkcs7_t *pkcs7;
1058
1059 snprintf(cert_label, BUF_LEN, "%s pkcs7", label);
1060
1061 if (!pem_asn1_load_file(filename, NULL, cert_label, &chunk, &pgp))
1062 {
1063 return NULL;
1064 }
1065
1066 pkcs7 = pkcs7_create_from_chunk(chunk, 0);
1067 free(chunk.ptr);
1068 return pkcs7;
1069 }