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
35 __RCSID("$Heimdal: cms.c 22327 2007-12-15 04:49:37Z lha $"
39 * @page page_cms CMS/PKCS7 message functions.
41 * CMS is defined in RFC 3369 and is an continuation of the RSA Labs
42 * standard PKCS7. The basic messages in CMS is
45 * Data signed with private key (RSA, DSA, ECDSA) or secret
48 * Data encrypted with private key (RSA)
50 * Data encrypted with secret (symmetric) key.
52 * Wrapper structure including type and data.
55 * See the library functions here: @ref hx509_cms
58 #define ALLOC(X, N) (X) = calloc((N), sizeof(*(X)))
59 #define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0)
62 * Wrap data and oid in a ContentInfo and encode it.
64 * @param oid type of the content.
65 * @param buf data to be wrapped. If a NULL pointer is passed in, the
66 * optional content field in the ContentInfo is not going be filled
68 * @param res the encoded buffer, the result should be freed with
69 * der_free_octet_string().
71 * @return Returns an hx509 error code.
77 hx509_cms_wrap_ContentInfo(const heim_oid
*oid
,
78 const heim_octet_string
*buf
,
79 heim_octet_string
*res
)
85 memset(res
, 0, sizeof(*res
));
86 memset(&ci
, 0, sizeof(ci
));
88 ret
= der_copy_oid(oid
, &ci
.contentType
);
93 if (ci
.content
== NULL
) {
94 free_ContentInfo(&ci
);
97 ci
.content
->data
= malloc(buf
->length
);
98 if (ci
.content
->data
== NULL
) {
99 free_ContentInfo(&ci
);
102 memcpy(ci
.content
->data
, buf
->data
, buf
->length
);
103 ci
.content
->length
= buf
->length
;
106 ASN1_MALLOC_ENCODE(ContentInfo
, res
->data
, res
->length
, &ci
, &size
, ret
);
107 free_ContentInfo(&ci
);
110 if (res
->length
!= size
)
111 _hx509_abort("internal ASN.1 encoder error");
117 * Decode an ContentInfo and unwrap data and oid it.
119 * @param in the encoded buffer.
120 * @param oid type of the content.
121 * @param out data to be wrapped.
122 * @param have_data since the data is optional, this flags show dthe
123 * diffrence between no data and the zero length data.
125 * @return Returns an hx509 error code.
131 hx509_cms_unwrap_ContentInfo(const heim_octet_string
*in
,
133 heim_octet_string
*out
,
140 memset(oid
, 0, sizeof(*oid
));
141 memset(out
, 0, sizeof(*out
));
143 ret
= decode_ContentInfo(in
->data
, in
->length
, &ci
, &size
);
147 ret
= der_copy_oid(&ci
.contentType
, oid
);
149 free_ContentInfo(&ci
);
153 ret
= der_copy_octet_string(ci
.content
, out
);
156 free_ContentInfo(&ci
);
160 memset(out
, 0, sizeof(*out
));
163 *have_data
= (ci
.content
!= NULL
) ? 1 : 0;
165 free_ContentInfo(&ci
);
171 #define CMS_ID_NAME 1
174 fill_CMSIdentifier(const hx509_cert cert
,
182 id
->element
= choice_CMSIdentifier_subjectKeyIdentifier
;
183 ret
= _hx509_find_extension_subject_key_id(_hx509_get_cert(cert
),
184 &id
->u
.subjectKeyIdentifier
);
191 id
->element
= choice_CMSIdentifier_issuerAndSerialNumber
;
192 ret
= hx509_cert_get_issuer(cert
, &name
);
195 ret
= hx509_name_to_Name(name
, &id
->u
.issuerAndSerialNumber
.issuer
);
196 hx509_name_free(&name
);
200 ret
= hx509_cert_get_serialnumber(cert
, &id
->u
.issuerAndSerialNumber
.serialNumber
);
204 _hx509_abort("CMS fill identifier with unknown type");
210 unparse_CMSIdentifier(hx509_context context
,
217 switch (id
->element
) {
218 case choice_CMSIdentifier_issuerAndSerialNumber
: {
219 IssuerAndSerialNumber
*iasn
;
222 iasn
= &id
->u
.issuerAndSerialNumber
;
224 ret
= _hx509_Name_to_string(&iasn
->issuer
, &name
);
227 ret
= der_print_hex_heim_integer(&iasn
->serialNumber
, &serial
);
232 asprintf(str
, "certificate issued by %s with serial number %s",
238 case choice_CMSIdentifier_subjectKeyIdentifier
: {
239 KeyIdentifier
*ki
= &id
->u
.subjectKeyIdentifier
;
243 len
= hex_encode(ki
->data
, ki
->length
, &keyid
);
247 asprintf(str
, "certificate with id %s", keyid
);
252 asprintf(str
, "certificate have unknown CMSidentifier type");
261 find_CMSIdentifier(hx509_context context
,
262 CMSIdentifier
*client
,
264 hx509_cert
*signer_cert
,
272 memset(&c
, 0, sizeof(c
));
273 _hx509_query_clear(&q
);
277 switch (client
->element
) {
278 case choice_CMSIdentifier_issuerAndSerialNumber
:
279 q
.serial
= &client
->u
.issuerAndSerialNumber
.serialNumber
;
280 q
.issuer_name
= &client
->u
.issuerAndSerialNumber
.issuer
;
281 q
.match
= HX509_QUERY_MATCH_SERIALNUMBER
|HX509_QUERY_MATCH_ISSUER_NAME
;
283 case choice_CMSIdentifier_subjectKeyIdentifier
:
284 q
.subject_id
= &client
->u
.subjectKeyIdentifier
;
285 q
.match
= HX509_QUERY_MATCH_SUBJECT_KEY_ID
;
288 hx509_set_error_string(context
, 0, HX509_CMS_NO_RECIPIENT_CERTIFICATE
,
289 "unknown CMS identifier element");
290 return HX509_CMS_NO_RECIPIENT_CERTIFICATE
;
295 q
.match
|= HX509_QUERY_MATCH_TIME
;
296 q
.timenow
= time(NULL
);
298 ret
= hx509_certs_find(context
, certs
, &q
, &cert
);
299 if (ret
== HX509_CERT_NOT_FOUND
) {
302 ret
= unparse_CMSIdentifier(context
, client
, &str
);
304 hx509_set_error_string(context
, 0,
305 HX509_CMS_NO_RECIPIENT_CERTIFICATE
,
306 "Failed to find %s", str
);
308 hx509_clear_error_string(context
);
309 return HX509_CMS_NO_RECIPIENT_CERTIFICATE
;
311 hx509_set_error_string(context
, HX509_ERROR_APPEND
,
312 HX509_CMS_NO_RECIPIENT_CERTIFICATE
,
313 "Failed to find CMS id in cert store");
314 return HX509_CMS_NO_RECIPIENT_CERTIFICATE
;
323 * Decode and unencrypt EnvelopedData.
325 * Extract data and parameteres from from the EnvelopedData. Also
326 * supports using detached EnvelopedData.
328 * @param context A hx509 context.
329 * @param certs Certificate that can decrypt the EnvelopedData
331 * @param flags HX509_CMS_UE flags to control the behavior.
332 * @param data pointer the structure the contains the DER/BER encoded
333 * EnvelopedData stucture.
334 * @param length length of the data that data point to.
335 * @param encryptedContent in case of detached signature, this
336 * contains the actual encrypted data, othersize its should be NULL.
337 * @param contentType output type oid, should be freed with der_free_oid().
338 * @param content the data, free with der_free_octet_string().
344 hx509_cms_unenvelope(hx509_context context
,
349 const heim_octet_string
*encryptedContent
,
350 heim_oid
*contentType
,
351 heim_octet_string
*content
)
353 heim_octet_string key
;
356 AlgorithmIdentifier
*ai
;
357 const heim_octet_string
*enccontent
;
358 heim_octet_string
*params
, params_data
;
359 heim_octet_string ivec
;
361 int ret
, i
, matched
= 0, findflags
= 0;
364 memset(&key
, 0, sizeof(key
));
365 memset(&ed
, 0, sizeof(ed
));
366 memset(&ivec
, 0, sizeof(ivec
));
367 memset(content
, 0, sizeof(*content
));
368 memset(contentType
, 0, sizeof(*contentType
));
370 if ((flags
& HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT
) == 0)
371 findflags
|= HX509_QUERY_KU_ENCIPHERMENT
;
373 ret
= decode_EnvelopedData(data
, length
, &ed
, &size
);
375 hx509_set_error_string(context
, 0, ret
,
376 "Failed to decode EnvelopedData");
380 if (ed
.recipientInfos
.len
== 0) {
381 ret
= HX509_CMS_NO_RECIPIENT_CERTIFICATE
;
382 hx509_set_error_string(context
, 0, ret
,
383 "No recipient info in enveloped data");
387 enccontent
= ed
.encryptedContentInfo
.encryptedContent
;
388 if (enccontent
== NULL
) {
389 if (encryptedContent
== NULL
) {
390 ret
= HX509_CMS_NO_DATA_AVAILABLE
;
391 hx509_set_error_string(context
, 0, ret
,
392 "Content missing from encrypted data");
395 enccontent
= encryptedContent
;
396 } else if (encryptedContent
!= NULL
) {
397 ret
= HX509_CMS_NO_DATA_AVAILABLE
;
398 hx509_set_error_string(context
, 0, ret
,
399 "Both internal and external encrypted data");
404 for (i
= 0; i
< ed
.recipientInfos
.len
; i
++) {
405 KeyTransRecipientInfo
*ri
;
409 ri
= &ed
.recipientInfos
.val
[i
];
411 ret
= find_CMSIdentifier(context
, &ri
->rid
, certs
, &cert
,
412 HX509_QUERY_PRIVATE_KEY
|findflags
);
416 matched
= 1; /* found a matching certificate, let decrypt */
418 ret
= _hx509_cert_private_decrypt(context
,
420 &ri
->keyEncryptionAlgorithm
.algorithm
,
423 hx509_cert_free(cert
);
425 break; /* succuessfully decrypted cert */
427 ret2
= unparse_CMSIdentifier(context
, &ri
->rid
, &str
);
429 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
430 "Failed to decrypt with %s", str
);
436 ret
= HX509_CMS_NO_RECIPIENT_CERTIFICATE
;
437 hx509_set_error_string(context
, 0, ret
,
438 "No private key matched any certificate");
443 ret
= HX509_CMS_NO_RECIPIENT_CERTIFICATE
;
444 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
445 "No private key decrypted the transfer key");
449 ret
= der_copy_oid(&ed
.encryptedContentInfo
.contentType
, contentType
);
451 hx509_set_error_string(context
, 0, ret
,
452 "Failed to copy EnvelopedData content oid");
456 ai
= &ed
.encryptedContentInfo
.contentEncryptionAlgorithm
;
457 if (ai
->parameters
) {
458 params_data
.data
= ai
->parameters
->data
;
459 params_data
.length
= ai
->parameters
->length
;
460 params
= ¶ms_data
;
467 ret
= hx509_crypto_init(context
, NULL
, &ai
->algorithm
, &crypto
);
472 ret
= hx509_crypto_set_params(context
, crypto
, params
, &ivec
);
474 hx509_crypto_destroy(crypto
);
479 ret
= hx509_crypto_set_key_data(crypto
, key
.data
, key
.length
);
481 hx509_crypto_destroy(crypto
);
482 hx509_set_error_string(context
, 0, ret
,
483 "Failed to set key for decryption "
488 ret
= hx509_crypto_decrypt(crypto
,
491 ivec
.length
? &ivec
: NULL
,
493 hx509_crypto_destroy(crypto
);
495 hx509_set_error_string(context
, 0, ret
,
496 "Failed to decrypt EnvelopedData");
503 free_EnvelopedData(&ed
);
504 der_free_octet_string(&key
);
506 der_free_octet_string(&ivec
);
508 der_free_oid(contentType
);
509 der_free_octet_string(content
);
516 * Encrypt end encode EnvelopedData.
518 * Encrypt and encode EnvelopedData. The data is encrypted with a
519 * random key and the the random key is encrypted with the
520 * certificates private key. This limits what private key type can be
523 * @param context A hx509 context.
524 * @param flags flags to control the behavior, no flags today
525 * @param cert Certificate to encrypt the EnvelopedData encryption key
527 * @param data pointer the data to encrypt.
528 * @param length length of the data that data point to.
529 * @param encryption_type Encryption cipher to use for the bulk data,
530 * use NULL to get default.
531 * @param contentType type of the data that is encrypted
532 * @param content the output of the function,
533 * free with der_free_octet_string().
539 hx509_cms_envelope_1(hx509_context context
,
544 const heim_oid
*encryption_type
,
545 const heim_oid
*contentType
,
546 heim_octet_string
*content
)
548 KeyTransRecipientInfo
*ri
;
549 heim_octet_string ivec
;
550 heim_octet_string key
;
551 hx509_crypto crypto
= NULL
;
556 memset(&ivec
, 0, sizeof(ivec
));
557 memset(&key
, 0, sizeof(key
));
558 memset(&ed
, 0, sizeof(ed
));
559 memset(content
, 0, sizeof(*content
));
561 if (encryption_type
== NULL
)
562 encryption_type
= oid_id_aes_256_cbc();
564 ret
= _hx509_check_key_usage(context
, cert
, 1 << 2, TRUE
);
568 ret
= hx509_crypto_init(context
, NULL
, encryption_type
, &crypto
);
572 ret
= hx509_crypto_set_random_key(crypto
, &key
);
574 hx509_set_error_string(context
, 0, ret
,
575 "Create random key for EnvelopedData content");
579 ret
= hx509_crypto_random_iv(crypto
, &ivec
);
581 hx509_set_error_string(context
, 0, ret
,
582 "Failed to create a random iv");
586 ret
= hx509_crypto_encrypt(crypto
,
590 &ed
.encryptedContentInfo
.encryptedContent
);
592 hx509_set_error_string(context
, 0, ret
,
593 "Failed to encrypt EnvelopedData content");
598 AlgorithmIdentifier
*enc_alg
;
599 enc_alg
= &ed
.encryptedContentInfo
.contentEncryptionAlgorithm
;
600 ret
= der_copy_oid(encryption_type
, &enc_alg
->algorithm
);
602 hx509_set_error_string(context
, 0, ret
,
603 "Failed to set crypto oid "
604 "for EnvelopedData");
607 ALLOC(enc_alg
->parameters
, 1);
608 if (enc_alg
->parameters
== NULL
) {
610 hx509_set_error_string(context
, 0, ret
,
611 "Failed to allocate crypto paramaters "
612 "for EnvelopedData");
616 ret
= hx509_crypto_get_params(context
,
619 enc_alg
->parameters
);
625 ALLOC_SEQ(&ed
.recipientInfos
, 1);
626 if (ed
.recipientInfos
.val
== NULL
) {
628 hx509_set_error_string(context
, 0, ret
,
629 "Failed to allocate recipients info "
630 "for EnvelopedData");
634 ri
= &ed
.recipientInfos
.val
[0];
637 ret
= fill_CMSIdentifier(cert
, CMS_ID_SKI
, &ri
->rid
);
639 hx509_set_error_string(context
, 0, ret
,
640 "Failed to set CMS identifier info "
641 "for EnvelopedData");
645 ret
= _hx509_cert_public_encrypt(context
,
647 &ri
->keyEncryptionAlgorithm
.algorithm
,
650 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
651 "Failed to encrypt transport key for "
661 ed
.originatorInfo
= NULL
;
663 ret
= der_copy_oid(contentType
, &ed
.encryptedContentInfo
.contentType
);
665 hx509_set_error_string(context
, 0, ret
,
666 "Failed to copy content oid for "
671 ed
.unprotectedAttrs
= NULL
;
673 ASN1_MALLOC_ENCODE(EnvelopedData
, content
->data
, content
->length
,
676 hx509_set_error_string(context
, 0, ret
,
677 "Failed to encode EnvelopedData");
680 if (size
!= content
->length
)
681 _hx509_abort("internal ASN.1 encoder error");
685 hx509_crypto_destroy(crypto
);
687 der_free_octet_string(content
);
688 der_free_octet_string(&key
);
689 der_free_octet_string(&ivec
);
690 free_EnvelopedData(&ed
);
696 any_to_certs(hx509_context context
, const SignedData
*sd
, hx509_certs certs
)
700 if (sd
->certificates
== NULL
)
703 for (i
= 0; i
< sd
->certificates
->len
; i
++) {
706 ret
= hx509_cert_init_data(context
,
707 sd
->certificates
->val
[i
].data
,
708 sd
->certificates
->val
[i
].length
,
712 ret
= hx509_certs_add(context
, certs
, c
);
721 static const Attribute
*
722 find_attribute(const CMSAttributes
*attr
, const heim_oid
*oid
)
725 for (i
= 0; i
< attr
->len
; i
++)
726 if (der_heim_oid_cmp(&attr
->val
[i
].type
, oid
) == 0)
727 return &attr
->val
[i
];
732 * Decode SignedData and verify that the signature is correct.
734 * @param context A hx509 context.
735 * @param ctx a hx509 version context
737 * @param length length of the data that data point to.
738 * @param signedContent
739 * @param pool certificate pool to build certificates paths.
740 * @param contentType free with der_free_oid()
741 * @param content the output of the function, free with
742 * der_free_octet_string().
743 * @param signer_certs list of the cerficates used to sign this
744 * request, free with hx509_certs_free().
750 hx509_cms_verify_signed(hx509_context context
,
751 hx509_verify_ctx ctx
,
754 const heim_octet_string
*signedContent
,
756 heim_oid
*contentType
,
757 heim_octet_string
*content
,
758 hx509_certs
*signer_certs
)
760 SignerInfo
*signer_info
;
761 hx509_cert cert
= NULL
;
762 hx509_certs certs
= NULL
;
765 int ret
, i
, found_valid_sig
;
767 *signer_certs
= NULL
;
768 content
->data
= NULL
;
770 contentType
->length
= 0;
771 contentType
->components
= NULL
;
773 memset(&sd
, 0, sizeof(sd
));
775 ret
= decode_SignedData(data
, length
, &sd
, &size
);
777 hx509_set_error_string(context
, 0, ret
,
778 "Failed to decode SignedData");
782 if (sd
.encapContentInfo
.eContent
== NULL
&& signedContent
== NULL
) {
783 ret
= HX509_CMS_NO_DATA_AVAILABLE
;
784 hx509_set_error_string(context
, 0, ret
,
785 "No content data in SignedData");
788 if (sd
.encapContentInfo
.eContent
&& signedContent
) {
789 ret
= HX509_CMS_NO_DATA_AVAILABLE
;
790 hx509_set_error_string(context
, 0, ret
,
791 "Both external and internal SignedData");
794 if (sd
.encapContentInfo
.eContent
)
795 signedContent
= sd
.encapContentInfo
.eContent
;
797 ret
= hx509_certs_init(context
, "MEMORY:cms-cert-buffer",
802 ret
= hx509_certs_init(context
, "MEMORY:cms-signer-certs",
803 0, NULL
, signer_certs
);
807 /* XXX Check CMS version */
809 ret
= any_to_certs(context
, &sd
, certs
);
814 ret
= hx509_certs_merge(context
, certs
, pool
);
819 for (found_valid_sig
= 0, i
= 0; i
< sd
.signerInfos
.len
; i
++) {
820 heim_octet_string
*signed_data
;
821 const heim_oid
*match_oid
;
824 signer_info
= &sd
.signerInfos
.val
[i
];
827 if (signer_info
->signature
.length
== 0) {
828 ret
= HX509_CMS_MISSING_SIGNER_DATA
;
829 hx509_set_error_string(context
, 0, ret
,
830 "SignerInfo %d in SignedData "
831 "missing sigature", i
);
835 ret
= find_CMSIdentifier(context
, &signer_info
->sid
, certs
, &cert
,
836 HX509_QUERY_KU_DIGITALSIGNATURE
);
840 if (signer_info
->signedAttrs
) {
841 const Attribute
*attr
;
844 heim_octet_string os
;
846 sa
.val
= signer_info
->signedAttrs
->val
;
847 sa
.len
= signer_info
->signedAttrs
->len
;
849 /* verify that sigature exists */
850 attr
= find_attribute(&sa
, oid_id_pkcs9_messageDigest());
852 ret
= HX509_CRYPTO_SIGNATURE_MISSING
;
853 hx509_set_error_string(context
, 0, ret
,
854 "SignerInfo have signed attributes "
855 "but messageDigest (signature) "
859 if (attr
->value
.len
!= 1) {
860 ret
= HX509_CRYPTO_SIGNATURE_MISSING
;
861 hx509_set_error_string(context
, 0, ret
,
862 "SignerInfo have more then one "
863 "messageDigest (signature)");
867 ret
= decode_MessageDigest(attr
->value
.val
[0].data
,
868 attr
->value
.val
[0].length
,
872 hx509_set_error_string(context
, 0, ret
,
874 "messageDigest (signature)");
878 ret
= _hx509_verify_signature(context
,
880 &signer_info
->digestAlgorithm
,
883 der_free_octet_string(&os
);
885 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
886 "Failed to verify messageDigest");
891 * Fetch content oid inside signedAttrs or set it to
894 attr
= find_attribute(&sa
, oid_id_pkcs9_contentType());
896 match_oid
= oid_id_pkcs7_data();
898 if (attr
->value
.len
!= 1) {
899 ret
= HX509_CMS_DATA_OID_MISMATCH
;
900 hx509_set_error_string(context
, 0, ret
,
901 "More then one oid in signedAttrs");
905 ret
= decode_ContentType(attr
->value
.val
[0].data
,
906 attr
->value
.val
[0].length
,
910 hx509_set_error_string(context
, 0, ret
,
912 "oid in signedAttrs");
915 match_oid
= &decode_oid
;
918 ALLOC(signed_data
, 1);
919 if (signed_data
== NULL
) {
920 if (match_oid
== &decode_oid
)
921 der_free_oid(&decode_oid
);
923 hx509_clear_error_string(context
);
927 ASN1_MALLOC_ENCODE(CMSAttributes
,
933 if (match_oid
== &decode_oid
)
934 der_free_oid(&decode_oid
);
936 hx509_clear_error_string(context
);
939 if (size
!= signed_data
->length
)
940 _hx509_abort("internal ASN.1 encoder error");
943 signed_data
= rk_UNCONST(signedContent
);
944 match_oid
= oid_id_pkcs7_data();
947 if (der_heim_oid_cmp(match_oid
, &sd
.encapContentInfo
.eContentType
)) {
948 ret
= HX509_CMS_DATA_OID_MISMATCH
;
949 hx509_set_error_string(context
, 0, ret
,
950 "Oid in message mismatch from the expected");
952 if (match_oid
== &decode_oid
)
953 der_free_oid(&decode_oid
);
956 ret
= hx509_verify_signature(context
,
958 &signer_info
->signatureAlgorithm
,
960 &signer_info
->signature
);
962 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
963 "Failed to verify sigature in "
966 if (signed_data
!= signedContent
) {
967 der_free_octet_string(signed_data
);
973 ret
= hx509_verify_path(context
, ctx
, cert
, certs
);
977 ret
= hx509_certs_add(context
, *signer_certs
, cert
);
985 hx509_cert_free(cert
);
988 if (found_valid_sig
== 0) {
990 ret
= HX509_CMS_SIGNER_NOT_FOUND
;
991 hx509_set_error_string(context
, 0, ret
,
992 "No signers where found");
997 ret
= der_copy_oid(&sd
.encapContentInfo
.eContentType
, contentType
);
999 hx509_clear_error_string(context
);
1003 content
->data
= malloc(signedContent
->length
);
1004 if (content
->data
== NULL
) {
1005 hx509_clear_error_string(context
);
1009 content
->length
= signedContent
->length
;
1010 memcpy(content
->data
, signedContent
->data
, content
->length
);
1013 free_SignedData(&sd
);
1015 hx509_certs_free(&certs
);
1018 hx509_certs_free(signer_certs
);
1019 der_free_oid(contentType
);
1020 der_free_octet_string(content
);
1027 add_one_attribute(Attribute
**attr
,
1029 const heim_oid
*oid
,
1030 heim_octet_string
*data
)
1035 d
= realloc(*attr
, sizeof((*attr
)[0]) * (*len
+ 1));
1040 ret
= der_copy_oid(oid
, &(*attr
)[*len
].type
);
1044 ALLOC_SEQ(&(*attr
)[*len
].value
, 1);
1045 if ((*attr
)[*len
].value
.val
== NULL
) {
1046 der_free_oid(&(*attr
)[*len
].type
);
1050 (*attr
)[*len
].value
.val
[0].data
= data
->data
;
1051 (*attr
)[*len
].value
.val
[0].length
= data
->length
;
1059 * Decode SignedData and verify that the signature is correct.
1061 * @param context A hx509 context.
1063 * @param eContentType the type of the data.
1064 * @param data data to sign
1065 * @param length length of the data that data point to.
1066 * @param digest_alg digest algorithm to use, use NULL to get the
1067 * default or the peer determined algorithm.
1068 * @param cert certificate to use for sign the data.
1069 * @param peer info about the peer the message to send the message to,
1070 * like what digest algorithm to use.
1071 * @param anchors trust anchors that the client will use, used to
1072 * polulate the certificates included in the message
1073 * @param pool certificates to use in try to build the path to the
1075 * @param signed_data the output of the function, free with
1076 * der_free_octet_string().
1078 * @ingroup hx509_cms
1082 hx509_cms_create_signed_1(hx509_context context
,
1084 const heim_oid
*eContentType
,
1085 const void *data
, size_t length
,
1086 const AlgorithmIdentifier
*digest_alg
,
1088 hx509_peer_info peer
,
1089 hx509_certs anchors
,
1091 heim_octet_string
*signed_data
)
1093 AlgorithmIdentifier digest
;
1095 SignerInfo
*signer_info
;
1096 heim_octet_string buf
, content
, sigdata
= { 0, NULL
};
1101 int cmsidflag
= CMS_ID_SKI
;
1103 memset(&sd
, 0, sizeof(sd
));
1104 memset(&name
, 0, sizeof(name
));
1105 memset(&path
, 0, sizeof(path
));
1106 memset(&digest
, 0, sizeof(digest
));
1108 content
.data
= rk_UNCONST(data
);
1109 content
.length
= length
;
1111 if (flags
& HX509_CMS_SIGATURE_ID_NAME
)
1112 cmsidflag
= CMS_ID_NAME
;
1114 if (_hx509_cert_private_key(cert
) == NULL
) {
1115 hx509_set_error_string(context
, 0, HX509_PRIVATE_KEY_MISSING
,
1116 "Private key missing for signing");
1117 return HX509_PRIVATE_KEY_MISSING
;
1120 if (digest_alg
== NULL
) {
1121 ret
= hx509_crypto_select(context
, HX509_SELECT_DIGEST
,
1122 _hx509_cert_private_key(cert
), peer
, &digest
);
1124 ret
= copy_AlgorithmIdentifier(digest_alg
, &digest
);
1126 hx509_clear_error_string(context
);
1131 sd
.version
= CMSVersion_v3
;
1133 if (eContentType
== NULL
)
1134 eContentType
= oid_id_pkcs7_data();
1136 der_copy_oid(eContentType
, &sd
.encapContentInfo
.eContentType
);
1139 if ((flags
& HX509_CMS_SIGATURE_DETACHED
) == 0) {
1140 ALLOC(sd
.encapContentInfo
.eContent
, 1);
1141 if (sd
.encapContentInfo
.eContent
== NULL
) {
1142 hx509_clear_error_string(context
);
1147 sd
.encapContentInfo
.eContent
->data
= malloc(length
);
1148 if (sd
.encapContentInfo
.eContent
->data
== NULL
) {
1149 hx509_clear_error_string(context
);
1153 memcpy(sd
.encapContentInfo
.eContent
->data
, data
, length
);
1154 sd
.encapContentInfo
.eContent
->length
= length
;
1157 ALLOC_SEQ(&sd
.signerInfos
, 1);
1158 if (sd
.signerInfos
.val
== NULL
) {
1159 hx509_clear_error_string(context
);
1164 signer_info
= &sd
.signerInfos
.val
[0];
1166 signer_info
->version
= 1;
1168 ret
= fill_CMSIdentifier(cert
, cmsidflag
, &signer_info
->sid
);
1170 hx509_clear_error_string(context
);
1174 signer_info
->signedAttrs
= NULL
;
1175 signer_info
->unsignedAttrs
= NULL
;
1178 ret
= copy_AlgorithmIdentifier(&digest
, &signer_info
->digestAlgorithm
);
1180 hx509_clear_error_string(context
);
1185 * If it isn't pkcs7-data send signedAttributes
1188 if (der_heim_oid_cmp(eContentType
, oid_id_pkcs7_data()) != 0) {
1190 heim_octet_string sig
;
1192 ALLOC(signer_info
->signedAttrs
, 1);
1193 if (signer_info
->signedAttrs
== NULL
) {
1198 ret
= _hx509_create_signature(context
,
1207 ASN1_MALLOC_ENCODE(MessageDigest
,
1213 der_free_octet_string(&sig
);
1215 hx509_clear_error_string(context
);
1218 if (size
!= buf
.length
)
1219 _hx509_abort("internal ASN.1 encoder error");
1221 ret
= add_one_attribute(&signer_info
->signedAttrs
->val
,
1222 &signer_info
->signedAttrs
->len
,
1223 oid_id_pkcs9_messageDigest(),
1226 hx509_clear_error_string(context
);
1231 ASN1_MALLOC_ENCODE(ContentType
,
1239 if (size
!= buf
.length
)
1240 _hx509_abort("internal ASN.1 encoder error");
1242 ret
= add_one_attribute(&signer_info
->signedAttrs
->val
,
1243 &signer_info
->signedAttrs
->len
,
1244 oid_id_pkcs9_contentType(),
1247 hx509_clear_error_string(context
);
1251 sa
.val
= signer_info
->signedAttrs
->val
;
1252 sa
.len
= signer_info
->signedAttrs
->len
;
1254 ASN1_MALLOC_ENCODE(CMSAttributes
,
1261 hx509_clear_error_string(context
);
1264 if (size
!= sigdata
.length
)
1265 _hx509_abort("internal ASN.1 encoder error");
1267 sigdata
.data
= content
.data
;
1268 sigdata
.length
= content
.length
;
1273 AlgorithmIdentifier sigalg
;
1275 ret
= hx509_crypto_select(context
, HX509_SELECT_PUBLIC_SIG
,
1276 _hx509_cert_private_key(cert
), peer
,
1281 ret
= _hx509_create_signature(context
,
1282 _hx509_cert_private_key(cert
),
1285 &signer_info
->signatureAlgorithm
,
1286 &signer_info
->signature
);
1287 free_AlgorithmIdentifier(&sigalg
);
1292 ALLOC_SEQ(&sd
.digestAlgorithms
, 1);
1293 if (sd
.digestAlgorithms
.val
== NULL
) {
1295 hx509_clear_error_string(context
);
1299 ret
= copy_AlgorithmIdentifier(&digest
, &sd
.digestAlgorithms
.val
[0]);
1301 hx509_clear_error_string(context
);
1306 * Provide best effort path
1309 _hx509_calculate_path(context
,
1310 HX509_CALCULATE_PATH_NO_ANCHOR
,
1318 _hx509_path_append(context
, &path
, cert
);
1324 ALLOC(sd
.certificates
, 1);
1325 if (sd
.certificates
== NULL
) {
1326 hx509_clear_error_string(context
);
1330 ALLOC_SEQ(sd
.certificates
, path
.len
);
1331 if (sd
.certificates
->val
== NULL
) {
1332 hx509_clear_error_string(context
);
1337 for (i
= 0; i
< path
.len
; i
++) {
1338 ret
= hx509_cert_binary(context
, path
.val
[i
],
1339 &sd
.certificates
->val
[i
]);
1341 hx509_clear_error_string(context
);
1347 ASN1_MALLOC_ENCODE(SignedData
,
1348 signed_data
->data
, signed_data
->length
,
1351 hx509_clear_error_string(context
);
1354 if (signed_data
->length
!= size
)
1355 _hx509_abort("internal ASN.1 encoder error");
1358 if (sigdata
.data
!= content
.data
)
1359 der_free_octet_string(&sigdata
);
1360 free_AlgorithmIdentifier(&digest
);
1361 _hx509_path_free(&path
);
1362 free_SignedData(&sd
);
1368 hx509_cms_decrypt_encrypted(hx509_context context
,
1372 heim_oid
*contentType
,
1373 heim_octet_string
*content
)
1375 heim_octet_string cont
;
1376 CMSEncryptedData ed
;
1377 AlgorithmIdentifier
*ai
;
1380 memset(content
, 0, sizeof(*content
));
1381 memset(&cont
, 0, sizeof(cont
));
1383 ret
= decode_CMSEncryptedData(data
, length
, &ed
, NULL
);
1385 hx509_set_error_string(context
, 0, ret
,
1386 "Failed to decode CMSEncryptedData");
1390 if (ed
.encryptedContentInfo
.encryptedContent
== NULL
) {
1391 ret
= HX509_CMS_NO_DATA_AVAILABLE
;
1392 hx509_set_error_string(context
, 0, ret
,
1393 "No content in EncryptedData");
1397 ret
= der_copy_oid(&ed
.encryptedContentInfo
.contentType
, contentType
);
1399 hx509_clear_error_string(context
);
1403 ai
= &ed
.encryptedContentInfo
.contentEncryptionAlgorithm
;
1404 if (ai
->parameters
== NULL
) {
1405 ret
= HX509_ALG_NOT_SUPP
;
1406 hx509_clear_error_string(context
);
1410 ret
= _hx509_pbe_decrypt(context
,
1413 ed
.encryptedContentInfo
.encryptedContent
,
1425 free_CMSEncryptedData(&ed
);