2 * Copyright (C) 2012 Tobias Brunner
3 * Copyright (C) 2002-2008 Andreas Steffen
4 * Copyright (C) 2005 Jan Hutter, Martin Willi
5 * 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
26 #include <asn1/asn1.h>
27 #include <asn1/asn1_parser.h>
28 #include <credentials/certificates/x509.h>
29 #include <credentials/keys/public_key.h>
30 #include <crypto/pkcs9.h>
31 #include <crypto/hashers/hasher.h>
32 #include <crypto/crypters/crypter.h>
33 #include <utils/linked_list.h>
37 typedef struct private_pkcs7_t private_pkcs7_t
;
40 * Private data of a pkcs7_t object.
42 struct private_pkcs7_t
{
44 * Public interface for this certificate.
54 * ASN.1 encoded content
59 * ASN.1 parsing start level
69 * ASN.1 encoded attributes
74 * Linked list of X.509 certificates
79 METHOD(pkcs7_t
, is_data
, bool,
80 private_pkcs7_t
*this)
82 return this->type
== OID_PKCS7_DATA
;
85 METHOD(pkcs7_t
, is_signedData
, bool,
86 private_pkcs7_t
*this)
88 return this->type
== OID_PKCS7_SIGNED_DATA
;
91 METHOD(pkcs7_t
, is_envelopedData
, bool,
92 private_pkcs7_t
*this)
94 return this->type
== OID_PKCS7_ENVELOPED_DATA
;
98 * ASN.1 definition of the PKCS#7 ContentInfo type
100 static const asn1Object_t contentInfoObjects
[] = {
101 { 0, "contentInfo", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
102 { 1, "contentType", ASN1_OID
, ASN1_BODY
}, /* 1 */
103 { 1, "content", ASN1_CONTEXT_C_0
, ASN1_OPT
|
105 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 3 */
106 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
108 #define PKCS7_INFO_TYPE 1
109 #define PKCS7_INFO_CONTENT 2
112 * Parse PKCS#7 contentInfo object
114 static bool parse_contentInfo(private_pkcs7_t
*this)
116 asn1_parser_t
*parser
;
119 bool success
= FALSE
;
126 parser
= asn1_parser_create(contentInfoObjects
, this->data
);
127 parser
->set_top_level(parser
, this->level
);
129 while (parser
->iterate(parser
, &objectID
, &object
))
131 if (objectID
== PKCS7_INFO_TYPE
)
133 this->type
= asn1_known_oid(object
);
134 if (this->type
< OID_PKCS7_DATA
||
135 this->type
> OID_PKCS7_ENCRYPTED_DATA
)
137 DBG1(DBG_LIB
, "unknown pkcs7 content type");
141 else if (objectID
== PKCS7_INFO_CONTENT
&& object
.len
> 0)
143 chunk_free(&this->content
);
144 this->content
= chunk_clone(object
);
147 success
= parser
->success(parser
);
152 chunk_free(&this->data
);
156 parser
->destroy(parser
);
161 * Check whether to abort the requested parsing
163 static bool abort_parsing(private_pkcs7_t
*this, int type
)
165 if (this->type
!= type
)
167 DBG1(DBG_LIB
, "pkcs7 content to be parsed is not of type '%s'",
168 oid_names
[type
].name
);
174 METHOD(pkcs7_t
, parse_data
, bool,
175 private_pkcs7_t
*this)
179 if (!parse_contentInfo(this) ||
180 abort_parsing(this, OID_PKCS7_DATA
))
184 data
= this->content
;
187 this->data
= chunk_empty
;
190 if (asn1_parse_simple_object(&data
, ASN1_OCTET_STRING
,
191 this->level
, "data"))
193 this->data
= chunk_clone(data
);
200 * ASN.1 definition of the PKCS#7 signedData type
202 static const asn1Object_t signedDataObjects
[] = {
203 { 0, "signedData", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
204 { 1, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 1 */
205 { 1, "digestAlgorithms", ASN1_SET
, ASN1_LOOP
}, /* 2 */
206 { 2, "algorithm", ASN1_EOC
, ASN1_RAW
}, /* 3 */
207 { 1, "end loop", ASN1_EOC
, ASN1_END
}, /* 4 */
208 { 1, "contentInfo", ASN1_EOC
, ASN1_RAW
}, /* 5 */
209 { 1, "certificates", ASN1_CONTEXT_C_0
, ASN1_OPT
|
211 { 2, "certificate", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 7 */
212 { 1, "end opt or loop", ASN1_EOC
, ASN1_END
}, /* 8 */
213 { 1, "crls", ASN1_CONTEXT_C_1
, ASN1_OPT
|
215 { 2, "crl", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 10 */
216 { 1, "end opt or loop", ASN1_EOC
, ASN1_END
}, /* 11 */
217 { 1, "signerInfos", ASN1_SET
, ASN1_LOOP
}, /* 12 */
218 { 2, "signerInfo", ASN1_SEQUENCE
, ASN1_NONE
}, /* 13 */
219 { 3, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 14 */
220 { 3, "issuerAndSerialNumber", ASN1_SEQUENCE
, ASN1_BODY
}, /* 15 */
221 { 4, "issuer", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 16 */
222 { 4, "serial", ASN1_INTEGER
, ASN1_BODY
}, /* 17 */
223 { 3, "digestAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 18 */
224 { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0
, ASN1_OPT
|
226 { 3, "end opt", ASN1_EOC
, ASN1_END
}, /* 20 */
227 { 3, "digestEncryptionAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 21 */
228 { 3, "encryptedDigest", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 22 */
229 { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 23 */
230 { 3, "end opt", ASN1_EOC
, ASN1_END
}, /* 24 */
231 { 1, "end loop", ASN1_EOC
, ASN1_END
}, /* 25 */
232 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
234 #define PKCS7_SIGNED_VERSION 1
235 #define PKCS7_DIGEST_ALG 3
236 #define PKCS7_SIGNED_CONTENT_INFO 5
237 #define PKCS7_SIGNED_CERT 7
238 #define PKCS7_SIGNER_INFO 13
239 #define PKCS7_SIGNER_INFO_VERSION 14
240 #define PKCS7_SIGNED_ISSUER 16
241 #define PKCS7_SIGNED_SERIAL_NUMBER 17
242 #define PKCS7_DIGEST_ALGORITHM 18
243 #define PKCS7_AUTH_ATTRIBUTES 19
244 #define PKCS7_DIGEST_ENC_ALGORITHM 21
245 #define PKCS7_ENCRYPTED_DIGEST 22
247 METHOD(pkcs7_t
, parse_signedData
, bool,
248 private_pkcs7_t
*this, certificate_t
*cacert
)
250 asn1_parser_t
*parser
;
252 int objectID
, version
;
253 int digest_alg
= OID_UNKNOWN
;
254 int enc_alg
= OID_UNKNOWN
;
256 bool success
= FALSE
;
258 chunk_t encrypted_digest
= chunk_empty
;
260 if (!parse_contentInfo(this) ||
261 abort_parsing(this, OID_PKCS7_SIGNED_DATA
))
266 parser
= asn1_parser_create(signedDataObjects
, this->content
);
267 parser
->set_top_level(parser
, this->level
);
269 while (parser
->iterate(parser
, &objectID
, &object
))
271 u_int level
= parser
->get_level(parser
);
275 case PKCS7_SIGNED_VERSION
:
276 version
= object
.len
? (int)*object
.ptr
: 0;
277 DBG2(DBG_LIB
, " v%d", version
);
279 case PKCS7_DIGEST_ALG
:
280 digest_alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
282 case PKCS7_SIGNED_CONTENT_INFO
:
284 pkcs7_t
*data
= pkcs7_create_from_chunk(object
, level
+1);
286 if (!data
|| !data
->parse_data(data
))
291 this->data
= chunk_clone(data
->get_data(data
));
295 case PKCS7_SIGNED_CERT
:
299 DBG2(DBG_LIB
, " parsing pkcs7-wrapped certificate");
300 cert
= lib
->creds
->create(lib
->creds
,
301 CRED_CERTIFICATE
, CERT_X509
,
302 BUILD_BLOB_ASN1_DER
, object
,
306 this->certs
->insert_last(this->certs
, cert
);
310 case PKCS7_SIGNER_INFO
:
312 DBG2(DBG_LIB
, " signer #%d", signerInfos
);
314 case PKCS7_SIGNER_INFO_VERSION
:
315 version
= object
.len
? (int)*object
.ptr
: 0;
316 DBG2(DBG_LIB
, " v%d", version
);
318 case PKCS7_SIGNED_ISSUER
:
320 identification_t
*issuer
;
322 issuer
= identification_create_from_encoding(ID_DER_ASN1_DN
, object
);
323 DBG2(DBG_LIB
, " '%Y'", issuer
);
324 issuer
->destroy(issuer
);
327 case PKCS7_AUTH_ATTRIBUTES
:
328 *object
.ptr
= ASN1_SET
;
329 this->attributes
= pkcs9_create_from_chunk(object
, level
+1);
330 *object
.ptr
= ASN1_CONTEXT_C_0
;
332 case PKCS7_DIGEST_ALGORITHM
:
333 digest_alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
335 case PKCS7_DIGEST_ENC_ALGORITHM
:
336 enc_alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
338 case PKCS7_ENCRYPTED_DIGEST
:
339 encrypted_digest
= object
;
342 success
= parser
->success(parser
);
345 parser
->destroy(parser
);
351 /* check the signature only if a cacert is available */
354 signature_scheme_t scheme
;
357 scheme
= signature_scheme_from_oid(digest_alg
);
358 if (scheme
== SIGN_UNKNOWN
)
360 DBG1(DBG_LIB
, "unsupported signature scheme");
363 if (signerInfos
== 0)
365 DBG1(DBG_LIB
, "no signerInfo object found");
368 else if (signerInfos
> 1)
370 DBG1(DBG_LIB
, "more than one signerInfo object found");
373 if (this->attributes
== NULL
)
375 DBG1(DBG_LIB
, "no authenticatedAttributes object found");
378 if (enc_alg
!= OID_RSA_ENCRYPTION
)
380 DBG1(DBG_LIB
, "only RSA digest encryption supported");
384 /* verify the signature */
385 key
= cacert
->get_public_key(cacert
);
388 DBG1(DBG_LIB
, "no public key found in CA certificate");
391 if (key
->verify(key
, scheme
,
392 this->attributes
->get_encoding(this->attributes
), encrypted_digest
))
394 DBG2(DBG_LIB
, "signature is valid");
398 DBG1(DBG_LIB
, "invalid signature");
404 if (this->data
.ptr
!= NULL
)
406 chunk_t messageDigest
;
408 messageDigest
= this->attributes
->get_attribute(this->attributes
,
409 OID_PKCS9_MESSAGE_DIGEST
);
410 if (messageDigest
.ptr
== NULL
)
412 DBG1(DBG_LIB
, "messageDigest attribute not found");
417 hash_algorithm_t algorithm
;
422 algorithm
= hasher_algorithm_from_oid(digest_alg
);
423 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, algorithm
);
426 DBG1(DBG_LIB
, "hash algorithm %N not supported",
427 hash_algorithm_names
, algorithm
);
430 hasher
->allocate_hash(hasher
, this->data
, &hash
);
431 hasher
->destroy(hasher
);
432 DBG3(DBG_LIB
, "hash: %B", &hash
);
434 valid
= chunk_equals(messageDigest
, hash
);
438 DBG2(DBG_LIB
, "messageDigest is valid");
442 DBG1(DBG_LIB
, "invalid messageDigest");
452 * ASN.1 definition of the PKCS#7 envelopedData type
454 static const asn1Object_t envelopedDataObjects
[] = {
455 { 0, "envelopedData", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
456 { 1, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 1 */
457 { 1, "recipientInfos", ASN1_SET
, ASN1_LOOP
}, /* 2 */
458 { 2, "recipientInfo", ASN1_SEQUENCE
, ASN1_BODY
}, /* 3 */
459 { 3, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 4 */
460 { 3, "issuerAndSerialNumber", ASN1_SEQUENCE
, ASN1_BODY
}, /* 5 */
461 { 4, "issuer", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 6 */
462 { 4, "serial", ASN1_INTEGER
, ASN1_BODY
}, /* 7 */
463 { 3, "encryptionAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 8 */
464 { 3, "encryptedKey", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 9 */
465 { 1, "end loop", ASN1_EOC
, ASN1_END
}, /* 10 */
466 { 1, "encryptedContentInfo", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 11 */
467 { 2, "contentType", ASN1_OID
, ASN1_BODY
}, /* 12 */
468 { 2, "contentEncryptionAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 13 */
469 { 2, "encryptedContent", ASN1_CONTEXT_S_0
, ASN1_BODY
}, /* 14 */
470 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
472 #define PKCS7_ENVELOPED_VERSION 1
473 #define PKCS7_RECIPIENT_INFO_VERSION 4
474 #define PKCS7_ISSUER 6
475 #define PKCS7_SERIAL_NUMBER 7
476 #define PKCS7_ENCRYPTION_ALG 8
477 #define PKCS7_ENCRYPTED_KEY 9
478 #define PKCS7_CONTENT_TYPE 12
479 #define PKCS7_CONTENT_ENC_ALGORITHM 13
480 #define PKCS7_ENCRYPTED_CONTENT 14
482 METHOD(pkcs7_t
, parse_envelopedData
, bool,
483 private_pkcs7_t
*this, chunk_t serialNumber
, private_key_t
*key
)
485 asn1_parser_t
*parser
;
487 int objectID
, version
;
488 bool success
= FALSE
;
490 chunk_t iv
= chunk_empty
;
491 chunk_t symmetric_key
= chunk_empty
;
492 chunk_t encrypted_content
= chunk_empty
;
494 crypter_t
*crypter
= NULL
;
496 if (!parse_contentInfo(this) ||
497 abort_parsing(this, OID_PKCS7_ENVELOPED_DATA
))
502 parser
= asn1_parser_create(envelopedDataObjects
, this->content
);
503 parser
->set_top_level(parser
, this->level
);
505 while (parser
->iterate(parser
, &objectID
, &object
))
507 u_int level
= parser
->get_level(parser
);
511 case PKCS7_ENVELOPED_VERSION
:
513 version
= object
.len
? (int)*object
.ptr
: 0;
514 DBG2(DBG_LIB
, " v%d", version
);
517 DBG1(DBG_LIB
, "envelopedData version is not 0");
522 case PKCS7_RECIPIENT_INFO_VERSION
:
524 version
= object
.len
? (int)*object
.ptr
: 0;
525 DBG2(DBG_LIB
, " v%d", version
);
528 DBG1(DBG_LIB
, "recipient info version is not 0");
535 identification_t
*issuer
;
537 issuer
= identification_create_from_encoding(ID_DER_ASN1_DN
,
539 DBG2(DBG_LIB
, " '%Y'", issuer
);
540 issuer
->destroy(issuer
);
543 case PKCS7_SERIAL_NUMBER
:
545 if (!chunk_equals(serialNumber
, object
))
547 DBG1(DBG_LIB
, "serial numbers do not match");
552 case PKCS7_ENCRYPTION_ALG
:
556 alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
557 if (alg
!= OID_RSA_ENCRYPTION
)
559 DBG1(DBG_LIB
, "only rsa encryption supported");
564 case PKCS7_ENCRYPTED_KEY
:
566 if (!key
->decrypt(key
, ENCRYPT_RSA_PKCS1
, object
, &symmetric_key
))
568 DBG1(DBG_LIB
, "symmetric key could not be decrypted with rsa");
571 DBG4(DBG_LIB
, "symmetric key %B", &symmetric_key
);
574 case PKCS7_CONTENT_TYPE
:
576 if (asn1_known_oid(object
) != OID_PKCS7_DATA
)
578 DBG1(DBG_LIB
, "encrypted content not of type pkcs7 data");
583 case PKCS7_CONTENT_ENC_ALGORITHM
:
585 encryption_algorithm_t enc_alg
;
589 alg
= asn1_parse_algorithmIdentifier(object
, level
, &iv
);
590 enc_alg
= encryption_algorithm_from_oid(alg
, &key_size
);
591 if (enc_alg
== ENCR_UNDEFINED
)
593 DBG1(DBG_LIB
, "unsupported content encryption algorithm");
596 crypter
= lib
->crypto
->create_crypter(lib
->crypto
, enc_alg
,
600 DBG1(DBG_LIB
, "crypter %N not available",
601 encryption_algorithm_names
, enc_alg
);
604 if (symmetric_key
.len
!= crypter
->get_key_size(crypter
))
606 DBG1(DBG_LIB
, "symmetric key length %d is wrong",
610 if (!asn1_parse_simple_object(&iv
, ASN1_OCTET_STRING
,
613 DBG1(DBG_LIB
, "IV could not be parsed");
616 if (iv
.len
!= crypter
->get_iv_size(crypter
))
618 DBG1(DBG_LIB
, "IV length %d is wrong", iv
.len
);
623 case PKCS7_ENCRYPTED_CONTENT
:
625 encrypted_content
= object
;
630 success
= parser
->success(parser
);
633 parser
->destroy(parser
);
640 /* decrypt the content */
641 crypter
->set_key(crypter
, symmetric_key
);
642 crypter
->decrypt(crypter
, encrypted_content
, iv
, &this->data
);
643 DBG4(DBG_LIB
, "decrypted content with padding: %B", &this->data
);
645 /* remove the padding */
647 u_char
*pos
= this->data
.ptr
+ this->data
.len
- 1;
648 u_char pattern
= *pos
;
649 size_t padding
= pattern
;
651 if (padding
> this->data
.len
)
653 DBG1(DBG_LIB
, "padding greater than data length");
656 this->data
.len
-= padding
;
658 while (padding
-- > 0)
660 if (*pos
-- != pattern
)
662 DBG1(DBG_LIB
, "wrong padding pattern");
671 chunk_clear(&symmetric_key
);
674 chunk_free(&this->data
);
679 METHOD(pkcs7_t
, get_data
, chunk_t
,
680 private_pkcs7_t
*this)
685 METHOD(pkcs7_t
, get_contentInfo
, chunk_t
,
686 private_pkcs7_t
*this)
688 chunk_t content_type
;
690 /* create DER-encoded OID for pkcs7_contentInfo type */
694 case OID_PKCS7_SIGNED_DATA
:
695 case OID_PKCS7_ENVELOPED_DATA
:
696 case OID_PKCS7_SIGNED_ENVELOPED_DATA
:
697 case OID_PKCS7_DIGESTED_DATA
:
698 case OID_PKCS7_ENCRYPTED_DATA
:
699 content_type
= asn1_build_known_oid(this->type
);
703 DBG1(DBG_LIB
, "invalid pkcs7 contentInfo type");
707 return this->content
.ptr
== NULL
708 ? asn1_wrap(ASN1_SEQUENCE
, "m", content_type
)
709 : asn1_wrap(ASN1_SEQUENCE
, "mm", content_type
,
710 asn1_simple_object(ASN1_CONTEXT_C_0
, this->content
));
713 METHOD(pkcs7_t
, create_certificate_enumerator
, enumerator_t
*,
714 private_pkcs7_t
*this)
716 return this->certs
->create_enumerator(this->certs
);
719 METHOD(pkcs7_t
, set_certificate
, void,
720 private_pkcs7_t
*this, certificate_t
*cert
)
724 this->certs
->insert_last(this->certs
, cert
);
728 METHOD(pkcs7_t
, set_attributes
, void,
729 private_pkcs7_t
*this, pkcs9_t
*attributes
)
731 this->attributes
= attributes
;
734 METHOD(pkcs7_t
, get_attributes
, pkcs9_t
*,
735 private_pkcs7_t
*this)
737 return this->attributes
;
741 * build a DER-encoded issuerAndSerialNumber object
743 chunk_t
pkcs7_build_issuerAndSerialNumber(certificate_t
*cert
)
745 identification_t
*issuer
= cert
->get_issuer(cert
);
746 chunk_t serial
= chunk_empty
;
748 if (cert
->get_type(cert
) == CERT_X509
)
750 x509_t
*x509
= (x509_t
*)cert
;
751 serial
= x509
->get_serial(x509
);
754 return asn1_wrap(ASN1_SEQUENCE
, "cm",
755 issuer
->get_encoding(issuer
),
756 asn1_integer("c", serial
));
759 METHOD(pkcs7_t
, build_envelopedData
, bool,
760 private_pkcs7_t
*this, certificate_t
*cert
, encryption_algorithm_t alg
,
763 chunk_t iv
, symmetricKey
, protectedKey
, in
, out
;
767 /* select OID of symmetric encryption algorithm */
768 alg_oid
= encryption_algorithm_to_oid(alg
, key_size
);
769 if (alg_oid
== OID_UNKNOWN
)
771 DBG1(DBG_LIB
, " encryption algorithm %N not supported",
772 encryption_algorithm_names
, alg
);
775 crypter
= lib
->crypto
->create_crypter(lib
->crypto
, alg
, key_size
/ 8);
778 DBG1(DBG_LIB
, " could not create crypter for algorithm %N",
779 encryption_algorithm_names
, alg
);
783 /* generate a true random symmetric encryption key
784 * and a pseudo-random iv
789 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_TRUE
);
790 if (!rng
|| !rng
->allocate_bytes(rng
, crypter
->get_key_size(crypter
),
793 DBG1(DBG_LIB
, " failed to allocate symmetric encryption key");
797 DBG4(DBG_LIB
, " symmetric encryption key: %B", &symmetricKey
);
800 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
801 if (!rng
|| !rng
->allocate_bytes(rng
, crypter
->get_iv_size(crypter
),
804 DBG1(DBG_LIB
, " failed to allocate initialization vector");
808 DBG4(DBG_LIB
, " initialization vector: %B", &iv
);
812 /* pad the data so that the total length becomes
813 * a multiple of the block size
816 size_t block_size
= crypter
->get_block_size(crypter
);
817 size_t padding
= block_size
- this->data
.len
% block_size
;
819 in
.len
= this->data
.len
+ padding
;
820 in
.ptr
= malloc(in
.len
);
822 DBG2(DBG_LIB
, " padding %d bytes of data to multiple block size of %d bytes",
823 (int)this->data
.len
, (int)in
.len
);
826 memcpy(in
.ptr
, this->data
.ptr
, this->data
.len
);
828 memset(in
.ptr
+ this->data
.len
, padding
, padding
);
830 DBG3(DBG_LIB
, " padded unencrypted data: %B", &in
);
832 /* symmetric encryption of data object */
833 crypter
->set_key(crypter
, symmetricKey
);
834 if (!crypter
->encrypt(crypter
, in
, iv
, &out
))
836 crypter
->destroy(crypter
);
838 chunk_clear(&symmetricKey
);
842 crypter
->destroy(crypter
);
844 DBG3(DBG_LIB
, " encrypted data: %B", &out
);
846 /* protect symmetric key by public key encryption */
848 public_key_t
*key
= cert
->get_public_key(cert
);
852 DBG1(DBG_LIB
, " public key not found in encryption certificate");
853 chunk_clear(&symmetricKey
);
858 key
->encrypt(key
, ENCRYPT_RSA_PKCS1
, symmetricKey
, &protectedKey
);
860 chunk_clear(&symmetricKey
);
863 /* build pkcs7 enveloped data object */
865 chunk_t contentEncryptionAlgorithm
= asn1_wrap(ASN1_SEQUENCE
, "mm",
866 asn1_build_known_oid(alg_oid
),
867 asn1_wrap(ASN1_OCTET_STRING
, "m", iv
));
869 chunk_t encryptedContentInfo
= asn1_wrap(ASN1_SEQUENCE
, "mmm",
870 asn1_build_known_oid(OID_PKCS7_DATA
),
871 contentEncryptionAlgorithm
,
872 asn1_wrap(ASN1_CONTEXT_S_0
, "m", out
));
874 chunk_t encryptedKey
= asn1_wrap(ASN1_OCTET_STRING
, "m", protectedKey
);
876 chunk_t recipientInfo
= asn1_wrap(ASN1_SEQUENCE
, "cmmm",
878 pkcs7_build_issuerAndSerialNumber(cert
),
879 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
),
882 this->content
= asn1_wrap(ASN1_SEQUENCE
, "cmm",
884 asn1_wrap(ASN1_SET
, "m", recipientInfo
),
885 encryptedContentInfo
);
886 chunk_free(&this->data
);
887 this->type
= OID_PKCS7_ENVELOPED_DATA
;
888 this->data
= get_contentInfo(this);
893 METHOD(pkcs7_t
, build_signedData
, bool,
894 private_pkcs7_t
*this, private_key_t
*private_key
, hash_algorithm_t alg
)
896 chunk_t authenticatedAttributes
= chunk_empty
;
897 chunk_t encryptedDigest
= chunk_empty
;
898 chunk_t signerInfo
, encoding
= chunk_empty
;
899 signature_scheme_t scheme
;
903 if (this->certs
->get_first(this->certs
, (void**)&cert
) != SUCCESS
)
905 DBG1(DBG_LIB
, " no pkcs7 signer certificate found");
908 digest_oid
= hasher_algorithm_to_oid(alg
);
909 scheme
= signature_scheme_from_oid(digest_oid
);
911 if (this->attributes
!= NULL
)
913 if (this->data
.ptr
!= NULL
)
915 chunk_t messageDigest
, signingTime
, attributes
;
919 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, alg
);
922 DBG1(DBG_LIB
, " hash algorithm %N not support",
923 hash_algorithm_names
, alg
);
926 hasher
->allocate_hash(hasher
, this->data
, &messageDigest
);
927 hasher
->destroy(hasher
);
928 this->attributes
->set_attribute(this->attributes
,
929 OID_PKCS9_MESSAGE_DIGEST
,
931 free(messageDigest
.ptr
);
933 /* take the current time as signingTime */
935 signingTime
= asn1_from_time(&now
, ASN1_UTCTIME
);
936 this->attributes
->set_attribute_raw(this->attributes
,
937 OID_PKCS9_SIGNING_TIME
, signingTime
);
938 this->attributes
->set_attribute_raw(this->attributes
,
939 OID_PKCS9_CONTENT_TYPE
,
940 asn1_build_known_oid(OID_PKCS7_DATA
));
942 attributes
= this->attributes
->get_encoding(this->attributes
);
944 private_key
->sign(private_key
, scheme
, attributes
, &encryptedDigest
);
945 authenticatedAttributes
= chunk_clone(attributes
);
946 *authenticatedAttributes
.ptr
= ASN1_CONTEXT_C_0
;
949 else if (this->data
.ptr
!= NULL
)
951 private_key
->sign(private_key
, scheme
, this->data
, &encryptedDigest
);
953 if (encryptedDigest
.ptr
)
955 encryptedDigest
= asn1_wrap(ASN1_OCTET_STRING
, "m", encryptedDigest
);
957 signerInfo
= asn1_wrap(ASN1_SEQUENCE
, "cmmmmm",
959 pkcs7_build_issuerAndSerialNumber(cert
),
960 asn1_algorithmIdentifier(digest_oid
),
961 authenticatedAttributes
,
962 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
),
965 if (this->data
.ptr
!= NULL
)
967 chunk_free(&this->content
);
968 this->content
= asn1_simple_object(ASN1_OCTET_STRING
, this->data
);
969 chunk_free(&this->data
);
971 this->type
= OID_PKCS7_DATA
;
972 this->data
= get_contentInfo(this);
973 chunk_free(&this->content
);
975 cert
->get_encoding(cert
, CERT_ASN1_DER
, &encoding
);
977 this->content
= asn1_wrap(ASN1_SEQUENCE
, "cmcmm",
979 asn1_wrap(ASN1_SET
, "m", asn1_algorithmIdentifier(digest_oid
)),
981 asn1_wrap(ASN1_CONTEXT_C_0
, "m", encoding
),
982 asn1_wrap(ASN1_SET
, "m", signerInfo
));
983 chunk_free(&this->data
);
984 this->type
= OID_PKCS7_SIGNED_DATA
;
985 this->data
= get_contentInfo(this);
990 METHOD(pkcs7_t
, destroy
, void,
991 private_pkcs7_t
*this)
993 DESTROY_IF(this->attributes
);
994 this->certs
->destroy_offset(this->certs
, offsetof(certificate_t
, destroy
));
995 free(this->content
.ptr
);
996 free(this->data
.ptr
);
1001 * Generic private constructor
1003 static private_pkcs7_t
*pkcs7_create_empty(void)
1005 private_pkcs7_t
*this;
1009 .is_data
= _is_data
,
1010 .is_signedData
= _is_signedData
,
1011 .is_envelopedData
= _is_envelopedData
,
1012 .parse_data
= _parse_data
,
1013 .parse_signedData
= _parse_signedData
,
1014 .parse_envelopedData
= _parse_envelopedData
,
1015 .get_data
= _get_data
,
1016 .get_contentInfo
= _get_contentInfo
,
1017 .create_certificate_enumerator
= _create_certificate_enumerator
,
1018 .set_certificate
= _set_certificate
,
1019 .set_attributes
= _set_attributes
,
1020 .get_attributes
= _get_attributes
,
1021 .build_envelopedData
= _build_envelopedData
,
1022 .build_signedData
= _build_signedData
,
1023 .destroy
= _destroy
,
1025 .type
= OID_UNKNOWN
,
1026 .certs
= linked_list_create(),
1033 * Described in header.
1035 pkcs7_t
*pkcs7_create_from_chunk(chunk_t chunk
, u_int level
)
1037 private_pkcs7_t
*this = pkcs7_create_empty();
1039 this->level
= level
;
1040 this->data
= chunk_clone(chunk
);
1042 return &this->public;
1046 * Described in header.
1048 pkcs7_t
*pkcs7_create_from_data(chunk_t data
)
1050 private_pkcs7_t
*this = pkcs7_create_empty();
1052 this->data
= chunk_clone(data
);
1054 return &this->public;