2 * Copyright (c) 2004 - 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 #include "crypto-headers.h"
39 * @page page_cert The basic certificate
41 * The basic hx509 cerificate object in hx509 is hx509_cert. The
42 * hx509_cert object is representing one X509/PKIX certificate and
43 * associated attributes; like private key, friendly name, etc.
45 * A hx509_cert object is usully found via the keyset interfaces (@ref
46 * page_keyset), but its also possible to create a certificate
47 * directly from a parsed object with hx509_cert_init() and
48 * hx509_cert_init_data().
50 * See the library functions here: @ref hx509_cert
53 struct hx509_verify_ctx_data
{
54 hx509_certs trust_anchors
;
56 #define HX509_VERIFY_CTX_F_TIME_SET 1
57 #define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE 2
58 #define HX509_VERIFY_CTX_F_REQUIRE_RFC3280 4
59 #define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS 8
60 #define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS 16
61 #define HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK 32
63 unsigned int max_depth
;
64 #define HX509_VERIFY_MAX_DEPTH 30
65 hx509_revoke_ctx revoke_ctx
;
68 #define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280)
69 #define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS)
70 #define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0)
72 struct _hx509_cert_attrs
{
74 hx509_cert_attribute
*val
;
77 struct hx509_cert_data
{
81 hx509_private_key private_key
;
82 struct _hx509_cert_attrs attrs
;
84 _hx509_cert_release_func release
;
88 typedef struct hx509_name_constraints
{
91 } hx509_name_constraints
;
93 #define GeneralSubtrees_SET(g,var) \
94 (g)->len = (var)->len, (g)->val = (var)->val;
97 * Creates a hx509 context that most functions in the library
98 * uses. The context is only allowed to be used by one thread at each
99 * moment. Free the context with hx509_context_free().
101 * @param context Returns a pointer to new hx509 context.
103 * @return Returns an hx509 error code.
109 hx509_context_init(hx509_context
*context
)
111 *context
= calloc(1, sizeof(**context
));
112 if (*context
== NULL
)
115 _hx509_ks_null_register(*context
);
116 _hx509_ks_mem_register(*context
);
117 _hx509_ks_file_register(*context
);
118 _hx509_ks_pkcs12_register(*context
);
119 _hx509_ks_pkcs11_register(*context
);
120 _hx509_ks_dir_register(*context
);
121 _hx509_ks_keychain_register(*context
);
123 ENGINE_add_conf_module();
124 OpenSSL_add_all_algorithms();
126 (*context
)->ocsp_time_diff
= HX509_DEFAULT_OCSP_TIME_DIFF
;
128 initialize_hx_error_table_r(&(*context
)->et_list
);
129 initialize_asn1_error_table_r(&(*context
)->et_list
);
131 #ifdef HX509_DEFAULT_ANCHORS
132 (void)hx509_certs_init(*context
, HX509_DEFAULT_ANCHORS
, 0,
133 NULL
, &(*context
)->default_trust_anchors
);
140 * Selects if the hx509_revoke_verify() function is going to require
141 * the existans of a revokation method (OCSP, CRL) or not. Note that
142 * hx509_verify_path(), hx509_cms_verify_signed(), and other function
143 * call hx509_revoke_verify().
145 * @param context hx509 context to change the flag for.
146 * @param flag zero, revokation method required, non zero missing
147 * revokation method ok
149 * @ingroup hx509_verify
153 hx509_context_set_missing_revoke(hx509_context context
, int flag
)
156 context
->flags
|= HX509_CTX_VERIFY_MISSING_OK
;
158 context
->flags
&= ~HX509_CTX_VERIFY_MISSING_OK
;
162 * Free the context allocated by hx509_context_init().
164 * @param context context to be freed.
170 hx509_context_free(hx509_context
*context
)
172 hx509_clear_error_string(*context
);
173 if ((*context
)->ks_ops
) {
174 free((*context
)->ks_ops
);
175 (*context
)->ks_ops
= NULL
;
177 (*context
)->ks_num_ops
= 0;
178 free_error_table ((*context
)->et_list
);
179 if ((*context
)->querystat
)
180 free((*context
)->querystat
);
181 memset(*context
, 0, sizeof(**context
));
191 _hx509_get_cert(hx509_cert cert
)
201 _hx509_cert_get_version(const Certificate
*t
)
203 return t
->tbsCertificate
.version
? *t
->tbsCertificate
.version
+ 1 : 1;
207 * Allocate and init an hx509 certificate object from the decoded
210 * @param context A hx509 context.
214 * @return Returns an hx509 error code.
216 * @ingroup hx509_cert
220 hx509_cert_init(hx509_context context
, const Certificate
*c
, hx509_cert
*cert
)
224 *cert
= malloc(sizeof(**cert
));
228 (*cert
)->friendlyname
= NULL
;
229 (*cert
)->attrs
.len
= 0;
230 (*cert
)->attrs
.val
= NULL
;
231 (*cert
)->private_key
= NULL
;
232 (*cert
)->basename
= NULL
;
233 (*cert
)->release
= NULL
;
236 (*cert
)->data
= calloc(1, sizeof(*(*cert
)->data
));
237 if ((*cert
)->data
== NULL
) {
241 ret
= copy_Certificate(c
, (*cert
)->data
);
251 * Just like hx509_cert_init(), but instead of a decode certificate
252 * takes an pointer and length to a memory region that contains a
253 * DER/BER encoded certificate.
255 * If the memory region doesn't contain just the certificate and
256 * nothing more the function will fail with
257 * HX509_EXTRA_DATA_AFTER_STRUCTURE.
259 * @param context A hx509 context.
260 * @param ptr pointer to memory region containing encoded certificate.
261 * @param len length of memory region.
262 * @param cert a return pointer to a hx509 certificate object, will
263 * contain NULL on error.
265 * @return An hx509 error code, see hx509_get_error_string().
267 * @ingroup hx509_cert
271 hx509_cert_init_data(hx509_context context
,
280 ret
= decode_Certificate(ptr
, len
, &t
, &size
);
282 hx509_set_error_string(context
, 0, ret
, "Failed to decode certificate");
286 hx509_set_error_string(context
, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE
,
287 "Extra data after certificate");
288 return HX509_EXTRA_DATA_AFTER_STRUCTURE
;
291 ret
= hx509_cert_init(context
, &t
, cert
);
292 free_Certificate(&t
);
297 _hx509_cert_set_release(hx509_cert cert
,
298 _hx509_cert_release_func release
,
301 cert
->release
= release
;
306 /* Doesn't make a copy of `private_key'. */
309 _hx509_cert_assign_key(hx509_cert cert
, hx509_private_key private_key
)
311 if (cert
->private_key
)
312 _hx509_private_key_free(&cert
->private_key
);
313 cert
->private_key
= _hx509_private_key_ref(private_key
);
318 * Free reference to the hx509 certificate object, if the refcounter
319 * reaches 0, the object if freed. Its allowed to pass in NULL.
321 * @param cert the cert to free.
323 * @ingroup hx509_cert
327 hx509_cert_free(hx509_cert cert
)
335 _hx509_abort("cert refcount <= 0 on free");
340 (cert
->release
)(cert
, cert
->ctx
);
342 if (cert
->private_key
)
343 _hx509_private_key_free(&cert
->private_key
);
345 free_Certificate(cert
->data
);
348 for (i
= 0; i
< cert
->attrs
.len
; i
++) {
349 der_free_octet_string(&cert
->attrs
.val
[i
]->data
);
350 der_free_oid(&cert
->attrs
.val
[i
]->oid
);
351 free(cert
->attrs
.val
[i
]);
353 free(cert
->attrs
.val
);
354 free(cert
->friendlyname
);
356 hx509_name_free(&cert
->basename
);
357 memset(cert
, 0, sizeof(cert
));
362 * Add a reference to a hx509 certificate object.
364 * @param cert a pointer to an hx509 certificate object.
366 * @return the same object as is passed in.
368 * @ingroup hx509_cert
372 hx509_cert_ref(hx509_cert cert
)
377 _hx509_abort("cert refcount <= 0");
380 _hx509_abort("cert refcount == 0");
385 * Allocate an verification context that is used fo control the
386 * verification process.
388 * @param context A hx509 context.
389 * @param ctx returns a pointer to a hx509_verify_ctx object.
391 * @return An hx509 error code, see hx509_get_error_string().
393 * @ingroup hx509_verify
397 hx509_verify_init_ctx(hx509_context context
, hx509_verify_ctx
*ctx
)
401 c
= calloc(1, sizeof(*c
));
405 c
->max_depth
= HX509_VERIFY_MAX_DEPTH
;
413 * Free an hx509 verification context.
415 * @param ctx the context to be freed.
417 * @ingroup hx509_verify
421 hx509_verify_destroy_ctx(hx509_verify_ctx ctx
)
424 hx509_certs_free(&ctx
->trust_anchors
);
425 hx509_revoke_free(&ctx
->revoke_ctx
);
426 memset(ctx
, 0, sizeof(*ctx
));
432 * Set the trust anchors in the verification context, makes an
433 * reference to the keyset, so the consumer can free the keyset
434 * independent of the destruction of the verification context (ctx).
435 * If there already is a keyset attached, it's released.
437 * @param ctx a verification context
438 * @param set a keyset containing the trust anchors.
440 * @ingroup hx509_verify
444 hx509_verify_attach_anchors(hx509_verify_ctx ctx
, hx509_certs set
)
446 if (ctx
->trust_anchors
)
447 hx509_certs_free(&ctx
->trust_anchors
);
448 ctx
->trust_anchors
= hx509_certs_ref(set
);
452 * Attach an revocation context to the verfication context, , makes an
453 * reference to the revoke context, so the consumer can free the
454 * revoke context independent of the destruction of the verification
455 * context. If there is no revoke context, the verification process is
456 * NOT going to check any verification status.
458 * @param ctx a verification context.
459 * @param revoke_ctx a revoke context.
461 * @ingroup hx509_verify
465 hx509_verify_attach_revoke(hx509_verify_ctx ctx
, hx509_revoke_ctx revoke_ctx
)
468 hx509_revoke_free(&ctx
->revoke_ctx
);
469 ctx
->revoke_ctx
= _hx509_revoke_ref(revoke_ctx
);
473 * Set the clock time the the verification process is going to
474 * use. Used to check certificate in the past and future time. If not
475 * set the current time will be used.
477 * @param ctx a verification context.
478 * @param t the time the verifiation is using.
481 * @ingroup hx509_verify
485 hx509_verify_set_time(hx509_verify_ctx ctx
, time_t t
)
487 ctx
->flags
|= HX509_VERIFY_CTX_F_TIME_SET
;
492 _hx509_verify_get_time(hx509_verify_ctx ctx
)
494 return ctx
->time_now
;
498 * Set the maximum depth of the certificate chain that the path
499 * builder is going to try.
501 * @param ctx a verification context
502 * @param max_depth maxium depth of the certificate chain, include
505 * @ingroup hx509_verify
509 hx509_verify_set_max_depth(hx509_verify_ctx ctx
, unsigned int max_depth
)
511 ctx
->max_depth
= max_depth
;
515 * Allow or deny the use of proxy certificates
517 * @param ctx a verification context
518 * @param boolean if non zero, allow proxy certificates.
520 * @ingroup hx509_verify
524 hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx
, int boolean
)
527 ctx
->flags
|= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
;
529 ctx
->flags
&= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
;
533 * Select strict RFC3280 verification of certificiates. This means
534 * checking key usage on CA certificates, this will make version 1
535 * certificiates unuseable.
537 * @param ctx a verification context
538 * @param boolean if non zero, use strict verification.
540 * @ingroup hx509_verify
544 hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx
, int boolean
)
547 ctx
->flags
|= HX509_VERIFY_CTX_F_REQUIRE_RFC3280
;
549 ctx
->flags
&= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280
;
553 * Allow using the operating system builtin trust anchors if no other
554 * trust anchors are configured.
556 * @param ctx a verification context
557 * @param boolean if non zero, useing the operating systems builtin
561 * @return An hx509 error code, see hx509_get_error_string().
563 * @ingroup hx509_cert
567 hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx
, int boolean
)
570 ctx
->flags
&= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS
;
572 ctx
->flags
|= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS
;
576 hx509_verify_ctx_f_allow_best_before_signature_algs(hx509_context ctx
,
580 ctx
->flags
&= ~HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK
;
582 ctx
->flags
|= HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK
;
585 static const Extension
*
586 find_extension(const Certificate
*cert
, const heim_oid
*oid
, int *idx
)
588 const TBSCertificate
*c
= &cert
->tbsCertificate
;
590 if (c
->version
== NULL
|| *c
->version
< 2 || c
->extensions
== NULL
)
593 for (;*idx
< c
->extensions
->len
; (*idx
)++) {
594 if (der_heim_oid_cmp(&c
->extensions
->val
[*idx
].extnID
, oid
) == 0)
595 return &c
->extensions
->val
[(*idx
)++];
601 find_extension_auth_key_id(const Certificate
*subject
,
602 AuthorityKeyIdentifier
*ai
)
608 memset(ai
, 0, sizeof(*ai
));
610 e
= find_extension(subject
, &asn1_oid_id_x509_ce_authorityKeyIdentifier
, &i
);
612 return HX509_EXTENSION_NOT_FOUND
;
614 return decode_AuthorityKeyIdentifier(e
->extnValue
.data
,
620 _hx509_find_extension_subject_key_id(const Certificate
*issuer
,
621 SubjectKeyIdentifier
*si
)
627 memset(si
, 0, sizeof(*si
));
629 e
= find_extension(issuer
, &asn1_oid_id_x509_ce_subjectKeyIdentifier
, &i
);
631 return HX509_EXTENSION_NOT_FOUND
;
633 return decode_SubjectKeyIdentifier(e
->extnValue
.data
,
639 find_extension_name_constraints(const Certificate
*subject
,
646 memset(nc
, 0, sizeof(*nc
));
648 e
= find_extension(subject
, &asn1_oid_id_x509_ce_nameConstraints
, &i
);
650 return HX509_EXTENSION_NOT_FOUND
;
652 return decode_NameConstraints(e
->extnValue
.data
,
658 find_extension_subject_alt_name(const Certificate
*cert
, int *i
,
664 memset(sa
, 0, sizeof(*sa
));
666 e
= find_extension(cert
, &asn1_oid_id_x509_ce_subjectAltName
, i
);
668 return HX509_EXTENSION_NOT_FOUND
;
670 return decode_GeneralNames(e
->extnValue
.data
,
676 find_extension_eku(const Certificate
*cert
, ExtKeyUsage
*eku
)
682 memset(eku
, 0, sizeof(*eku
));
684 e
= find_extension(cert
, &asn1_oid_id_x509_ce_extKeyUsage
, &i
);
686 return HX509_EXTENSION_NOT_FOUND
;
688 return decode_ExtKeyUsage(e
->extnValue
.data
,
694 add_to_list(hx509_octet_string_list
*list
, const heim_octet_string
*entry
)
699 p
= realloc(list
->val
, (list
->len
+ 1) * sizeof(list
->val
[0]));
703 ret
= der_copy_octet_string(entry
, &list
->val
[list
->len
]);
711 * Free a list of octet strings returned by another hx509 library
714 * @param list list to be freed.
716 * @ingroup hx509_misc
720 hx509_free_octet_string_list(hx509_octet_string_list
*list
)
723 for (i
= 0; i
< list
->len
; i
++)
724 der_free_octet_string(&list
->val
[i
]);
731 * Return a list of subjectAltNames specified by oid in the
732 * certificate. On error the
734 * The returned list of octet string should be freed with
735 * hx509_free_octet_string_list().
737 * @param context A hx509 context.
738 * @param cert a hx509 certificate object.
739 * @param oid an oid to for SubjectAltName.
740 * @param list list of matching SubjectAltName.
742 * @return An hx509 error code, see hx509_get_error_string().
744 * @ingroup hx509_cert
748 hx509_cert_find_subjectAltName_otherName(hx509_context context
,
751 hx509_octet_string_list
*list
)
761 ret
= find_extension_subject_alt_name(_hx509_get_cert(cert
), &i
, &sa
);
763 if (ret
== HX509_EXTENSION_NOT_FOUND
) {
765 } else if (ret
!= 0) {
766 hx509_set_error_string(context
, 0, ret
, "Error searching for SAN");
767 hx509_free_octet_string_list(list
);
771 for (j
= 0; j
< sa
.len
; j
++) {
772 if (sa
.val
[j
].element
== choice_GeneralName_otherName
&&
773 der_heim_oid_cmp(&sa
.val
[j
].u
.otherName
.type_id
, oid
) == 0)
775 ret
= add_to_list(list
, &sa
.val
[j
].u
.otherName
.value
);
777 hx509_set_error_string(context
, 0, ret
,
778 "Error adding an exra SAN to "
780 hx509_free_octet_string_list(list
);
781 free_GeneralNames(&sa
);
786 free_GeneralNames(&sa
);
792 check_key_usage(hx509_context context
, const Certificate
*cert
,
793 unsigned flags
, int req_present
)
801 if (_hx509_cert_get_version(cert
) < 3)
804 e
= find_extension(cert
, &asn1_oid_id_x509_ce_keyUsage
, &i
);
807 hx509_set_error_string(context
, 0, HX509_KU_CERT_MISSING
,
808 "Required extension key "
809 "usage missing from certifiate");
810 return HX509_KU_CERT_MISSING
;
815 ret
= decode_KeyUsage(e
->extnValue
.data
, e
->extnValue
.length
, &ku
, &size
);
818 ku_flags
= KeyUsage2int(ku
);
819 if ((ku_flags
& flags
) != flags
) {
820 unsigned missing
= (~ku_flags
) & flags
;
821 char buf
[256], *name
;
823 unparse_flags(missing
, asn1_KeyUsage_units(), buf
, sizeof(buf
));
824 _hx509_unparse_Name(&cert
->tbsCertificate
.subject
, &name
);
825 hx509_set_error_string(context
, 0, HX509_KU_CERT_MISSING
,
826 "Key usage %s required but missing "
827 "from certifiate %s", buf
, name
);
829 return HX509_KU_CERT_MISSING
;
835 * Return 0 on matching key usage 'flags' for 'cert', otherwise return
836 * an error code. If 'req_present' the existance is required of the
837 * KeyUsage extension.
841 _hx509_check_key_usage(hx509_context context
, hx509_cert cert
,
842 unsigned flags
, int req_present
)
844 return check_key_usage(context
, _hx509_get_cert(cert
), flags
, req_present
);
847 enum certtype
{ PROXY_CERT
, EE_CERT
, CA_CERT
};
850 check_basic_constraints(hx509_context context
, const Certificate
*cert
,
851 enum certtype type
, int depth
)
858 if (_hx509_cert_get_version(cert
) < 3)
861 e
= find_extension(cert
, &asn1_oid_id_x509_ce_basicConstraints
, &i
);
869 ret
= _hx509_unparse_Name(&cert
->tbsCertificate
.subject
, &name
);
871 hx509_set_error_string(context
, 0, HX509_EXTENSION_NOT_FOUND
,
872 "basicConstraints missing from "
873 "CA certifiacte %s", name
);
875 return HX509_EXTENSION_NOT_FOUND
;
880 ret
= decode_BasicConstraints(e
->extnValue
.data
,
881 e
->extnValue
.length
, &bc
,
887 if (bc
.cA
!= NULL
&& *bc
.cA
)
888 ret
= HX509_PARENT_IS_CA
;
894 if (bc
.cA
== NULL
|| !*bc
.cA
)
895 ret
= HX509_PARENT_NOT_CA
;
896 else if (bc
.pathLenConstraint
)
897 if (depth
- 1 > *bc
.pathLenConstraint
)
898 ret
= HX509_CA_PATH_TOO_DEEP
;
901 free_BasicConstraints(&bc
);
906 _hx509_cert_is_parent_cmp(const Certificate
*subject
,
907 const Certificate
*issuer
,
908 int allow_self_signed
)
911 AuthorityKeyIdentifier ai
;
912 SubjectKeyIdentifier si
;
913 int ret_ai
, ret_si
, ret
;
915 ret
= _hx509_name_cmp(&issuer
->tbsCertificate
.subject
,
916 &subject
->tbsCertificate
.issuer
,
923 memset(&ai
, 0, sizeof(ai
));
924 memset(&si
, 0, sizeof(si
));
927 * Try to find AuthorityKeyIdentifier, if it's not present in the
928 * subject certificate nor the parent.
931 ret_ai
= find_extension_auth_key_id(subject
, &ai
);
932 if (ret_ai
&& ret_ai
!= HX509_EXTENSION_NOT_FOUND
)
934 ret_si
= _hx509_find_extension_subject_key_id(issuer
, &si
);
935 if (ret_si
&& ret_si
!= HX509_EXTENSION_NOT_FOUND
)
938 if (ret_si
&& ret_ai
)
943 if (allow_self_signed
) {
946 } else if (ai
.keyIdentifier
) {
952 if (ai
.keyIdentifier
== NULL
) {
955 if (ai
.authorityCertIssuer
== NULL
)
957 if (ai
.authorityCertSerialNumber
== NULL
)
960 diff
= der_heim_integer_cmp(ai
.authorityCertSerialNumber
,
961 &issuer
->tbsCertificate
.serialNumber
);
964 if (ai
.authorityCertIssuer
->len
!= 1)
966 if (ai
.authorityCertIssuer
->val
[0].element
!= choice_GeneralName_directoryName
)
970 ai
.authorityCertIssuer
->val
[0].u
.directoryName
.element
;
972 ai
.authorityCertIssuer
->val
[0].u
.directoryName
.u
.rdnSequence
;
974 ret
= _hx509_name_cmp(&issuer
->tbsCertificate
.subject
,
983 diff
= der_heim_octet_string_cmp(ai
.keyIdentifier
, &si
);
988 free_AuthorityKeyIdentifier(&ai
);
989 free_SubjectKeyIdentifier(&si
);
994 certificate_is_anchor(hx509_context context
,
995 hx509_certs trust_anchors
,
996 const hx509_cert cert
)
1002 if (trust_anchors
== NULL
)
1005 _hx509_query_clear(&q
);
1007 q
.match
= HX509_QUERY_MATCH_CERTIFICATE
;
1008 q
.certificate
= _hx509_get_cert(cert
);
1010 ret
= hx509_certs_find(context
, trust_anchors
, &q
, &c
);
1017 certificate_is_self_signed(hx509_context context
,
1018 const Certificate
*cert
,
1022 ret
= _hx509_name_cmp(&cert
->tbsCertificate
.subject
,
1023 &cert
->tbsCertificate
.issuer
, &diff
);
1024 *self_signed
= (diff
== 0);
1026 hx509_set_error_string(context
, 0, ret
,
1027 "Failed to check if self signed");
1032 * The subjectName is "null" when it's empty set of relative DBs.
1036 subject_null_p(const Certificate
*c
)
1038 return c
->tbsCertificate
.subject
.u
.rdnSequence
.len
== 0;
1043 find_parent(hx509_context context
,
1045 hx509_certs trust_anchors
,
1051 AuthorityKeyIdentifier ai
;
1056 memset(&ai
, 0, sizeof(ai
));
1058 _hx509_query_clear(&q
);
1060 if (!subject_null_p(current
->data
)) {
1061 q
.match
|= HX509_QUERY_FIND_ISSUER_CERT
;
1062 q
.subject
= _hx509_get_cert(current
);
1064 ret
= find_extension_auth_key_id(current
->data
, &ai
);
1066 hx509_set_error_string(context
, 0, HX509_CERTIFICATE_MALFORMED
,
1067 "Subjectless certificate missing AuthKeyID");
1068 return HX509_CERTIFICATE_MALFORMED
;
1071 if (ai
.keyIdentifier
== NULL
) {
1072 free_AuthorityKeyIdentifier(&ai
);
1073 hx509_set_error_string(context
, 0, HX509_CERTIFICATE_MALFORMED
,
1074 "Subjectless certificate missing keyIdentifier "
1075 "inside AuthKeyID");
1076 return HX509_CERTIFICATE_MALFORMED
;
1079 q
.subject_id
= ai
.keyIdentifier
;
1080 q
.match
= HX509_QUERY_MATCH_SUBJECT_KEY_ID
;
1084 q
.match
|= HX509_QUERY_NO_MATCH_PATH
;
1087 q
.timenow
= time_now
;
1088 q
.match
|= HX509_QUERY_MATCH_TIME
;
1090 ret
= hx509_certs_find(context
, pool
, &q
, parent
);
1092 free_AuthorityKeyIdentifier(&ai
);
1095 q
.match
&= ~HX509_QUERY_MATCH_TIME
;
1098 if (trust_anchors
) {
1099 ret
= hx509_certs_find(context
, trust_anchors
, &q
, parent
);
1101 free_AuthorityKeyIdentifier(&ai
);
1105 free_AuthorityKeyIdentifier(&ai
);
1111 ret
= hx509_cert_get_subject(current
, &name
);
1113 hx509_clear_error_string(context
);
1114 return HX509_ISSUER_NOT_FOUND
;
1116 ret
= hx509_name_to_string(name
, &str
);
1117 hx509_name_free(&name
);
1119 hx509_clear_error_string(context
);
1120 return HX509_ISSUER_NOT_FOUND
;
1123 hx509_set_error_string(context
, 0, HX509_ISSUER_NOT_FOUND
,
1124 "Failed to find issuer for "
1125 "certificate with subject: '%s'", str
);
1128 return HX509_ISSUER_NOT_FOUND
;
1136 is_proxy_cert(hx509_context context
,
1137 const Certificate
*cert
,
1138 ProxyCertInfo
*rinfo
)
1146 memset(rinfo
, 0, sizeof(*rinfo
));
1148 e
= find_extension(cert
, &asn1_oid_id_pkix_pe_proxyCertInfo
, &i
);
1150 hx509_clear_error_string(context
);
1151 return HX509_EXTENSION_NOT_FOUND
;
1154 ret
= decode_ProxyCertInfo(e
->extnValue
.data
,
1155 e
->extnValue
.length
,
1159 hx509_clear_error_string(context
);
1162 if (size
!= e
->extnValue
.length
) {
1163 free_ProxyCertInfo(&info
);
1164 hx509_clear_error_string(context
);
1165 return HX509_EXTRA_DATA_AFTER_STRUCTURE
;
1168 free_ProxyCertInfo(&info
);
1176 * Path operations are like MEMORY based keyset, but with exposed
1177 * internal so we can do easy searches.
1181 _hx509_path_append(hx509_context context
, hx509_path
*path
, hx509_cert cert
)
1184 val
= realloc(path
->val
, (path
->len
+ 1) * sizeof(path
->val
[0]));
1186 hx509_set_error_string(context
, 0, ENOMEM
, "out of memory");
1191 path
->val
[path
->len
] = hx509_cert_ref(cert
);
1198 _hx509_path_free(hx509_path
*path
)
1202 for (i
= 0; i
< path
->len
; i
++)
1203 hx509_cert_free(path
->val
[i
]);
1210 * Find path by looking up issuer for the top certificate and continue
1211 * until an anchor certificate is found or max limit is found. A
1212 * certificate never included twice in the path.
1214 * If the trust anchors are not given, calculate optimistic path, just
1215 * follow the chain upward until we no longer find a parent or we hit
1216 * the max path limit. In this case, a failure will always be returned
1217 * depending on what error condition is hit first.
1219 * The path includes a path from the top certificate to the anchor
1222 * The caller needs to free `path´ both on successful built path and
1227 _hx509_calculate_path(hx509_context context
,
1230 hx509_certs anchors
,
1231 unsigned int max_depth
,
1236 hx509_cert parent
, current
;
1240 max_depth
= HX509_VERIFY_MAX_DEPTH
;
1242 ret
= _hx509_path_append(context
, path
, cert
);
1246 current
= hx509_cert_ref(cert
);
1248 while (!certificate_is_anchor(context
, anchors
, current
)) {
1250 ret
= find_parent(context
, time_now
, anchors
, path
,
1251 pool
, current
, &parent
);
1252 hx509_cert_free(current
);
1256 ret
= _hx509_path_append(context
, path
, parent
);
1261 if (path
->len
> max_depth
) {
1262 hx509_cert_free(current
);
1263 hx509_set_error_string(context
, 0, HX509_PATH_TOO_LONG
,
1264 "Path too long while bulding "
1265 "certificate chain");
1266 return HX509_PATH_TOO_LONG
;
1270 if ((flags
& HX509_CALCULATE_PATH_NO_ANCHOR
) &&
1272 certificate_is_anchor(context
, anchors
, path
->val
[path
->len
- 1]))
1274 hx509_cert_free(path
->val
[path
->len
- 1]);
1278 hx509_cert_free(current
);
1283 _hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier
*p
,
1284 const AlgorithmIdentifier
*q
)
1287 diff
= der_heim_oid_cmp(&p
->algorithm
, &q
->algorithm
);
1290 if (p
->parameters
) {
1292 return heim_any_cmp(p
->parameters
,
1305 _hx509_Certificate_cmp(const Certificate
*p
, const Certificate
*q
)
1308 diff
= der_heim_bit_string_cmp(&p
->signatureValue
, &q
->signatureValue
);
1311 diff
= _hx509_AlgorithmIdentifier_cmp(&p
->signatureAlgorithm
,
1312 &q
->signatureAlgorithm
);
1315 diff
= der_heim_octet_string_cmp(&p
->tbsCertificate
._save
,
1316 &q
->tbsCertificate
._save
);
1321 * Compare to hx509 certificate object, useful for sorting.
1323 * @param p a hx509 certificate object.
1324 * @param q a hx509 certificate object.
1326 * @return 0 the objects are the same, returns > 0 is p is "larger"
1327 * then q, < 0 if p is "smaller" then q.
1329 * @ingroup hx509_cert
1333 hx509_cert_cmp(hx509_cert p
, hx509_cert q
)
1335 return _hx509_Certificate_cmp(p
->data
, q
->data
);
1339 * Return the name of the issuer of the hx509 certificate.
1341 * @param p a hx509 certificate object.
1342 * @param name a pointer to a hx509 name, should be freed by
1343 * hx509_name_free().
1345 * @return An hx509 error code, see hx509_get_error_string().
1347 * @ingroup hx509_cert
1351 hx509_cert_get_issuer(hx509_cert p
, hx509_name
*name
)
1353 return _hx509_name_from_Name(&p
->data
->tbsCertificate
.issuer
, name
);
1357 * Return the name of the subject of the hx509 certificate.
1359 * @param p a hx509 certificate object.
1360 * @param name a pointer to a hx509 name, should be freed by
1361 * hx509_name_free(). See also hx509_cert_get_base_subject().
1363 * @return An hx509 error code, see hx509_get_error_string().
1365 * @ingroup hx509_cert
1369 hx509_cert_get_subject(hx509_cert p
, hx509_name
*name
)
1371 return _hx509_name_from_Name(&p
->data
->tbsCertificate
.subject
, name
);
1375 * Return the name of the base subject of the hx509 certificate. If
1376 * the certiicate is a verified proxy certificate, the this function
1377 * return the base certificate (root of the proxy chain). If the proxy
1378 * certificate is not verified with the base certificate
1379 * HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned.
1381 * @param context a hx509 context.
1382 * @param c a hx509 certificate object.
1383 * @param name a pointer to a hx509 name, should be freed by
1384 * hx509_name_free(). See also hx509_cert_get_subject().
1386 * @return An hx509 error code, see hx509_get_error_string().
1388 * @ingroup hx509_cert
1392 hx509_cert_get_base_subject(hx509_context context
, hx509_cert c
,
1396 return hx509_name_copy(context
, c
->basename
, name
);
1397 if (is_proxy_cert(context
, c
->data
, NULL
) == 0) {
1398 int ret
= HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED
;
1399 hx509_set_error_string(context
, 0, ret
,
1400 "Proxy certificate have not been "
1401 "canonicalize yet, no base name");
1404 return _hx509_name_from_Name(&c
->data
->tbsCertificate
.subject
, name
);
1408 * Get serial number of the certificate.
1410 * @param p a hx509 certificate object.
1411 * @param i serial number, should be freed ith der_free_heim_integer().
1413 * @return An hx509 error code, see hx509_get_error_string().
1415 * @ingroup hx509_cert
1419 hx509_cert_get_serialnumber(hx509_cert p
, heim_integer
*i
)
1421 return der_copy_heim_integer(&p
->data
->tbsCertificate
.serialNumber
, i
);
1425 * Get notBefore time of the certificate.
1427 * @param p a hx509 certificate object.
1429 * @return return not before time
1431 * @ingroup hx509_cert
1435 hx509_cert_get_notBefore(hx509_cert p
)
1437 return _hx509_Time2time_t(&p
->data
->tbsCertificate
.validity
.notBefore
);
1441 * Get notAfter time of the certificate.
1443 * @param p a hx509 certificate object.
1445 * @return return not after time.
1447 * @ingroup hx509_cert
1451 hx509_cert_get_notAfter(hx509_cert p
)
1453 return _hx509_Time2time_t(&p
->data
->tbsCertificate
.validity
.notAfter
);
1457 * Get the SubjectPublicKeyInfo structure from the hx509 certificate.
1459 * @param context a hx509 context.
1460 * @param p a hx509 certificate object.
1461 * @param spki SubjectPublicKeyInfo, should be freed with
1462 * free_SubjectPublicKeyInfo().
1464 * @return An hx509 error code, see hx509_get_error_string().
1466 * @ingroup hx509_cert
1470 hx509_cert_get_SPKI(hx509_context context
, hx509_cert p
, SubjectPublicKeyInfo
*spki
)
1474 ret
= copy_SubjectPublicKeyInfo(&p
->data
->tbsCertificate
.subjectPublicKeyInfo
, spki
);
1476 hx509_set_error_string(context
, 0, ret
, "Failed to copy SPKI");
1481 * Get the AlgorithmIdentifier from the hx509 certificate.
1483 * @param context a hx509 context.
1484 * @param p a hx509 certificate object.
1485 * @param alg AlgorithmIdentifier, should be freed with
1486 * free_AlgorithmIdentifier(). The algorithmidentifier is
1487 * typicly rsaEncryption, or id-ecPublicKey, or some other
1488 * public key mechanism.
1490 * @return An hx509 error code, see hx509_get_error_string().
1492 * @ingroup hx509_cert
1496 hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context
,
1498 AlgorithmIdentifier
*alg
)
1502 ret
= copy_AlgorithmIdentifier(&p
->data
->tbsCertificate
.subjectPublicKeyInfo
.algorithm
, alg
);
1504 hx509_set_error_string(context
, 0, ret
,
1505 "Failed to copy SPKI AlgorithmIdentifier");
1511 _hx509_cert_private_key(hx509_cert p
)
1513 return p
->private_key
;
1517 hx509_cert_have_private_key(hx509_cert p
)
1519 return p
->private_key
? 1 : 0;
1524 _hx509_cert_private_key_exportable(hx509_cert p
)
1526 if (p
->private_key
== NULL
)
1528 return _hx509_private_key_exportable(p
->private_key
);
1532 _hx509_cert_private_decrypt(hx509_context context
,
1533 const heim_octet_string
*ciphertext
,
1534 const heim_oid
*encryption_oid
,
1536 heim_octet_string
*cleartext
)
1538 cleartext
->data
= NULL
;
1539 cleartext
->length
= 0;
1541 if (p
->private_key
== NULL
) {
1542 hx509_set_error_string(context
, 0, HX509_PRIVATE_KEY_MISSING
,
1543 "Private key missing");
1544 return HX509_PRIVATE_KEY_MISSING
;
1547 return _hx509_private_key_private_decrypt(context
,
1555 _hx509_cert_public_encrypt(hx509_context context
,
1556 const heim_octet_string
*cleartext
,
1558 heim_oid
*encryption_oid
,
1559 heim_octet_string
*ciphertext
)
1561 return _hx509_public_encrypt(context
,
1563 encryption_oid
, ciphertext
);
1571 _hx509_Time2time_t(const Time
*t
)
1573 switch(t
->element
) {
1574 case choice_Time_utcTime
:
1575 return t
->u
.utcTime
;
1576 case choice_Time_generalTime
:
1577 return t
->u
.generalTime
;
1587 init_name_constraints(hx509_name_constraints
*nc
)
1589 memset(nc
, 0, sizeof(*nc
));
1594 add_name_constraints(hx509_context context
, const Certificate
*c
, int not_ca
,
1595 hx509_name_constraints
*nc
)
1597 NameConstraints tnc
;
1600 ret
= find_extension_name_constraints(c
, &tnc
);
1601 if (ret
== HX509_EXTENSION_NOT_FOUND
)
1604 hx509_set_error_string(context
, 0, ret
, "Failed getting NameConstraints");
1606 } else if (not_ca
) {
1607 ret
= HX509_VERIFY_CONSTRAINTS
;
1608 hx509_set_error_string(context
, 0, ret
, "Not a CA and "
1609 "have NameConstraints");
1611 NameConstraints
*val
;
1612 val
= realloc(nc
->val
, sizeof(nc
->val
[0]) * (nc
->len
+ 1));
1614 hx509_clear_error_string(context
);
1619 ret
= copy_NameConstraints(&tnc
, &nc
->val
[nc
->len
]);
1621 hx509_clear_error_string(context
);
1627 free_NameConstraints(&tnc
);
1632 match_RDN(const RelativeDistinguishedName
*c
,
1633 const RelativeDistinguishedName
*n
)
1637 if (c
->len
!= n
->len
)
1638 return HX509_NAME_CONSTRAINT_ERROR
;
1640 for (i
= 0; i
< n
->len
; i
++) {
1643 if (der_heim_oid_cmp(&c
->val
[i
].type
, &n
->val
[i
].type
) != 0)
1644 return HX509_NAME_CONSTRAINT_ERROR
;
1645 ret
= _hx509_name_ds_cmp(&c
->val
[i
].value
, &n
->val
[i
].value
, &diff
);
1649 return HX509_NAME_CONSTRAINT_ERROR
;
1655 match_X501Name(const Name
*c
, const Name
*n
)
1659 if (c
->element
!= choice_Name_rdnSequence
1660 || n
->element
!= choice_Name_rdnSequence
)
1662 if (c
->u
.rdnSequence
.len
> n
->u
.rdnSequence
.len
)
1663 return HX509_NAME_CONSTRAINT_ERROR
;
1664 for (i
= 0; i
< c
->u
.rdnSequence
.len
; i
++) {
1665 ret
= match_RDN(&c
->u
.rdnSequence
.val
[i
], &n
->u
.rdnSequence
.val
[i
]);
1674 match_general_name(const GeneralName
*c
, const GeneralName
*n
, int *match
)
1677 * Name constraints only apply to the same name type, see RFC3280,
1680 assert(c
->element
== n
->element
);
1682 switch(c
->element
) {
1683 case choice_GeneralName_otherName
:
1684 if (der_heim_oid_cmp(&c
->u
.otherName
.type_id
,
1685 &n
->u
.otherName
.type_id
) != 0)
1686 return HX509_NAME_CONSTRAINT_ERROR
;
1687 if (heim_any_cmp(&c
->u
.otherName
.value
,
1688 &n
->u
.otherName
.value
) != 0)
1689 return HX509_NAME_CONSTRAINT_ERROR
;
1692 case choice_GeneralName_rfc822Name
: {
1695 s
= strchr(c
->u
.rfc822Name
, '@');
1697 if (strcasecmp(c
->u
.rfc822Name
, n
->u
.rfc822Name
) != 0)
1698 return HX509_NAME_CONSTRAINT_ERROR
;
1700 s
= strchr(n
->u
.rfc822Name
, '@');
1702 return HX509_NAME_CONSTRAINT_ERROR
;
1703 len1
= strlen(c
->u
.rfc822Name
);
1704 len2
= strlen(s
+ 1);
1706 return HX509_NAME_CONSTRAINT_ERROR
;
1707 if (strcasecmp(s
+ 1 + len2
- len1
, c
->u
.rfc822Name
) != 0)
1708 return HX509_NAME_CONSTRAINT_ERROR
;
1709 if (len1
< len2
&& s
[len2
- len1
+ 1] != '.')
1710 return HX509_NAME_CONSTRAINT_ERROR
;
1715 case choice_GeneralName_dNSName
: {
1718 lenc
= strlen(c
->u
.dNSName
);
1719 lenn
= strlen(n
->u
.dNSName
);
1721 return HX509_NAME_CONSTRAINT_ERROR
;
1722 if (strcasecmp(&n
->u
.dNSName
[lenn
- lenc
], c
->u
.dNSName
) != 0)
1723 return HX509_NAME_CONSTRAINT_ERROR
;
1724 if (lenc
!= lenn
&& n
->u
.dNSName
[lenn
- lenc
- 1] != '.')
1725 return HX509_NAME_CONSTRAINT_ERROR
;
1729 case choice_GeneralName_directoryName
: {
1730 Name c_name
, n_name
;
1733 c_name
._save
.data
= NULL
;
1734 c_name
._save
.length
= 0;
1735 c_name
.element
= c
->u
.directoryName
.element
;
1736 c_name
.u
.rdnSequence
= c
->u
.directoryName
.u
.rdnSequence
;
1738 n_name
._save
.data
= NULL
;
1739 n_name
._save
.length
= 0;
1740 n_name
.element
= n
->u
.directoryName
.element
;
1741 n_name
.u
.rdnSequence
= n
->u
.directoryName
.u
.rdnSequence
;
1743 ret
= match_X501Name(&c_name
, &n_name
);
1748 case choice_GeneralName_uniformResourceIdentifier
:
1749 case choice_GeneralName_iPAddress
:
1750 case choice_GeneralName_registeredID
:
1752 return HX509_NAME_CONSTRAINT_ERROR
;
1757 match_alt_name(const GeneralName
*n
, const Certificate
*c
,
1758 int *same
, int *match
)
1765 ret
= find_extension_subject_alt_name(c
, &i
, &sa
);
1766 if (ret
== HX509_EXTENSION_NOT_FOUND
) {
1769 } else if (ret
!= 0)
1772 for (j
= 0; j
< sa
.len
; j
++) {
1773 if (n
->element
== sa
.val
[j
].element
) {
1775 ret
= match_general_name(n
, &sa
.val
[j
], match
);
1778 free_GeneralNames(&sa
);
1785 match_tree(const GeneralSubtrees
*t
, const Certificate
*c
, int *match
)
1787 int name
, alt_name
, same
;
1791 name
= alt_name
= same
= *match
= 0;
1792 for (i
= 0; i
< t
->len
; i
++) {
1793 if (t
->val
[i
].minimum
&& t
->val
[i
].maximum
)
1797 * If the constraint apply to directoryNames, test is with
1798 * subjectName of the certificate if the certificate have a
1799 * non-null (empty) subjectName.
1802 if (t
->val
[i
].base
.element
== choice_GeneralName_directoryName
1803 && !subject_null_p(c
))
1805 GeneralName certname
;
1807 memset(&certname
, 0, sizeof(certname
));
1808 certname
.element
= choice_GeneralName_directoryName
;
1809 certname
.u
.directoryName
.element
=
1810 c
->tbsCertificate
.subject
.element
;
1811 certname
.u
.directoryName
.u
.rdnSequence
=
1812 c
->tbsCertificate
.subject
.u
.rdnSequence
;
1814 ret
= match_general_name(&t
->val
[i
].base
, &certname
, &name
);
1817 /* Handle subjectAltNames, this is icky since they
1818 * restrictions only apply if the subjectAltName is of the
1819 * same type. So if there have been a match of type, require
1820 * altname to be set.
1822 ret
= match_alt_name(&t
->val
[i
].base
, c
, &same
, &alt_name
);
1824 if (name
&& (!same
|| alt_name
))
1830 check_name_constraints(hx509_context context
,
1831 const hx509_name_constraints
*nc
,
1832 const Certificate
*c
)
1837 for (i
= 0 ; i
< nc
->len
; i
++) {
1840 if (nc
->val
[i
].permittedSubtrees
) {
1841 GeneralSubtrees_SET(&gs
, nc
->val
[i
].permittedSubtrees
);
1842 ret
= match_tree(&gs
, c
, &match
);
1844 hx509_clear_error_string(context
);
1847 /* allow null subjectNames, they wont matches anything */
1848 if (match
== 0 && !subject_null_p(c
)) {
1849 hx509_set_error_string(context
, 0, HX509_VERIFY_CONSTRAINTS
,
1850 "Error verify constraints, "
1851 "certificate didn't match any "
1852 "permitted subtree");
1853 return HX509_VERIFY_CONSTRAINTS
;
1856 if (nc
->val
[i
].excludedSubtrees
) {
1857 GeneralSubtrees_SET(&gs
, nc
->val
[i
].excludedSubtrees
);
1858 ret
= match_tree(&gs
, c
, &match
);
1860 hx509_clear_error_string(context
);
1864 hx509_set_error_string(context
, 0, HX509_VERIFY_CONSTRAINTS
,
1865 "Error verify constraints, "
1866 "certificate included in excluded "
1868 return HX509_VERIFY_CONSTRAINTS
;
1876 free_name_constraints(hx509_name_constraints
*nc
)
1880 for (i
= 0 ; i
< nc
->len
; i
++)
1881 free_NameConstraints(&nc
->val
[i
]);
1886 * Build and verify the path for the certificate to the trust anchor
1887 * specified in the verify context. The path is constructed from the
1888 * certificate, the pool and the trust anchors.
1890 * @param context A hx509 context.
1891 * @param ctx A hx509 verification context.
1892 * @param cert the certificate to build the path from.
1893 * @param pool A keyset of certificates to build the chain from.
1895 * @return An hx509 error code, see hx509_get_error_string().
1897 * @ingroup hx509_verify
1901 hx509_verify_path(hx509_context context
,
1902 hx509_verify_ctx ctx
,
1906 hx509_name_constraints nc
;
1908 int ret
, i
, proxy_cert_depth
, selfsigned_depth
, diff
;
1911 hx509_certs anchors
= NULL
;
1913 memset(&proxy_issuer
, 0, sizeof(proxy_issuer
));
1915 ret
= init_name_constraints(&nc
);
1922 if ((ctx
->flags
& HX509_VERIFY_CTX_F_TIME_SET
) == 0)
1923 ctx
->time_now
= time(NULL
);
1928 if (ctx
->trust_anchors
)
1929 anchors
= hx509_certs_ref(ctx
->trust_anchors
);
1930 else if (context
->default_trust_anchors
&& ALLOW_DEF_TA(ctx
))
1931 anchors
= hx509_certs_ref(context
->default_trust_anchors
);
1933 ret
= hx509_certs_init(context
, "MEMORY:no-TA", 0, NULL
, &anchors
);
1939 * Calculate the path from the certificate user presented to the
1942 ret
= _hx509_calculate_path(context
, 0, ctx
->time_now
,
1943 anchors
, ctx
->max_depth
,
1949 * Check CA and proxy certificate chain from the top of the
1950 * certificate chain. Also check certificate is valid with respect
1951 * to the current time.
1955 proxy_cert_depth
= 0;
1956 selfsigned_depth
= 0;
1958 if (ctx
->flags
& HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
)
1963 for (i
= 0; i
< path
.len
; i
++) {
1967 c
= _hx509_get_cert(path
.val
[i
]);
1970 * Lets do some basic check on issuer like
1971 * keyUsage.keyCertSign and basicConstraints.cA bit depending
1972 * on what type of certificate this is.
1978 /* XXX make constants for keyusage */
1979 ret
= check_key_usage(context
, c
, 1 << 5,
1980 REQUIRE_RFC3280(ctx
) ? TRUE
: FALSE
);
1982 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
1983 "Key usage missing from CA certificate");
1987 /* self signed cert doesn't add to path length */
1988 if (i
+ 1 != path
.len
) {
1991 ret
= certificate_is_self_signed(context
, c
, &selfsigned
);
2002 if (is_proxy_cert(context
, c
, &info
) == 0) {
2005 if (info
.pCPathLenConstraint
!= NULL
&&
2006 *info
.pCPathLenConstraint
< i
)
2008 free_ProxyCertInfo(&info
);
2009 ret
= HX509_PATH_TOO_LONG
;
2010 hx509_set_error_string(context
, 0, ret
,
2011 "Proxy certificate chain "
2012 "longer then allowed");
2015 /* XXX MUST check info.proxyPolicy */
2016 free_ProxyCertInfo(&info
);
2019 if (find_extension(c
, &asn1_oid_id_x509_ce_subjectAltName
, &j
)) {
2020 ret
= HX509_PROXY_CERT_INVALID
;
2021 hx509_set_error_string(context
, 0, ret
,
2022 "Proxy certificate have explicity "
2023 "forbidden subjectAltName");
2028 if (find_extension(c
, &asn1_oid_id_x509_ce_issuerAltName
, &j
)) {
2029 ret
= HX509_PROXY_CERT_INVALID
;
2030 hx509_set_error_string(context
, 0, ret
,
2031 "Proxy certificate have explicity "
2032 "forbidden issuerAltName");
2037 * The subject name of the proxy certificate should be
2038 * CN=XXX,<proxy issuer>, prune of CN and check if its
2039 * the same over the whole chain of proxy certs and
2040 * then check with the EE cert when we get to it.
2043 if (proxy_cert_depth
) {
2044 ret
= _hx509_name_cmp(&proxy_issuer
, &c
->tbsCertificate
.subject
, &diff
);
2046 hx509_set_error_string(context
, 0, ret
, "Out of memory");
2050 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2051 hx509_set_error_string(context
, 0, ret
,
2052 "Base proxy name not right");
2057 free_Name(&proxy_issuer
);
2059 ret
= copy_Name(&c
->tbsCertificate
.subject
, &proxy_issuer
);
2061 hx509_clear_error_string(context
);
2065 j
= proxy_issuer
.u
.rdnSequence
.len
;
2066 if (proxy_issuer
.u
.rdnSequence
.len
< 2
2067 || proxy_issuer
.u
.rdnSequence
.val
[j
- 1].len
> 1
2068 || der_heim_oid_cmp(&proxy_issuer
.u
.rdnSequence
.val
[j
- 1].val
[0].type
,
2069 &asn1_oid_id_at_commonName
))
2071 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2072 hx509_set_error_string(context
, 0, ret
,
2073 "Proxy name too short or "
2074 "does not have Common name "
2079 free_RelativeDistinguishedName(&proxy_issuer
.u
.rdnSequence
.val
[j
- 1]);
2080 proxy_issuer
.u
.rdnSequence
.len
-= 1;
2082 ret
= _hx509_name_cmp(&proxy_issuer
, &c
->tbsCertificate
.issuer
, &diff
);
2084 hx509_set_error_string(context
, 0, ret
, "Out of memory");
2088 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2089 hx509_set_error_string(context
, 0, ret
,
2090 "Proxy issuer name not as expected");
2097 * Now we are done with the proxy certificates, this
2098 * cert was an EE cert and we we will fall though to
2099 * EE checking below.
2107 * If there where any proxy certificates in the chain
2108 * (proxy_cert_depth > 0), check that the proxy issuer
2109 * matched proxy certificates "base" subject.
2111 if (proxy_cert_depth
) {
2113 ret
= _hx509_name_cmp(&proxy_issuer
,
2114 &c
->tbsCertificate
.subject
, &diff
);
2116 hx509_set_error_string(context
, 0, ret
, "out of memory");
2120 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2121 hx509_clear_error_string(context
);
2125 hx509_name_free(&cert
->basename
);
2127 ret
= _hx509_name_from_Name(&proxy_issuer
, &cert
->basename
);
2129 hx509_clear_error_string(context
);
2137 ret
= check_basic_constraints(context
, c
, type
,
2138 i
- proxy_cert_depth
- selfsigned_depth
);
2143 * Don't check the trust anchors expiration time since they
2144 * are transported out of band, from RFC3820.
2146 if (i
+ 1 != path
.len
|| CHECK_TA(ctx
)) {
2148 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
2149 if (t
> ctx
->time_now
) {
2150 ret
= HX509_CERT_USED_BEFORE_TIME
;
2151 hx509_clear_error_string(context
);
2154 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notAfter
);
2155 if (t
< ctx
->time_now
) {
2156 ret
= HX509_CERT_USED_AFTER_TIME
;
2157 hx509_clear_error_string(context
);
2162 if (type
== EE_CERT
)
2164 else if (type
== PROXY_CERT
)
2169 * Verify constraints, do this backward so path constraints are
2170 * checked in the right order.
2173 for (ret
= 0, i
= path
.len
- 1; i
>= 0; i
--) {
2177 c
= _hx509_get_cert(path
.val
[i
]);
2179 ret
= certificate_is_self_signed(context
, c
, &selfsigned
);
2183 /* verify name constraints, not for selfsigned and anchor */
2184 if (!selfsigned
|| i
+ 1 != path
.len
) {
2185 ret
= check_name_constraints(context
, &nc
, c
);
2190 ret
= add_name_constraints(context
, c
, i
== 0, &nc
);
2194 /* XXX verify all other silly constraints */
2199 * Verify that no certificates has been revoked.
2202 if (ctx
->revoke_ctx
) {
2205 ret
= hx509_certs_init(context
, "MEMORY:revoke-certs", 0,
2210 for (i
= 0; i
< path
.len
; i
++) {
2211 ret
= hx509_certs_add(context
, certs
, path
.val
[i
]);
2213 hx509_certs_free(&certs
);
2217 ret
= hx509_certs_merge(context
, certs
, pool
);
2219 hx509_certs_free(&certs
);
2223 for (i
= 0; i
< path
.len
- 1; i
++) {
2224 int parent
= (i
< path
.len
- 1) ? i
+ 1 : i
;
2226 ret
= hx509_revoke_verify(context
,
2233 hx509_certs_free(&certs
);
2237 hx509_certs_free(&certs
);
2241 * Verify signatures, do this backward so public key working
2242 * parameter is passed up from the anchor up though the chain.
2245 for (i
= path
.len
- 1; i
>= 0; i
--) {
2249 c
= _hx509_get_cert(path
.val
[i
]);
2251 /* is last in chain (trust anchor) */
2252 if (i
+ 1 == path
.len
) {
2255 signer
= path
.val
[i
];
2257 ret
= certificate_is_self_signed(context
, signer
->data
, &selfsigned
);
2261 /* if trust anchor is not self signed, don't check sig */
2265 /* take next certificate in chain */
2266 signer
= path
.val
[i
+ 1];
2269 /* verify signatureValue */
2270 ret
= _hx509_verify_signature_bitstring(context
,
2272 &c
->signatureAlgorithm
,
2273 &c
->tbsCertificate
._save
,
2274 &c
->signatureValue
);
2276 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
2277 "Failed to verify signature of certificate");
2281 * Verify that the sigature algorithm "best-before" date is
2282 * before the creation date of the certificate, do this for
2283 * trust anchors too, since any trust anchor that is created
2284 * after a algorithm is known to be bad deserved to be invalid.
2286 * Skip the leaf certificate for now...
2289 if (i
!= 0 && (ctx
->flags
& HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK
) == 0) {
2291 _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
2292 ret
= _hx509_signature_best_before(context
,
2293 &c
->signatureAlgorithm
,
2301 hx509_certs_free(&anchors
);
2302 free_Name(&proxy_issuer
);
2303 free_name_constraints(&nc
);
2304 _hx509_path_free(&path
);
2310 * Verify a signature made using the private key of an certificate.
2312 * @param context A hx509 context.
2313 * @param signer the certificate that made the signature.
2314 * @param alg algorthm that was used to sign the data.
2315 * @param data the data that was signed.
2316 * @param sig the sigature to verify.
2318 * @return An hx509 error code, see hx509_get_error_string().
2320 * @ingroup hx509_crypto
2324 hx509_verify_signature(hx509_context context
,
2325 const hx509_cert signer
,
2326 const AlgorithmIdentifier
*alg
,
2327 const heim_octet_string
*data
,
2328 const heim_octet_string
*sig
)
2330 return _hx509_verify_signature(context
, signer
, alg
, data
, sig
);
2334 _hx509_verify_signature_bitstring(hx509_context context
,
2335 const hx509_cert signer
,
2336 const AlgorithmIdentifier
*alg
,
2337 const heim_octet_string
*data
,
2338 const heim_bit_string
*sig
)
2340 heim_octet_string os
;
2342 if (sig
->length
& 7) {
2343 hx509_set_error_string(context
, 0, HX509_CRYPTO_SIG_INVALID_FORMAT
,
2344 "signature not multiple of 8 bits");
2345 return HX509_CRYPTO_SIG_INVALID_FORMAT
;
2348 os
.data
= sig
->data
;
2349 os
.length
= sig
->length
/ 8;
2351 return _hx509_verify_signature(context
, signer
, alg
, data
, &os
);
2357 * Verify that the certificate is allowed to be used for the hostname
2360 * @param context A hx509 context.
2361 * @param cert the certificate to match with
2362 * @param flags Flags to modify the behavior:
2363 * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok
2364 * @param type type of hostname:
2365 * - HX509_HN_HOSTNAME for plain hostname.
2366 * - HX509_HN_DNSSRV for DNS SRV names.
2367 * @param hostname the hostname to check
2368 * @param sa address of the host
2369 * @param sa_size length of address
2371 * @return An hx509 error code, see hx509_get_error_string().
2373 * @ingroup hx509_cert
2377 hx509_verify_hostname(hx509_context context
,
2378 const hx509_cert cert
,
2380 hx509_hostname_type type
,
2381 const char *hostname
,
2382 const struct sockaddr
*sa
,
2383 /* XXX krb5_socklen_t */ int sa_size
)
2389 if (sa
&& sa_size
<= 0)
2392 memset(&san
, 0, sizeof(san
));
2396 ret
= find_extension_subject_alt_name(cert
->data
, &i
, &san
);
2397 if (ret
== HX509_EXTENSION_NOT_FOUND
)
2400 return HX509_PARSING_NAME_FAILED
;
2402 for (j
= 0; j
< san
.len
; j
++) {
2403 switch (san
.val
[j
].element
) {
2404 case choice_GeneralName_dNSName
:
2405 if (strcasecmp(san
.val
[j
].u
.dNSName
, hostname
) == 0) {
2406 free_GeneralNames(&san
);
2414 free_GeneralNames(&san
);
2417 name
= &cert
->data
->tbsCertificate
.subject
;
2419 /* Find first CN= in the name, and try to match the hostname on that */
2420 for (ret
= 0, i
= name
->u
.rdnSequence
.len
- 1; ret
== 0 && i
>= 0; i
--) {
2421 for (j
= 0; ret
== 0 && j
< name
->u
.rdnSequence
.val
[i
].len
; j
++) {
2422 AttributeTypeAndValue
*n
= &name
->u
.rdnSequence
.val
[i
].val
[j
];
2424 if (der_heim_oid_cmp(&n
->type
, &asn1_oid_id_at_commonName
) == 0) {
2425 DirectoryString
*ds
= &n
->value
;
2426 switch (ds
->element
) {
2427 case choice_DirectoryString_printableString
:
2428 if (strcasecmp(ds
->u
.printableString
, hostname
) == 0)
2431 case choice_DirectoryString_ia5String
:
2432 if (strcasecmp(ds
->u
.ia5String
, hostname
) == 0)
2435 case choice_DirectoryString_utf8String
:
2436 if (strcasecmp(ds
->u
.utf8String
, hostname
) == 0)
2441 ret
= HX509_NAME_CONSTRAINT_ERROR
;
2446 if ((flags
& HX509_VHN_F_ALLOW_NO_MATCH
) == 0)
2447 ret
= HX509_NAME_CONSTRAINT_ERROR
;
2453 _hx509_set_cert_attribute(hx509_context context
,
2455 const heim_oid
*oid
,
2456 const heim_octet_string
*attr
)
2458 hx509_cert_attribute a
;
2461 if (hx509_cert_get_attribute(cert
, oid
) != NULL
)
2464 d
= realloc(cert
->attrs
.val
,
2465 sizeof(cert
->attrs
.val
[0]) * (cert
->attrs
.len
+ 1));
2467 hx509_clear_error_string(context
);
2470 cert
->attrs
.val
= d
;
2472 a
= malloc(sizeof(*a
));
2476 der_copy_octet_string(attr
, &a
->data
);
2477 der_copy_oid(oid
, &a
->oid
);
2479 cert
->attrs
.val
[cert
->attrs
.len
] = a
;
2486 * Get an external attribute for the certificate, examples are
2487 * friendly name and id.
2489 * @param cert hx509 certificate object to search
2490 * @param oid an oid to search for.
2492 * @return an hx509_cert_attribute, only valid as long as the
2493 * certificate is referenced.
2495 * @ingroup hx509_cert
2498 hx509_cert_attribute
2499 hx509_cert_get_attribute(hx509_cert cert
, const heim_oid
*oid
)
2502 for (i
= 0; i
< cert
->attrs
.len
; i
++)
2503 if (der_heim_oid_cmp(oid
, &cert
->attrs
.val
[i
]->oid
) == 0)
2504 return cert
->attrs
.val
[i
];
2509 * Set the friendly name on the certificate.
2511 * @param cert The certificate to set the friendly name on
2512 * @param name Friendly name.
2514 * @return An hx509 error code, see hx509_get_error_string().
2516 * @ingroup hx509_cert
2520 hx509_cert_set_friendly_name(hx509_cert cert
, const char *name
)
2522 if (cert
->friendlyname
)
2523 free(cert
->friendlyname
);
2524 cert
->friendlyname
= strdup(name
);
2525 if (cert
->friendlyname
== NULL
)
2531 * Get friendly name of the certificate.
2533 * @param cert cert to get the friendly name from.
2535 * @return an friendly name or NULL if there is. The friendly name is
2536 * only valid as long as the certificate is referenced.
2538 * @ingroup hx509_cert
2542 hx509_cert_get_friendly_name(hx509_cert cert
)
2544 hx509_cert_attribute a
;
2545 PKCS9_friendlyName n
;
2549 if (cert
->friendlyname
)
2550 return cert
->friendlyname
;
2552 a
= hx509_cert_get_attribute(cert
, &asn1_oid_id_pkcs_9_at_friendlyName
);
2556 ret
= hx509_cert_get_subject(cert
, &name
);
2559 ret
= hx509_name_to_string(name
, &cert
->friendlyname
);
2560 hx509_name_free(&name
);
2563 return cert
->friendlyname
;
2566 ret
= decode_PKCS9_friendlyName(a
->data
.data
, a
->data
.length
, &n
, &sz
);
2571 free_PKCS9_friendlyName(&n
);
2575 cert
->friendlyname
= malloc(n
.val
[0].length
+ 1);
2576 if (cert
->friendlyname
== NULL
) {
2577 free_PKCS9_friendlyName(&n
);
2581 for (i
= 0; i
< n
.val
[0].length
; i
++) {
2582 if (n
.val
[0].data
[i
] <= 0xff)
2583 cert
->friendlyname
[i
] = n
.val
[0].data
[i
] & 0xff;
2585 cert
->friendlyname
[i
] = 'X';
2587 cert
->friendlyname
[i
] = '\0';
2588 free_PKCS9_friendlyName(&n
);
2590 return cert
->friendlyname
;
2594 _hx509_query_clear(hx509_query
*q
)
2596 memset(q
, 0, sizeof(*q
));
2600 * Allocate an query controller. Free using hx509_query_free().
2602 * @param context A hx509 context.
2603 * @param q return pointer to a hx509_query.
2605 * @return An hx509 error code, see hx509_get_error_string().
2607 * @ingroup hx509_cert
2611 hx509_query_alloc(hx509_context context
, hx509_query
**q
)
2613 *q
= calloc(1, sizeof(**q
));
2621 * Set match options for the hx509 query controller.
2623 * @param q query controller.
2624 * @param option options to control the query controller.
2626 * @return An hx509 error code, see hx509_get_error_string().
2628 * @ingroup hx509_cert
2632 hx509_query_match_option(hx509_query
*q
, hx509_query_option option
)
2635 case HX509_QUERY_OPTION_PRIVATE_KEY
:
2636 q
->match
|= HX509_QUERY_PRIVATE_KEY
;
2638 case HX509_QUERY_OPTION_KU_ENCIPHERMENT
:
2639 q
->match
|= HX509_QUERY_KU_ENCIPHERMENT
;
2641 case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE
:
2642 q
->match
|= HX509_QUERY_KU_DIGITALSIGNATURE
;
2644 case HX509_QUERY_OPTION_KU_KEYCERTSIGN
:
2645 q
->match
|= HX509_QUERY_KU_KEYCERTSIGN
;
2647 case HX509_QUERY_OPTION_END
:
2654 * Set the issuer and serial number of match in the query
2655 * controller. The function make copies of the isser and serial number.
2657 * @param q a hx509 query controller
2658 * @param issuer issuer to search for
2659 * @param serialNumber the serialNumber of the issuer.
2661 * @return An hx509 error code, see hx509_get_error_string().
2663 * @ingroup hx509_cert
2667 hx509_query_match_issuer_serial(hx509_query
*q
,
2669 const heim_integer
*serialNumber
)
2673 der_free_heim_integer(q
->serial
);
2676 q
->serial
= malloc(sizeof(*q
->serial
));
2677 if (q
->serial
== NULL
)
2679 ret
= der_copy_heim_integer(serialNumber
, q
->serial
);
2685 if (q
->issuer_name
) {
2686 free_Name(q
->issuer_name
);
2687 free(q
->issuer_name
);
2689 q
->issuer_name
= malloc(sizeof(*q
->issuer_name
));
2690 if (q
->issuer_name
== NULL
)
2692 ret
= copy_Name(issuer
, q
->issuer_name
);
2694 free(q
->issuer_name
);
2695 q
->issuer_name
= NULL
;
2698 q
->match
|= HX509_QUERY_MATCH_SERIALNUMBER
|HX509_QUERY_MATCH_ISSUER_NAME
;
2703 * Set the query controller to match on a friendly name
2705 * @param q a hx509 query controller.
2706 * @param name a friendly name to match on
2708 * @return An hx509 error code, see hx509_get_error_string().
2710 * @ingroup hx509_cert
2714 hx509_query_match_friendly_name(hx509_query
*q
, const char *name
)
2716 if (q
->friendlyname
)
2717 free(q
->friendlyname
);
2718 q
->friendlyname
= strdup(name
);
2719 if (q
->friendlyname
== NULL
)
2721 q
->match
|= HX509_QUERY_MATCH_FRIENDLY_NAME
;
2726 * Set the query controller to require an one specific EKU (extended
2727 * key usage). Any previous EKU matching is overwitten. If NULL is
2728 * passed in as the eku, the EKU requirement is reset.
2730 * @param q a hx509 query controller.
2731 * @param eku an EKU to match on.
2733 * @return An hx509 error code, see hx509_get_error_string().
2735 * @ingroup hx509_cert
2739 hx509_query_match_eku(hx509_query
*q
, const heim_oid
*eku
)
2745 der_free_oid(q
->eku
);
2749 q
->match
&= ~HX509_QUERY_MATCH_EKU
;
2752 der_free_oid(q
->eku
);
2754 q
->eku
= calloc(1, sizeof(*q
->eku
));
2758 ret
= der_copy_oid(eku
, q
->eku
);
2764 q
->match
|= HX509_QUERY_MATCH_EKU
;
2770 hx509_query_match_expr(hx509_context context
, hx509_query
*q
, const char *expr
)
2773 _hx509_expr_free(q
->expr
);
2778 q
->match
&= ~HX509_QUERY_MATCH_EXPR
;
2780 q
->expr
= _hx509_expr_parse(expr
);
2782 q
->match
|= HX509_QUERY_MATCH_EXPR
;
2789 * Set the query controller to match using a specific match function.
2791 * @param q a hx509 query controller.
2792 * @param func function to use for matching, if the argument is NULL,
2793 * the match function is removed.
2794 * @param ctx context passed to the function.
2796 * @return An hx509 error code, see hx509_get_error_string().
2798 * @ingroup hx509_cert
2802 hx509_query_match_cmp_func(hx509_query
*q
,
2803 int (*func
)(hx509_context
, hx509_cert
, void *),
2807 q
->match
|= HX509_QUERY_MATCH_FUNCTION
;
2809 q
->match
&= ~HX509_QUERY_MATCH_FUNCTION
;
2811 q
->cmp_func_ctx
= ctx
;
2816 * Free the query controller.
2818 * @param context A hx509 context.
2819 * @param q a pointer to the query controller.
2821 * @ingroup hx509_cert
2825 hx509_query_free(hx509_context context
, hx509_query
*q
)
2831 der_free_heim_integer(q
->serial
);
2834 if (q
->issuer_name
) {
2835 free_Name(q
->issuer_name
);
2836 free(q
->issuer_name
);
2839 der_free_oid(q
->eku
);
2842 if (q
->friendlyname
)
2843 free(q
->friendlyname
);
2845 _hx509_expr_free(q
->expr
);
2847 memset(q
, 0, sizeof(*q
));
2852 _hx509_query_match_cert(hx509_context context
, const hx509_query
*q
, hx509_cert cert
)
2854 Certificate
*c
= _hx509_get_cert(cert
);
2857 _hx509_query_statistic(context
, 1, q
);
2859 if ((q
->match
& HX509_QUERY_FIND_ISSUER_CERT
) &&
2860 _hx509_cert_is_parent_cmp(q
->subject
, c
, 0) != 0)
2863 if ((q
->match
& HX509_QUERY_MATCH_CERTIFICATE
) &&
2864 _hx509_Certificate_cmp(q
->certificate
, c
) != 0)
2867 if ((q
->match
& HX509_QUERY_MATCH_SERIALNUMBER
)
2868 && der_heim_integer_cmp(&c
->tbsCertificate
.serialNumber
, q
->serial
) != 0)
2871 if (q
->match
& HX509_QUERY_MATCH_ISSUER_NAME
) {
2872 ret
= _hx509_name_cmp(&c
->tbsCertificate
.issuer
, q
->issuer_name
, &diff
);
2877 if (q
->match
& HX509_QUERY_MATCH_SUBJECT_NAME
) {
2878 ret
= _hx509_name_cmp(&c
->tbsCertificate
.subject
, q
->subject_name
, &diff
);
2883 if (q
->match
& HX509_QUERY_MATCH_SUBJECT_KEY_ID
) {
2884 SubjectKeyIdentifier si
;
2886 ret
= _hx509_find_extension_subject_key_id(c
, &si
);
2888 if (der_heim_octet_string_cmp(&si
, q
->subject_id
) != 0)
2890 free_SubjectKeyIdentifier(&si
);
2895 if ((q
->match
& HX509_QUERY_MATCH_ISSUER_ID
))
2897 if ((q
->match
& HX509_QUERY_PRIVATE_KEY
) &&
2898 _hx509_cert_private_key(cert
) == NULL
)
2903 if (q
->match
& HX509_QUERY_KU_DIGITALSIGNATURE
)
2905 if (q
->match
& HX509_QUERY_KU_NONREPUDIATION
)
2907 if (q
->match
& HX509_QUERY_KU_ENCIPHERMENT
)
2909 if (q
->match
& HX509_QUERY_KU_DATAENCIPHERMENT
)
2911 if (q
->match
& HX509_QUERY_KU_KEYAGREEMENT
)
2913 if (q
->match
& HX509_QUERY_KU_KEYCERTSIGN
)
2915 if (q
->match
& HX509_QUERY_KU_CRLSIGN
)
2917 if (ku
&& check_key_usage(context
, c
, ku
, TRUE
))
2920 if ((q
->match
& HX509_QUERY_ANCHOR
))
2923 if (q
->match
& HX509_QUERY_MATCH_LOCAL_KEY_ID
) {
2924 hx509_cert_attribute a
;
2926 a
= hx509_cert_get_attribute(cert
, &asn1_oid_id_pkcs_9_at_localKeyId
);
2929 if (der_heim_octet_string_cmp(&a
->data
, q
->local_key_id
) != 0)
2933 if (q
->match
& HX509_QUERY_NO_MATCH_PATH
) {
2936 for (i
= 0; i
< q
->path
->len
; i
++)
2937 if (hx509_cert_cmp(q
->path
->val
[i
], cert
) == 0)
2940 if (q
->match
& HX509_QUERY_MATCH_FRIENDLY_NAME
) {
2941 const char *name
= hx509_cert_get_friendly_name(cert
);
2944 if (strcasecmp(q
->friendlyname
, name
) != 0)
2947 if (q
->match
& HX509_QUERY_MATCH_FUNCTION
) {
2948 ret
= (*q
->cmp_func
)(context
, cert
, q
->cmp_func_ctx
);
2953 if (q
->match
& HX509_QUERY_MATCH_KEY_HASH_SHA1
) {
2954 heim_octet_string os
;
2956 os
.data
= c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.data
;
2958 c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.length
/ 8;
2960 ret
= _hx509_verify_signature(context
,
2962 hx509_signature_sha1(),
2969 if (q
->match
& HX509_QUERY_MATCH_TIME
) {
2971 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
2974 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notAfter
);
2979 /* If an EKU is required, check the cert for it. */
2980 if ((q
->match
& HX509_QUERY_MATCH_EKU
) &&
2981 hx509_cert_check_eku(context
, cert
, q
->eku
, 0))
2984 if ((q
->match
& HX509_QUERY_MATCH_EXPR
)) {
2985 hx509_env env
= NULL
;
2987 ret
= _hx509_cert_to_env(context
, cert
, &env
);
2991 ret
= _hx509_expr_eval(context
, env
, q
->expr
);
2992 hx509_env_free(&env
);
2997 if (q
->match
& ~HX509_QUERY_MASK
)
3004 * Set a statistic file for the query statistics.
3006 * @param context A hx509 context.
3007 * @param fn statistics file name
3009 * @ingroup hx509_cert
3013 hx509_query_statistic_file(hx509_context context
, const char *fn
)
3015 if (context
->querystat
)
3016 free(context
->querystat
);
3017 context
->querystat
= strdup(fn
);
3021 _hx509_query_statistic(hx509_context context
, int type
, const hx509_query
*q
)
3024 if (context
->querystat
== NULL
)
3026 f
= fopen(context
->querystat
, "a");
3030 fprintf(f
, "%d %d\n", type
, q
->match
);
3034 static const char *statname
[] = {
3036 "match serialnumber",
3037 "match issuer name",
3038 "match subject name",
3039 "match subject key id",
3043 "ku digitalsignature",
3046 "ku nonrepudiation",
3048 "ku dataencipherment",
3050 "match certificate",
3051 "match local key id",
3053 "match friendly name",
3055 "match key hash sha1",
3060 unsigned long stats
;
3066 stat_sort(const void *a
, const void *b
)
3068 const struct stat_el
*ae
= a
;
3069 const struct stat_el
*be
= b
;
3070 return be
->stats
- ae
->stats
;
3074 * Unparse the statistics file and print the result on a FILE descriptor.
3076 * @param context A hx509 context.
3077 * @param printtype tyep to print
3078 * @param out the FILE to write the data on.
3080 * @ingroup hx509_cert
3084 hx509_query_unparse_stats(hx509_context context
, int printtype
, FILE *out
)
3088 int type
, mask
, i
, num
;
3089 unsigned long multiqueries
= 0, totalqueries
= 0;
3090 struct stat_el stats
[32];
3092 if (context
->querystat
== NULL
)
3094 f
= fopen(context
->querystat
, "r");
3096 fprintf(out
, "No statistic file %s: %s.\n",
3097 context
->querystat
, strerror(errno
));
3102 for (i
= 0; i
< sizeof(stats
)/sizeof(stats
[0]); i
++) {
3107 while (fscanf(f
, "%d %d\n", &type
, &mask
) == 2) {
3108 if (type
!= printtype
)
3111 while (mask
&& i
< sizeof(stats
)/sizeof(stats
[0])) {
3125 qsort(stats
, sizeof(stats
)/sizeof(stats
[0]), sizeof(stats
[0]), stat_sort
);
3129 errx(1, "out of memory");
3131 rtbl_set_separator (t
, " ");
3133 rtbl_add_column_by_id (t
, 0, "Name", 0);
3134 rtbl_add_column_by_id (t
, 1, "Counter", 0);
3137 for (i
= 0; i
< sizeof(stats
)/sizeof(stats
[0]); i
++) {
3140 if (stats
[i
].index
< sizeof(statname
)/sizeof(statname
[0]))
3141 rtbl_add_column_entry_by_id (t
, 0, statname
[stats
[i
].index
]);
3143 snprintf(str
, sizeof(str
), "%d", stats
[i
].index
);
3144 rtbl_add_column_entry_by_id (t
, 0, str
);
3146 snprintf(str
, sizeof(str
), "%lu", stats
[i
].stats
);
3147 rtbl_add_column_entry_by_id (t
, 1, str
);
3150 rtbl_format(t
, out
);
3153 fprintf(out
, "\nQueries: multi %lu total %lu\n",
3154 multiqueries
, totalqueries
);
3158 * Check the extended key usage on the hx509 certificate.
3160 * @param context A hx509 context.
3161 * @param cert A hx509 context.
3162 * @param eku the EKU to check for
3163 * @param allow_any_eku if the any EKU is set, allow that to be a
3166 * @return An hx509 error code, see hx509_get_error_string().
3168 * @ingroup hx509_cert
3172 hx509_cert_check_eku(hx509_context context
, hx509_cert cert
,
3173 const heim_oid
*eku
, int allow_any_eku
)
3178 ret
= find_extension_eku(_hx509_get_cert(cert
), &e
);
3180 hx509_clear_error_string(context
);
3184 for (i
= 0; i
< e
.len
; i
++) {
3185 if (der_heim_oid_cmp(eku
, &e
.val
[i
]) == 0) {
3186 free_ExtKeyUsage(&e
);
3189 if (allow_any_eku
) {
3191 if (der_heim_oid_cmp(id_any_eku
, &e
.val
[i
]) == 0) {
3192 free_ExtKeyUsage(&e
);
3198 free_ExtKeyUsage(&e
);
3199 hx509_clear_error_string(context
);
3200 return HX509_CERTIFICATE_MISSING_EKU
;
3204 _hx509_cert_get_keyusage(hx509_context context
,
3213 memset(ku
, 0, sizeof(*ku
));
3215 cert
= _hx509_get_cert(c
);
3217 if (_hx509_cert_get_version(cert
) < 3)
3220 e
= find_extension(cert
, &asn1_oid_id_x509_ce_keyUsage
, &i
);
3222 return HX509_KU_CERT_MISSING
;
3224 ret
= decode_KeyUsage(e
->extnValue
.data
, e
->extnValue
.length
, ku
, &size
);
3231 _hx509_cert_get_eku(hx509_context context
,
3237 memset(e
, 0, sizeof(*e
));
3239 ret
= find_extension_eku(_hx509_get_cert(cert
), e
);
3240 if (ret
&& ret
!= HX509_EXTENSION_NOT_FOUND
) {
3241 hx509_clear_error_string(context
);
3248 * Encodes the hx509 certificate as a DER encode binary.
3250 * @param context A hx509 context.
3251 * @param c the certificate to encode.
3252 * @param os the encode certificate, set to NULL, 0 on case of
3253 * error. Free the returned structure with hx509_xfree().
3255 * @return An hx509 error code, see hx509_get_error_string().
3257 * @ingroup hx509_cert
3261 hx509_cert_binary(hx509_context context
, hx509_cert c
, heim_octet_string
*os
)
3269 ASN1_MALLOC_ENCODE(Certificate
, os
->data
, os
->length
,
3270 _hx509_get_cert(c
), &size
, ret
);
3276 if (os
->length
!= size
)
3277 _hx509_abort("internal ASN.1 encoder error");
3283 * Last to avoid lost __attribute__s due to #undef.
3286 #undef __attribute__
3287 #define __attribute__(X)
3290 _hx509_abort(const char *fmt
, ...)
3291 __attribute__ ((noreturn
, format (printf
, 1, 2)))
3303 * Free a data element allocated in the library.
3305 * @param ptr data to be freed.
3307 * @ingroup hx509_misc
3311 hx509_xfree(void *ptr
)
3321 _hx509_cert_to_env(hx509_context context
, hx509_cert cert
, hx509_env
*env
)
3327 hx509_env envcert
= NULL
;
3332 asprintf(&buf
, "%d", _hx509_cert_get_version(_hx509_get_cert(cert
)));
3333 ret
= hx509_env_add(context
, &envcert
, "version", buf
);
3339 ret
= hx509_cert_get_subject(cert
, &name
);
3343 ret
= hx509_name_to_string(name
, &buf
);
3345 hx509_name_free(&name
);
3349 ret
= hx509_env_add(context
, &envcert
, "subject", buf
);
3350 hx509_name_free(&name
);
3355 ret
= hx509_cert_get_issuer(cert
, &name
);
3359 ret
= hx509_name_to_string(name
, &buf
);
3360 hx509_name_free(&name
);
3364 ret
= hx509_env_add(context
, &envcert
, "issuer", buf
);
3371 ret
= _hx509_cert_get_eku(context
, cert
, &eku
);
3372 if (ret
== HX509_EXTENSION_NOT_FOUND
)
3378 hx509_env enveku
= NULL
;
3380 for (i
= 0; i
< eku
.len
; i
++) {
3382 ret
= der_print_heim_oid(&eku
.val
[i
], '.', &buf
);
3384 free_ExtKeyUsage(&eku
);
3385 hx509_env_free(&enveku
);
3388 ret
= hx509_env_add(context
, &enveku
, buf
, "oid-name-here");
3391 free_ExtKeyUsage(&eku
);
3392 hx509_env_free(&enveku
);
3396 free_ExtKeyUsage(&eku
);
3398 ret
= hx509_env_add_binding(context
, &envcert
, "eku", enveku
);
3400 hx509_env_free(&enveku
);
3406 Certificate
*c
= _hx509_get_cert(cert
);
3407 heim_octet_string os
, sig
;
3408 hx509_env envhash
= NULL
;
3410 os
.data
= c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.data
;
3412 c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.length
/ 8;
3414 ret
= _hx509_create_signature(context
,
3416 hx509_signature_sha1(),
3423 ret
= hex_encode(sig
.data
, sig
.length
, &buf
);
3424 der_free_octet_string(&sig
);
3427 hx509_set_error_string(context
, 0, ret
,
3432 ret
= hx509_env_add(context
, &envhash
, "sha1", buf
);
3437 ret
= hx509_env_add_binding(context
, &envcert
, "hash", envhash
);
3439 hx509_env_free(&envhash
);
3444 ret
= hx509_env_add_binding(context
, env
, "certificate", envcert
);
3451 hx509_env_free(&envcert
);
3456 * Print a simple representation of a certificate
3458 * @param context A hx509 context, can be NULL
3459 * @param cert certificate to print
3460 * @param out the stdio output stream, if NULL, stdout is used
3462 * @return An hx509 error code
3464 * @ingroup hx509_cert
3468 hx509_print_cert(hx509_context context
, hx509_cert cert
, FILE *out
)
3477 ret
= hx509_cert_get_issuer(cert
, &name
);
3480 hx509_name_to_string(name
, &str
);
3481 hx509_name_free(&name
);
3482 fprintf(out
, " issuer: \"%s\"\n", str
);
3485 ret
= hx509_cert_get_subject(cert
, &name
);
3488 hx509_name_to_string(name
, &str
);
3489 hx509_name_free(&name
);
3490 fprintf(out
, " subject: \"%s\"\n", str
);
3494 heim_integer serialNumber
;
3496 ret
= hx509_cert_get_serialnumber(cert
, &serialNumber
);
3499 ret
= der_print_hex_heim_integer(&serialNumber
, &str
);
3502 der_free_heim_integer(&serialNumber
);
3503 fprintf(out
, " serial: %s\n", str
);
3507 printf(" keyusage: ");
3508 ret
= hx509_cert_keyusage_print(context
, cert
, &str
);
3510 fprintf(out
, "%s\n", str
);