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