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