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