Use IV length of a crypter instead of block size for IV calculations
[strongswan.git] / src / pluto / pkcs7.c
1 /* Support of PKCS#7 data structures
2 * Copyright (C) 2005 Jan Hutter, Martin Willi
3 * Copyright (C) 2002-2009 Andreas Steffen
4 *
5 * HSR 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 #include <asn1/asn1.h>
25 #include <asn1/asn1_parser.h>
26 #include <asn1/oid.h>
27 #include <crypto/rngs/rng.h>
28 #include <crypto/crypters/crypter.h>
29 #include <credentials/certificates/x509.h>
30
31 #include "pkcs7.h"
32
33 const contentInfo_t empty_contentInfo = {
34 OID_UNKNOWN , /* type */
35 { NULL, 0 } /* content */
36 };
37
38 /**
39 * ASN.1 definition of the PKCS#7 ContentInfo type
40 */
41 static const asn1Object_t contentInfoObjects[] = {
42 { 0, "contentInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
43 { 1, "contentType", ASN1_OID, ASN1_BODY }, /* 1 */
44 { 1, "content", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_BODY }, /* 2 */
45 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
46 { 0, "exit", ASN1_EOC, ASN1_EXIT }
47 };
48 #define PKCS7_INFO_TYPE 1
49 #define PKCS7_INFO_CONTENT 2
50
51 /**
52 * ASN.1 definition of the PKCS#7 signedData type
53 */
54 static const asn1Object_t signedDataObjects[] = {
55 { 0, "signedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
56 { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
57 { 1, "digestAlgorithms", ASN1_SET, ASN1_LOOP }, /* 2 */
58 { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 3 */
59 { 1, "end loop", ASN1_EOC, ASN1_END }, /* 4 */
60 { 1, "contentInfo", ASN1_EOC, ASN1_RAW }, /* 5 */
61 { 1, "certificates", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_LOOP }, /* 6 */
62 { 2, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 7 */
63 { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 8 */
64 { 1, "crls", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_LOOP }, /* 9 */
65 { 2, "crl", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */
66 { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 11 */
67 { 1, "signerInfos", ASN1_SET, ASN1_LOOP }, /* 12 */
68 { 2, "signerInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */
69 { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 14 */
70 { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 15 */
71 { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 16 */
72 { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 17 */
73 { 3, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 18 */
74 { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_OBJ }, /* 19 */
75 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
76 { 3, "digestEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */
77 { 3, "encryptedDigest", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */
78 { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 23 */
79 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 24 */
80 { 1, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
81 { 0, "exit", ASN1_EOC, ASN1_EXIT }
82 };
83 #define PKCS7_SIGNED_VERSION 1
84 #define PKCS7_DIGEST_ALG 3
85 #define PKCS7_SIGNED_CONTENT_INFO 5
86 #define PKCS7_SIGNED_CERT 7
87 #define PKCS7_SIGNER_INFO 13
88 #define PKCS7_SIGNER_INFO_VERSION 14
89 #define PKCS7_SIGNED_ISSUER 16
90 #define PKCS7_SIGNED_SERIAL_NUMBER 17
91 #define PKCS7_DIGEST_ALGORITHM 18
92 #define PKCS7_AUTH_ATTRIBUTES 19
93 #define PKCS7_DIGEST_ENC_ALGORITHM 21
94 #define PKCS7_ENCRYPTED_DIGEST 22
95
96 /**
97 * ASN.1 definition of the PKCS#7 envelopedData type
98 */
99 static const asn1Object_t envelopedDataObjects[] = {
100 { 0, "envelopedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
101 { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
102 { 1, "recipientInfos", ASN1_SET, ASN1_LOOP }, /* 2 */
103 { 2, "recipientInfo", ASN1_SEQUENCE, ASN1_BODY }, /* 3 */
104 { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 4 */
105 { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */
106 { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */
107 { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 7 */
108 { 3, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 8 */
109 { 3, "encryptedKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */
110 { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */
111 { 1, "encryptedContentInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
112 { 2, "contentType", ASN1_OID, ASN1_BODY }, /* 12 */
113 { 2, "contentEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 13 */
114 { 2, "encryptedContent", ASN1_CONTEXT_S_0, ASN1_BODY }, /* 14 */
115 { 0, "exit", ASN1_EOC, ASN1_EXIT }
116 };
117 #define PKCS7_ENVELOPED_VERSION 1
118 #define PKCS7_RECIPIENT_INFO_VERSION 4
119 #define PKCS7_ISSUER 6
120 #define PKCS7_SERIAL_NUMBER 7
121 #define PKCS7_ENCRYPTION_ALG 8
122 #define PKCS7_ENCRYPTED_KEY 9
123 #define PKCS7_CONTENT_TYPE 12
124 #define PKCS7_CONTENT_ENC_ALGORITHM 13
125 #define PKCS7_ENCRYPTED_CONTENT 14
126 #define PKCS7_ENVELOPED_ROOF 15
127
128 /**
129 * Parse PKCS#7 ContentInfo object
130 */
131 bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0, contentInfo_t *cInfo)
132 {
133 asn1_parser_t *parser;
134 chunk_t object;
135 int objectID;
136 bool success = FALSE;
137
138 parser = asn1_parser_create(contentInfoObjects, blob);
139 parser->set_top_level(parser, level0);
140
141 while (parser->iterate(parser, &objectID, &object))
142 {
143 if (objectID == PKCS7_INFO_TYPE)
144 {
145 cInfo->type = asn1_known_oid(object);
146 if (cInfo->type < OID_PKCS7_DATA
147 || cInfo->type > OID_PKCS7_ENCRYPTED_DATA)
148 {
149 DBG1(DBG_LIB, "unknown pkcs7 content type");
150 goto end;
151 }
152 }
153 else if (objectID == PKCS7_INFO_CONTENT)
154 {
155 cInfo->content = object;
156 }
157 }
158 success = parser->success(parser);
159
160 end:
161 parser->destroy(parser);
162 return success;
163 }
164
165 /**
166 * Parse a PKCS#7 signedData object
167 */
168 bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
169 linked_list_t *certs,
170 chunk_t *attributes, certificate_t *cacert)
171 {
172 asn1_parser_t *parser;
173 chunk_t object;
174 int digest_alg = OID_UNKNOWN;
175 int enc_alg = OID_UNKNOWN;
176 int signerInfos = 0;
177 int version;
178 int objectID;
179 bool success = FALSE;
180
181 contentInfo_t cInfo = empty_contentInfo;
182 chunk_t encrypted_digest = chunk_empty;
183
184 if (!pkcs7_parse_contentInfo(blob, 0, &cInfo))
185 {
186 return FALSE;
187 }
188 if (cInfo.type != OID_PKCS7_SIGNED_DATA)
189 {
190 DBG1(DBG_LIB, "pkcs7 content type is not signedData");
191 return FALSE;
192 }
193
194 parser = asn1_parser_create(signedDataObjects, cInfo.content);
195 parser->set_top_level(parser, 2);
196
197 while (parser->iterate(parser, &objectID, &object))
198 {
199 u_int level = parser->get_level(parser);
200
201 switch (objectID)
202 {
203 case PKCS7_SIGNED_VERSION:
204 version = object.len ? (int)*object.ptr : 0;
205 DBG2(DBG_LIB, " v%d", version);
206 break;
207 case PKCS7_DIGEST_ALG:
208 digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
209 break;
210 case PKCS7_SIGNED_CONTENT_INFO:
211 if (data != NULL)
212 {
213 pkcs7_parse_contentInfo(object, level, data);
214 }
215 break;
216 case PKCS7_SIGNED_CERT:
217 {
218 certificate_t *cert;
219
220 DBG2(DBG_LIB, " parsing pkcs7-wrapped certificate");
221 cert = lib->creds->create(lib->creds,
222 CRED_CERTIFICATE, CERT_X509,
223 BUILD_BLOB_ASN1_DER, object,
224 BUILD_END);
225 if (cert)
226 {
227 certs->insert_last(certs, cert);
228 }
229 }
230 break;
231 case PKCS7_SIGNER_INFO:
232 signerInfos++;
233 DBG2(DBG_LIB, " signer #%d", signerInfos);
234 break;
235 case PKCS7_SIGNER_INFO_VERSION:
236 version = object.len ? (int)*object.ptr : 0;
237 DBG2(DBG_LIB, " v%d", version);
238 break;
239 case PKCS7_SIGNED_ISSUER:
240 {
241 identification_t *issuer = identification_create_from_encoding(
242 ID_DER_ASN1_DN, object);
243 DBG2(DBG_LIB, " \"%Y\"", issuer);
244 issuer->destroy(issuer);
245 break;
246 }
247 case PKCS7_AUTH_ATTRIBUTES:
248 if (attributes != NULL)
249 {
250 *attributes = object;
251 *attributes->ptr = ASN1_SET;
252 }
253 break;
254 case PKCS7_DIGEST_ALGORITHM:
255 digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
256 break;
257 case PKCS7_DIGEST_ENC_ALGORITHM:
258 enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
259 break;
260 case PKCS7_ENCRYPTED_DIGEST:
261 encrypted_digest = object;
262 }
263 }
264 success = parser->success(parser);
265 parser->destroy(parser);
266 if (!success)
267 {
268 return FALSE;
269 }
270
271 /* check the signature only if a cacert is available */
272 if (cacert != NULL)
273 {
274 public_key_t *key;
275 signature_scheme_t scheme;
276
277 scheme = signature_scheme_from_oid(digest_alg);
278 if (scheme == SIGN_UNKNOWN)
279 {
280 DBG1(DBG_LIB, "unsupported signature scheme");
281 return FALSE;
282 }
283 if (signerInfos == 0)
284 {
285 DBG1(DBG_LIB, "no signerInfo object found");
286 return FALSE;
287 }
288 else if (signerInfos > 1)
289 {
290 DBG1(DBG_LIB, "more than one signerInfo object found");
291 return FALSE;
292 }
293 if (attributes->ptr == NULL)
294 {
295 DBG1(DBG_LIB, "no authenticatedAttributes object found");
296 return FALSE;
297 }
298 if (enc_alg != OID_RSA_ENCRYPTION)
299 {
300 DBG1(DBG_LIB, "only RSA digest encryption supported");
301 return FALSE;
302 }
303
304 /* verify the signature */
305 key = cacert->get_public_key(cacert);
306 if (key == NULL)
307 {
308 DBG1(DBG_LIB, "no public key found in CA certificate");
309 return FALSE;
310 }
311 if (key->verify(key, scheme, *attributes, encrypted_digest))
312 {
313 DBG2(DBG_LIB, "signature is valid");
314 }
315 else
316 {
317 DBG1(DBG_LIB, "invalid signature");
318 success = FALSE;
319 }
320 key->destroy(key);
321 }
322 return success;
323 }
324
325 /**
326 * Parse a PKCS#7 envelopedData object
327 */
328 bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
329 chunk_t serialNumber,
330 private_key_t *key)
331 {
332 asn1_parser_t *parser;
333 chunk_t object;
334 chunk_t iv = chunk_empty;
335 chunk_t symmetric_key = chunk_empty;
336 chunk_t encrypted_content = chunk_empty;
337
338 crypter_t *crypter = NULL;
339
340 int enc_alg = OID_UNKNOWN;
341 int content_enc_alg = OID_UNKNOWN;
342 int version;
343 int objectID;
344 bool success = FALSE;
345
346 contentInfo_t cInfo = empty_contentInfo;
347 *data = chunk_empty;
348
349 if (!pkcs7_parse_contentInfo(blob, 0, &cInfo))
350 {
351 goto failed;
352 }
353 if (cInfo.type != OID_PKCS7_ENVELOPED_DATA)
354 {
355 DBG1(DBG_LIB, "pkcs7 content type is not envelopedData");
356 goto failed;
357 }
358
359 parser = asn1_parser_create(envelopedDataObjects, cInfo.content);
360 parser->set_top_level(parser, 2);
361
362 while (parser->iterate(parser, &objectID, &object))
363 {
364 u_int level = parser->get_level(parser);
365
366 switch (objectID)
367 {
368 case PKCS7_ENVELOPED_VERSION:
369 version = object.len ? (int)*object.ptr : 0;
370 DBG2(DBG_LIB, " v%d", version);
371 if (version != 0)
372 {
373 DBG1(DBG_LIB, "envelopedData version is not 0");
374 goto end;
375 }
376 break;
377 case PKCS7_RECIPIENT_INFO_VERSION:
378 version = object.len ? (int)*object.ptr : 0;
379 DBG2(DBG_LIB, " v%d", version);
380 if (version != 0)
381 {
382 DBG1(DBG_LIB, "recipient info version is not 0");
383 goto end;
384 }
385 break;
386 case PKCS7_ISSUER:
387 {
388 identification_t *issuer = identification_create_from_encoding(
389 ID_DER_ASN1_DN, object);
390 DBG2(DBG_LIB, " \"%Y\"", issuer);
391 issuer->destroy(issuer);
392 break;
393 }
394 case PKCS7_SERIAL_NUMBER:
395 if (!chunk_equals(serialNumber, object))
396 {
397 DBG1(DBG_LIB, "serial numbers do not match");
398 goto end;
399 }
400 break;
401 case PKCS7_ENCRYPTION_ALG:
402 enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
403 if (enc_alg != OID_RSA_ENCRYPTION)
404 {
405 DBG1(DBG_LIB, "only rsa encryption supported");
406 goto end;
407 }
408 break;
409 case PKCS7_ENCRYPTED_KEY:
410 if (!key->decrypt(key, ENCRYPT_RSA_PKCS1, object, &symmetric_key))
411 {
412 DBG1(DBG_LIB, "symmetric key could not be decrypted with rsa");
413 goto end;
414 }
415 DBG4(DBG_LIB, "symmetric key %B", &symmetric_key);
416 break;
417 case PKCS7_CONTENT_TYPE:
418 if (asn1_known_oid(object) != OID_PKCS7_DATA)
419 {
420 DBG1(DBG_LIB, "encrypted content not of type pkcs7 data");
421 goto end;
422 }
423 break;
424 case PKCS7_CONTENT_ENC_ALGORITHM:
425 content_enc_alg = asn1_parse_algorithmIdentifier(object, level, &iv);
426
427 if (content_enc_alg == OID_UNKNOWN)
428 {
429 DBG1(DBG_LIB, "unknown content encryption algorithm");
430 goto end;
431 }
432 if (!asn1_parse_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV"))
433 {
434 DBG1(DBG_LIB, "IV could not be parsed");
435 goto end;
436 }
437 break;
438 case PKCS7_ENCRYPTED_CONTENT:
439 encrypted_content = object;
440 break;
441 }
442 }
443 success = parser->success(parser);
444
445 end:
446 parser->destroy(parser);
447 if (!success)
448 {
449 goto failed;
450 }
451 success = FALSE;
452
453 /* decrypt the content */
454 {
455 encryption_algorithm_t alg;
456 size_t key_size;
457 crypter_t *crypter;
458
459 alg = encryption_algorithm_from_oid(content_enc_alg, &key_size);
460 if (alg == ENCR_UNDEFINED)
461 {
462 DBG1(DBG_LIB, "unsupported content encryption algorithm");
463 goto failed;
464 }
465 crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size);
466 if (crypter == NULL)
467 {
468 DBG1(DBG_LIB, "crypter %N not available", encryption_algorithm_names, alg);
469 goto failed;
470 }
471 if (symmetric_key.len != crypter->get_key_size(crypter))
472 {
473 DBG1(DBG_LIB, "symmetric key length %d is wrong", symmetric_key.len);
474 goto failed;
475 }
476 if (iv.len != crypter->get_iv_size(crypter))
477 {
478 DBG1(DBG_LIB, "IV length %d is wrong", iv.len);
479 goto failed;
480 }
481 crypter->set_key(crypter, symmetric_key);
482 crypter->decrypt(crypter, encrypted_content, iv, data);
483 DBG4(DBG_LIB, "decrypted content with padding: %B", data);
484 }
485
486 /* remove the padding */
487 {
488 u_char *pos = data->ptr + data->len - 1;
489 u_char pattern = *pos;
490 size_t padding = pattern;
491
492 if (padding > data->len)
493 {
494 DBG1(DBG_LIB, "padding greater than data length");
495 goto failed;
496 }
497 data->len -= padding;
498
499 while (padding-- > 0)
500 {
501 if (*pos-- != pattern)
502 {
503 DBG1(DBG_LIB, "wrong padding pattern");
504 goto failed;
505 }
506 }
507 }
508 success = TRUE;
509
510 failed:
511 DESTROY_IF(crypter);
512 chunk_clear(&symmetric_key);
513 if (!success)
514 {
515 free(data->ptr);
516 }
517 return success;
518 }
519
520 /**
521 * @brief Builds a contentType attribute
522 *
523 * @return ASN.1 encoded contentType attribute
524 */
525 chunk_t pkcs7_contentType_attribute(void)
526 {
527 return asn1_wrap(ASN1_SEQUENCE, "mm",
528 asn1_build_known_oid(OID_PKCS9_CONTENT_TYPE),
529 asn1_wrap(ASN1_SET, "m",
530 asn1_build_known_oid(OID_PKCS7_DATA)));
531 }
532
533 /**
534 * @brief Builds a messageDigest attribute
535 *
536 *
537 * @param[in] blob content to create digest of
538 * @param[in] digest_alg digest algorithm to be used
539 * @return ASN.1 encoded messageDigest attribute
540 *
541 */
542 chunk_t pkcs7_messageDigest_attribute(chunk_t content, int digest_alg)
543 {
544 chunk_t digest;
545 hash_algorithm_t hash_alg;
546 hasher_t *hasher;
547
548 hash_alg = hasher_algorithm_from_oid(digest_alg);
549 hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
550 hasher->allocate_hash(hasher, content, &digest);
551 hasher->destroy(hasher);
552
553 return asn1_wrap(ASN1_SEQUENCE, "mm",
554 asn1_build_known_oid(OID_PKCS9_MESSAGE_DIGEST),
555 asn1_wrap(ASN1_SET, "m",
556 asn1_wrap(ASN1_OCTET_STRING, "m", digest)));
557 }
558
559 /**
560 * build a DER-encoded contentInfo object
561 */
562 static chunk_t pkcs7_build_contentInfo(contentInfo_t *cInfo)
563 {
564 return (cInfo->content.ptr) ?
565 asn1_wrap(ASN1_SEQUENCE, "mm",
566 asn1_build_known_oid(cInfo->type),
567 asn1_simple_object(ASN1_CONTEXT_C_0, cInfo->content)) :
568 asn1_build_known_oid(cInfo->type);
569 }
570
571 /**
572 * build issuerAndSerialNumber object
573 */
574 chunk_t pkcs7_build_issuerAndSerialNumber(certificate_t *cert)
575 {
576 identification_t *issuer = cert->get_issuer(cert);
577 x509_t *x509 = (x509_t*)cert;
578
579 return asn1_wrap(ASN1_SEQUENCE, "cm",
580 issuer->get_encoding(issuer),
581 asn1_integer("c", x509->get_serial(x509)));
582 }
583
584 /**
585 * create a signed pkcs7 contentInfo object
586 */
587 chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
588 certificate_t *cert, int digest_alg,
589 private_key_t *key)
590 {
591 contentInfo_t pkcs7Data, signedData;
592 chunk_t authenticatedAttributes = chunk_empty;
593 chunk_t encryptedDigest = chunk_empty;
594 chunk_t signerInfo, cInfo, signature, encoding = chunk_empty;;
595 signature_scheme_t scheme = signature_scheme_from_oid(digest_alg);
596
597 if (attributes.ptr)
598 {
599 if (key->sign(key, scheme, attributes, &signature))
600 {
601 encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", signature);
602 authenticatedAttributes = chunk_clone(attributes);
603 *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
604 }
605 }
606 else if (data.ptr)
607 {
608 if (key->sign(key, scheme, data, &signature))
609 {
610 encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", signature);
611 }
612 }
613 signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmmmmm"
614 , ASN1_INTEGER_1
615 , pkcs7_build_issuerAndSerialNumber(cert)
616 , asn1_algorithmIdentifier(digest_alg)
617 , authenticatedAttributes
618 , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION)
619 , encryptedDigest);
620
621 pkcs7Data.type = OID_PKCS7_DATA;
622 pkcs7Data.content = (data.ptr == NULL)? chunk_empty
623 : asn1_simple_object(ASN1_OCTET_STRING, data);
624
625 cert->get_encoding(cert, CERT_ASN1_DER, &encoding);
626 signedData.type = OID_PKCS7_SIGNED_DATA;
627 signedData.content = asn1_wrap(ASN1_SEQUENCE, "cmmmm"
628 , ASN1_INTEGER_1
629 , asn1_wrap(ASN1_SET, "m", asn1_algorithmIdentifier(digest_alg))
630 , pkcs7_build_contentInfo(&pkcs7Data)
631 , asn1_wrap(ASN1_CONTEXT_C_0, "m", encoding)
632 , asn1_wrap(ASN1_SET, "m", signerInfo));
633
634 cInfo = pkcs7_build_contentInfo(&signedData);
635 DBG3(DBG_LIB, "signedData %B", &cInfo);
636
637 free(pkcs7Data.content.ptr);
638 free(signedData.content.ptr);
639 return cInfo;
640 }
641
642 /**
643 * create a symmetrically encrypted pkcs7 contentInfo object
644 */
645 chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert, int enc_alg)
646 {
647 encryption_algorithm_t alg;
648 size_t alg_key_size;
649 chunk_t symmetricKey, protectedKey, iv, in, out;
650 crypter_t *crypter;
651
652 alg = encryption_algorithm_from_oid(enc_alg, &alg_key_size);
653 crypter = lib->crypto->create_crypter(lib->crypto, alg,
654 alg_key_size/BITS_PER_BYTE);
655 if (crypter == NULL)
656 {
657 DBG1(DBG_LIB, "crypter for %N not available", encryption_algorithm_names, alg);
658 return chunk_empty;
659 }
660
661 /* generate a true random symmetric encryption key and a pseudo-random iv */
662 {
663 rng_t *rng;
664
665 rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
666 rng->allocate_bytes(rng, crypter->get_key_size(crypter), &symmetricKey);
667 DBG4(DBG_LIB, "symmetric encryption key %B", &symmetricKey);
668 rng->destroy(rng);
669
670 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
671 rng->allocate_bytes(rng, crypter->get_iv_size(crypter), &iv);
672 DBG4(DBG_LIB, "initialization vector: %B", &iv);
673 rng->destroy(rng);
674 }
675
676 /* pad the data to a multiple of the block size */
677 {
678 size_t block_size = crypter->get_block_size(crypter);
679 size_t padding = block_size - data.len % block_size;
680
681 in.len = data.len + padding;
682 in.ptr = malloc(in.len);
683
684 DBG2(DBG_LIB, "padding %u bytes of data to multiple block size of %u bytes",
685 data.len, in.len);
686
687 /* copy data */
688 memcpy(in.ptr, data.ptr, data.len);
689 /* append padding */
690 memset(in.ptr + data.len, padding, padding);
691 }
692 DBG3(DBG_LIB, "padded unencrypted data %B", &in);
693
694 /* symmetric encryption of data object */
695 crypter->set_key(crypter, symmetricKey);
696 crypter->encrypt(crypter, in, iv, &out);
697 crypter->destroy(crypter);
698 chunk_clear(&in);
699 DBG3(DBG_LIB, "encrypted data %B", &out);
700
701 /* protect symmetric key by public key encryption */
702 {
703 public_key_t *key = cert->get_public_key(cert);
704
705 if (key == NULL)
706 {
707 DBG1(DBG_LIB, "public key not found in encryption certificate");
708 chunk_clear(&symmetricKey);
709 chunk_free(&iv);
710 chunk_free(&out);
711 return chunk_empty;
712 }
713 key->encrypt(key, ENCRYPT_RSA_PKCS1, symmetricKey, &protectedKey);
714 key->destroy(key);
715 }
716
717 /* build pkcs7 enveloped data object */
718 {
719
720 chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "mm"
721 , asn1_build_known_oid(enc_alg)
722 , asn1_simple_object(ASN1_OCTET_STRING, iv));
723
724 chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "mmm"
725 , asn1_build_known_oid(OID_PKCS7_DATA)
726 , contentEncryptionAlgorithm
727 , asn1_wrap(ASN1_CONTEXT_S_0, "m", out));
728
729 chunk_t encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m"
730 , protectedKey);
731
732 chunk_t recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmmm"
733 , ASN1_INTEGER_0
734 , pkcs7_build_issuerAndSerialNumber(cert)
735 , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION)
736 , encryptedKey);
737
738 chunk_t cInfo;
739 contentInfo_t envelopedData;
740
741 envelopedData.type = OID_PKCS7_ENVELOPED_DATA;
742 envelopedData.content = asn1_wrap(ASN1_SEQUENCE, "cmm"
743 , ASN1_INTEGER_0
744 , asn1_wrap(ASN1_SET, "m", recipientInfo)
745 , encryptedContentInfo);
746
747 cInfo = pkcs7_build_contentInfo(&envelopedData);
748 DBG3(DBG_LIB, "envelopedData %B", &cInfo);
749
750 chunk_free(&envelopedData.content);
751 chunk_free(&iv);
752 chunk_clear(&symmetricKey);
753 return cInfo;
754 }
755 }