1 /* Support of PKCS#7 data structures
2 * Copyright (C) 2005 Jan Hutter, Martin Willi
3 * Copyright (C) 2002-2009 Andreas Steffen
5 * HSR Hochschule fuer Technik Rapperswil, Switzerland
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>.
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
25 #include <asn1/asn1.h>
26 #include <asn1/asn1_parser.h>
28 #include <crypto/rngs/rng.h>
29 #include <crypto/crypters/crypter.h>
31 #include "constants.h"
37 const contentInfo_t empty_contentInfo
= {
38 OID_UNKNOWN
, /* type */
39 { NULL
, 0 } /* content */
43 * ASN.1 definition of the PKCS#7 ContentInfo type
45 static const asn1Object_t contentInfoObjects
[] = {
46 { 0, "contentInfo", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
47 { 1, "contentType", ASN1_OID
, ASN1_BODY
}, /* 1 */
48 { 1, "content", ASN1_CONTEXT_C_0
, ASN1_OPT
|ASN1_BODY
}, /* 2 */
49 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 3 */
50 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
52 #define PKCS7_INFO_TYPE 1
53 #define PKCS7_INFO_CONTENT 2
56 * ASN.1 definition of the PKCS#7 signedData type
58 static const asn1Object_t signedDataObjects
[] = {
59 { 0, "signedData", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
60 { 1, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 1 */
61 { 1, "digestAlgorithms", ASN1_SET
, ASN1_LOOP
}, /* 2 */
62 { 2, "algorithm", ASN1_EOC
, ASN1_RAW
}, /* 3 */
63 { 1, "end loop", ASN1_EOC
, ASN1_END
}, /* 4 */
64 { 1, "contentInfo", ASN1_EOC
, ASN1_RAW
}, /* 5 */
65 { 1, "certificates", ASN1_CONTEXT_C_0
, ASN1_OPT
|ASN1_LOOP
}, /* 6 */
66 { 2, "certificate", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 7 */
67 { 1, "end opt or loop", ASN1_EOC
, ASN1_END
}, /* 8 */
68 { 1, "crls", ASN1_CONTEXT_C_1
, ASN1_OPT
|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
|ASN1_OBJ
}, /* 19 */
79 { 3, "end opt", ASN1_EOC
, ASN1_END
}, /* 20 */
80 { 3, "digestEncryptionAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 21 */
81 { 3, "encryptedDigest", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 22 */
82 { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 23 */
83 { 3, "end opt", ASN1_EOC
, ASN1_END
}, /* 24 */
84 { 1, "end loop", ASN1_EOC
, ASN1_END
}, /* 25 */
85 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
87 #define PKCS7_DIGEST_ALG 3
88 #define PKCS7_SIGNED_CONTENT_INFO 5
89 #define PKCS7_SIGNED_CERT 7
90 #define PKCS7_SIGNER_INFO 13
91 #define PKCS7_SIGNED_ISSUER 16
92 #define PKCS7_SIGNED_SERIAL_NUMBER 17
93 #define PKCS7_DIGEST_ALGORITHM 18
94 #define PKCS7_AUTH_ATTRIBUTES 19
95 #define PKCS7_DIGEST_ENC_ALGORITHM 21
96 #define PKCS7_ENCRYPTED_DIGEST 22
99 * ASN.1 definition of the PKCS#7 envelopedData type
101 static const asn1Object_t envelopedDataObjects
[] = {
102 { 0, "envelopedData", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
103 { 1, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 1 */
104 { 1, "recipientInfos", ASN1_SET
, ASN1_LOOP
}, /* 2 */
105 { 2, "recipientInfo", ASN1_SEQUENCE
, ASN1_BODY
}, /* 3 */
106 { 3, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 4 */
107 { 3, "issuerAndSerialNumber", ASN1_SEQUENCE
, ASN1_BODY
}, /* 5 */
108 { 4, "issuer", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 6 */
109 { 4, "serial", ASN1_INTEGER
, ASN1_BODY
}, /* 7 */
110 { 3, "encryptionAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 8 */
111 { 3, "encryptedKey", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 9 */
112 { 1, "end loop", ASN1_EOC
, ASN1_END
}, /* 10 */
113 { 1, "encryptedContentInfo", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 11 */
114 { 2, "contentType", ASN1_OID
, ASN1_BODY
}, /* 12 */
115 { 2, "contentEncryptionAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 13 */
116 { 2, "encryptedContent", ASN1_CONTEXT_S_0
, ASN1_BODY
}, /* 14 */
117 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
119 #define PKCS7_ENVELOPED_VERSION 1
120 #define PKCS7_RECIPIENT_INFO_VERSION 4
121 #define PKCS7_ISSUER 6
122 #define PKCS7_SERIAL_NUMBER 7
123 #define PKCS7_ENCRYPTION_ALG 8
124 #define PKCS7_ENCRYPTED_KEY 9
125 #define PKCS7_CONTENT_TYPE 12
126 #define PKCS7_CONTENT_ENC_ALGORITHM 13
127 #define PKCS7_ENCRYPTED_CONTENT 14
128 #define PKCS7_ENVELOPED_ROOF 15
131 * PKCS7 contentInfo OIDs
134 static u_char ASN1_pkcs7_data_oid_str
[] = {
135 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01
138 static u_char ASN1_pkcs7_signed_data_oid_str
[] = {
139 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02
142 static u_char ASN1_pkcs7_enveloped_data_oid_str
[] = {
143 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x03
146 static u_char ASN1_pkcs7_signed_enveloped_data_oid_str
[] = {
147 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x04
150 static u_char ASN1_pkcs7_digested_data_oid_str
[] = {
151 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x05
154 static char ASN1_pkcs7_encrypted_data_oid_str
[] = {
155 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06
158 static const chunk_t ASN1_pkcs7_data_oid
=
159 chunk_from_buf(ASN1_pkcs7_data_oid_str
);
160 static const chunk_t ASN1_pkcs7_signed_data_oid
=
161 chunk_from_buf(ASN1_pkcs7_signed_data_oid_str
);
162 static const chunk_t ASN1_pkcs7_enveloped_data_oid
=
163 chunk_from_buf(ASN1_pkcs7_enveloped_data_oid_str
);
164 static const chunk_t ASN1_pkcs7_signed_enveloped_data_oid
=
165 chunk_from_buf(ASN1_pkcs7_signed_enveloped_data_oid_str
);
166 static const chunk_t ASN1_pkcs7_digested_data_oid
=
167 chunk_from_buf(ASN1_pkcs7_digested_data_oid_str
);
168 static const chunk_t ASN1_pkcs7_encrypted_data_oid
=
169 chunk_from_buf(ASN1_pkcs7_encrypted_data_oid_str
);
172 * 3DES and DES encryption OIDs
175 static u_char ASN1_3des_ede_cbc_oid_str
[] = {
176 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x07
179 static u_char ASN1_des_cbc_oid_str
[] = {
180 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x07
183 static const chunk_t ASN1_3des_ede_cbc_oid
=
184 chunk_from_buf(ASN1_3des_ede_cbc_oid_str
);
185 static const chunk_t ASN1_des_cbc_oid
=
186 chunk_from_buf(ASN1_des_cbc_oid_str
);
189 * PKCS#7 attribute type OIDs
192 static u_char ASN1_contentType_oid_str
[] = {
193 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03
196 static u_char ASN1_messageDigest_oid_str
[] = {
197 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04
200 static const chunk_t ASN1_contentType_oid
=
201 chunk_from_buf(ASN1_contentType_oid_str
);
202 static const chunk_t ASN1_messageDigest_oid
=
203 chunk_from_buf(ASN1_messageDigest_oid_str
);
206 * Parse PKCS#7 ContentInfo object
208 bool pkcs7_parse_contentInfo(chunk_t blob
, u_int level0
, contentInfo_t
*cInfo
)
210 asn1_parser_t
*parser
;
213 bool success
= FALSE
;
215 parser
= asn1_parser_create(contentInfoObjects
, blob
);
216 parser
->set_top_level(parser
, level0
);
218 while (parser
->iterate(parser
, &objectID
, &object
))
220 if (objectID
== PKCS7_INFO_TYPE
)
222 cInfo
->type
= asn1_known_oid(object
);
223 if (cInfo
->type
< OID_PKCS7_DATA
224 || cInfo
->type
> OID_PKCS7_ENCRYPTED_DATA
)
226 DBG1("unknown pkcs7 content type");
230 else if (objectID
== PKCS7_INFO_CONTENT
)
232 cInfo
->content
= object
;
235 success
= parser
->success(parser
);
238 parser
->destroy(parser
);
243 * Parse a PKCS#7 signedData object
245 bool pkcs7_parse_signedData(chunk_t blob
, contentInfo_t
*data
, x509cert_t
**cert
,
246 chunk_t
*attributes
, const x509cert_t
*cacert
)
249 asn1_parser_t
*parser
;
251 int digest_alg
= OID_UNKNOWN
;
252 int enc_alg
= OID_UNKNOWN
;
255 bool success
= FALSE
;
257 contentInfo_t cInfo
= empty_contentInfo
;
258 chunk_t encrypted_digest
= chunk_empty
;
260 if (!pkcs7_parse_contentInfo(blob
, 0, &cInfo
))
264 if (cInfo
.type
!= OID_PKCS7_SIGNED_DATA
)
266 DBG1("pkcs7 content type is not signedData");
270 parser
= asn1_parser_create(signedDataObjects
, blob
);
271 parser
->set_top_level(parser
, 2);
273 while (parser
->iterate(parser
, &objectID
, &object
))
275 u_int level
= parser
->get_level(parser
);
279 case PKCS7_DIGEST_ALG
:
280 digest_alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
282 case PKCS7_SIGNED_CONTENT_INFO
:
285 pkcs7_parse_contentInfo(object
, level
, data
);
288 case PKCS7_SIGNED_CERT
:
291 chunk_t cert_blob
= chunk_clone(object
);
292 x509cert_t
*newcert
= malloc_thing(x509cert_t
);
294 *newcert
= empty_x509cert
;
296 DBG2(" parsing pkcs7-wrapped certificate");
297 if (parse_x509cert(cert_blob
, level
+1, newcert
))
299 newcert
->next
= *cert
;
304 free_x509cert(newcert
);
308 case PKCS7_SIGNER_INFO
:
310 DBG2(" signer #%d", signerInfos
);
312 case PKCS7_SIGNED_ISSUER
:
313 dntoa(buf
, BUF_LEN
, object
);
316 case PKCS7_AUTH_ATTRIBUTES
:
317 if (attributes
!= NULL
)
319 *attributes
= object
;
320 *attributes
->ptr
= ASN1_SET
;
323 case PKCS7_DIGEST_ALGORITHM
:
324 digest_alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
326 case PKCS7_DIGEST_ENC_ALGORITHM
:
327 enc_alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
329 case PKCS7_ENCRYPTED_DIGEST
:
330 encrypted_digest
= object
;
333 success
= parser
->success(parser
);
334 parser
->destroy(parser
);
340 /* check the signature only if a cacert is available */
343 public_key_t
*key
= cacert
->public_key
;
344 signature_scheme_t scheme
= SIGN_RSA_EMSA_PKCS1_SHA1
;
346 if (signerInfos
== 0)
348 DBG1("no signerInfo object found");
351 else if (signerInfos
> 1)
353 DBG1("more than one signerInfo object found");
356 if (attributes
->ptr
== NULL
)
358 DBG1("no authenticatedAttributes object found");
361 if (enc_alg
!= OID_RSA_ENCRYPTION
)
363 DBG1("only RSA digest encryption supported");
369 scheme
= SIGN_RSA_EMSA_PKCS1_MD5
;
372 scheme
= SIGN_RSA_EMSA_PKCS1_SHA1
;
375 scheme
= SIGN_RSA_EMSA_PKCS1_SHA256
;
378 scheme
= SIGN_RSA_EMSA_PKCS1_SHA384
;
381 scheme
= SIGN_RSA_EMSA_PKCS1_SHA512
;
386 if (key
->verify(key
, scheme
, *attributes
, encrypted_digest
))
388 DBG2("signature is valid");
392 DBG1("invalid signature");
400 * Parse a PKCS#7 envelopedData object
402 bool pkcs7_parse_envelopedData(chunk_t blob
, chunk_t
*data
,
403 chunk_t serialNumber
,
406 asn1_parser_t
*parser
;
408 chunk_t iv
= chunk_empty
;
409 chunk_t symmetric_key
= chunk_empty
;
410 chunk_t encrypted_content
= chunk_empty
;
412 crypter_t
*crypter
= NULL
;
415 int enc_alg
= OID_UNKNOWN
;
416 int content_enc_alg
= OID_UNKNOWN
;
418 bool success
= FALSE
;
420 contentInfo_t cInfo
= empty_contentInfo
;
423 if (!pkcs7_parse_contentInfo(blob
, 0, &cInfo
))
427 if (cInfo
.type
!= OID_PKCS7_ENVELOPED_DATA
)
429 DBG1("pkcs7 content type is not envelopedData");
433 parser
= asn1_parser_create(envelopedDataObjects
, cInfo
.content
);
434 parser
->set_top_level(parser
, 2);
436 while (parser
->iterate(parser
, &objectID
, &object
))
438 u_int level
= parser
->get_level(parser
);
442 case PKCS7_ENVELOPED_VERSION
:
443 if (*object
.ptr
!= 0)
445 DBG1("envelopedData version is not 0");
449 case PKCS7_RECIPIENT_INFO_VERSION
:
450 if (*object
.ptr
!= 0)
452 DBG1("recipient info version is not 0");
457 dntoa(buf
, BUF_LEN
, object
);
460 case PKCS7_SERIAL_NUMBER
:
461 if (!chunk_equals(serialNumber
, object
))
463 DBG1("serial numbers do not match");
467 case PKCS7_ENCRYPTION_ALG
:
468 enc_alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
469 if (enc_alg
!= OID_RSA_ENCRYPTION
)
471 DBG1("only rsa encryption supported");
475 case PKCS7_ENCRYPTED_KEY
:
476 if (!key
->decrypt(key
, object
, &symmetric_key
))
478 DBG1("symmetric key could not be decrypted with rsa");
481 DBG4("symmetric key %B", &symmetric_key
);
483 case PKCS7_CONTENT_TYPE
:
484 if (asn1_known_oid(object
) != OID_PKCS7_DATA
)
486 DBG1("encrypted content not of type pkcs7 data");
490 case PKCS7_CONTENT_ENC_ALGORITHM
:
491 content_enc_alg
= asn1_parse_algorithmIdentifier(object
, level
, &iv
);
493 if (content_enc_alg
== OID_UNKNOWN
)
495 DBG1("unknown content encryption algorithm");
498 if (!asn1_parse_simple_object(&iv
, ASN1_OCTET_STRING
, level
+1, "IV"))
500 DBG1("IV could not be parsed");
504 case PKCS7_ENCRYPTED_CONTENT
:
505 encrypted_content
= object
;
509 success
= parser
->success(parser
);
512 parser
->destroy(parser
);
519 /* decrypt the content */
521 encryption_algorithm_t alg
;
525 alg
= encryption_algorithm_from_oid(content_enc_alg
, &key_size
);
526 if (alg
== ENCR_UNDEFINED
)
528 DBG1("unsupported content encryption algorithm");
531 crypter
= lib
->crypto
->create_crypter(lib
->crypto
, alg
, key_size
);
534 DBG1("crypter %N not available", encryption_algorithm_names
, alg
);
537 if (symmetric_key
.len
!= crypter
->get_key_size(crypter
))
539 DBG1("symmetric key length %d is wrong", symmetric_key
.len
);
542 if (iv
.len
!= crypter
->get_block_size(crypter
))
544 DBG1("IV length %d is wrong", iv
.len
);
547 crypter
->set_key(crypter
, symmetric_key
);
548 crypter
->decrypt(crypter
, encrypted_content
, iv
, data
);
549 DBG4("decrypted content with padding: %B", data
);
552 /* remove the padding */
554 u_char
*pos
= data
->ptr
+ data
->len
- 1;
555 u_char pattern
= *pos
;
556 size_t padding
= pattern
;
558 if (padding
> data
->len
)
560 DBG1("padding greater than data length");
563 data
->len
-= padding
;
565 while (padding
-- > 0)
567 if (*pos
-- != pattern
)
569 DBG1("wrong padding pattern");
578 chunk_clear(&symmetric_key
);
587 * @brief Builds a contentType attribute
589 * @return ASN.1 encoded contentType attribute
591 chunk_t
pkcs7_contentType_attribute(void)
593 return asn1_wrap(ASN1_SEQUENCE
, "cm"
594 , ASN1_contentType_oid
595 , asn1_simple_object(ASN1_SET
, ASN1_pkcs7_data_oid
));
599 * @brief Builds a messageDigest attribute
602 * @param[in] blob content to create digest of
603 * @param[in] digest_alg digest algorithm to be used
604 * @return ASN.1 encoded messageDigest attribute
607 chunk_t
pkcs7_messageDigest_attribute(chunk_t content
, int digest_alg
)
610 hash_algorithm_t hash_alg
;
613 hash_alg
= hasher_algorithm_from_oid(digest_alg
);
614 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, hash_alg
);
615 hasher
->allocate_hash(hasher
, content
, &digest
);
617 return asn1_wrap(ASN1_SEQUENCE
, "cm",
618 ASN1_messageDigest_oid
,
619 asn1_wrap(ASN1_SET
, "m",
620 asn1_wrap(ASN1_OCTET_STRING
, "m", digest
)
626 * build a DER-encoded contentInfo object
628 static chunk_t
pkcs7_build_contentInfo(contentInfo_t
*cInfo
)
630 chunk_t content_type
;
632 /* select DER-encoded OID for pkcs7 contentInfo type */
636 content_type
= ASN1_pkcs7_data_oid
;
638 case OID_PKCS7_SIGNED_DATA
:
639 content_type
= ASN1_pkcs7_signed_data_oid
;
641 case OID_PKCS7_ENVELOPED_DATA
:
642 content_type
= ASN1_pkcs7_enveloped_data_oid
;
644 case OID_PKCS7_SIGNED_ENVELOPED_DATA
:
645 content_type
= ASN1_pkcs7_signed_enveloped_data_oid
;
647 case OID_PKCS7_DIGESTED_DATA
:
648 content_type
= ASN1_pkcs7_digested_data_oid
;
650 case OID_PKCS7_ENCRYPTED_DATA
:
651 content_type
= ASN1_pkcs7_encrypted_data_oid
;
655 DBG1("invalid pkcs7 contentInfo type");
659 return (cInfo
->content
.ptr
== NULL
)
660 ?
asn1_simple_object(ASN1_SEQUENCE
, content_type
)
661 : asn1_wrap(ASN1_SEQUENCE
, "cm"
663 , asn1_simple_object(ASN1_CONTEXT_C_0
, cInfo
->content
)
668 * build issuerAndSerialNumber object
670 chunk_t
pkcs7_build_issuerAndSerialNumber(const x509cert_t
*cert
)
672 return asn1_wrap(ASN1_SEQUENCE
, "cm"
674 , asn1_simple_object(ASN1_INTEGER
, cert
->serialNumber
));
678 * create a signed pkcs7 contentInfo object
680 chunk_t
pkcs7_build_signedData(chunk_t data
, chunk_t attributes
,
681 const x509cert_t
*cert
, int digest_alg
,
684 contentInfo_t pkcs7Data
, signedData
;
685 chunk_t authenticatedAttributes
, encryptedDigest
, signerInfo
, cInfo
;
687 chunk_t digestAlgorithm
= asn1_algorithmIdentifier(digest_alg
);
689 if (attributes
.ptr
!= NULL
)
691 encryptedDigest
= x509_build_signature(attributes
, digest_alg
, key
,
693 authenticatedAttributes
= chunk_clone(attributes
);
694 *authenticatedAttributes
.ptr
= ASN1_CONTEXT_C_0
;
698 encryptedDigest
= (data
.ptr
== NULL
)? chunk_empty
699 : x509_build_signature(data
, digest_alg
, key
, FALSE
);
700 authenticatedAttributes
= chunk_empty
;
703 signerInfo
= asn1_wrap(ASN1_SEQUENCE
, "cmcmcm"
705 , pkcs7_build_issuerAndSerialNumber(cert
)
707 , authenticatedAttributes
708 , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
)
711 pkcs7Data
.type
= OID_PKCS7_DATA
;
712 pkcs7Data
.content
= (data
.ptr
== NULL
)? chunk_empty
713 : asn1_simple_object(ASN1_OCTET_STRING
, data
);
715 signedData
.type
= OID_PKCS7_SIGNED_DATA
;
716 signedData
.content
= asn1_wrap(ASN1_SEQUENCE
, "cmmmm"
718 , asn1_simple_object(ASN1_SET
, digestAlgorithm
)
719 , pkcs7_build_contentInfo(&pkcs7Data
)
720 , asn1_simple_object(ASN1_CONTEXT_C_0
, cert
->certificate
)
721 , asn1_wrap(ASN1_SET
, "m", signerInfo
));
723 cInfo
= pkcs7_build_contentInfo(&signedData
);
724 DBG3("signedData %B", &cInfo
);
726 free(pkcs7Data
.content
.ptr
);
727 free(signedData
.content
.ptr
);
732 * create a symmetrically encrypted pkcs7 contentInfo object
734 chunk_t
pkcs7_build_envelopedData(chunk_t data
, const x509cert_t
*cert
, int enc_alg
)
736 encryption_algorithm_t alg
;
738 chunk_t symmetricKey
, protectedKey
, iv
, in
, out
;
741 alg
= encryption_algorithm_from_oid(enc_alg
, &alg_key_size
);
742 crypter
= lib
->crypto
->create_crypter(lib
->crypto
, alg
,
743 alg_key_size
/BITS_PER_BYTE
);
746 DBG1("crypter for %N not available", encryption_algorithm_names
, alg
);
750 /* generate a true random symmetric encryption key and a pseudo-random iv */
754 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_TRUE
);
755 rng
->allocate_bytes(rng
, crypter
->get_key_size(crypter
), &symmetricKey
);
756 DBG4("symmetric encryption key %B", &symmetricKey
);
759 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
760 rng
->allocate_bytes(rng
, crypter
->get_block_size(crypter
), &iv
);
761 DBG4("initialization vector: %B", &iv
);
765 /* pad the data to a multiple of the block size */
767 size_t block_size
= crypter
->get_block_size(crypter
);
768 size_t padding
= block_size
- data
.len
% block_size
;
770 in
.len
= data
.len
+ padding
;
771 in
.ptr
= malloc(in
.len
);
773 DBG2("padding %u bytes of data to multiple block size of %u bytes",
777 memcpy(in
.ptr
, data
.ptr
, data
.len
);
779 memset(in
.ptr
+ data
.len
, padding
, padding
);
781 DBG3("padded unencrypted data %B", &in
);
783 /* symmetric encryption of data object */
784 crypter
->set_key(crypter
, symmetricKey
);
785 crypter
->encrypt(crypter
, in
, iv
, &out
);
786 crypter
->destroy(crypter
);
787 DBG3("encrypted data %B", &out
);
791 cert
->public_key
->encrypt(cert
->public_key
, symmetricKey
, &protectedKey
);
793 /* build pkcs7 enveloped data object */
796 chunk_t contentEncryptionAlgorithm
= asn1_wrap(ASN1_SEQUENCE
, "mm"
797 , asn1_build_known_oid(enc_alg
)
798 , asn1_simple_object(ASN1_OCTET_STRING
, iv
));
800 chunk_t encryptedContentInfo
= asn1_wrap(ASN1_SEQUENCE
, "cmm"
801 , ASN1_pkcs7_data_oid
802 , contentEncryptionAlgorithm
803 , asn1_wrap(ASN1_CONTEXT_S_0
, "m", out
));
805 chunk_t encryptedKey
= asn1_wrap(ASN1_OCTET_STRING
, "m"
808 chunk_t recipientInfo
= asn1_wrap(ASN1_SEQUENCE
, "cmcm"
810 , pkcs7_build_issuerAndSerialNumber(cert
)
811 , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
)
815 contentInfo_t envelopedData
;
817 envelopedData
.type
= OID_PKCS7_ENVELOPED_DATA
;
818 envelopedData
.content
= asn1_wrap(ASN1_SEQUENCE
, "cmm"
820 , asn1_wrap(ASN1_SET
, "m", recipientInfo
)
821 , encryptedContentInfo
);
823 cInfo
= pkcs7_build_contentInfo(&envelopedData
);
824 DBG3("envelopedData %B", &cInfo
);
826 free(envelopedData
.content
.ptr
);
827 free(symmetricKey
.ptr
);