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
125 * Implements pkcs7_t.is_data.
127 static bool is_data(private_pkcs7_t
*this)
129 return this->type
== OID_PKCS7_DATA
;
133 * Implements pkcs7_t.is_signedData.
135 static bool is_signedData(private_pkcs7_t
*this)
137 return this->type
== OID_PKCS7_SIGNED_DATA
;
141 * Implements pkcs7_t.is_envelopedData.
143 static bool is_envelopedData(private_pkcs7_t
*this)
145 return this->type
== OID_PKCS7_ENVELOPED_DATA
;
149 * Check whether to abort the requested parsing
151 static bool abort_parsing(private_pkcs7_t
*this, int type
)
153 if (this->type
!= type
)
155 DBG1(DBG_LIB
, "pkcs7 content to be parsed is not of type '%s'",
161 DBG1(DBG_LIB
, "pkcs7 content has already been parsed");
169 * Implements pkcs7_t.parse_data.
171 static bool parse_data(private_pkcs7_t
*this)
173 chunk_t data
= this->content
;
175 if (abort_parsing(this, OID_PKCS7_DATA
))
181 this->data
= chunk_empty
;
184 if (asn1_parse_simple_object(&data
, ASN1_OCTET_STRING
, this->level
, "data"))
186 this->data
= chunk_clone(data
);
196 * ASN.1 definition of the PKCS#7 signedData type
198 static const asn1Object_t signedDataObjects
[] = {
199 { 0, "signedData", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
200 { 1, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 1 */
201 { 1, "digestAlgorithms", ASN1_SET
, ASN1_LOOP
}, /* 2 */
202 { 2, "algorithm", ASN1_EOC
, ASN1_RAW
}, /* 3 */
203 { 1, "end loop", ASN1_EOC
, ASN1_END
}, /* 4 */
204 { 1, "contentInfo", ASN1_EOC
, ASN1_RAW
}, /* 5 */
205 { 1, "certificates", ASN1_CONTEXT_C_0
, ASN1_OPT
|
207 { 2, "certificate", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 7 */
208 { 1, "end opt or loop", ASN1_EOC
, ASN1_END
}, /* 8 */
209 { 1, "crls", ASN1_CONTEXT_C_1
, ASN1_OPT
|
211 { 2, "crl", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 10 */
212 { 1, "end opt or loop", ASN1_EOC
, ASN1_END
}, /* 11 */
213 { 1, "signerInfos", ASN1_SET
, ASN1_LOOP
}, /* 12 */
214 { 2, "signerInfo", ASN1_SEQUENCE
, ASN1_NONE
}, /* 13 */
215 { 3, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 14 */
216 { 3, "issuerAndSerialNumber", ASN1_SEQUENCE
, ASN1_BODY
}, /* 15 */
217 { 4, "issuer", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 16 */
218 { 4, "serial", ASN1_INTEGER
, ASN1_BODY
}, /* 17 */
219 { 3, "digestAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 18 */
220 { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0
, ASN1_OPT
|
222 { 3, "end opt", ASN1_EOC
, ASN1_END
}, /* 20 */
223 { 3, "digestEncryptionAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 21 */
224 { 3, "encryptedDigest", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 22 */
225 { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 23 */
226 { 3, "end opt", ASN1_EOC
, ASN1_END
}, /* 24 */
227 { 1, "end loop", ASN1_EOC
, ASN1_END
}, /* 25 */
228 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
230 #define PKCS7_DIGEST_ALG 3
231 #define PKCS7_SIGNED_CONTENT_INFO 5
232 #define PKCS7_SIGNED_CERT 7
233 #define PKCS7_SIGNER_INFO 13
234 #define PKCS7_SIGNED_ISSUER 16
235 #define PKCS7_SIGNED_SERIAL_NUMBER 17
236 #define PKCS7_DIGEST_ALGORITHM 18
237 #define PKCS7_AUTH_ATTRIBUTES 19
238 #define PKCS7_DIGEST_ENC_ALGORITHM 21
239 #define PKCS7_ENCRYPTED_DIGEST 22
242 * Implements pkcs7_t.parse_signedData.
244 static bool parse_signedData(private_pkcs7_t
*this, x509_t
*cacert
)
246 asn1_parser_t
*parser
;
249 int digest_alg
= OID_UNKNOWN
;
250 int enc_alg
= OID_UNKNOWN
;
252 bool success
= FALSE
;
254 chunk_t encrypted_digest
= chunk_empty
;
256 if (abort_parsing(this, OID_PKCS7_SIGNED_DATA
))
261 parser
= asn1_parser_create(signedDataObjects
, this->content
);
262 parser
->set_top_level(parser
, this->level
);
264 while (parser
->iterate(parser
, &objectID
, &object
))
266 u_int level
= parser
->get_level(parser
);
270 case PKCS7_DIGEST_ALG
:
271 digest_alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
273 case PKCS7_SIGNED_CONTENT_INFO
:
276 pkcs7_t
*data
= pkcs7_create_from_chunk(object
, level
+1);
282 if (!data
->parse_data(data
))
287 pureData
= data
->get_data(data
);
288 this->data
= (pureData
.len
)?
chunk_clone(pureData
) : chunk_empty
;
292 case PKCS7_SIGNED_CERT
:
294 x509_t
*cert
= x509_create_from_chunk(chunk_clone(object
), level
+1);
298 this->certs
->insert_last(this->certs
, (void*)cert
);
302 case PKCS7_SIGNER_INFO
:
304 DBG2(DBG_LIB
, " signer #%d", signerInfos
);
306 case PKCS7_SIGNED_ISSUER
:
308 identification_t
*issuer
;
310 issuer
= identification_create_from_encoding(ID_DER_ASN1_DN
, object
);
311 DBG2(DBG_LIB
, " '%Y'", issuer
);
312 issuer
->destroy(issuer
);
315 case PKCS7_AUTH_ATTRIBUTES
:
316 *object
.ptr
= ASN1_SET
;
317 this->attributes
= pkcs9_create_from_chunk(object
, level
+1);
318 *object
.ptr
= ASN1_CONTEXT_C_0
;
320 case PKCS7_DIGEST_ALGORITHM
:
321 digest_alg
= parse_algorithmIdentifier(object
, level
, NULL
);
323 case PKCS7_DIGEST_ENC_ALGORITHM
:
324 enc_alg
= parse_algorithmIdentifier(object
, level
, NULL
);
326 case PKCS7_ENCRYPTED_DIGEST
:
327 encrypted_digest
= object
;
330 success
= parser
->success(parser
);
333 parser
->destroy(parser
);
339 /* check the signature only if a cacert is available */
342 hash_algorithm_t algorithm
= hasher_algorithm_from_oid(digest_alg
);
343 rsa_public_key_t
*signer
= cacert
->get_public_key(cacert
);
345 if (signerInfos
== 0)
347 DBG1(DBG_LIB
, "no signerInfo object found");
350 else if (signerInfos
> 1)
352 DBG1(DBG_LIB
, "more than one signerInfo object found");
355 if (this->attributes
== NULL
)
357 DBG1(DBG_LIB
, "no authenticatedAttributes object found");
360 if (enc_alg
!= OID_RSA_ENCRYPTION
)
362 DBG1(DBG_LIB
, "only RSA digest encryption supported");
365 if (signer
->verify_emsa_pkcs1_signature(signer
, algorithm
,
366 this->attributes
->get_encoding(this->attributes
), encrypted_digest
) != SUCCESS
)
368 DBG1(DBG_LIB
, "invalid digest signature");
373 DBG2(DBG_LIB
, "digest signature is valid");
375 if (this->data
.ptr
!= NULL
)
377 chunk_t messageDigest
= this->attributes
->get_messageDigest(this->attributes
);
379 if (messageDigest
.ptr
== NULL
)
381 DBG1(DBG_LIB
, "messageDigest attribute not found");
390 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, algorithm
)
393 DBG1(DBG_LIB
, "hash algorithm %N not supported",
394 hash_algorithm_names
, algorithm
);
395 free(messageDigest
.ptr
);
398 hasher
->allocate_hash(hasher
, this->data
, &hash
);
399 hasher
->destroy(hasher
);
400 DBG3(DBG_LIB
, "hash: %B", &hash
);
402 valid
= chunk_equals(messageDigest
, hash
);
403 free(messageDigest
.ptr
);
407 DBG2(DBG_LIB
, "messageDigest is valid");
411 DBG1(DBG_LIB
, "invalid messageDigest");
421 * ASN.1 definition of the PKCS#7 envelopedData type
423 static const asn1Object_t envelopedDataObjects
[] = {
424 { 0, "envelopedData", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
425 { 1, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 1 */
426 { 1, "recipientInfos", ASN1_SET
, ASN1_LOOP
}, /* 2 */
427 { 2, "recipientInfo", ASN1_SEQUENCE
, ASN1_BODY
}, /* 3 */
428 { 3, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 4 */
429 { 3, "issuerAndSerialNumber", ASN1_SEQUENCE
, ASN1_BODY
}, /* 5 */
430 { 4, "issuer", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 6 */
431 { 4, "serial", ASN1_INTEGER
, ASN1_BODY
}, /* 7 */
432 { 3, "encryptionAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 8 */
433 { 3, "encryptedKey", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 9 */
434 { 1, "end loop", ASN1_EOC
, ASN1_END
}, /* 10 */
435 { 1, "encryptedContentInfo", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 11 */
436 { 2, "contentType", ASN1_OID
, ASN1_BODY
}, /* 12 */
437 { 2, "contentEncryptionAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 13 */
438 { 2, "encryptedContent", ASN1_CONTEXT_S_0
, ASN1_BODY
}, /* 14 */
439 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
441 #define PKCS7_ENVELOPED_VERSION 1
442 #define PKCS7_RECIPIENT_INFO_VERSION 4
443 #define PKCS7_ISSUER 6
444 #define PKCS7_SERIAL_NUMBER 7
445 #define PKCS7_ENCRYPTION_ALG 8
446 #define PKCS7_ENCRYPTED_KEY 9
447 #define PKCS7_CONTENT_TYPE 12
448 #define PKCS7_CONTENT_ENC_ALGORITHM 13
449 #define PKCS7_ENCRYPTED_CONTENT 14
452 * Parse PKCS#7 envelopedData content
454 static bool parse_envelopedData(private_pkcs7_t
*this, chunk_t serialNumber
,
455 rsa_private_key_t
*key
)
457 asn1_parser_t
*parser
;
460 bool success
= FALSE
;
462 chunk_t iv
= chunk_empty
;
463 chunk_t symmetric_key
= chunk_empty
;
464 chunk_t encrypted_content
= chunk_empty
;
466 crypter_t
*crypter
= NULL
;
468 if (abort_parsing(this, OID_PKCS7_ENVELOPED_DATA
))
473 parser
= asn1_parser_create(envelopedDataObjects
, this->content
);
474 parser
->set_top_level(parser
, this->level
);
476 while (parser
->iterate(parser
, &objectID
, &object
))
480 case PKCS7_ENVELOPED_VERSION
:
481 if (*object
.ptr
!= 0)
483 DBG1(DBG_LIB
, "envelopedData version is not 0");
487 case PKCS7_RECIPIENT_INFO_VERSION
:
488 if (*object
.ptr
!= 0)
490 DBG1(DBG_LIB
, "recipient info version is not 0");
496 identification_t
*issuer
;
498 issuer
= identification_create_from_encoding(ID_DER_ASN1_DN
, object
);
499 DBG2(DBG_LIB
, " '%Y'", issuer
);
500 issuer
->destroy(issuer
);
503 case PKCS7_SERIAL_NUMBER
:
504 if (!chunk_equals(serialNumber
, object
))
506 DBG1(DBG_LIB
, "serial numbers do not match");
510 case PKCS7_ENCRYPTION_ALG
:
512 int alg
= parse_algorithmIdentifier(object
, level
, NULL
);
514 if (alg
!= OID_RSA_ENCRYPTION
)
516 DBG1(DBG_LIB
, "only rsa encryption supported");
521 case PKCS7_ENCRYPTED_KEY
:
522 if (key
->pkcs1_decrypt(key
, object
, &symmetric_key
) != SUCCESS
)
524 DBG1(DBG_LIB
, "symmetric key could not be decrypted with rsa");
527 DBG4(DBG_LIB
, "symmetric key : %B", &symmetric_key
);
529 case PKCS7_CONTENT_TYPE
:
530 if (known_oid(object
) != OID_PKCS7_DATA
)
532 DBG1(DBG_LIB
, "encrypted content not of type pkcs7 data");
536 case PKCS7_CONTENT_ENC_ALGORITHM
:
538 int alg
= parse_algorithmIdentifier(object
, level
, &iv
);
543 crypter
= crypter_create(ENCR_DES
, 0);
545 case OID_3DES_EDE_CBC
:
546 crypter
= crypter_create(ENCR_3DES
, 0);
549 DBG1(DBG_LIB
, "Only DES and 3DES supported for symmetric encryption");
552 if (symmetric_key
.len
!= crypter
->get_key_size(crypter
))
554 DBG1(DBG_LIB
, "symmetric key has wrong length");
557 if (!parse_asn1_simple_object(&iv
, ASN1_OCTET_STRING
, level
+1, "IV"))
559 DBG1(DBG_LIB
, "IV could not be parsed");
562 if (iv
.len
!= crypter
->get_iv_size(crypter
))
564 DBG1(DBG_LIB
, "IV has wrong length");
569 case PKCS7_ENCRYPTED_CONTENT
:
570 encrypted_content
= object
;
574 success
= parser
->success(parser
);
577 parser
->destroy(parser
);
583 /* decrypt the content */
584 crypter
->set_key(crypter
, symmetric_key
);
585 crypter
->decrypt(crypter
, encrypted_content
, iv
, &this->data
);
586 DBG3(DBG_LIB
, "decrypted content with padding: %B", &this->data
);
588 /* remove the padding */
590 u_char
*pos
= this->data
.ptr
+ this->data
.len
- 1;
591 u_char pattern
= *pos
;
592 size_t padding
= pattern
;
594 if (padding
> this->data
.len
)
596 DBG1(DBG_LIB
, "padding greater than data length");
599 this->data
.len
-= padding
;
601 while (padding
-- > 0)
603 if (*pos
-- != pattern
)
605 DBG1(DBG_LIB
, "wrong padding pattern");
610 crypter
->destroy(crypter
);
611 free(symmetric_key
.ptr
);
616 free(symmetric_key
.ptr
);
617 chunk_free(&this->data
);
622 * Implements pkcs7_t.get_data.
624 static chunk_t
get_data(private_pkcs7_t
*this)
630 * Implements pkcs7_t.get_contentInfo.
632 static chunk_t
get_contentInfo(private_pkcs7_t
*this)
634 chunk_t content_type
;
636 /* select DER-encoded OID for pkcs7_contentInfo type */
640 content_type
= ASN1_pkcs7_data_oid
;
642 case OID_PKCS7_SIGNED_DATA
:
643 content_type
= ASN1_pkcs7_signed_data_oid
;
645 case OID_PKCS7_ENVELOPED_DATA
:
646 content_type
= ASN1_pkcs7_enveloped_data_oid
;
648 case OID_PKCS7_SIGNED_ENVELOPED_DATA
:
649 content_type
= ASN1_pkcs7_signed_enveloped_data_oid
;
651 case OID_PKCS7_DIGESTED_DATA
:
652 content_type
= ASN1_pkcs7_digested_data_oid
;
654 case OID_PKCS7_ENCRYPTED_DATA
:
655 content_type
= ASN1_pkcs7_encrypted_data_oid
;
659 DBG1(DBG_LIB
, "invalid pkcs7 contentInfo type");
663 return (this->content
.ptr
== NULL
)
664 ?
asn1_simple_object(ASN1_SEQUENCE
, content_type
)
665 : asn1_wrap(ASN1_SEQUENCE
, "cm",
667 asn1_simple_object(ASN1_CONTEXT_C_0
, this->content
)
672 * Implements pkcs7_t.create_certificate_iterator
674 static iterator_t
*create_certificate_iterator(const private_pkcs7_t
*this)
676 return this->certs
->create_iterator(this->certs
, TRUE
);
680 * Implements pkcs7_t.set_certificate
682 static void set_certificate(private_pkcs7_t
*this, x509_t
*cert
)
686 /* TODO the certificate is currently not cloned */
687 this->certs
->insert_last(this->certs
, cert
);
692 * Implements pkcs7_t.set_attributes
694 static void set_attributes(private_pkcs7_t
*this, pkcs9_t
*attributes
)
696 this->attributes
= attributes
;
700 * build a DER-encoded issuerAndSerialNumber object
702 chunk_t
pkcs7_build_issuerAndSerialNumber(x509_t
*cert
)
704 identification_t
*issuer
= cert
->get_issuer(cert
);
706 return asn1_wrap(ASN1_SEQUENCE
, "cm",
707 issuer
->get_encoding(issuer
),
708 asn1_simple_object(ASN1_INTEGER
, cert
->get_serialNumber(cert
)));
712 * Implements pkcs7_t.build_envelopedData.
714 bool build_envelopedData(private_pkcs7_t
*this, x509_t
*cert
,
715 encryption_algorithm_t alg
)
717 chunk_t iv
, symmetricKey
, in
, out
, alg_oid
;
720 /* select OID of symmetric encryption algorithm */
724 alg_oid
= ASN1_des_cbc_oid
;
727 alg_oid
= ASN1_3des_ede_cbc_oid
;
730 DBG1(DBG_LIB
, " encryption algorithm %N not supported",
731 encryption_algorithm_names
, alg
);
735 crypter
= crypter_create(alg
, 0);
738 DBG1(DBG_LIB
, " could not create crypter for algorithm %N",
739 encryption_algorithm_names
, alg
);
743 /* generate a true random symmetric encryption key
744 * and a pseudo-random iv
749 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_TRUE
);
750 rng
->allocate_bytes(rng
, crypter
->get_key_size(crypter
), &symmetricKey
);
751 DBG4(DBG_LIB
, " symmetric encryption key: %B", &symmetricKey
);
754 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
755 rng
->allocate_bytes(rng
, crypter
->get_iv_size(crypter
), &iv
);
756 DBG4(DBG_LIB
, " initialization vector: %B", &iv
);
760 /* pad the data so that the total length becomes
761 * a multiple of the block size
764 size_t block_size
= crypter
->get_block_size(crypter
);
765 size_t padding
= block_size
- this->data
.len
% block_size
;
767 in
.len
= this->data
.len
+ padding
;
768 in
.ptr
= malloc(in
.len
);
770 DBG2(DBG_LIB
, " padding %d bytes of data to multiple block size of %d bytes",
771 (int)this->data
.len
, (int)in
.len
);
774 memcpy(in
.ptr
, this->data
.ptr
, this->data
.len
);
776 memset(in
.ptr
+ this->data
.len
, padding
, padding
);
778 DBG3(DBG_LIB
, " padded unencrypted data: %B", &in
);
780 /* symmetric encryption of data object */
781 crypter
->set_key(crypter
, symmetricKey
);
782 crypter
->encrypt(crypter
, in
, iv
, &out
);
783 crypter
->destroy(crypter
);
785 DBG3(DBG_LIB
, " encrypted data: %B", &out
);
787 /* build pkcs7 enveloped data object */
789 chunk_t contentEncryptionAlgorithm
= asn1_wrap(ASN1_SEQUENCE
, "cm",
791 asn1_wrap(ASN1_OCTET_STRING
, "m", iv
));
793 chunk_t encryptedContentInfo
= asn1_wrap(ASN1_SEQUENCE
, "cmm",
795 contentEncryptionAlgorithm
,
796 asn1_wrap(ASN1_CONTEXT_S_0
, "m", out
));
798 chunk_t wrappedKey
, encryptedKey
, recipientInfo
;
800 rsa_public_key_t
*public_key
= cert
->get_public_key(cert
);
802 public_key
->pkcs1_encrypt(public_key
, symmetricKey
, &wrappedKey
);
803 chunk_clear(&symmetricKey
);
805 encryptedKey
= asn1_wrap(ASN1_OCTET_STRING
, "m", wrappedKey
);
807 recipientInfo
= asn1_wrap(ASN1_SEQUENCE
, "cmmm",
809 pkcs7_build_issuerAndSerialNumber(cert
),
810 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
),
813 this->content
= asn1_wrap(ASN1_SEQUENCE
, "cmm",
815 asn1_wrap(ASN1_SET
, "m", recipientInfo
),
816 encryptedContentInfo
);
817 this->type
= OID_PKCS7_ENVELOPED_DATA
;
823 * Implements pkcs7_t.build_signedData.
825 bool build_signedData(private_pkcs7_t
*this, rsa_private_key_t
*private_key
,
826 hash_algorithm_t alg
)
828 int signature_oid
= hasher_signature_algorithm_to_oid(alg
,
829 private_key
->get_type(private_key
));
830 chunk_t authenticatedAttributes
= chunk_empty
;
831 chunk_t encryptedDigest
= chunk_empty
;
835 if (this->certs
->get_first(this->certs
, (void**)&cert
) != SUCCESS
)
837 DBG1(DBG_LIB
, " no pkcs7 signer certificate found");
841 if (this->attributes
!= NULL
)
843 if(this->data
.ptr
!= NULL
)
847 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, alg
);
850 DBG1(DBG_LIB
, " hash algorithm %N not support",
851 hash_algorithm_names
, alg
);
855 /* take the current time as signingTime */
856 time_t now
= time(NULL
);
857 chunk_t signingTime
= asn1_from_time(&now
, ASN1_UTCTIME
);
859 chunk_t messageDigest
, attributes
;
861 hasher
->allocate_hash(hasher
, this->data
, &messageDigest
);
862 hasher
->destroy(hasher
);
863 this->attributes
->set_attribute(this->attributes
,
864 OID_PKCS9_CONTENT_TYPE
, ASN1_pkcs7_data_oid
);
865 this->attributes
->set_messageDigest(this->attributes
,
867 this->attributes
->set_attribute(this->attributes
,
868 OID_PKCS9_SIGNING_TIME
, signingTime
);
869 attributes
= this->attributes
->get_encoding(this->attributes
);
871 free(messageDigest
.ptr
);
872 free(signingTime
.ptr
);
874 private_key
->build_emsa_pkcs1_signature(private_key
, alg
,
875 attributes
, &encryptedDigest
);
876 authenticatedAttributes
= chunk_clone(attributes
);
877 *authenticatedAttributes
.ptr
= ASN1_CONTEXT_C_0
;
880 else if (this->data
.ptr
!= NULL
)
882 private_key
->build_emsa_pkcs1_signature(private_key
, alg
,
883 this->data
, &encryptedDigest
);
885 if (encryptedDigest
.ptr
)
887 encryptedDigest
= asn1_wrap(ASN1_OCTET_STRING
, "m", encryptedDigest
);
890 signerInfo
= asn1_wrap(ASN1_SEQUENCE
, "cmmmmm",
892 pkcs7_build_issuerAndSerialNumber(cert
),
893 asn1_algorithmIdentifier(signature_oid
),
894 authenticatedAttributes
,
895 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
),
898 if (this->data
.ptr
!= NULL
)
900 this->content
= asn1_simple_object(ASN1_OCTET_STRING
, this->data
);
901 chunk_free(&this->data
);
903 this->type
= OID_PKCS7_DATA
;
904 this->data
= get_contentInfo(this);
905 chunk_free(&this->content
);
907 this->type
= OID_PKCS7_SIGNED_DATA
;
909 this->content
= asn1_wrap(ASN1_SEQUENCE
, "cmcmm",
911 asn1_wrap(ASN1_SET
, "m", asn1_algorithmIdentifier(signature_oid
)),
913 asn1_simple_object(ASN1_CONTEXT_C_0
, cert
->get_certificate(cert
)),
914 asn1_wrap(ASN1_SET
, "m", signerInfo
));
920 * Implements pkcs7_t.destroy
922 static void destroy(private_pkcs7_t
*this)
924 DESTROY_IF(this->attributes
);
925 this->certs
->destroy_offset(this->certs
, offsetof(x509_t
, destroy
));
926 free(this->content
.ptr
);
927 free(this->data
.ptr
);
932 * ASN.1 definition of the PKCS#7 ContentInfo type
934 static const asn1Object_t contentInfoObjects
[] = {
935 { 0, "contentInfo", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
936 { 1, "contentType", ASN1_OID
, ASN1_BODY
}, /* 1 */
937 { 1, "content", ASN1_CONTEXT_C_0
, ASN1_OPT
|
939 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 3 */
940 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
942 #define PKCS7_INFO_TYPE 1
943 #define PKCS7_INFO_CONTENT 2
946 * Parse PKCS#7 contentInfo object
948 static bool parse_contentInfo(chunk_t blob
, u_int level0
, private_pkcs7_t
*cInfo
)
950 asn1_parser_t
*parser
;
953 bool success
= FALSE
;
955 parser
= asn1_parser_create(contentInfoObjects
, blob
);
956 parser
->set_top_level(parser
, level0
);
958 while (parser
->iterate(parser
, &objectID
, &object
))
960 if (objectID
== PKCS7_INFO_TYPE
)
962 cInfo
->type
= known_oid(object
);
963 if (cInfo
->type
< OID_PKCS7_DATA
964 || cInfo
->type
> OID_PKCS7_ENCRYPTED_DATA
)
966 DBG1(DBG_LIB
, "unknown pkcs7 content type");
970 else if (objectID
== PKCS7_INFO_CONTENT
&& object
.len
> 0)
972 cInfo
->content
= chunk_clone(object
);
975 success
= parser
->success(parser
);
978 parser
->destroy(parser
);
983 * Generic private constructor
985 static private_pkcs7_t
*pkcs7_create_empty(void)
987 private_pkcs7_t
*this = malloc_thing(private_pkcs7_t
);
990 this->type
= OID_UNKNOWN
;
991 this->content
= chunk_empty
;
992 this->parsed
= FALSE
;
994 this->data
= chunk_empty
;
995 this->attributes
= NULL
;
996 this->certs
= linked_list_create();
998 /*public functions */
999 this->public.is_data
= (bool (*) (pkcs7_t
*))is_data
;
1000 this->public.is_signedData
= (bool (*) (pkcs7_t
*))is_signedData
;
1001 this->public.is_envelopedData
= (bool (*) (pkcs7_t
*))is_envelopedData
;
1002 this->public.parse_data
= (bool (*) (pkcs7_t
*))parse_data
;
1003 this->public.parse_signedData
= (bool (*) (pkcs7_t
*,x509_t
*))parse_signedData
;
1004 this->public.parse_envelopedData
= (bool (*) (pkcs7_t
*,chunk_t
,rsa_private_key_t
*))parse_envelopedData
;
1005 this->public.get_data
= (chunk_t (*) (pkcs7_t
*))get_data
;
1006 this->public.get_contentInfo
= (chunk_t (*) (pkcs7_t
*))get_contentInfo
;
1007 this->public.create_certificate_iterator
= (iterator_t
* (*) (pkcs7_t
*))create_certificate_iterator
;
1008 this->public.set_certificate
= (void (*) (pkcs7_t
*,x509_t
*))set_certificate
;
1009 this->public.set_attributes
= (void (*) (pkcs7_t
*,pkcs9_t
*))set_attributes
;
1010 this->public.build_envelopedData
= (bool (*) (pkcs7_t
*,x509_t
*,encryption_algorithm_t
))build_envelopedData
;
1011 this->public.build_signedData
= (bool (*) (pkcs7_t
*,rsa_private_key_t
*,hash_algorithm_t
))build_signedData
;
1012 this->public.destroy
= (void (*) (pkcs7_t
*))destroy
;
1018 * Described in header.
1020 pkcs7_t
*pkcs7_create_from_chunk(chunk_t chunk
, u_int level
)
1022 private_pkcs7_t
*this = pkcs7_create_empty();
1024 this->level
= level
+ 2;
1025 if (!parse_contentInfo(chunk
, level
, this))
1030 return &this->public;
1034 * Described in header.
1036 pkcs7_t
*pkcs7_create_from_data(chunk_t data
)
1038 private_pkcs7_t
*this = pkcs7_create_empty();
1040 this->data
= chunk_clone(data
);
1041 this->parsed
= TRUE
;
1043 return &this->public;