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
24 #include <asn1/asn1.h>
25 #include <asn1/asn1_parser.h>
27 #include <crypto/rngs/rng.h>
28 #include <crypto/crypters/crypter.h>
29 #include <credentials/certificates/x509.h>
33 const contentInfo_t empty_contentInfo
= {
34 OID_UNKNOWN
, /* type */
35 { NULL
, 0 } /* content */
39 * ASN.1 definition of the PKCS#7 ContentInfo type
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
}
48 #define PKCS7_INFO_TYPE 1
49 #define PKCS7_INFO_CONTENT 2
52 * ASN.1 definition of the PKCS#7 signedData type
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
}
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
97 * ASN.1 definition of the PKCS#7 envelopedData type
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
}
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
129 * Parse PKCS#7 ContentInfo object
131 bool pkcs7_parse_contentInfo(chunk_t blob
, u_int level0
, contentInfo_t
*cInfo
)
133 asn1_parser_t
*parser
;
136 bool success
= FALSE
;
138 parser
= asn1_parser_create(contentInfoObjects
, blob
);
139 parser
->set_top_level(parser
, level0
);
141 while (parser
->iterate(parser
, &objectID
, &object
))
143 if (objectID
== PKCS7_INFO_TYPE
)
145 cInfo
->type
= asn1_known_oid(object
);
146 if (cInfo
->type
< OID_PKCS7_DATA
147 || cInfo
->type
> OID_PKCS7_ENCRYPTED_DATA
)
149 DBG1(DBG_LIB
, "unknown pkcs7 content type");
153 else if (objectID
== PKCS7_INFO_CONTENT
)
155 cInfo
->content
= object
;
158 success
= parser
->success(parser
);
161 parser
->destroy(parser
);
166 * Parse a PKCS#7 signedData object
168 bool pkcs7_parse_signedData(chunk_t blob
, contentInfo_t
*data
,
169 linked_list_t
*certs
,
170 chunk_t
*attributes
, certificate_t
*cacert
)
172 asn1_parser_t
*parser
;
174 int digest_alg
= OID_UNKNOWN
;
175 int enc_alg
= OID_UNKNOWN
;
179 bool success
= FALSE
;
181 contentInfo_t cInfo
= empty_contentInfo
;
182 chunk_t encrypted_digest
= chunk_empty
;
184 if (!pkcs7_parse_contentInfo(blob
, 0, &cInfo
))
188 if (cInfo
.type
!= OID_PKCS7_SIGNED_DATA
)
190 DBG1(DBG_LIB
, "pkcs7 content type is not signedData");
194 parser
= asn1_parser_create(signedDataObjects
, cInfo
.content
);
195 parser
->set_top_level(parser
, 2);
197 while (parser
->iterate(parser
, &objectID
, &object
))
199 u_int level
= parser
->get_level(parser
);
203 case PKCS7_SIGNED_VERSION
:
204 version
= object
.len ?
(int)*object
.ptr
: 0;
205 DBG2(DBG_LIB
, " v%d", version
);
207 case PKCS7_DIGEST_ALG
:
208 digest_alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
210 case PKCS7_SIGNED_CONTENT_INFO
:
213 pkcs7_parse_contentInfo(object
, level
, data
);
216 case PKCS7_SIGNED_CERT
:
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
,
227 certs
->insert_last(certs
, cert
);
231 case PKCS7_SIGNER_INFO
:
233 DBG2(DBG_LIB
, " signer #%d", signerInfos
);
235 case PKCS7_SIGNER_INFO_VERSION
:
236 version
= object
.len ?
(int)*object
.ptr
: 0;
237 DBG2(DBG_LIB
, " v%d", version
);
239 case PKCS7_SIGNED_ISSUER
:
241 identification_t
*issuer
= identification_create_from_encoding(
242 ID_DER_ASN1_DN
, object
);
243 DBG2(DBG_LIB
, " \"%Y\"", issuer
);
244 issuer
->destroy(issuer
);
247 case PKCS7_AUTH_ATTRIBUTES
:
248 if (attributes
!= NULL
)
250 *attributes
= object
;
251 *attributes
->ptr
= ASN1_SET
;
254 case PKCS7_DIGEST_ALGORITHM
:
255 digest_alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
257 case PKCS7_DIGEST_ENC_ALGORITHM
:
258 enc_alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
260 case PKCS7_ENCRYPTED_DIGEST
:
261 encrypted_digest
= object
;
264 success
= parser
->success(parser
);
265 parser
->destroy(parser
);
271 /* check the signature only if a cacert is available */
275 signature_scheme_t scheme
;
277 scheme
= signature_scheme_from_oid(digest_alg
);
278 if (scheme
== SIGN_UNKNOWN
)
280 DBG1(DBG_LIB
, "unsupported signature scheme");
283 if (signerInfos
== 0)
285 DBG1(DBG_LIB
, "no signerInfo object found");
288 else if (signerInfos
> 1)
290 DBG1(DBG_LIB
, "more than one signerInfo object found");
293 if (attributes
->ptr
== NULL
)
295 DBG1(DBG_LIB
, "no authenticatedAttributes object found");
298 if (enc_alg
!= OID_RSA_ENCRYPTION
)
300 DBG1(DBG_LIB
, "only RSA digest encryption supported");
304 /* verify the signature */
305 key
= cacert
->get_public_key(cacert
);
308 DBG1(DBG_LIB
, "no public key found in CA certificate");
311 if (key
->verify(key
, scheme
, *attributes
, encrypted_digest
))
313 DBG2(DBG_LIB
, "signature is valid");
317 DBG1(DBG_LIB
, "invalid signature");
326 * Parse a PKCS#7 envelopedData object
328 bool pkcs7_parse_envelopedData(chunk_t blob
, chunk_t
*data
,
329 chunk_t serialNumber
,
332 asn1_parser_t
*parser
;
334 chunk_t iv
= chunk_empty
;
335 chunk_t symmetric_key
= chunk_empty
;
336 chunk_t encrypted_content
= chunk_empty
;
338 crypter_t
*crypter
= NULL
;
340 int enc_alg
= OID_UNKNOWN
;
341 int content_enc_alg
= OID_UNKNOWN
;
344 bool success
= FALSE
;
346 contentInfo_t cInfo
= empty_contentInfo
;
349 if (!pkcs7_parse_contentInfo(blob
, 0, &cInfo
))
353 if (cInfo
.type
!= OID_PKCS7_ENVELOPED_DATA
)
355 DBG1(DBG_LIB
, "pkcs7 content type is not envelopedData");
359 parser
= asn1_parser_create(envelopedDataObjects
, cInfo
.content
);
360 parser
->set_top_level(parser
, 2);
362 while (parser
->iterate(parser
, &objectID
, &object
))
364 u_int level
= parser
->get_level(parser
);
368 case PKCS7_ENVELOPED_VERSION
:
369 version
= object
.len ?
(int)*object
.ptr
: 0;
370 DBG2(DBG_LIB
, " v%d", version
);
373 DBG1(DBG_LIB
, "envelopedData version is not 0");
377 case PKCS7_RECIPIENT_INFO_VERSION
:
378 version
= object
.len ?
(int)*object
.ptr
: 0;
379 DBG2(DBG_LIB
, " v%d", version
);
382 DBG1(DBG_LIB
, "recipient info version is not 0");
388 identification_t
*issuer
= identification_create_from_encoding(
389 ID_DER_ASN1_DN
, object
);
390 DBG2(DBG_LIB
, " \"%Y\"", issuer
);
391 issuer
->destroy(issuer
);
394 case PKCS7_SERIAL_NUMBER
:
395 if (!chunk_equals(serialNumber
, object
))
397 DBG1(DBG_LIB
, "serial numbers do not match");
401 case PKCS7_ENCRYPTION_ALG
:
402 enc_alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
403 if (enc_alg
!= OID_RSA_ENCRYPTION
)
405 DBG1(DBG_LIB
, "only rsa encryption supported");
409 case PKCS7_ENCRYPTED_KEY
:
410 if (!key
->decrypt(key
, ENCRYPT_RSA_PKCS1
, object
, &symmetric_key
))
412 DBG1(DBG_LIB
, "symmetric key could not be decrypted with rsa");
415 DBG4(DBG_LIB
, "symmetric key %B", &symmetric_key
);
417 case PKCS7_CONTENT_TYPE
:
418 if (asn1_known_oid(object
) != OID_PKCS7_DATA
)
420 DBG1(DBG_LIB
, "encrypted content not of type pkcs7 data");
424 case PKCS7_CONTENT_ENC_ALGORITHM
:
425 content_enc_alg
= asn1_parse_algorithmIdentifier(object
, level
, &iv
);
427 if (content_enc_alg
== OID_UNKNOWN
)
429 DBG1(DBG_LIB
, "unknown content encryption algorithm");
432 if (!asn1_parse_simple_object(&iv
, ASN1_OCTET_STRING
, level
+1, "IV"))
434 DBG1(DBG_LIB
, "IV could not be parsed");
438 case PKCS7_ENCRYPTED_CONTENT
:
439 encrypted_content
= object
;
443 success
= parser
->success(parser
);
446 parser
->destroy(parser
);
453 /* decrypt the content */
455 encryption_algorithm_t alg
;
459 alg
= encryption_algorithm_from_oid(content_enc_alg
, &key_size
);
460 if (alg
== ENCR_UNDEFINED
)
462 DBG1(DBG_LIB
, "unsupported content encryption algorithm");
465 crypter
= lib
->crypto
->create_crypter(lib
->crypto
, alg
, key_size
);
468 DBG1(DBG_LIB
, "crypter %N not available", encryption_algorithm_names
, alg
);
471 if (symmetric_key
.len
!= crypter
->get_key_size(crypter
))
473 DBG1(DBG_LIB
, "symmetric key length %d is wrong", symmetric_key
.len
);
476 if (iv
.len
!= crypter
->get_block_size(crypter
))
478 DBG1(DBG_LIB
, "IV length %d is wrong", iv
.len
);
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
);
486 /* remove the padding */
488 u_char
*pos
= data
->ptr
+ data
->len
- 1;
489 u_char pattern
= *pos
;
490 size_t padding
= pattern
;
492 if (padding
> data
->len
)
494 DBG1(DBG_LIB
, "padding greater than data length");
497 data
->len
-= padding
;
499 while (padding
-- > 0)
501 if (*pos
-- != pattern
)
503 DBG1(DBG_LIB
, "wrong padding pattern");
512 chunk_clear(&symmetric_key
);
521 * @brief Builds a contentType attribute
523 * @return ASN.1 encoded contentType attribute
525 chunk_t
pkcs7_contentType_attribute(void)
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
)));
534 * @brief Builds a messageDigest attribute
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
542 chunk_t
pkcs7_messageDigest_attribute(chunk_t content
, int digest_alg
)
545 hash_algorithm_t hash_alg
;
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
);
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
)));
560 * build a DER-encoded contentInfo object
562 static chunk_t
pkcs7_build_contentInfo(contentInfo_t
*cInfo
)
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
);
572 * build issuerAndSerialNumber object
574 chunk_t
pkcs7_build_issuerAndSerialNumber(certificate_t
*cert
)
576 identification_t
*issuer
= cert
->get_issuer(cert
);
577 x509_t
*x509
= (x509_t
*)cert
;
579 return asn1_wrap(ASN1_SEQUENCE
, "cm",
580 issuer
->get_encoding(issuer
),
581 asn1_integer("c", x509
->get_serial(x509
)));
585 * create a signed pkcs7 contentInfo object
587 chunk_t
pkcs7_build_signedData(chunk_t data
, chunk_t attributes
,
588 certificate_t
*cert
, int digest_alg
,
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
);
599 if (key
->sign(key
, scheme
, attributes
, &signature
))
601 encryptedDigest
= asn1_wrap(ASN1_OCTET_STRING
, "m", signature
);
602 authenticatedAttributes
= chunk_clone(attributes
);
603 *authenticatedAttributes
.ptr
= ASN1_CONTEXT_C_0
;
608 if (key
->sign(key
, scheme
, data
, &signature
))
610 encryptedDigest
= asn1_wrap(ASN1_OCTET_STRING
, "m", signature
);
613 signerInfo
= asn1_wrap(ASN1_SEQUENCE
, "cmmmmm"
615 , pkcs7_build_issuerAndSerialNumber(cert
)
616 , asn1_algorithmIdentifier(digest_alg
)
617 , authenticatedAttributes
618 , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
)
621 pkcs7Data
.type
= OID_PKCS7_DATA
;
622 pkcs7Data
.content
= (data
.ptr
== NULL
)? chunk_empty
623 : asn1_simple_object(ASN1_OCTET_STRING
, data
);
625 cert
->get_encoding(cert
, CERT_ASN1_DER
, &encoding
);
626 signedData
.type
= OID_PKCS7_SIGNED_DATA
;
627 signedData
.content
= asn1_wrap(ASN1_SEQUENCE
, "cmmmm"
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
));
634 cInfo
= pkcs7_build_contentInfo(&signedData
);
635 DBG3(DBG_LIB
, "signedData %B", &cInfo
);
637 free(pkcs7Data
.content
.ptr
);
638 free(signedData
.content
.ptr
);
643 * create a symmetrically encrypted pkcs7 contentInfo object
645 chunk_t
pkcs7_build_envelopedData(chunk_t data
, certificate_t
*cert
, int enc_alg
)
647 encryption_algorithm_t alg
;
649 chunk_t symmetricKey
, protectedKey
, iv
, in
, out
;
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
);
657 DBG1(DBG_LIB
, "crypter for %N not available", encryption_algorithm_names
, alg
);
661 /* generate a true random symmetric encryption key and a pseudo-random iv */
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
);
670 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
671 rng
->allocate_bytes(rng
, crypter
->get_block_size(crypter
), &iv
);
672 DBG4(DBG_LIB
, "initialization vector: %B", &iv
);
676 /* pad the data to a multiple of the block size */
678 size_t block_size
= crypter
->get_block_size(crypter
);
679 size_t padding
= block_size
- data
.len
% block_size
;
681 in
.len
= data
.len
+ padding
;
682 in
.ptr
= malloc(in
.len
);
684 DBG2(DBG_LIB
, "padding %u bytes of data to multiple block size of %u bytes",
688 memcpy(in
.ptr
, data
.ptr
, data
.len
);
690 memset(in
.ptr
+ data
.len
, padding
, padding
);
692 DBG3(DBG_LIB
, "padded unencrypted data %B", &in
);
694 /* symmetric encryption of data object */
695 crypter
->set_key(crypter
, symmetricKey
);
696 crypter
->encrypt(crypter
, in
, iv
, &out
);
697 crypter
->destroy(crypter
);
699 DBG3(DBG_LIB
, "encrypted data %B", &out
);
701 /* protect symmetric key by public key encryption */
703 public_key_t
*key
= cert
->get_public_key(cert
);
707 DBG1(DBG_LIB
, "public key not found in encryption certificate");
708 chunk_clear(&symmetricKey
);
713 key
->encrypt(key
, ENCRYPT_RSA_PKCS1
, symmetricKey
, &protectedKey
);
717 /* build pkcs7 enveloped data object */
720 chunk_t contentEncryptionAlgorithm
= asn1_wrap(ASN1_SEQUENCE
, "mm"
721 , asn1_build_known_oid(enc_alg
)
722 , asn1_simple_object(ASN1_OCTET_STRING
, iv
));
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
));
729 chunk_t encryptedKey
= asn1_wrap(ASN1_OCTET_STRING
, "m"
732 chunk_t recipientInfo
= asn1_wrap(ASN1_SEQUENCE
, "cmmm"
734 , pkcs7_build_issuerAndSerialNumber(cert
)
735 , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
)
739 contentInfo_t envelopedData
;
741 envelopedData
.type
= OID_PKCS7_ENVELOPED_DATA
;
742 envelopedData
.content
= asn1_wrap(ASN1_SEQUENCE
, "cmm"
744 , asn1_wrap(ASN1_SET
, "m", recipientInfo
)
745 , encryptedContentInfo
);
747 cInfo
= pkcs7_build_contentInfo(&envelopedData
);
748 DBG3(DBG_LIB
, "envelopedData %B", &cInfo
);
750 chunk_free(&envelopedData
.content
);
752 chunk_clear(&symmetricKey
);