2 * Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #define ALLOC(X, N) (X) = calloc((N), sizeof(*(X)))
38 #define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0)
41 hx509_cms_wrap_ContentInfo(const heim_oid
*oid
,
42 const heim_octet_string
*buf
,
43 heim_octet_string
*res
)
49 memset(res
, 0, sizeof(*res
));
50 memset(&ci
, 0, sizeof(ci
));
52 ret
= der_copy_oid(oid
, &ci
.contentType
);
56 if (ci
.content
== NULL
) {
57 free_ContentInfo(&ci
);
60 ci
.content
->data
= malloc(buf
->length
);
61 if (ci
.content
->data
== NULL
) {
62 free_ContentInfo(&ci
);
65 memcpy(ci
.content
->data
, buf
->data
, buf
->length
);
66 ci
.content
->length
= buf
->length
;
68 ASN1_MALLOC_ENCODE(ContentInfo
, res
->data
, res
->length
, &ci
, &size
, ret
);
69 free_ContentInfo(&ci
);
72 if (res
->length
!= size
)
73 _hx509_abort("internal ASN.1 encoder error");
79 hx509_cms_unwrap_ContentInfo(const heim_octet_string
*in
,
81 heim_octet_string
*out
,
88 memset(oid
, 0, sizeof(*oid
));
89 memset(out
, 0, sizeof(*out
));
91 ret
= decode_ContentInfo(in
->data
, in
->length
, &ci
, &size
);
95 ret
= der_copy_oid(&ci
.contentType
, oid
);
97 free_ContentInfo(&ci
);
101 ret
= der_copy_octet_string(ci
.content
, out
);
104 free_ContentInfo(&ci
);
108 memset(out
, 0, sizeof(*out
));
111 *have_data
= (ci
.content
!= NULL
) ? 1 : 0;
113 free_ContentInfo(&ci
);
119 #define CMS_ID_NAME 1
122 fill_CMSIdentifier(const hx509_cert cert
,
130 id
->element
= choice_CMSIdentifier_subjectKeyIdentifier
;
131 ret
= _hx509_find_extension_subject_key_id(_hx509_get_cert(cert
),
132 &id
->u
.subjectKeyIdentifier
);
139 id
->element
= choice_CMSIdentifier_issuerAndSerialNumber
;
140 ret
= hx509_cert_get_issuer(cert
, &name
);
143 ret
= hx509_name_to_Name(name
, &id
->u
.issuerAndSerialNumber
.issuer
);
144 hx509_name_free(&name
);
148 ret
= hx509_cert_get_serialnumber(cert
, &id
->u
.issuerAndSerialNumber
.serialNumber
);
152 _hx509_abort("CMS fill identifier with unknown type");
158 unparse_CMSIdentifier(hx509_context context
,
165 switch (id
->element
) {
166 case choice_CMSIdentifier_issuerAndSerialNumber
: {
167 IssuerAndSerialNumber
*iasn
;
170 iasn
= &id
->u
.issuerAndSerialNumber
;
172 ret
= _hx509_Name_to_string(&iasn
->issuer
, &name
);
175 ret
= der_print_hex_heim_integer(&iasn
->serialNumber
, &serial
);
180 asprintf(str
, "certificate issued by %s with serial number %s",
186 case choice_CMSIdentifier_subjectKeyIdentifier
: {
187 KeyIdentifier
*ki
= &id
->u
.subjectKeyIdentifier
;
191 len
= hex_encode(ki
->data
, ki
->length
, &keyid
);
195 asprintf(str
, "certificate with id %s", keyid
);
200 asprintf(str
, "certificate have unknown CMSidentifier type");
209 find_CMSIdentifier(hx509_context context
,
210 CMSIdentifier
*client
,
212 hx509_cert
*signer_cert
,
220 memset(&c
, 0, sizeof(c
));
221 _hx509_query_clear(&q
);
225 switch (client
->element
) {
226 case choice_CMSIdentifier_issuerAndSerialNumber
:
227 q
.serial
= &client
->u
.issuerAndSerialNumber
.serialNumber
;
228 q
.issuer_name
= &client
->u
.issuerAndSerialNumber
.issuer
;
229 q
.match
= HX509_QUERY_MATCH_SERIALNUMBER
|HX509_QUERY_MATCH_ISSUER_NAME
;
231 case choice_CMSIdentifier_subjectKeyIdentifier
:
232 q
.subject_id
= &client
->u
.subjectKeyIdentifier
;
233 q
.match
= HX509_QUERY_MATCH_SUBJECT_KEY_ID
;
236 hx509_set_error_string(context
, 0, HX509_CMS_NO_RECIPIENT_CERTIFICATE
,
237 "unknown CMS identifier element");
238 return HX509_CMS_NO_RECIPIENT_CERTIFICATE
;
243 q
.match
|= HX509_QUERY_MATCH_TIME
;
244 q
.timenow
= time(NULL
);
246 ret
= hx509_certs_find(context
, certs
, &q
, &cert
);
247 if (ret
== HX509_CERT_NOT_FOUND
) {
250 ret
= unparse_CMSIdentifier(context
, client
, &str
);
252 hx509_set_error_string(context
, 0,
253 HX509_CMS_NO_RECIPIENT_CERTIFICATE
,
254 "Failed to find %s", str
);
256 hx509_clear_error_string(context
);
257 return HX509_CMS_NO_RECIPIENT_CERTIFICATE
;
259 hx509_set_error_string(context
, HX509_ERROR_APPEND
,
260 HX509_CMS_NO_RECIPIENT_CERTIFICATE
,
261 "Failed to find CMS id in cert store");
262 return HX509_CMS_NO_RECIPIENT_CERTIFICATE
;
271 hx509_cms_unenvelope(hx509_context context
,
276 const heim_octet_string
*encryptedContent
,
277 heim_oid
*contentType
,
278 heim_octet_string
*content
)
280 heim_octet_string key
;
283 AlgorithmIdentifier
*ai
;
284 const heim_octet_string
*enccontent
;
285 heim_octet_string
*params
, params_data
;
286 heim_octet_string ivec
;
288 int ret
, i
, matched
= 0, findflags
= 0;
291 memset(&key
, 0, sizeof(key
));
292 memset(&ed
, 0, sizeof(ed
));
293 memset(&ivec
, 0, sizeof(ivec
));
294 memset(content
, 0, sizeof(*content
));
295 memset(contentType
, 0, sizeof(*contentType
));
297 if ((flags
& HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT
) == 0)
298 findflags
|= HX509_QUERY_KU_ENCIPHERMENT
;
300 ret
= decode_EnvelopedData(data
, length
, &ed
, &size
);
302 hx509_set_error_string(context
, 0, ret
,
303 "Failed to decode EnvelopedData");
307 if (ed
.recipientInfos
.len
== 0) {
308 ret
= HX509_CMS_NO_RECIPIENT_CERTIFICATE
;
309 hx509_set_error_string(context
, 0, ret
,
310 "No recipient info in enveloped data");
314 enccontent
= ed
.encryptedContentInfo
.encryptedContent
;
315 if (enccontent
== NULL
) {
316 if (encryptedContent
== NULL
) {
317 ret
= HX509_CMS_NO_DATA_AVAILABLE
;
318 hx509_set_error_string(context
, 0, ret
,
319 "Content missing from encrypted data");
322 enccontent
= encryptedContent
;
323 } else if (encryptedContent
!= NULL
) {
324 ret
= HX509_CMS_NO_DATA_AVAILABLE
;
325 hx509_set_error_string(context
, 0, ret
,
326 "Both internal and external encrypted data");
331 for (i
= 0; i
< ed
.recipientInfos
.len
; i
++) {
332 KeyTransRecipientInfo
*ri
;
336 ri
= &ed
.recipientInfos
.val
[i
];
338 ret
= find_CMSIdentifier(context
, &ri
->rid
, certs
, &cert
,
339 HX509_QUERY_PRIVATE_KEY
|findflags
);
343 matched
= 1; /* found a matching certificate, let decrypt */
345 ret
= _hx509_cert_private_decrypt(context
,
347 &ri
->keyEncryptionAlgorithm
.algorithm
,
350 hx509_cert_free(cert
);
352 break; /* succuessfully decrypted cert */
354 ret2
= unparse_CMSIdentifier(context
, &ri
->rid
, &str
);
356 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
357 "Failed to decrypt with %s", str
);
363 ret
= HX509_CMS_NO_RECIPIENT_CERTIFICATE
;
364 hx509_set_error_string(context
, 0, ret
,
365 "No private key matched any certificate");
370 ret
= HX509_CMS_NO_RECIPIENT_CERTIFICATE
;
371 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
372 "No private key decrypted the transfer key");
376 ret
= der_copy_oid(&ed
.encryptedContentInfo
.contentType
, contentType
);
378 hx509_set_error_string(context
, 0, ret
,
379 "Failed to copy EnvelopedData content oid");
383 ai
= &ed
.encryptedContentInfo
.contentEncryptionAlgorithm
;
384 if (ai
->parameters
) {
385 params_data
.data
= ai
->parameters
->data
;
386 params_data
.length
= ai
->parameters
->length
;
387 params
= ¶ms_data
;
394 ret
= hx509_crypto_init(context
, NULL
, &ai
->algorithm
, &crypto
);
399 ret
= hx509_crypto_set_params(context
, crypto
, params
, &ivec
);
401 hx509_crypto_destroy(crypto
);
406 ret
= hx509_crypto_set_key_data(crypto
, key
.data
, key
.length
);
408 hx509_crypto_destroy(crypto
);
409 hx509_set_error_string(context
, 0, ret
,
410 "Failed to set key for decryption "
415 ret
= hx509_crypto_decrypt(crypto
,
418 ivec
.length
? &ivec
: NULL
,
420 hx509_crypto_destroy(crypto
);
422 hx509_set_error_string(context
, 0, ret
,
423 "Failed to decrypt EnvelopedData");
430 free_EnvelopedData(&ed
);
431 der_free_octet_string(&key
);
433 der_free_octet_string(&ivec
);
435 der_free_oid(contentType
);
436 der_free_octet_string(content
);
443 hx509_cms_envelope_1(hx509_context context
,
448 const heim_oid
*encryption_type
,
449 const heim_oid
*contentType
,
450 heim_octet_string
*content
)
452 KeyTransRecipientInfo
*ri
;
453 heim_octet_string ivec
;
454 heim_octet_string key
;
455 hx509_crypto crypto
= NULL
;
460 memset(&ivec
, 0, sizeof(ivec
));
461 memset(&key
, 0, sizeof(key
));
462 memset(&ed
, 0, sizeof(ed
));
463 memset(content
, 0, sizeof(*content
));
465 if (encryption_type
== NULL
)
466 encryption_type
= oid_id_aes_256_cbc();
468 ret
= _hx509_check_key_usage(context
, cert
, 1 << 2, TRUE
);
472 ret
= hx509_crypto_init(context
, NULL
, encryption_type
, &crypto
);
476 ret
= hx509_crypto_set_random_key(crypto
, &key
);
478 hx509_set_error_string(context
, 0, ret
,
479 "Create random key for EnvelopedData content");
483 ret
= hx509_crypto_random_iv(crypto
, &ivec
);
485 hx509_set_error_string(context
, 0, ret
,
486 "Failed to create a random iv");
490 ret
= hx509_crypto_encrypt(crypto
,
494 &ed
.encryptedContentInfo
.encryptedContent
);
496 hx509_set_error_string(context
, 0, ret
,
497 "Failed to encrypt EnvelopedData content");
502 AlgorithmIdentifier
*enc_alg
;
503 enc_alg
= &ed
.encryptedContentInfo
.contentEncryptionAlgorithm
;
504 ret
= der_copy_oid(encryption_type
, &enc_alg
->algorithm
);
506 hx509_set_error_string(context
, 0, ret
,
507 "Failed to set crypto oid "
508 "for EnvelopedData");
511 ALLOC(enc_alg
->parameters
, 1);
512 if (enc_alg
->parameters
== NULL
) {
514 hx509_set_error_string(context
, 0, ret
,
515 "Failed to allocate crypto paramaters "
516 "for EnvelopedData");
520 ret
= hx509_crypto_get_params(context
,
523 enc_alg
->parameters
);
529 ALLOC_SEQ(&ed
.recipientInfos
, 1);
530 if (ed
.recipientInfos
.val
== NULL
) {
532 hx509_set_error_string(context
, 0, ret
,
533 "Failed to allocate recipients info "
534 "for EnvelopedData");
538 ri
= &ed
.recipientInfos
.val
[0];
541 ret
= fill_CMSIdentifier(cert
, CMS_ID_SKI
, &ri
->rid
);
543 hx509_set_error_string(context
, 0, ret
,
544 "Failed to set CMS identifier info "
545 "for EnvelopedData");
549 ret
= _hx509_cert_public_encrypt(context
,
551 &ri
->keyEncryptionAlgorithm
.algorithm
,
554 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
555 "Failed to encrypt transport key for "
565 ed
.originatorInfo
= NULL
;
567 ret
= der_copy_oid(contentType
, &ed
.encryptedContentInfo
.contentType
);
569 hx509_set_error_string(context
, 0, ret
,
570 "Failed to copy content oid for "
575 ed
.unprotectedAttrs
= NULL
;
577 ASN1_MALLOC_ENCODE(EnvelopedData
, content
->data
, content
->length
,
580 hx509_set_error_string(context
, 0, ret
,
581 "Failed to encode EnvelopedData");
584 if (size
!= content
->length
)
585 _hx509_abort("internal ASN.1 encoder error");
589 hx509_crypto_destroy(crypto
);
591 der_free_octet_string(content
);
592 der_free_octet_string(&key
);
593 der_free_octet_string(&ivec
);
594 free_EnvelopedData(&ed
);
600 any_to_certs(hx509_context context
, const SignedData
*sd
, hx509_certs certs
)
604 if (sd
->certificates
== NULL
)
607 for (i
= 0; i
< sd
->certificates
->len
; i
++) {
610 ret
= hx509_cert_init_data(context
,
611 sd
->certificates
->val
[i
].data
,
612 sd
->certificates
->val
[i
].length
,
616 ret
= hx509_certs_add(context
, certs
, c
);
625 static const Attribute
*
626 find_attribute(const CMSAttributes
*attr
, const heim_oid
*oid
)
629 for (i
= 0; i
< attr
->len
; i
++)
630 if (der_heim_oid_cmp(&attr
->val
[i
].type
, oid
) == 0)
631 return &attr
->val
[i
];
636 hx509_cms_verify_signed(hx509_context context
,
637 hx509_verify_ctx ctx
,
640 const heim_octet_string
*signedContent
,
642 heim_oid
*contentType
,
643 heim_octet_string
*content
,
644 hx509_certs
*signer_certs
)
646 SignerInfo
*signer_info
;
647 hx509_cert cert
= NULL
;
648 hx509_certs certs
= NULL
;
651 int ret
, i
, found_valid_sig
;
653 *signer_certs
= NULL
;
654 content
->data
= NULL
;
656 contentType
->length
= 0;
657 contentType
->components
= NULL
;
659 memset(&sd
, 0, sizeof(sd
));
661 ret
= decode_SignedData(data
, length
, &sd
, &size
);
663 hx509_set_error_string(context
, 0, ret
,
664 "Failed to decode SignedData");
668 if (sd
.encapContentInfo
.eContent
== NULL
&& signedContent
== NULL
) {
669 ret
= HX509_CMS_NO_DATA_AVAILABLE
;
670 hx509_set_error_string(context
, 0, ret
,
671 "No content data in SignedData");
674 if (sd
.encapContentInfo
.eContent
&& signedContent
) {
675 ret
= HX509_CMS_NO_DATA_AVAILABLE
;
676 hx509_set_error_string(context
, 0, ret
,
677 "Both external and internal SignedData");
680 if (sd
.encapContentInfo
.eContent
)
681 signedContent
= sd
.encapContentInfo
.eContent
;
683 ret
= hx509_certs_init(context
, "MEMORY:cms-cert-buffer",
688 ret
= hx509_certs_init(context
, "MEMORY:cms-signer-certs",
689 0, NULL
, signer_certs
);
693 /* XXX Check CMS version */
695 ret
= any_to_certs(context
, &sd
, certs
);
700 ret
= hx509_certs_merge(context
, certs
, store
);
705 for (found_valid_sig
= 0, i
= 0; i
< sd
.signerInfos
.len
; i
++) {
706 heim_octet_string
*signed_data
;
707 const heim_oid
*match_oid
;
710 signer_info
= &sd
.signerInfos
.val
[i
];
713 if (signer_info
->signature
.length
== 0) {
714 ret
= HX509_CMS_MISSING_SIGNER_DATA
;
715 hx509_set_error_string(context
, 0, ret
,
716 "SignerInfo %d in SignedData "
717 "missing sigature", i
);
721 ret
= find_CMSIdentifier(context
, &signer_info
->sid
, certs
, &cert
,
722 HX509_QUERY_KU_DIGITALSIGNATURE
);
726 if (signer_info
->signedAttrs
) {
727 const Attribute
*attr
;
730 heim_octet_string os
;
732 sa
.val
= signer_info
->signedAttrs
->val
;
733 sa
.len
= signer_info
->signedAttrs
->len
;
735 /* verify that sigature exists */
736 attr
= find_attribute(&sa
, oid_id_pkcs9_messageDigest());
738 ret
= HX509_CRYPTO_SIGNATURE_MISSING
;
739 hx509_set_error_string(context
, 0, ret
,
740 "SignerInfo have signed attributes "
741 "but messageDigest (signature) "
745 if (attr
->value
.len
!= 1) {
746 ret
= HX509_CRYPTO_SIGNATURE_MISSING
;
747 hx509_set_error_string(context
, 0, ret
,
748 "SignerInfo have more then one "
749 "messageDigest (signature)");
753 ret
= decode_MessageDigest(attr
->value
.val
[0].data
,
754 attr
->value
.val
[0].length
,
758 hx509_set_error_string(context
, 0, ret
,
760 "messageDigest (signature)");
764 ret
= _hx509_verify_signature(context
,
766 &signer_info
->digestAlgorithm
,
769 der_free_octet_string(&os
);
771 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
772 "Failed to verify messageDigest");
777 * Fetch content oid inside signedAttrs or set it to
780 attr
= find_attribute(&sa
, oid_id_pkcs9_contentType());
782 match_oid
= oid_id_pkcs7_data();
784 if (attr
->value
.len
!= 1) {
785 ret
= HX509_CMS_DATA_OID_MISMATCH
;
786 hx509_set_error_string(context
, 0, ret
,
787 "More then one oid in signedAttrs");
791 ret
= decode_ContentType(attr
->value
.val
[0].data
,
792 attr
->value
.val
[0].length
,
796 hx509_set_error_string(context
, 0, ret
,
798 "oid in signedAttrs");
801 match_oid
= &decode_oid
;
804 ALLOC(signed_data
, 1);
805 if (signed_data
== NULL
) {
806 if (match_oid
== &decode_oid
)
807 der_free_oid(&decode_oid
);
809 hx509_clear_error_string(context
);
813 ASN1_MALLOC_ENCODE(CMSAttributes
,
819 if (match_oid
== &decode_oid
)
820 der_free_oid(&decode_oid
);
822 hx509_clear_error_string(context
);
825 if (size
!= signed_data
->length
)
826 _hx509_abort("internal ASN.1 encoder error");
829 signed_data
= rk_UNCONST(signedContent
);
830 match_oid
= oid_id_pkcs7_data();
833 if (der_heim_oid_cmp(match_oid
, &sd
.encapContentInfo
.eContentType
)) {
834 ret
= HX509_CMS_DATA_OID_MISMATCH
;
835 hx509_set_error_string(context
, 0, ret
,
836 "Oid in message mismatch from the expected");
838 if (match_oid
== &decode_oid
)
839 der_free_oid(&decode_oid
);
842 ret
= hx509_verify_signature(context
,
844 &signer_info
->signatureAlgorithm
,
846 &signer_info
->signature
);
848 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
849 "Failed to verify sigature in "
852 if (signed_data
!= signedContent
) {
853 der_free_octet_string(signed_data
);
859 ret
= hx509_verify_path(context
, ctx
, cert
, certs
);
863 ret
= hx509_certs_add(context
, *signer_certs
, cert
);
871 hx509_cert_free(cert
);
874 if (found_valid_sig
== 0) {
876 ret
= HX509_CMS_SIGNER_NOT_FOUND
;
877 hx509_set_error_string(context
, 0, ret
,
878 "No signers where found");
883 ret
= der_copy_oid(&sd
.encapContentInfo
.eContentType
, contentType
);
885 hx509_clear_error_string(context
);
889 content
->data
= malloc(signedContent
->length
);
890 if (content
->data
== NULL
) {
891 hx509_clear_error_string(context
);
895 content
->length
= signedContent
->length
;
896 memcpy(content
->data
, signedContent
->data
, content
->length
);
899 free_SignedData(&sd
);
901 hx509_certs_free(&certs
);
904 hx509_certs_free(signer_certs
);
905 der_free_oid(contentType
);
906 der_free_octet_string(content
);
913 add_one_attribute(Attribute
**attr
,
916 heim_octet_string
*data
)
921 d
= realloc(*attr
, sizeof((*attr
)[0]) * (*len
+ 1));
926 ret
= der_copy_oid(oid
, &(*attr
)[*len
].type
);
930 ALLOC_SEQ(&(*attr
)[*len
].value
, 1);
931 if ((*attr
)[*len
].value
.val
== NULL
) {
932 der_free_oid(&(*attr
)[*len
].type
);
936 (*attr
)[*len
].value
.val
[0].data
= data
->data
;
937 (*attr
)[*len
].value
.val
[0].length
= data
->length
;
945 hx509_cms_create_signed_1(hx509_context context
,
947 const heim_oid
*eContentType
,
948 const void *data
, size_t length
,
949 const AlgorithmIdentifier
*digest_alg
,
951 hx509_peer_info peer
,
954 heim_octet_string
*signed_data
)
956 AlgorithmIdentifier digest
;
958 SignerInfo
*signer_info
;
959 heim_octet_string buf
, content
, sigdata
= { 0, NULL
};
964 int cmsidflag
= CMS_ID_SKI
;
966 memset(&sd
, 0, sizeof(sd
));
967 memset(&name
, 0, sizeof(name
));
968 memset(&path
, 0, sizeof(path
));
969 memset(&digest
, 0, sizeof(digest
));
971 content
.data
= rk_UNCONST(data
);
972 content
.length
= length
;
974 if (flags
& HX509_CMS_SIGATURE_ID_NAME
)
975 cmsidflag
= CMS_ID_NAME
;
977 if (_hx509_cert_private_key(cert
) == NULL
) {
978 hx509_set_error_string(context
, 0, HX509_PRIVATE_KEY_MISSING
,
979 "Private key missing for signing");
980 return HX509_PRIVATE_KEY_MISSING
;
983 if (digest_alg
== NULL
) {
984 ret
= hx509_crypto_select(context
, HX509_SELECT_DIGEST
,
985 _hx509_cert_private_key(cert
), peer
, &digest
);
987 ret
= copy_AlgorithmIdentifier(digest_alg
, &digest
);
989 hx509_clear_error_string(context
);
994 sd
.version
= CMSVersion_v3
;
996 if (eContentType
== NULL
)
997 eContentType
= oid_id_pkcs7_data();
999 der_copy_oid(eContentType
, &sd
.encapContentInfo
.eContentType
);
1002 if ((flags
& HX509_CMS_SIGATURE_DETACHED
) == 0) {
1003 ALLOC(sd
.encapContentInfo
.eContent
, 1);
1004 if (sd
.encapContentInfo
.eContent
== NULL
) {
1005 hx509_clear_error_string(context
);
1010 sd
.encapContentInfo
.eContent
->data
= malloc(length
);
1011 if (sd
.encapContentInfo
.eContent
->data
== NULL
) {
1012 hx509_clear_error_string(context
);
1016 memcpy(sd
.encapContentInfo
.eContent
->data
, data
, length
);
1017 sd
.encapContentInfo
.eContent
->length
= length
;
1020 ALLOC_SEQ(&sd
.signerInfos
, 1);
1021 if (sd
.signerInfos
.val
== NULL
) {
1022 hx509_clear_error_string(context
);
1027 signer_info
= &sd
.signerInfos
.val
[0];
1029 signer_info
->version
= 1;
1031 ret
= fill_CMSIdentifier(cert
, cmsidflag
, &signer_info
->sid
);
1033 hx509_clear_error_string(context
);
1037 signer_info
->signedAttrs
= NULL
;
1038 signer_info
->unsignedAttrs
= NULL
;
1041 ret
= copy_AlgorithmIdentifier(&digest
, &signer_info
->digestAlgorithm
);
1043 hx509_clear_error_string(context
);
1048 * If it isn't pkcs7-data send signedAttributes
1051 if (der_heim_oid_cmp(eContentType
, oid_id_pkcs7_data()) != 0) {
1053 heim_octet_string sig
;
1055 ALLOC(signer_info
->signedAttrs
, 1);
1056 if (signer_info
->signedAttrs
== NULL
) {
1061 ret
= _hx509_create_signature(context
,
1070 ASN1_MALLOC_ENCODE(MessageDigest
,
1076 der_free_octet_string(&sig
);
1078 hx509_clear_error_string(context
);
1081 if (size
!= buf
.length
)
1082 _hx509_abort("internal ASN.1 encoder error");
1084 ret
= add_one_attribute(&signer_info
->signedAttrs
->val
,
1085 &signer_info
->signedAttrs
->len
,
1086 oid_id_pkcs9_messageDigest(),
1089 hx509_clear_error_string(context
);
1094 ASN1_MALLOC_ENCODE(ContentType
,
1102 if (size
!= buf
.length
)
1103 _hx509_abort("internal ASN.1 encoder error");
1105 ret
= add_one_attribute(&signer_info
->signedAttrs
->val
,
1106 &signer_info
->signedAttrs
->len
,
1107 oid_id_pkcs9_contentType(),
1110 hx509_clear_error_string(context
);
1114 sa
.val
= signer_info
->signedAttrs
->val
;
1115 sa
.len
= signer_info
->signedAttrs
->len
;
1117 ASN1_MALLOC_ENCODE(CMSAttributes
,
1124 hx509_clear_error_string(context
);
1127 if (size
!= sigdata
.length
)
1128 _hx509_abort("internal ASN.1 encoder error");
1130 sigdata
.data
= content
.data
;
1131 sigdata
.length
= content
.length
;
1136 AlgorithmIdentifier sigalg
;
1138 ret
= hx509_crypto_select(context
, HX509_SELECT_PUBLIC_SIG
,
1139 _hx509_cert_private_key(cert
), peer
,
1144 ret
= _hx509_create_signature(context
,
1145 _hx509_cert_private_key(cert
),
1148 &signer_info
->signatureAlgorithm
,
1149 &signer_info
->signature
);
1150 free_AlgorithmIdentifier(&sigalg
);
1155 ALLOC_SEQ(&sd
.digestAlgorithms
, 1);
1156 if (sd
.digestAlgorithms
.val
== NULL
) {
1158 hx509_clear_error_string(context
);
1162 ret
= copy_AlgorithmIdentifier(&digest
, &sd
.digestAlgorithms
.val
[0]);
1164 hx509_clear_error_string(context
);
1169 * Provide best effort path
1172 _hx509_calculate_path(context
,
1173 HX509_CALCULATE_PATH_NO_ANCHOR
,
1181 _hx509_path_append(context
, &path
, cert
);
1187 ALLOC(sd
.certificates
, 1);
1188 if (sd
.certificates
== NULL
) {
1189 hx509_clear_error_string(context
);
1193 ALLOC_SEQ(sd
.certificates
, path
.len
);
1194 if (sd
.certificates
->val
== NULL
) {
1195 hx509_clear_error_string(context
);
1200 for (i
= 0; i
< path
.len
; i
++) {
1201 ret
= hx509_cert_binary(context
, path
.val
[i
],
1202 &sd
.certificates
->val
[i
]);
1204 hx509_clear_error_string(context
);
1210 ASN1_MALLOC_ENCODE(SignedData
,
1211 signed_data
->data
, signed_data
->length
,
1214 hx509_clear_error_string(context
);
1217 if (signed_data
->length
!= size
)
1218 _hx509_abort("internal ASN.1 encoder error");
1221 if (sigdata
.data
!= content
.data
)
1222 der_free_octet_string(&sigdata
);
1223 free_AlgorithmIdentifier(&digest
);
1224 _hx509_path_free(&path
);
1225 free_SignedData(&sd
);
1231 hx509_cms_decrypt_encrypted(hx509_context context
,
1235 heim_oid
*contentType
,
1236 heim_octet_string
*content
)
1238 heim_octet_string cont
;
1239 CMSEncryptedData ed
;
1240 AlgorithmIdentifier
*ai
;
1243 memset(content
, 0, sizeof(*content
));
1244 memset(&cont
, 0, sizeof(cont
));
1246 ret
= decode_CMSEncryptedData(data
, length
, &ed
, NULL
);
1248 hx509_set_error_string(context
, 0, ret
,
1249 "Failed to decode CMSEncryptedData");
1253 if (ed
.encryptedContentInfo
.encryptedContent
== NULL
) {
1254 ret
= HX509_CMS_NO_DATA_AVAILABLE
;
1255 hx509_set_error_string(context
, 0, ret
,
1256 "No content in EncryptedData");
1260 ret
= der_copy_oid(&ed
.encryptedContentInfo
.contentType
, contentType
);
1262 hx509_clear_error_string(context
);
1266 ai
= &ed
.encryptedContentInfo
.contentEncryptionAlgorithm
;
1267 if (ai
->parameters
== NULL
) {
1268 ret
= HX509_ALG_NOT_SUPP
;
1269 hx509_clear_error_string(context
);
1273 ret
= _hx509_pbe_decrypt(context
,
1276 ed
.encryptedContentInfo
.encryptedContent
,
1288 free_CMSEncryptedData(&ed
);