2 * Copyright (C) 2005 Jan Hutter, Martin Willi
3 * Copyright (C) 2002-2008 Andreas Steffen
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
25 #include <asn1/asn1.h>
26 #include <asn1/asn1_parser.h>
27 #include <credentials/certificates/x509.h>
28 #include <credentials/keys/public_key.h>
29 #include <crypto/pkcs9.h>
30 #include <crypto/hashers/hasher.h>
31 #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 * Has the content already been parsed?
64 * ASN.1 parsing start level
74 * ASN.1 encoded attributes
79 * Linked list of X.509 certificates
85 * PKCS7 contentInfo OIDs
87 static chunk_t ASN1_pkcs7_data_oid
= chunk_from_chars(
89 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01
91 static chunk_t ASN1_pkcs7_signed_data_oid
= chunk_from_chars(
93 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02
95 static chunk_t ASN1_pkcs7_enveloped_data_oid
= chunk_from_chars(
97 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x03
99 static chunk_t ASN1_pkcs7_signed_enveloped_data_oid
= chunk_from_chars(
101 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x04
103 static chunk_t ASN1_pkcs7_digested_data_oid
= chunk_from_chars(
105 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x05
107 static chunk_t ASN1_pkcs7_encrypted_data_oid
= chunk_from_chars(
109 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06
113 * 3DES and DES encryption OIDs
115 static const chunk_t ASN1_3des_ede_cbc_oid
= chunk_from_chars(
117 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x07
119 static const chunk_t ASN1_des_cbc_oid
= chunk_from_chars(
121 0x2B, 0x0E, 0x03, 0x02, 0x07
124 METHOD(pkcs7_t
, is_data
, bool,
125 private_pkcs7_t
*this)
127 return this->type
== OID_PKCS7_DATA
;
130 METHOD(pkcs7_t
, is_signedData
, bool,
131 private_pkcs7_t
*this)
133 return this->type
== OID_PKCS7_SIGNED_DATA
;
136 METHOD(pkcs7_t
, is_envelopedData
, bool,
137 private_pkcs7_t
*this)
139 return this->type
== OID_PKCS7_ENVELOPED_DATA
;
143 * Check whether to abort the requested parsing
145 static bool abort_parsing(private_pkcs7_t
*this, int type
)
147 if (this->type
!= type
)
149 DBG1(DBG_LIB
, "pkcs7 content to be parsed is not of type '%s'",
155 DBG1(DBG_LIB
, "pkcs7 content has already been parsed");
162 METHOD(pkcs7_t
, parse_data
, bool,
163 private_pkcs7_t
*this)
165 chunk_t data
= this->content
;
167 if (abort_parsing(this, OID_PKCS7_DATA
))
173 this->data
= chunk_empty
;
176 if (asn1_parse_simple_object(&data
, ASN1_OCTET_STRING
, this->level
, "data"))
178 this->data
= chunk_clone(data
);
188 * ASN.1 definition of the PKCS#7 signedData type
190 static const asn1Object_t signedDataObjects
[] = {
191 { 0, "signedData", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
192 { 1, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 1 */
193 { 1, "digestAlgorithms", ASN1_SET
, ASN1_LOOP
}, /* 2 */
194 { 2, "algorithm", ASN1_EOC
, ASN1_RAW
}, /* 3 */
195 { 1, "end loop", ASN1_EOC
, ASN1_END
}, /* 4 */
196 { 1, "contentInfo", ASN1_EOC
, ASN1_RAW
}, /* 5 */
197 { 1, "certificates", ASN1_CONTEXT_C_0
, ASN1_OPT
|
199 { 2, "certificate", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 7 */
200 { 1, "end opt or loop", ASN1_EOC
, ASN1_END
}, /* 8 */
201 { 1, "crls", ASN1_CONTEXT_C_1
, ASN1_OPT
|
203 { 2, "crl", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 10 */
204 { 1, "end opt or loop", ASN1_EOC
, ASN1_END
}, /* 11 */
205 { 1, "signerInfos", ASN1_SET
, ASN1_LOOP
}, /* 12 */
206 { 2, "signerInfo", ASN1_SEQUENCE
, ASN1_NONE
}, /* 13 */
207 { 3, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 14 */
208 { 3, "issuerAndSerialNumber", ASN1_SEQUENCE
, ASN1_BODY
}, /* 15 */
209 { 4, "issuer", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 16 */
210 { 4, "serial", ASN1_INTEGER
, ASN1_BODY
}, /* 17 */
211 { 3, "digestAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 18 */
212 { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0
, ASN1_OPT
|
214 { 3, "end opt", ASN1_EOC
, ASN1_END
}, /* 20 */
215 { 3, "digestEncryptionAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 21 */
216 { 3, "encryptedDigest", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 22 */
217 { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 23 */
218 { 3, "end opt", ASN1_EOC
, ASN1_END
}, /* 24 */
219 { 1, "end loop", ASN1_EOC
, ASN1_END
}, /* 25 */
220 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
222 #define PKCS7_DIGEST_ALG 3
223 #define PKCS7_SIGNED_CONTENT_INFO 5
224 #define PKCS7_SIGNED_CERT 7
225 #define PKCS7_SIGNER_INFO 13
226 #define PKCS7_SIGNED_ISSUER 16
227 #define PKCS7_SIGNED_SERIAL_NUMBER 17
228 #define PKCS7_DIGEST_ALGORITHM 18
229 #define PKCS7_AUTH_ATTRIBUTES 19
230 #define PKCS7_DIGEST_ENC_ALGORITHM 21
231 #define PKCS7_ENCRYPTED_DIGEST 22
233 METHOD(pkcs7_t
, parse_signedData
, bool,
234 private_pkcs7_t
*this, x509_t
*cacert
)
236 asn1_parser_t
*parser
;
239 int digest_alg
= OID_UNKNOWN
;
240 int enc_alg
= OID_UNKNOWN
;
242 bool success
= FALSE
;
244 chunk_t encrypted_digest
= chunk_empty
;
246 if (abort_parsing(this, OID_PKCS7_SIGNED_DATA
))
251 parser
= asn1_parser_create(signedDataObjects
, this->content
);
252 parser
->set_top_level(parser
, this->level
);
254 while (parser
->iterate(parser
, &objectID
, &object
))
256 u_int level
= parser
->get_level(parser
);
260 case PKCS7_DIGEST_ALG
:
261 digest_alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
263 case PKCS7_SIGNED_CONTENT_INFO
:
266 pkcs7_t
*data
= pkcs7_create_from_chunk(object
, level
+1);
272 if (!data
->parse_data(data
))
277 pureData
= data
->get_data(data
);
278 this->data
= (pureData
.len
)?
chunk_clone(pureData
) : chunk_empty
;
282 case PKCS7_SIGNED_CERT
:
284 x509_t
*cert
= x509_create_from_chunk(chunk_clone(object
), level
+1);
288 this->certs
->insert_last(this->certs
, (void*)cert
);
292 case PKCS7_SIGNER_INFO
:
294 DBG2(DBG_LIB
, " signer #%d", signerInfos
);
296 case PKCS7_SIGNED_ISSUER
:
298 identification_t
*issuer
;
300 issuer
= identification_create_from_encoding(ID_DER_ASN1_DN
, object
);
301 DBG2(DBG_LIB
, " '%Y'", issuer
);
302 issuer
->destroy(issuer
);
305 case PKCS7_AUTH_ATTRIBUTES
:
306 *object
.ptr
= ASN1_SET
;
307 this->attributes
= pkcs9_create_from_chunk(object
, level
+1);
308 *object
.ptr
= ASN1_CONTEXT_C_0
;
310 case PKCS7_DIGEST_ALGORITHM
:
311 digest_alg
= parse_algorithmIdentifier(object
, level
, NULL
);
313 case PKCS7_DIGEST_ENC_ALGORITHM
:
314 enc_alg
= parse_algorithmIdentifier(object
, level
, NULL
);
316 case PKCS7_ENCRYPTED_DIGEST
:
317 encrypted_digest
= object
;
320 success
= parser
->success(parser
);
323 parser
->destroy(parser
);
329 /* check the signature only if a cacert is available */
332 hash_algorithm_t algorithm
= hasher_algorithm_from_oid(digest_alg
);
333 rsa_public_key_t
*signer
= cacert
->get_public_key(cacert
);
335 if (signerInfos
== 0)
337 DBG1(DBG_LIB
, "no signerInfo object found");
340 else if (signerInfos
> 1)
342 DBG1(DBG_LIB
, "more than one signerInfo object found");
345 if (this->attributes
== NULL
)
347 DBG1(DBG_LIB
, "no authenticatedAttributes object found");
350 if (enc_alg
!= OID_RSA_ENCRYPTION
)
352 DBG1(DBG_LIB
, "only RSA digest encryption supported");
355 if (signer
->verify_emsa_pkcs1_signature(signer
, algorithm
,
356 this->attributes
->get_encoding(this->attributes
), encrypted_digest
) != SUCCESS
)
358 DBG1(DBG_LIB
, "invalid digest signature");
363 DBG2(DBG_LIB
, "digest signature is valid");
365 if (this->data
.ptr
!= NULL
)
367 chunk_t messageDigest
= this->attributes
->get_messageDigest(this->attributes
);
369 if (messageDigest
.ptr
== NULL
)
371 DBG1(DBG_LIB
, "messageDigest attribute not found");
380 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, algorithm
)
383 DBG1(DBG_LIB
, "hash algorithm %N not supported",
384 hash_algorithm_names
, algorithm
);
385 free(messageDigest
.ptr
);
388 hasher
->allocate_hash(hasher
, this->data
, &hash
);
389 hasher
->destroy(hasher
);
390 DBG3(DBG_LIB
, "hash: %B", &hash
);
392 valid
= chunk_equals(messageDigest
, hash
);
393 free(messageDigest
.ptr
);
397 DBG2(DBG_LIB
, "messageDigest is valid");
401 DBG1(DBG_LIB
, "invalid messageDigest");
411 * ASN.1 definition of the PKCS#7 envelopedData type
413 static const asn1Object_t envelopedDataObjects
[] = {
414 { 0, "envelopedData", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
415 { 1, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 1 */
416 { 1, "recipientInfos", ASN1_SET
, ASN1_LOOP
}, /* 2 */
417 { 2, "recipientInfo", ASN1_SEQUENCE
, ASN1_BODY
}, /* 3 */
418 { 3, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 4 */
419 { 3, "issuerAndSerialNumber", ASN1_SEQUENCE
, ASN1_BODY
}, /* 5 */
420 { 4, "issuer", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 6 */
421 { 4, "serial", ASN1_INTEGER
, ASN1_BODY
}, /* 7 */
422 { 3, "encryptionAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 8 */
423 { 3, "encryptedKey", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 9 */
424 { 1, "end loop", ASN1_EOC
, ASN1_END
}, /* 10 */
425 { 1, "encryptedContentInfo", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 11 */
426 { 2, "contentType", ASN1_OID
, ASN1_BODY
}, /* 12 */
427 { 2, "contentEncryptionAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 13 */
428 { 2, "encryptedContent", ASN1_CONTEXT_S_0
, ASN1_BODY
}, /* 14 */
429 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
431 #define PKCS7_ENVELOPED_VERSION 1
432 #define PKCS7_RECIPIENT_INFO_VERSION 4
433 #define PKCS7_ISSUER 6
434 #define PKCS7_SERIAL_NUMBER 7
435 #define PKCS7_ENCRYPTION_ALG 8
436 #define PKCS7_ENCRYPTED_KEY 9
437 #define PKCS7_CONTENT_TYPE 12
438 #define PKCS7_CONTENT_ENC_ALGORITHM 13
439 #define PKCS7_ENCRYPTED_CONTENT 14
441 METHOD(parse_envelopedData
, bool,
442 private_pkcs7_t
*this, chunk_t serialNumber
, rsa_private_key_t
*key
)
444 asn1_parser_t
*parser
;
447 bool success
= FALSE
;
449 chunk_t iv
= chunk_empty
;
450 chunk_t symmetric_key
= chunk_empty
;
451 chunk_t encrypted_content
= chunk_empty
;
453 crypter_t
*crypter
= NULL
;
455 if (abort_parsing(this, OID_PKCS7_ENVELOPED_DATA
))
460 parser
= asn1_parser_create(envelopedDataObjects
, this->content
);
461 parser
->set_top_level(parser
, this->level
);
463 while (parser
->iterate(parser
, &objectID
, &object
))
467 case PKCS7_ENVELOPED_VERSION
:
468 if (*object
.ptr
!= 0)
470 DBG1(DBG_LIB
, "envelopedData version is not 0");
474 case PKCS7_RECIPIENT_INFO_VERSION
:
475 if (*object
.ptr
!= 0)
477 DBG1(DBG_LIB
, "recipient info version is not 0");
483 identification_t
*issuer
;
485 issuer
= identification_create_from_encoding(ID_DER_ASN1_DN
, object
);
486 DBG2(DBG_LIB
, " '%Y'", issuer
);
487 issuer
->destroy(issuer
);
490 case PKCS7_SERIAL_NUMBER
:
491 if (!chunk_equals(serialNumber
, object
))
493 DBG1(DBG_LIB
, "serial numbers do not match");
497 case PKCS7_ENCRYPTION_ALG
:
499 int alg
= parse_algorithmIdentifier(object
, level
, NULL
);
501 if (alg
!= OID_RSA_ENCRYPTION
)
503 DBG1(DBG_LIB
, "only rsa encryption supported");
508 case PKCS7_ENCRYPTED_KEY
:
509 if (key
->pkcs1_decrypt(key
, object
, &symmetric_key
) != SUCCESS
)
511 DBG1(DBG_LIB
, "symmetric key could not be decrypted with rsa");
514 DBG4(DBG_LIB
, "symmetric key : %B", &symmetric_key
);
516 case PKCS7_CONTENT_TYPE
:
517 if (known_oid(object
) != OID_PKCS7_DATA
)
519 DBG1(DBG_LIB
, "encrypted content not of type pkcs7 data");
523 case PKCS7_CONTENT_ENC_ALGORITHM
:
525 int alg
= parse_algorithmIdentifier(object
, level
, &iv
);
530 crypter
= crypter_create(ENCR_DES
, 0);
532 case OID_3DES_EDE_CBC
:
533 crypter
= crypter_create(ENCR_3DES
, 0);
536 DBG1(DBG_LIB
, "Only DES and 3DES supported for symmetric encryption");
539 if (symmetric_key
.len
!= crypter
->get_key_size(crypter
))
541 DBG1(DBG_LIB
, "symmetric key has wrong length");
544 if (!parse_asn1_simple_object(&iv
, ASN1_OCTET_STRING
, level
+1, "IV"))
546 DBG1(DBG_LIB
, "IV could not be parsed");
549 if (iv
.len
!= crypter
->get_iv_size(crypter
))
551 DBG1(DBG_LIB
, "IV has wrong length");
556 case PKCS7_ENCRYPTED_CONTENT
:
557 encrypted_content
= object
;
561 success
= parser
->success(parser
);
564 parser
->destroy(parser
);
570 /* decrypt the content */
571 crypter
->set_key(crypter
, symmetric_key
);
572 crypter
->decrypt(crypter
, encrypted_content
, iv
, &this->data
);
573 DBG3(DBG_LIB
, "decrypted content with padding: %B", &this->data
);
575 /* remove the padding */
577 u_char
*pos
= this->data
.ptr
+ this->data
.len
- 1;
578 u_char pattern
= *pos
;
579 size_t padding
= pattern
;
581 if (padding
> this->data
.len
)
583 DBG1(DBG_LIB
, "padding greater than data length");
586 this->data
.len
-= padding
;
588 while (padding
-- > 0)
590 if (*pos
-- != pattern
)
592 DBG1(DBG_LIB
, "wrong padding pattern");
597 crypter
->destroy(crypter
);
598 free(symmetric_key
.ptr
);
603 free(symmetric_key
.ptr
);
604 chunk_free(&this->data
);
608 METHOD(pkcs7_t
, get_data
, chunk_t
,
609 private_pkcs7_t
*this)
614 METHOD(pkcs7_t
, get_contentInfo
, chunk_t
,
615 private_pkcs7_t
*this)
617 chunk_t content_type
;
619 /* select DER-encoded OID for pkcs7_contentInfo type */
623 content_type
= ASN1_pkcs7_data_oid
;
625 case OID_PKCS7_SIGNED_DATA
:
626 content_type
= ASN1_pkcs7_signed_data_oid
;
628 case OID_PKCS7_ENVELOPED_DATA
:
629 content_type
= ASN1_pkcs7_enveloped_data_oid
;
631 case OID_PKCS7_SIGNED_ENVELOPED_DATA
:
632 content_type
= ASN1_pkcs7_signed_enveloped_data_oid
;
634 case OID_PKCS7_DIGESTED_DATA
:
635 content_type
= ASN1_pkcs7_digested_data_oid
;
637 case OID_PKCS7_ENCRYPTED_DATA
:
638 content_type
= ASN1_pkcs7_encrypted_data_oid
;
642 DBG1(DBG_LIB
, "invalid pkcs7 contentInfo type");
646 return (this->content
.ptr
== NULL
)
647 ?
asn1_simple_object(ASN1_SEQUENCE
, content_type
)
648 : asn1_wrap(ASN1_SEQUENCE
, "cm",
650 asn1_simple_object(ASN1_CONTEXT_C_0
, this->content
)
654 METHOD(pkcs7_t
, create_certificate_enumerator
, enumerator_t
*,
655 private_pkcs7_t
*this)
657 return this->certs
->create_enumerator(this->certs
);
660 METHOD(pkcs7_t
, set_certificate
, void,
661 private_pkcs7_t
*this, x509_t
*cert
)
665 /* TODO the certificate is currently not cloned */
666 this->certs
->insert_last(this->certs
, cert
);
670 METHOD(pkcs7_t
, set_attributes
, void,
671 private_pkcs7_t
*this, pkcs9_t
*attributes
)
673 this->attributes
= attributes
;
677 * build a DER-encoded issuerAndSerialNumber object
679 chunk_t
pkcs7_build_issuerAndSerialNumber(x509_t
*cert
)
681 identification_t
*issuer
= cert
->get_issuer(cert
);
683 return asn1_wrap(ASN1_SEQUENCE
, "cm",
684 issuer
->get_encoding(issuer
),
685 asn1_simple_object(ASN1_INTEGER
, cert
->get_serialNumber(cert
)));
688 METHOD(pkcs7_t
, build_envelopedData
, bool,
689 private_pkcs7_t
*this, x509_t
*cert
, encryption_algorithm_t alg
)
691 chunk_t iv
, symmetricKey
, in
, out
, alg_oid
;
694 /* select OID of symmetric encryption algorithm */
698 alg_oid
= ASN1_des_cbc_oid
;
701 alg_oid
= ASN1_3des_ede_cbc_oid
;
704 DBG1(DBG_LIB
, " encryption algorithm %N not supported",
705 encryption_algorithm_names
, alg
);
709 crypter
= crypter_create(alg
, 0);
712 DBG1(DBG_LIB
, " could not create crypter for algorithm %N",
713 encryption_algorithm_names
, alg
);
717 /* generate a true random symmetric encryption key
718 * and a pseudo-random iv
723 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_TRUE
);
724 rng
->allocate_bytes(rng
, crypter
->get_key_size(crypter
), &symmetricKey
);
725 DBG4(DBG_LIB
, " symmetric encryption key: %B", &symmetricKey
);
728 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
729 rng
->allocate_bytes(rng
, crypter
->get_iv_size(crypter
), &iv
);
730 DBG4(DBG_LIB
, " initialization vector: %B", &iv
);
734 /* pad the data so that the total length becomes
735 * a multiple of the block size
738 size_t block_size
= crypter
->get_block_size(crypter
);
739 size_t padding
= block_size
- this->data
.len
% block_size
;
741 in
.len
= this->data
.len
+ padding
;
742 in
.ptr
= malloc(in
.len
);
744 DBG2(DBG_LIB
, " padding %d bytes of data to multiple block size of %d bytes",
745 (int)this->data
.len
, (int)in
.len
);
748 memcpy(in
.ptr
, this->data
.ptr
, this->data
.len
);
750 memset(in
.ptr
+ this->data
.len
, padding
, padding
);
752 DBG3(DBG_LIB
, " padded unencrypted data: %B", &in
);
754 /* symmetric encryption of data object */
755 crypter
->set_key(crypter
, symmetricKey
);
756 crypter
->encrypt(crypter
, in
, iv
, &out
);
757 crypter
->destroy(crypter
);
759 DBG3(DBG_LIB
, " encrypted data: %B", &out
);
761 /* build pkcs7 enveloped data object */
763 chunk_t contentEncryptionAlgorithm
= asn1_wrap(ASN1_SEQUENCE
, "cm",
765 asn1_wrap(ASN1_OCTET_STRING
, "m", iv
));
767 chunk_t encryptedContentInfo
= asn1_wrap(ASN1_SEQUENCE
, "cmm",
769 contentEncryptionAlgorithm
,
770 asn1_wrap(ASN1_CONTEXT_S_0
, "m", out
));
772 chunk_t wrappedKey
, encryptedKey
, recipientInfo
;
774 rsa_public_key_t
*public_key
= cert
->get_public_key(cert
);
776 public_key
->pkcs1_encrypt(public_key
, symmetricKey
, &wrappedKey
);
777 chunk_clear(&symmetricKey
);
779 encryptedKey
= asn1_wrap(ASN1_OCTET_STRING
, "m", wrappedKey
);
781 recipientInfo
= asn1_wrap(ASN1_SEQUENCE
, "cmmm",
783 pkcs7_build_issuerAndSerialNumber(cert
),
784 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
),
787 this->content
= asn1_wrap(ASN1_SEQUENCE
, "cmm",
789 asn1_wrap(ASN1_SET
, "m", recipientInfo
),
790 encryptedContentInfo
);
791 this->type
= OID_PKCS7_ENVELOPED_DATA
;
796 METHOD(pkcs7_t
, build_signedData
, bool,
797 private_pkcs7_t
*this, rsa_private_key_t
*private_key
, hash_algorithm_t alg
)
799 int signature_oid
= hasher_signature_algorithm_to_oid(alg
,
800 private_key
->get_type(private_key
));
801 chunk_t authenticatedAttributes
= chunk_empty
;
802 chunk_t encryptedDigest
= chunk_empty
;
806 if (this->certs
->get_first(this->certs
, (void**)&cert
) != SUCCESS
)
808 DBG1(DBG_LIB
, " no pkcs7 signer certificate found");
812 if (this->attributes
!= NULL
)
814 if(this->data
.ptr
!= NULL
)
818 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, alg
);
821 DBG1(DBG_LIB
, " hash algorithm %N not support",
822 hash_algorithm_names
, alg
);
826 /* take the current time as signingTime */
827 time_t now
= time(NULL
);
828 chunk_t signingTime
= asn1_from_time(&now
, ASN1_UTCTIME
);
830 chunk_t messageDigest
, attributes
;
832 hasher
->allocate_hash(hasher
, this->data
, &messageDigest
);
833 hasher
->destroy(hasher
);
834 this->attributes
->set_attribute(this->attributes
,
835 OID_PKCS9_CONTENT_TYPE
, ASN1_pkcs7_data_oid
);
836 this->attributes
->set_messageDigest(this->attributes
,
838 this->attributes
->set_attribute(this->attributes
,
839 OID_PKCS9_SIGNING_TIME
, signingTime
);
840 attributes
= this->attributes
->get_encoding(this->attributes
);
842 free(messageDigest
.ptr
);
843 free(signingTime
.ptr
);
845 private_key
->build_emsa_pkcs1_signature(private_key
, alg
,
846 attributes
, &encryptedDigest
);
847 authenticatedAttributes
= chunk_clone(attributes
);
848 *authenticatedAttributes
.ptr
= ASN1_CONTEXT_C_0
;
851 else if (this->data
.ptr
!= NULL
)
853 private_key
->build_emsa_pkcs1_signature(private_key
, alg
,
854 this->data
, &encryptedDigest
);
856 if (encryptedDigest
.ptr
)
858 encryptedDigest
= asn1_wrap(ASN1_OCTET_STRING
, "m", encryptedDigest
);
861 signerInfo
= asn1_wrap(ASN1_SEQUENCE
, "cmmmmm",
863 pkcs7_build_issuerAndSerialNumber(cert
),
864 asn1_algorithmIdentifier(signature_oid
),
865 authenticatedAttributes
,
866 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
),
869 if (this->data
.ptr
!= NULL
)
871 this->content
= asn1_simple_object(ASN1_OCTET_STRING
, this->data
);
872 chunk_free(&this->data
);
874 this->type
= OID_PKCS7_DATA
;
875 this->data
= get_contentInfo(this);
876 chunk_free(&this->content
);
878 this->type
= OID_PKCS7_SIGNED_DATA
;
880 this->content
= asn1_wrap(ASN1_SEQUENCE
, "cmcmm",
882 asn1_wrap(ASN1_SET
, "m", asn1_algorithmIdentifier(signature_oid
)),
884 asn1_simple_object(ASN1_CONTEXT_C_0
, cert
->get_certificate(cert
)),
885 asn1_wrap(ASN1_SET
, "m", signerInfo
));
890 METHOD(pkcs7_t
, destroy
, void,
891 private_pkcs7_t
*this)
893 DESTROY_IF(this->attributes
);
894 this->certs
->destroy_offset(this->certs
, offsetof(x509_t
, destroy
));
895 free(this->content
.ptr
);
896 free(this->data
.ptr
);
901 * ASN.1 definition of the PKCS#7 ContentInfo type
903 static const asn1Object_t contentInfoObjects
[] = {
904 { 0, "contentInfo", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
905 { 1, "contentType", ASN1_OID
, ASN1_BODY
}, /* 1 */
906 { 1, "content", ASN1_CONTEXT_C_0
, ASN1_OPT
|
908 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 3 */
909 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
911 #define PKCS7_INFO_TYPE 1
912 #define PKCS7_INFO_CONTENT 2
915 * Parse PKCS#7 contentInfo object
917 static bool parse_contentInfo(chunk_t blob
, u_int level0
, private_pkcs7_t
*cInfo
)
919 asn1_parser_t
*parser
;
922 bool success
= FALSE
;
924 parser
= asn1_parser_create(contentInfoObjects
, blob
);
925 parser
->set_top_level(parser
, level0
);
927 while (parser
->iterate(parser
, &objectID
, &object
))
929 if (objectID
== PKCS7_INFO_TYPE
)
931 cInfo
->type
= known_oid(object
);
932 if (cInfo
->type
< OID_PKCS7_DATA
933 || cInfo
->type
> OID_PKCS7_ENCRYPTED_DATA
)
935 DBG1(DBG_LIB
, "unknown pkcs7 content type");
939 else if (objectID
== PKCS7_INFO_CONTENT
&& object
.len
> 0)
941 cInfo
->content
= chunk_clone(object
);
944 success
= parser
->success(parser
);
947 parser
->destroy(parser
);
952 * Generic private constructor
954 static private_pkcs7_t
*pkcs7_create_empty(void)
956 private_pkcs7_t
*this;
961 .is_signedData
= _is_signedData
,
962 .is_envelopedData
= _is_envelopedData
,
963 .parse_data
= _parse_data
,
964 .parse_signedData
= _parse_signedData
,
965 .parse_envelopedData
= _parse_envelopedData
,
966 .get_data
= _get_data
,
967 .get_contentInfo
= _get_contentInfo
,
968 .create_certificate_enumerator
= _create_certificate_enumerator
,
969 .set_certificate
= _set_certificate
,
970 .set_attributes
= _set_attributes
,
971 .build_envelopedData
= _build_envelopedData
,
972 .build_signedData
= _build_signedData
,
976 .certs
= linked_list_create(),
983 * Described in header.
985 pkcs7_t
*pkcs7_create_from_chunk(chunk_t chunk
, u_int level
)
987 private_pkcs7_t
*this = pkcs7_create_empty();
989 this->level
= level
+ 2;
990 if (!parse_contentInfo(chunk
, level
, this))
995 return &this->public;
999 * Described in header.
1001 pkcs7_t
*pkcs7_create_from_data(chunk_t data
)
1003 private_pkcs7_t
*this = pkcs7_create_empty();
1005 this->data
= chunk_clone(data
);
1006 this->parsed
= TRUE
;
1008 return &this->public;