]> git.ipfire.org Git - people/ms/strongswan.git/blob - programs/pluto/pkcs7.c
- import of strongswan-2.7.0
[people/ms/strongswan.git] / programs / 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 * RCSID $Id: pkcs7.c,v 1.13 2005/12/22 22:11:24 as Exp $
17 */
18
19 #include <stdlib.h>
20 #include <string.h>
21 #include <crypto/des.h>
22
23 #include <freeswan.h>
24
25 #include "constants.h"
26 #include "defs.h"
27 #include "asn1.h"
28 #include "oid.h"
29 #include "log.h"
30 #include "x509.h"
31 #include "certs.h"
32 #include "pkcs7.h"
33 #include "rnd.h"
34
35 const contentInfo_t empty_contentInfo = {
36 OID_UNKNOWN , /* type */
37 { NULL, 0 } /* content */
38 };
39
40 /* ASN.1 definition of the PKCS#7 ContentInfo type */
41
42 static const asn1Object_t contentInfoObjects[] = {
43 { 0, "contentInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
44 { 1, "contentType", ASN1_OID, ASN1_BODY }, /* 1 */
45 { 1, "content", ASN1_CONTEXT_C_0, ASN1_OPT |
46 ASN1_BODY }, /* 2 */
47 { 1, "end opt", ASN1_EOC, ASN1_END } /* 3 */
48 };
49
50 #define PKCS7_INFO_TYPE 1
51 #define PKCS7_INFO_CONTENT 2
52 #define PKCS7_INFO_ROOF 4
53
54 /* ASN.1 definition of the PKCS#7 signedData type */
55
56 static const asn1Object_t signedDataObjects[] = {
57 { 0, "signedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
58 { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
59 { 1, "digestAlgorithms", ASN1_SET, ASN1_LOOP }, /* 2 */
60 { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 3 */
61 { 1, "end loop", ASN1_EOC, ASN1_END }, /* 4 */
62 { 1, "contentInfo", ASN1_EOC, ASN1_RAW }, /* 5 */
63 { 1, "certificates", ASN1_CONTEXT_C_0, ASN1_OPT |
64 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 |
68 ASN1_LOOP }, /* 9 */
69 { 2, "crl", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */
70 { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 11 */
71 { 1, "signerInfos", ASN1_SET, ASN1_LOOP }, /* 12 */
72 { 2, "signerInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */
73 { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 14 */
74 { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 15 */
75 { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 16 */
76 { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 17 */
77 { 3, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 18 */
78 { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0, ASN1_OPT |
79 ASN1_OBJ }, /* 19 */
80 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
81 { 3, "digestEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */
82 { 3, "encryptedDigest", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */
83 { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 23 */
84 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 24 */
85 { 1, "end loop", ASN1_EOC, ASN1_END } /* 25 */
86 };
87
88 #define PKCS7_DIGEST_ALG 3
89 #define PKCS7_SIGNED_CONTENT_INFO 5
90 #define PKCS7_SIGNED_CERT 7
91 #define PKCS7_SIGNER_INFO 13
92 #define PKCS7_SIGNED_ISSUER 16
93 #define PKCS7_SIGNED_SERIAL_NUMBER 17
94 #define PKCS7_DIGEST_ALGORITHM 18
95 #define PKCS7_AUTH_ATTRIBUTES 19
96 #define PKCS7_DIGEST_ENC_ALGORITHM 21
97 #define PKCS7_ENCRYPTED_DIGEST 22
98 #define PKCS7_SIGNED_ROOF 26
99
100 /* ASN.1 definition of the PKCS#7 envelopedData type */
101
102 static const asn1Object_t envelopedDataObjects[] = {
103 { 0, "envelopedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
104 { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
105 { 1, "recipientInfos", ASN1_SET, ASN1_LOOP }, /* 2 */
106 { 2, "recipientInfo", ASN1_SEQUENCE, ASN1_BODY }, /* 3 */
107 { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 4 */
108 { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */
109 { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */
110 { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 7 */
111 { 3, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 8 */
112 { 3, "encryptedKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */
113 { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */
114 { 1, "encryptedContentInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
115 { 2, "contentType", ASN1_OID, ASN1_BODY }, /* 12 */
116 { 2, "contentEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 13 */
117 { 2, "encryptedContent", ASN1_CONTEXT_S_0, ASN1_BODY } /* 14 */
118 };
119
120 #define PKCS7_ENVELOPED_VERSION 1
121 #define PKCS7_RECIPIENT_INFO_VERSION 4
122 #define PKCS7_ISSUER 6
123 #define PKCS7_SERIAL_NUMBER 7
124 #define PKCS7_ENCRYPTION_ALG 8
125 #define PKCS7_ENCRYPTED_KEY 9
126 #define PKCS7_CONTENT_TYPE 12
127 #define PKCS7_CONTENT_ENC_ALGORITHM 13
128 #define PKCS7_ENCRYPTED_CONTENT 14
129 #define PKCS7_ENVELOPED_ROOF 15
130
131 /* PKCS7 contentInfo OIDs */
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 strchunk(ASN1_pkcs7_data_oid_str);
159 static const chunk_t ASN1_pkcs7_signed_data_oid =
160 strchunk(ASN1_pkcs7_signed_data_oid_str);
161 static const chunk_t ASN1_pkcs7_enveloped_data_oid =
162 strchunk(ASN1_pkcs7_enveloped_data_oid_str);
163 static const chunk_t ASN1_pkcs7_signed_enveloped_data_oid =
164 strchunk(ASN1_pkcs7_signed_enveloped_data_oid_str);
165 static const chunk_t ASN1_pkcs7_digested_data_oid =
166 strchunk(ASN1_pkcs7_digested_data_oid_str);
167 static const chunk_t ASN1_pkcs7_encrypted_data_oid =
168 strchunk(ASN1_pkcs7_encrypted_data_oid_str);
169
170 /* 3DES and DES encryption OIDs */
171
172 static u_char ASN1_3des_ede_cbc_oid_str[] = {
173 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x07
174 };
175
176 static u_char ASN1_des_cbc_oid_str[] = {
177 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x07
178 };
179
180 static const chunk_t ASN1_3des_ede_cbc_oid =
181 strchunk(ASN1_3des_ede_cbc_oid_str);
182 static const chunk_t ASN1_des_cbc_oid =
183 strchunk(ASN1_des_cbc_oid_str);
184
185 /* PKCS#7 attribute type OIDs */
186
187 static u_char ASN1_contentType_oid_str[] = {
188 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03
189 };
190
191 static u_char ASN1_messageDigest_oid_str[] = {
192 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04
193 };
194
195 static const chunk_t ASN1_contentType_oid =
196 strchunk(ASN1_contentType_oid_str);
197 static const chunk_t ASN1_messageDigest_oid =
198 strchunk(ASN1_messageDigest_oid_str);
199
200 /*
201 * Parse PKCS#7 ContentInfo object
202 */
203 bool
204 pkcs7_parse_contentInfo(chunk_t blob, u_int level0, contentInfo_t *cInfo)
205 {
206 asn1_ctx_t ctx;
207 chunk_t object;
208 u_int level;
209 int objectID = 0;
210
211 asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);
212
213 while (objectID < PKCS7_INFO_ROOF)
214 {
215 if (!extract_object(contentInfoObjects, &objectID, &object, &level, &ctx))
216 return FALSE;
217
218 if (objectID == PKCS7_INFO_TYPE)
219 {
220 cInfo->type = known_oid(object);
221 if (cInfo->type < OID_PKCS7_DATA
222 || cInfo->type > OID_PKCS7_ENCRYPTED_DATA)
223 {
224 plog("unknown pkcs7 content type");
225 return FALSE;
226 }
227 }
228 else if (objectID == PKCS7_INFO_CONTENT)
229 {
230 cInfo->content = object;
231 }
232 objectID++;
233 }
234 return TRUE;
235 }
236
237 /*
238 * Parse a PKCS#7 signedData object
239 */
240 bool
241 pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
242 , chunk_t *attributes, const x509cert_t *cacert)
243 {
244 u_char buf[BUF_LEN];
245 asn1_ctx_t ctx;
246 chunk_t object;
247 u_int level;
248 int digest_alg = OID_UNKNOWN;
249 int enc_alg = OID_UNKNOWN;
250 int signerInfos = 0;
251 int objectID = 0;
252
253 contentInfo_t cInfo = empty_contentInfo;
254 chunk_t encrypted_digest = empty_chunk;
255
256 if (!pkcs7_parse_contentInfo(blob, 0, &cInfo))
257 return FALSE;
258
259 if (cInfo.type != OID_PKCS7_SIGNED_DATA)
260 {
261 plog("pkcs7 content type is not signedData");
262 return FALSE;
263 }
264
265 asn1_init(&ctx, cInfo.content, 2, FALSE, DBG_RAW);
266
267 while (objectID < PKCS7_SIGNED_ROOF)
268 {
269 if (!extract_object(signedDataObjects, &objectID, &object, &level, &ctx))
270 return FALSE;
271
272 switch (objectID)
273 {
274 case PKCS7_DIGEST_ALG:
275 digest_alg = parse_algorithmIdentifier(object, level, NULL);
276 break;
277 case PKCS7_SIGNED_CONTENT_INFO:
278 if (data != NULL)
279 {
280 pkcs7_parse_contentInfo(object, level, data);
281 }
282 break;
283 case PKCS7_SIGNED_CERT:
284 if (cert != NULL)
285 {
286 chunk_t cert_blob;
287
288 x509cert_t *newcert = alloc_thing(x509cert_t
289 , "pkcs7 wrapped x509cert");
290
291 clonetochunk(cert_blob, object.ptr, object.len
292 , "pkcs7 cert blob");
293 *newcert = empty_x509cert;
294
295 DBG(DBG_CONTROL | DBG_PARSING,
296 DBG_log("parsing pkcs7-wrapped certificate")
297 )
298 if (parse_x509cert(cert_blob, level+1, newcert))
299 {
300 newcert->next = *cert;
301 *cert = newcert;
302 }
303 else
304 {
305 free_x509cert(newcert);
306 }
307 }
308 break;
309 case PKCS7_SIGNER_INFO:
310 signerInfos++;
311 DBG(DBG_PARSING,
312 DBG_log(" signer #%d", signerInfos)
313 )
314 break;
315 case PKCS7_SIGNED_ISSUER:
316 DBG(DBG_PARSING,
317 dntoa(buf, BUF_LEN, object);
318 DBG_log(" '%s'",buf)
319 )
320 break;
321 case PKCS7_AUTH_ATTRIBUTES:
322 if (attributes != NULL)
323 {
324 *attributes = object;
325 *attributes->ptr = ASN1_SET;
326 }
327 break;
328 case PKCS7_DIGEST_ALGORITHM:
329 digest_alg = parse_algorithmIdentifier(object, level, NULL);
330 break;
331 case PKCS7_DIGEST_ENC_ALGORITHM:
332 enc_alg = parse_algorithmIdentifier(object, level, NULL);
333 break;
334 case PKCS7_ENCRYPTED_DIGEST:
335 encrypted_digest = object;
336 }
337 objectID++;
338 }
339
340 /* check the signature only if a cacert is available */
341 if (cacert != NULL)
342 {
343 if (signerInfos == 0)
344 {
345 plog("no signerInfo object found");
346 return FALSE;
347 }
348 else if (signerInfos > 1)
349 {
350 plog("more than one signerInfo object found");
351 return FALSE;
352 }
353 if (attributes->ptr == NULL)
354 {
355 plog("no authenticatedAttributes object found");
356 return FALSE;
357 }
358 if (!check_signature(*attributes, encrypted_digest, digest_alg
359 , enc_alg, cacert))
360 {
361 plog("invalid signature");
362 return FALSE;
363 }
364 else
365 {
366 DBG(DBG_CONTROL,
367 DBG_log("signature is valid")
368 )
369 }
370 }
371 return TRUE;
372 }
373
374 /*
375 * Parse a PKCS#7 envelopedData object
376 */
377 bool
378 pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data
379 , chunk_t serialNumber, const RSA_private_key_t *key)
380 {
381 asn1_ctx_t ctx;
382 chunk_t object;
383 chunk_t iv = empty_chunk;
384 chunk_t symmetric_key = empty_chunk;
385 chunk_t encrypted_content = empty_chunk;
386
387 u_char buf[BUF_LEN];
388 u_int level;
389 u_int total_keys = 3;
390 int enc_alg = OID_UNKNOWN;
391 int content_enc_alg = OID_UNKNOWN;
392 int objectID = 0;
393
394 contentInfo_t cInfo = empty_contentInfo;
395 *data = empty_chunk;
396
397 if (!pkcs7_parse_contentInfo(blob, 0, &cInfo))
398 goto failed;
399
400 if (cInfo.type != OID_PKCS7_ENVELOPED_DATA)
401 {
402 plog("pkcs7 content type is not envelopedData");
403 return FALSE;
404 }
405
406 asn1_init(&ctx, cInfo.content, 2, FALSE, DBG_RAW);
407
408 while (objectID < PKCS7_ENVELOPED_ROOF)
409 {
410 if (!extract_object(envelopedDataObjects, &objectID, &object, &level, &ctx))
411 goto failed;
412
413 switch (objectID)
414 {
415 case PKCS7_ENVELOPED_VERSION:
416 if (*object.ptr != 0)
417 {
418 plog("envelopedData version is not 0");
419 goto failed;
420 }
421 break;
422 case PKCS7_RECIPIENT_INFO_VERSION:
423 if (*object.ptr != 0)
424 {
425 plog("recipient info version is not 0");
426 goto failed;
427 }
428 break;
429 case PKCS7_ISSUER:
430 DBG(DBG_PARSING,
431 dntoa(buf, BUF_LEN, object);
432 DBG_log(" '%s'", buf)
433 )
434 break;
435 case PKCS7_SERIAL_NUMBER:
436 if (!same_chunk(serialNumber, object))
437 {
438 plog("serial numbers do not match");
439 goto failed;
440 }
441 break;
442 case PKCS7_ENCRYPTION_ALG:
443 enc_alg = parse_algorithmIdentifier(object, level, NULL);
444 if (enc_alg != OID_RSA_ENCRYPTION)
445 {
446 plog("only rsa encryption supported");
447 goto failed;
448 }
449 break;
450 case PKCS7_ENCRYPTED_KEY:
451 if (!RSA_decrypt(key, object, &symmetric_key))
452 {
453 plog("symmetric key could not be decrypted with rsa");
454 goto failed;
455 }
456 DBG(DBG_PRIVATE,
457 DBG_dump_chunk("symmetric key :", symmetric_key)
458 )
459 break;
460 case PKCS7_CONTENT_TYPE:
461 if (known_oid(object) != OID_PKCS7_DATA)
462 {
463 plog("encrypted content not of type pkcs7 data");
464 goto failed;
465 }
466 break;
467 case PKCS7_CONTENT_ENC_ALGORITHM:
468 content_enc_alg = parse_algorithmIdentifier(object, level, &iv);
469
470 switch (content_enc_alg)
471 {
472 case OID_DES_CBC:
473 total_keys = 1;
474 break;
475 case OID_3DES_EDE_CBC:
476 total_keys = 3;
477 break;
478 default:
479 plog("Only DES and 3DES supported for symmetric encryption");
480 goto failed;
481 }
482 if (symmetric_key.len != (total_keys * DES_CBC_BLOCK_SIZE))
483 {
484 plog("key length is not %d",(total_keys * DES_CBC_BLOCK_SIZE));
485 goto failed;
486 }
487 if (!parse_asn1_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV"))
488 {
489 plog("IV could not be parsed");
490 goto failed;
491 }
492 if (iv.len != DES_CBC_BLOCK_SIZE)
493 {
494 plog("IV has wrong length");
495 goto failed;
496 }
497 break;
498 case PKCS7_ENCRYPTED_CONTENT:
499 encrypted_content = object;
500 break;
501 }
502 objectID++;
503 }
504
505 /* decrypt the content */
506 {
507 u_int i;
508 des_cblock des_key[3], des_iv;
509 des_key_schedule key_s[3];
510
511 memcpy((char *)des_key, symmetric_key.ptr, symmetric_key.len);
512 memcpy((char *)des_iv, iv.ptr, iv.len);
513
514 for (i = 0; i < total_keys; i++)
515 {
516 if (des_set_key(&des_key[i], key_s[i]))
517 {
518 plog("des key schedule failed");
519 goto failed;
520 }
521 }
522
523 data->len = encrypted_content.len;
524 data->ptr = alloc_bytes(data->len, "decrypted data");
525
526 switch (content_enc_alg)
527 {
528 case OID_DES_CBC:
529 des_cbc_encrypt((des_cblock*)encrypted_content.ptr
530 , (des_cblock*)data->ptr, data->len
531 , key_s[0], &des_iv, DES_DECRYPT);
532 break;
533 case OID_3DES_EDE_CBC:
534 des_ede3_cbc_encrypt( (des_cblock*)encrypted_content.ptr
535 , (des_cblock*)data->ptr, data->len
536 , key_s[0], key_s[1], key_s[2]
537 , &des_iv, DES_DECRYPT);
538 }
539 DBG(DBG_PRIVATE,
540 DBG_dump_chunk("decrypted content with padding:\n", *data)
541 )
542 }
543
544 /* remove the padding */
545 {
546 u_char *pos = data->ptr + data->len - 1;
547 u_char pattern = *pos;
548 size_t padding = pattern;
549
550 if (padding > data->len)
551 {
552 plog("padding greater than data length");
553 goto failed;
554 }
555 data->len -= padding;
556
557 while (padding-- > 0)
558 {
559 if (*pos-- != pattern)
560 {
561 plog("wrong padding pattern");
562 goto failed;
563 }
564 }
565 }
566 freeanychunk(symmetric_key);
567 return TRUE;
568
569 failed:
570 freeanychunk(symmetric_key);
571 pfreeany(data->ptr);
572 return FALSE;
573 }
574
575 /**
576 * @brief Builds a contentType attribute
577 *
578 * @return ASN.1 encoded contentType attribute
579 */
580 chunk_t
581 pkcs7_contentType_attribute(void)
582 {
583 return asn1_wrap(ASN1_SEQUENCE, "cm"
584 , ASN1_contentType_oid
585 , asn1_simple_object(ASN1_SET, ASN1_pkcs7_data_oid));
586 }
587
588 /**
589 * @brief Builds a messageDigest attribute
590 *
591 *
592 * @param[in] blob content to create digest of
593 * @param[in] digest_alg digest algorithm to be used
594 * @return ASN.1 encoded messageDigest attribute
595 *
596 */
597 chunk_t
598 pkcs7_messageDigest_attribute(chunk_t content, int digest_alg)
599 {
600 u_char digest_buf[MAX_DIGEST_LEN];
601 chunk_t digest = { digest_buf, MAX_DIGEST_LEN };
602
603 compute_digest(content, digest_alg, &digest);
604
605 return asn1_wrap(ASN1_SEQUENCE, "cm"
606 , ASN1_messageDigest_oid
607 , asn1_wrap(ASN1_SET, "m"
608 , asn1_simple_object(ASN1_OCTET_STRING, digest)
609 )
610 );
611 }
612 /*
613 * build a DER-encoded contentInfo object
614 */
615 static chunk_t
616 pkcs7_build_contentInfo(contentInfo_t *cInfo)
617 {
618 chunk_t content_type;
619
620 /* select DER-encoded OID for pkcs7 contentInfo type */
621 switch(cInfo->type)
622 {
623 case OID_PKCS7_DATA:
624 content_type = ASN1_pkcs7_data_oid;
625 break;
626 case OID_PKCS7_SIGNED_DATA:
627 content_type = ASN1_pkcs7_signed_data_oid;
628 break;
629 case OID_PKCS7_ENVELOPED_DATA:
630 content_type = ASN1_pkcs7_enveloped_data_oid;
631 break;
632 case OID_PKCS7_SIGNED_ENVELOPED_DATA:
633 content_type = ASN1_pkcs7_signed_enveloped_data_oid;
634 break;
635 case OID_PKCS7_DIGESTED_DATA:
636 content_type = ASN1_pkcs7_digested_data_oid;
637 break;
638 case OID_PKCS7_ENCRYPTED_DATA:
639 content_type = ASN1_pkcs7_encrypted_data_oid;
640 break;
641 case OID_UNKNOWN:
642 default:
643 fprintf(stderr, "invalid pkcs7 contentInfo type");
644 return empty_chunk;
645 }
646
647 return (cInfo->content.ptr == NULL)
648 ? asn1_simple_object(ASN1_SEQUENCE, content_type)
649 : asn1_wrap(ASN1_SEQUENCE, "cm"
650 , content_type
651 , asn1_simple_object(ASN1_CONTEXT_C_0, cInfo->content)
652 );
653 }
654
655 /*
656 * build issuerAndSerialNumber object
657 */
658 chunk_t
659 pkcs7_build_issuerAndSerialNumber(const x509cert_t *cert)
660 {
661 return asn1_wrap(ASN1_SEQUENCE, "cm"
662 , cert->issuer
663 , asn1_simple_object(ASN1_INTEGER, cert->serialNumber));
664 }
665
666 /*
667 * create a signed pkcs7 contentInfo object
668 */
669 chunk_t
670 pkcs7_build_signedData(chunk_t data, chunk_t attributes, const x509cert_t *cert
671 , int digest_alg, const RSA_private_key_t *key)
672 {
673 contentInfo_t pkcs7Data, signedData;
674 chunk_t authenticatedAttributes, encryptedDigest, signerInfo, cInfo;
675
676 chunk_t digestAlgorithm = asn1_algorithmIdentifier(digest_alg);
677
678 if (attributes.ptr != NULL)
679 {
680 encryptedDigest = pkcs1_build_signature(attributes, digest_alg
681 , key, FALSE);
682 clonetochunk(authenticatedAttributes, attributes.ptr, attributes.len
683 , "authenticatedAttributes");
684 *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
685 }
686 else
687 {
688 encryptedDigest = (data.ptr == NULL)? empty_chunk
689 : pkcs1_build_signature(data, digest_alg, key, FALSE);
690 authenticatedAttributes = empty_chunk;
691 }
692
693 signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmcmcm"
694 , ASN1_INTEGER_1
695 , pkcs7_build_issuerAndSerialNumber(cert)
696 , digestAlgorithm
697 , authenticatedAttributes
698 , ASN1_rsaEncryption_id
699 , encryptedDigest);
700
701 pkcs7Data.type = OID_PKCS7_DATA;
702 pkcs7Data.content = (data.ptr == NULL)? empty_chunk
703 : asn1_simple_object(ASN1_OCTET_STRING, data);
704
705 signedData.type = OID_PKCS7_SIGNED_DATA;
706 signedData.content = asn1_wrap(ASN1_SEQUENCE, "cmmmm"
707 , ASN1_INTEGER_1
708 , asn1_simple_object(ASN1_SET, digestAlgorithm)
709 , pkcs7_build_contentInfo(&pkcs7Data)
710 , asn1_simple_object(ASN1_CONTEXT_C_0, cert->certificate)
711 , asn1_wrap(ASN1_SET, "m", signerInfo));
712
713 cInfo = pkcs7_build_contentInfo(&signedData);
714 DBG(DBG_RAW,
715 DBG_dump_chunk("signedData:\n", cInfo)
716 )
717
718 freeanychunk(pkcs7Data.content);
719 freeanychunk(signedData.content);
720 return cInfo;
721 }
722
723 /*
724 * create a symmetrically encrypted pkcs7 contentInfo object
725 */
726 chunk_t
727 pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int cipher)
728 {
729 bool des_check_key_save;
730 des_key_schedule ks[3];
731 des_cblock key[3], des_iv, des_iv_buf;
732
733 chunk_t iv = { (u_char *)des_iv_buf, DES_CBC_BLOCK_SIZE };
734 chunk_t out;
735 chunk_t cipher_oid;
736
737 u_int total_keys, i;
738 size_t padding = pad_up(data.len, DES_CBC_BLOCK_SIZE);
739
740 RSA_public_key_t public_key;
741
742 init_RSA_public_key(&public_key, cert->publicExponent
743 , cert->modulus);
744
745 if (padding == 0)
746 padding += DES_CBC_BLOCK_SIZE;
747
748 out.len = data.len + padding;
749 out.ptr = alloc_bytes(out.len, "DES-encrypted output");
750
751 DBG(DBG_CONTROL,
752 DBG_log("padding %d bytes of data to multiple DES block size of %d bytes"
753 , (int)data.len, (int)out.len)
754 )
755
756 /* copy data */
757 memcpy(out.ptr, data.ptr, data.len);
758 /* append padding */
759 memset(out.ptr + data.len, padding, padding);
760
761 DBG(DBG_RAW,
762 DBG_dump_chunk("Padded unencrypted data:\n", out)
763 )
764
765 /* select OID and keylength for specified cipher */
766 switch (cipher)
767 {
768 case OID_DES_CBC:
769 total_keys = 1;
770 cipher_oid = ASN1_des_cbc_oid;
771 break;
772 case OID_3DES_EDE_CBC:
773 default:
774 total_keys = 3;
775 cipher_oid = ASN1_3des_ede_cbc_oid;
776 }
777 DBG(DBG_CONTROLMORE,
778 DBG_log("pkcs7 encryption cipher: %s", oid_names[cipher].name)
779 )
780
781 /* generate a strong random key for DES/3DES */
782 des_check_key_save = des_check_key;
783 des_check_key = TRUE;
784 for (i = 0; i < total_keys;i++)
785 {
786 for (;;)
787 {
788 get_rnd_bytes((char*)key[i], DES_CBC_BLOCK_SIZE);
789 des_set_odd_parity(&key[i]);
790 if (!des_set_key(&key[i], ks[i]))
791 break;
792 plog("weak DES key discarded - we try again");
793 }
794 DBG(DBG_PRIVATE,
795 DBG_dump("DES key:", key[i], 8)
796 )
797 }
798 des_check_key = des_check_key_save;
799
800 /* generate an iv for DES/3DES CBC */
801 get_rnd_bytes(des_iv, DES_CBC_BLOCK_SIZE);
802 memcpy(iv.ptr, des_iv, DES_CBC_BLOCK_SIZE);
803 DBG(DBG_RAW,
804 DBG_dump_chunk("DES IV :", iv)
805 )
806
807 /* encryption using specified cipher */
808 switch (cipher)
809 {
810 case OID_DES_CBC:
811 des_cbc_encrypt((des_cblock*)out.ptr, (des_cblock*)out.ptr, out.len
812 , ks[0], &des_iv, DES_ENCRYPT);
813 break;
814 case OID_3DES_EDE_CBC:
815 default:
816 des_ede3_cbc_encrypt((des_cblock*)out.ptr, (des_cblock*)out.ptr, out.len
817 , ks[0], ks[1], ks[2], &des_iv, DES_ENCRYPT);
818 }
819 DBG(DBG_RAW,
820 DBG_dump_chunk("Encrypted data:\n", out));
821
822 /* build pkcs7 enveloped data object */
823 {
824 chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "cm"
825 , cipher_oid
826 , asn1_simple_object(ASN1_OCTET_STRING, iv));
827
828 chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "cmm"
829 , ASN1_pkcs7_data_oid
830 , contentEncryptionAlgorithm
831 , asn1_wrap(ASN1_CONTEXT_S_0, "m", out));
832
833 chunk_t plainKey = { (u_char *)key, DES_CBC_BLOCK_SIZE * total_keys };
834
835 chunk_t encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m"
836 , RSA_encrypt(&public_key, plainKey));
837
838 chunk_t recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmcm"
839 , ASN1_INTEGER_0
840 , pkcs7_build_issuerAndSerialNumber(cert)
841 , ASN1_rsaEncryption_id
842 , encryptedKey);
843
844 chunk_t cInfo;
845 contentInfo_t envelopedData;
846
847 envelopedData.type = OID_PKCS7_ENVELOPED_DATA;
848 envelopedData.content = asn1_wrap(ASN1_SEQUENCE, "cmm"
849 , ASN1_INTEGER_0
850 , asn1_wrap(ASN1_SET, "m", recipientInfo)
851 , encryptedContentInfo);
852
853 cInfo = pkcs7_build_contentInfo(&envelopedData);
854 DBG(DBG_RAW,
855 DBG_dump_chunk("envelopedData:\n", cInfo)
856 )
857
858 free_RSA_public_content(&public_key);
859 freeanychunk(envelopedData.content);
860 return cInfo;
861 }
862 }