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