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