extended and debugged PKCS#7 signedData support
[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 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 this->data = chunk_clone(object);
352 break;
353 case PKCS7_SIGNED_CERT:
354 {
355 x509_t *cert = x509_create_from_chunk(chunk_clone(object), level+1);
356
357 if (cert)
358 {
359 this->certs->insert_last(this->certs, (void*)cert);
360 }
361 }
362 break;
363 case PKCS7_SIGNER_INFO:
364 signerInfos++;
365 DBG2(" signer #%d", signerInfos);
366 break;
367 case PKCS7_SIGNED_ISSUER:
368 {
369 identification_t *issuer;
370
371 issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
372 DBG2(" '%D'", issuer);
373 issuer->destroy(issuer);
374 }
375 break;
376 case PKCS7_AUTH_ATTRIBUTES:
377 *object.ptr = ASN1_SET;
378 this->attributes = pkcs9_create_from_chunk(object, level+1);
379 break;
380 case PKCS7_DIGEST_ALGORITHM:
381 digest_alg = parse_algorithmIdentifier(object, level, NULL);
382 break;
383 case PKCS7_DIGEST_ENC_ALGORITHM:
384 enc_alg = parse_algorithmIdentifier(object, level, NULL);
385 break;
386 case PKCS7_ENCRYPTED_DIGEST:
387 encrypted_digest = object;
388 }
389 objectID++;
390 }
391
392 /* check the signature only if a cacert is available */
393 if (cacert != NULL)
394 {
395 hash_algorithm_t algorithm = hasher_algorithm_from_oid(digest_alg);
396 rsa_public_key_t *signer = cacert->get_public_key(cacert);
397
398 if (signerInfos == 0)
399 {
400 DBG1("no signerInfo object found");
401 return FALSE;
402 }
403 else if (signerInfos > 1)
404 {
405 DBG1("more than one signerInfo object found");
406 return FALSE;
407 }
408 if (this->attributes == NULL)
409 {
410 DBG1("no authenticatedAttributes object found");
411 return FALSE;
412 }
413 if (enc_alg != OID_RSA_ENCRYPTION)
414 {
415 DBG1("only RSA digest encryption supported");
416 return FALSE;
417 }
418 if (signer->verify_emsa_pkcs1_signature(signer, algorithm,
419 this->attributes->get_encoding(this->attributes), encrypted_digest) != SUCCESS)
420 {
421 DBG1("invalid digest signature");
422 return FALSE;
423 }
424 else
425 {
426 DBG2("digest signature is valid");
427 }
428 }
429 return TRUE;
430 }
431
432 /**
433 * Parse PKCS#7 envelopedData content
434 */
435 static bool parse_envelopedData(private_pkcs7_t *this, chunk_t serialNumber,
436 rsa_private_key_t *key)
437 {
438 asn1_ctx_t ctx;
439 chunk_t object;
440 u_int level;
441 int objectID = 0;
442
443 chunk_t iv = chunk_empty;
444 chunk_t symmetric_key = chunk_empty;
445 chunk_t encrypted_content = chunk_empty;
446
447 crypter_t *crypter = NULL;
448
449 if (abort_parsing(this, OID_PKCS7_ENVELOPED_DATA))
450 {
451 return FALSE;
452 }
453
454 asn1_init(&ctx, this->content, this->level, FALSE, FALSE);
455
456 while (objectID < PKCS7_ENVELOPED_ROOF)
457 {
458 if (!extract_object(envelopedDataObjects, &objectID, &object, &level, &ctx))
459 {
460 goto failed;
461 }
462
463 switch (objectID)
464 {
465 case PKCS7_ENVELOPED_VERSION:
466 if (*object.ptr != 0)
467 {
468 DBG1("envelopedData version is not 0");
469 goto failed;
470 }
471 break;
472 case PKCS7_RECIPIENT_INFO_VERSION:
473 if (*object.ptr != 0)
474 {
475 DBG1("recipient info version is not 0");
476 goto failed;
477 }
478 break;
479 case PKCS7_ISSUER:
480 {
481 identification_t *issuer;
482
483 issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
484 DBG2(" '%D'", issuer);
485 issuer->destroy(issuer);
486 }
487 break;
488 case PKCS7_SERIAL_NUMBER:
489 if (!chunk_equals(serialNumber, object))
490 {
491 DBG1("serial numbers do not match");
492 goto failed;
493 }
494 break;
495 case PKCS7_ENCRYPTION_ALG:
496 {
497 int alg = parse_algorithmIdentifier(object, level, NULL);
498
499 if (alg != OID_RSA_ENCRYPTION)
500 {
501 DBG1("only rsa encryption supported");
502 goto failed;
503 }
504 }
505 break;
506 case PKCS7_ENCRYPTED_KEY:
507 if (key->pkcs1_decrypt(key, object, &symmetric_key) != SUCCESS)
508 {
509 DBG1("symmetric key could not be decrypted with rsa");
510 goto failed;
511 }
512 DBG4("symmetric key : %B", &symmetric_key);
513 break;
514 case PKCS7_CONTENT_TYPE:
515 if (known_oid(object) != OID_PKCS7_DATA)
516 {
517 DBG1("encrypted content not of type pkcs7 data");
518 goto failed;
519 }
520 break;
521 case PKCS7_CONTENT_ENC_ALGORITHM:
522 {
523 int alg = parse_algorithmIdentifier(object, level, &iv);
524
525 switch (alg)
526 {
527 case OID_DES_CBC:
528 crypter = crypter_create(ENCR_DES, 0);
529 break;
530 case OID_3DES_EDE_CBC:
531 crypter = crypter_create(ENCR_3DES, 0);
532 break;
533 default:
534 DBG1("Only DES and 3DES supported for symmetric encryption");
535 goto failed;
536 }
537 if (symmetric_key.len != crypter->get_key_size(crypter))
538 {
539 DBG1("symmetric key has wrong length");
540 goto failed;
541 }
542 if (!parse_asn1_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV"))
543 {
544 DBG1("IV could not be parsed");
545 goto failed;
546 }
547 if (iv.len != crypter->get_block_size(crypter))
548 {
549 DBG1("IV has wrong length");
550 goto failed;
551 }
552 }
553 break;
554 case PKCS7_ENCRYPTED_CONTENT:
555 encrypted_content = object;
556 break;
557 }
558 objectID++;
559 }
560
561 /* decrypt the content */
562 crypter->set_key(crypter, symmetric_key);
563 crypter->decrypt(crypter, encrypted_content, iv, &this->data);
564 DBG3("decrypted content with padding: %B", &this->data);
565
566 /* remove the padding */
567 {
568 u_char *pos = this->data.ptr + this->data.len - 1;
569 u_char pattern = *pos;
570 size_t padding = pattern;
571
572 if (padding > this->data.len)
573 {
574 DBG1("padding greater than data length");
575 goto failed;
576 }
577 this->data.len -= padding;
578
579 while (padding-- > 0)
580 {
581 if (*pos-- != pattern)
582 {
583 DBG1("wrong padding pattern");
584 goto failed;
585 }
586 }
587 }
588 crypter->destroy(crypter);
589 free(symmetric_key.ptr);
590 return TRUE;
591
592 failed:
593 DESTROY_IF(crypter);
594 free(symmetric_key.ptr);
595 chunk_free(&this->data);
596 return FALSE;
597 }
598
599 /**
600 * Implements pkcs7_t.get_data.
601 */
602 static chunk_t get_data(private_pkcs7_t *this)
603 {
604 return this->data;
605 }
606
607 /**
608 * Implements pkcs7_t.get_contentInfo.
609 */
610 static chunk_t get_contentInfo(private_pkcs7_t *this)
611 {
612 chunk_t content_type;
613
614 /* select DER-encoded OID for pkcs7_contentInfo type */
615 switch(this->type)
616 {
617 case OID_PKCS7_DATA:
618 content_type = ASN1_pkcs7_data_oid;
619 break;
620 case OID_PKCS7_SIGNED_DATA:
621 content_type = ASN1_pkcs7_signed_data_oid;
622 break;
623 case OID_PKCS7_ENVELOPED_DATA:
624 content_type = ASN1_pkcs7_enveloped_data_oid;
625 break;
626 case OID_PKCS7_SIGNED_ENVELOPED_DATA:
627 content_type = ASN1_pkcs7_signed_enveloped_data_oid;
628 break;
629 case OID_PKCS7_DIGESTED_DATA:
630 content_type = ASN1_pkcs7_digested_data_oid;
631 break;
632 case OID_PKCS7_ENCRYPTED_DATA:
633 content_type = ASN1_pkcs7_encrypted_data_oid;
634 break;
635 case OID_UNKNOWN:
636 default:
637 DBG1("invalid pkcs7 contentInfo type");
638 return chunk_empty;
639 }
640
641 return (this->content.ptr == NULL)
642 ? asn1_simple_object(ASN1_SEQUENCE, content_type)
643 : asn1_wrap(ASN1_SEQUENCE, "cm",
644 content_type,
645 asn1_simple_object(ASN1_CONTEXT_C_0, this->content)
646 );
647 }
648
649 /**
650 * Implements pkcs7_t.create_certificate_iterator
651 */
652 static iterator_t *create_certificate_iterator(const private_pkcs7_t *this)
653 {
654 return this->certs->create_iterator(this->certs, TRUE);
655 }
656
657 /**
658 * Implements pkcs7_t.set_certificate
659 */
660 static void set_certificate(private_pkcs7_t *this, x509_t *cert)
661 {
662 if (cert)
663 {
664 /* TODO the certificate is currently not cloned */
665 this->certs->insert_last(this->certs, cert);
666 }
667 }
668
669 /**
670 * Implements pkcs7_t.set_attributes
671 */
672 static void set_attributes(private_pkcs7_t *this, pkcs9_t *attributes)
673 {
674 this->attributes = attributes;
675 }
676
677 /**
678 * build a DER-encoded issuerAndSerialNumber object
679 */
680 chunk_t pkcs7_build_issuerAndSerialNumber(x509_t *cert)
681 {
682 identification_t *issuer = cert->get_issuer(cert);
683
684 return asn1_wrap(ASN1_SEQUENCE, "cm",
685 issuer->get_encoding(issuer),
686 asn1_simple_object(ASN1_INTEGER, cert->get_serialNumber(cert)));
687 }
688
689 /**
690 * Implements pkcs7_t.build_envelopedData.
691 */
692 bool build_envelopedData(private_pkcs7_t *this, x509_t *cert,
693 encryption_algorithm_t alg)
694 {
695 chunk_t iv, symmetricKey, in, out, alg_oid;
696 crypter_t *crypter;
697
698 /* select OID of symmetric encryption algorithm */
699 switch (alg)
700 {
701 case ENCR_DES:
702 alg_oid = ASN1_des_cbc_oid;
703 break;
704 case ENCR_3DES:
705 alg_oid = ASN1_3des_ede_cbc_oid;
706 break;
707 default:
708 DBG1(" encryption algorithm %N not supported",
709 encryption_algorithm_names, alg);
710 return FALSE;
711 }
712
713 crypter = crypter_create(alg, 0);
714 if (crypter == NULL)
715 {
716 DBG1(" could not create crypter for algorithm %N",
717 encryption_algorithm_names, alg);
718 return FALSE;
719 }
720
721 /* generate a true random symmetric encryption key
722 * and a pseudo-random iv
723 */
724 {
725 randomizer_t *randomizer = randomizer_create();
726
727 randomizer->allocate_random_bytes(randomizer,
728 crypter->get_key_size(crypter), &symmetricKey);
729 DBG4(" symmetric encryption key: %B", &symmetricKey);
730
731 randomizer->allocate_pseudo_random_bytes(randomizer,
732 crypter->get_block_size(crypter), &iv);
733 DBG4(" initialization vector: %B", &iv);
734
735 randomizer->destroy(randomizer);
736 }
737
738 /* pad the data so that the total length becomes
739 * a multiple of the block size
740 */
741 {
742 size_t block_size = crypter->get_block_size(crypter);
743 size_t padding = block_size - this->data.len % block_size;
744
745 in.len = this->data.len + padding;
746 in.ptr = malloc(in.len);
747
748 DBG2(" padding %d bytes of data to multiple block size of %d bytes",
749 (int)this->data.len, (int)in.len);
750
751 /* copy data */
752 memcpy(in.ptr, this->data.ptr, this->data.len);
753 /* append padding */
754 memset(in.ptr + this->data.len, padding, padding);
755 }
756 DBG3(" padded unencrypted data: %B", &in);
757
758 /* symmetric encryption of data object */
759 crypter->set_key(crypter, symmetricKey);
760 crypter->encrypt(crypter, in, iv, &out);
761 crypter->destroy(crypter);
762 chunk_free_randomized(&in);
763 DBG3(" encrypted data: %B", &out);
764
765 /* build pkcs7 enveloped data object */
766 {
767 chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "cm",
768 alg_oid,
769 asn1_wrap(ASN1_OCTET_STRING, "m", iv));
770
771 chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "cmm",
772 ASN1_pkcs7_data_oid,
773 contentEncryptionAlgorithm,
774 asn1_wrap(ASN1_CONTEXT_S_0, "m", out));
775
776 chunk_t wrappedKey, encryptedKey, recipientInfo;
777
778 rsa_public_key_t *public_key = cert->get_public_key(cert);
779
780 public_key->pkcs1_encrypt(public_key, symmetricKey, &wrappedKey);
781 chunk_free_randomized(&symmetricKey);
782
783 encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m", wrappedKey);
784
785 recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmcm",
786 ASN1_INTEGER_0,
787 pkcs7_build_issuerAndSerialNumber(cert),
788 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
789 encryptedKey);
790
791 this->content = asn1_wrap(ASN1_SEQUENCE, "cmm",
792 ASN1_INTEGER_0,
793 asn1_wrap(ASN1_SET, "m", recipientInfo),
794 encryptedContentInfo);
795 this->type = OID_PKCS7_ENVELOPED_DATA;
796 }
797 return TRUE;
798 }
799
800 /**
801 * Implements pkcs7_t.build_signedData.
802 */
803 bool build_signedData(private_pkcs7_t *this, rsa_private_key_t *private_key,
804 hash_algorithm_t alg)
805 {
806 int signature_oid = hasher_signature_algorithm_to_oid(alg);
807 chunk_t authenticatedAttributes = chunk_empty;
808 chunk_t encryptedDigest = chunk_empty;
809 chunk_t signerInfo;
810 x509_t *cert;
811
812 if (this->certs->get_first(this->certs, (void**)&cert) != SUCCESS)
813 {
814 DBG1(" no pkcs7 signer certificate found");
815 return FALSE;
816 }
817
818 if (this->attributes != NULL)
819 {
820 chunk_t attributes = this->attributes->get_encoding(this->attributes);
821
822 if (attributes.ptr)
823 {
824 private_key->build_emsa_pkcs1_signature(private_key, alg,
825 attributes, &encryptedDigest);
826 authenticatedAttributes = chunk_clone(attributes);
827 *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
828 }
829 }
830 else if (this->data.ptr != NULL)
831 {
832 private_key->build_emsa_pkcs1_signature(private_key, alg,
833 this->data, &encryptedDigest);
834 }
835 if (encryptedDigest.ptr)
836 {
837 encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", encryptedDigest);
838 }
839
840 signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmcmcm",
841 ASN1_INTEGER_1,
842 pkcs7_build_issuerAndSerialNumber(cert),
843 asn1_algorithmIdentifier(signature_oid),
844 authenticatedAttributes,
845 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
846 encryptedDigest);
847
848 if (this->data.ptr != NULL)
849 {
850 this->content = asn1_simple_object(ASN1_OCTET_STRING, this->data);
851 chunk_free(&this->data);
852 }
853 this->type = OID_PKCS7_DATA;
854 this->data = get_contentInfo(this);
855 chunk_free(&this->content);
856
857 this->type = OID_PKCS7_SIGNED_DATA;
858
859 this->content = asn1_wrap(ASN1_SEQUENCE, "cmcmm",
860 ASN1_INTEGER_1,
861 asn1_simple_object(ASN1_SET, asn1_algorithmIdentifier(signature_oid)),
862 this->data,
863 asn1_simple_object(ASN1_CONTEXT_C_0, cert->get_certificate(cert)),
864 asn1_wrap(ASN1_SET, "m", signerInfo));
865
866 return TRUE;
867 }
868
869 /**
870 * Implements pkcs7_t.destroy
871 */
872 static void destroy(private_pkcs7_t *this)
873 {
874 DESTROY_IF(this->attributes);
875 this->certs->destroy_offset(this->certs, offsetof(x509_t, destroy));
876 free(this->content.ptr);
877 free(this->data.ptr);
878 free(this);
879 }
880
881 /**
882 * Parse PKCS#7 contentInfo object
883 */
884 static bool parse_contentInfo(chunk_t blob, u_int level0, private_pkcs7_t *cInfo)
885 {
886 asn1_ctx_t ctx;
887 chunk_t object;
888 u_int level;
889 int objectID = 0;
890
891 asn1_init(&ctx, blob, level0, FALSE, FALSE);
892
893 while (objectID < PKCS7_INFO_ROOF)
894 {
895 if (!extract_object(contentInfoObjects, &objectID, &object, &level, &ctx))
896 {
897 return FALSE;
898 }
899
900 if (objectID == PKCS7_INFO_TYPE)
901 {
902 cInfo->type = known_oid(object);
903 if (cInfo->type < OID_PKCS7_DATA
904 || cInfo->type > OID_PKCS7_ENCRYPTED_DATA)
905 {
906 DBG1("unknown pkcs7 content type");
907 return FALSE;
908 }
909 }
910 else if (objectID == PKCS7_INFO_CONTENT)
911 {
912 cInfo->content = chunk_clone(object);
913 }
914 objectID++;
915 }
916 return TRUE;
917 }
918
919 /**
920 * Generic private constructor
921 */
922 static private_pkcs7_t *pkcs7_create_empty(void)
923 {
924 private_pkcs7_t *this = malloc_thing(private_pkcs7_t);
925
926 /* initialize */
927 this->type = OID_UNKNOWN;
928 this->content = chunk_empty;
929 this->parsed = FALSE;
930 this->level = 0;
931 this->data = chunk_empty;
932 this->attributes = NULL;
933 this->certs = linked_list_create();
934
935 /*public functions */
936 this->public.is_data = (bool (*) (pkcs7_t*))is_data;
937 this->public.is_signedData = (bool (*) (pkcs7_t*))is_signedData;
938 this->public.is_envelopedData = (bool (*) (pkcs7_t*))is_envelopedData;
939 this->public.parse_data = (bool (*) (pkcs7_t*))parse_data;
940 this->public.parse_signedData = (bool (*) (pkcs7_t*,x509_t*))parse_signedData;
941 this->public.parse_envelopedData = (bool (*) (pkcs7_t*,chunk_t,rsa_private_key_t*))parse_envelopedData;
942 this->public.get_data = (chunk_t (*) (pkcs7_t*))get_data;
943 this->public.get_contentInfo = (chunk_t (*) (pkcs7_t*))get_contentInfo;
944 this->public.create_certificate_iterator = (iterator_t* (*) (pkcs7_t*))create_certificate_iterator;
945 this->public.set_certificate = (void (*) (pkcs7_t*,x509_t*))set_certificate;
946 this->public.set_attributes = (void (*) (pkcs7_t*,pkcs9_t*))set_attributes;
947 this->public.build_envelopedData = (bool (*) (pkcs7_t*,x509_t*,encryption_algorithm_t))build_envelopedData;
948 this->public.build_signedData = (bool (*) (pkcs7_t*,rsa_private_key_t*,hash_algorithm_t))build_signedData;
949 this->public.destroy = (void (*) (pkcs7_t*))destroy;
950
951 return this;
952 }
953
954 /*
955 * Described in header.
956 */
957 pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level)
958 {
959 private_pkcs7_t *this = pkcs7_create_empty();
960
961 this->level = level + 2;
962 if (!parse_contentInfo(chunk, level, this))
963 {
964 destroy(this);
965 return NULL;
966 }
967 return &this->public;
968 }
969
970 /*
971 * Described in header.
972 */
973 pkcs7_t *pkcs7_create_from_data(chunk_t data)
974 {
975 private_pkcs7_t *this = pkcs7_create_empty();
976
977 this->data = chunk_clone(data);
978 this->parsed = TRUE;
979
980 return &this->public;
981 }
982
983 /*
984 * Described in header.
985 */
986 pkcs7_t *pkcs7_create_from_file(const char *filename, const char *label)
987 {
988 bool pgp = FALSE;
989 chunk_t chunk = chunk_empty;
990 char cert_label[BUF_LEN];
991 pkcs7_t *pkcs7;
992
993 snprintf(cert_label, BUF_LEN, "%s pkcs7", label);
994
995 if (!pem_asn1_load_file(filename, NULL, cert_label, &chunk, &pgp))
996 {
997 return NULL;
998 }
999
1000 pkcs7 = pkcs7_create_from_chunk(chunk, 0);
1001 free(chunk.ptr);
1002 return pkcs7;
1003 }