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
36 #include "crypto-headers.h"
40 * @page page_cert The basic certificate
42 * The basic hx509 cerificate object in hx509 is hx509_cert. The
43 * hx509_cert object is representing one X509/PKIX certificate and
44 * associated attributes; like private key, friendly name, etc.
46 * A hx509_cert object is usully found via the keyset interfaces (@ref
47 * page_keyset), but its also possible to create a certificate
48 * directly from a parsed object with hx509_cert_init() and
49 * hx509_cert_init_data().
51 * See the library functions here: @ref hx509_cert
54 struct hx509_verify_ctx_data
{
55 hx509_certs trust_anchors
;
57 #define HX509_VERIFY_CTX_F_TIME_SET 1
58 #define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE 2
59 #define HX509_VERIFY_CTX_F_REQUIRE_RFC3280 4
60 #define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS 8
61 #define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS 16
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 (OSCP, 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
)
202 _hx509_print_cert_subject(hx509_cert cert
)
208 ret
= hx509_cert_get_subject(cert
, &name
);
212 ret
= hx509_name_to_string(name
, &subject_name
);
213 hx509_name_free(&name
);
217 printf("name: %s\n", subject_name
);
228 _hx509_cert_get_version(const Certificate
*t
)
230 return t
->tbsCertificate
.version
? *t
->tbsCertificate
.version
+ 1 : 1;
234 * Allocate and init an hx509 certificate object from the decoded
237 * @param context A hx509 context.
241 * @return Returns an hx509 error code.
243 * @ingroup hx509_cert
247 hx509_cert_init(hx509_context context
, const Certificate
*c
, hx509_cert
*cert
)
251 *cert
= malloc(sizeof(**cert
));
255 (*cert
)->friendlyname
= NULL
;
256 (*cert
)->attrs
.len
= 0;
257 (*cert
)->attrs
.val
= NULL
;
258 (*cert
)->private_key
= NULL
;
259 (*cert
)->basename
= NULL
;
260 (*cert
)->release
= NULL
;
263 (*cert
)->data
= calloc(1, sizeof(*(*cert
)->data
));
264 if ((*cert
)->data
== NULL
) {
268 ret
= copy_Certificate(c
, (*cert
)->data
);
278 * Just like hx509_cert_init(), but instead of a decode certificate
279 * takes an pointer and length to a memory region that contains a
280 * DER/BER encoded certificate.
282 * If the memory region doesn't contain just the certificate and
283 * nothing more the function will fail with
284 * HX509_EXTRA_DATA_AFTER_STRUCTURE.
286 * @param context A hx509 context.
287 * @param ptr pointer to memory region containing encoded certificate.
288 * @param len length of memory region.
289 * @param cert a return pointer to a hx509 certificate object, will
290 * contain NULL on error.
292 * @return An hx509 error code, see hx509_get_error_string().
294 * @ingroup hx509_cert
298 hx509_cert_init_data(hx509_context context
,
307 ret
= decode_Certificate(ptr
, len
, &t
, &size
);
309 hx509_set_error_string(context
, 0, ret
, "Failed to decode certificate");
313 hx509_set_error_string(context
, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE
,
314 "Extra data after certificate");
315 return HX509_EXTRA_DATA_AFTER_STRUCTURE
;
318 ret
= hx509_cert_init(context
, &t
, cert
);
319 free_Certificate(&t
);
324 _hx509_cert_set_release(hx509_cert cert
,
325 _hx509_cert_release_func release
,
328 cert
->release
= release
;
333 /* Doesn't make a copy of `private_key'. */
336 _hx509_cert_assign_key(hx509_cert cert
, hx509_private_key private_key
)
338 if (cert
->private_key
)
339 _hx509_private_key_free(&cert
->private_key
);
340 cert
->private_key
= _hx509_private_key_ref(private_key
);
345 * Free reference to the hx509 certificate object, if the refcounter
346 * reaches 0, the object if freed. Its allowed to pass in NULL.
348 * @param cert the cert to free.
350 * @ingroup hx509_cert
354 hx509_cert_free(hx509_cert cert
)
362 _hx509_abort("cert refcount <= 0 on free");
367 (cert
->release
)(cert
, cert
->ctx
);
369 if (cert
->private_key
)
370 _hx509_private_key_free(&cert
->private_key
);
372 free_Certificate(cert
->data
);
375 for (i
= 0; i
< cert
->attrs
.len
; i
++) {
376 der_free_octet_string(&cert
->attrs
.val
[i
]->data
);
377 der_free_oid(&cert
->attrs
.val
[i
]->oid
);
378 free(cert
->attrs
.val
[i
]);
380 free(cert
->attrs
.val
);
381 free(cert
->friendlyname
);
383 hx509_name_free(&cert
->basename
);
384 memset(cert
, 0, sizeof(cert
));
389 * Add a reference to a hx509 certificate object.
391 * @param cert a pointer to an hx509 certificate object.
393 * @return the same object as is passed in.
395 * @ingroup hx509_cert
399 hx509_cert_ref(hx509_cert cert
)
404 _hx509_abort("cert refcount <= 0");
407 _hx509_abort("cert refcount == 0");
412 * Allocate an verification context that is used fo control the
413 * verification process.
415 * @param context A hx509 context.
416 * @param ctx returns a pointer to a hx509_verify_ctx object.
418 * @return An hx509 error code, see hx509_get_error_string().
420 * @ingroup hx509_verify
424 hx509_verify_init_ctx(hx509_context context
, hx509_verify_ctx
*ctx
)
428 c
= calloc(1, sizeof(*c
));
432 c
->max_depth
= HX509_VERIFY_MAX_DEPTH
;
440 * Free an hx509 verification context.
442 * @param ctx the context to be freed.
444 * @ingroup hx509_verify
448 hx509_verify_destroy_ctx(hx509_verify_ctx ctx
)
451 hx509_certs_free(&ctx
->trust_anchors
);
452 hx509_revoke_free(&ctx
->revoke_ctx
);
453 memset(ctx
, 0, sizeof(*ctx
));
459 * Set the trust anchors in the verification context, makes an
460 * reference to the keyset, so the consumer can free the keyset
461 * independent of the destruction of the verification context (ctx).
463 * @param ctx a verification context
464 * @param set a keyset containing the trust anchors.
466 * @ingroup hx509_verify
470 hx509_verify_attach_anchors(hx509_verify_ctx ctx
, hx509_certs set
)
472 ctx
->trust_anchors
= _hx509_certs_ref(set
);
476 * Attach an revocation context to the verfication context, , makes an
477 * reference to the revoke context, so the consumer can free the
478 * revoke context independent of the destruction of the verification
479 * context. If there is no revoke context, the verification process is
480 * NOT going to check any verification status.
482 * @param ctx a verification context.
483 * @param revoke_ctx a revoke context.
485 * @ingroup hx509_verify
489 hx509_verify_attach_revoke(hx509_verify_ctx ctx
, hx509_revoke_ctx revoke_ctx
)
492 hx509_revoke_free(&ctx
->revoke_ctx
);
493 ctx
->revoke_ctx
= _hx509_revoke_ref(revoke_ctx
);
497 * Set the clock time the the verification process is going to
498 * use. Used to check certificate in the past and future time. If not
499 * set the current time will be used.
501 * @param ctx a verification context.
502 * @param t the time the verifiation is using.
505 * @ingroup hx509_verify
509 hx509_verify_set_time(hx509_verify_ctx ctx
, time_t t
)
511 ctx
->flags
|= HX509_VERIFY_CTX_F_TIME_SET
;
516 * Set the maximum depth of the certificate chain that the path
517 * builder is going to try.
519 * @param ctx a verification context
520 * @param max_depth maxium depth of the certificate chain, include
523 * @ingroup hx509_verify
527 hx509_verify_set_max_depth(hx509_verify_ctx ctx
, unsigned int max_depth
)
529 ctx
->max_depth
= max_depth
;
533 * Allow or deny the use of proxy certificates
535 * @param ctx a verification context
536 * @param boolean if non zero, allow proxy certificates.
538 * @ingroup hx509_verify
542 hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx
, int boolean
)
545 ctx
->flags
|= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
;
547 ctx
->flags
&= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
;
551 * Select strict RFC3280 verification of certificiates. This means
552 * checking key usage on CA certificates, this will make version 1
553 * certificiates unuseable.
555 * @param ctx a verification context
556 * @param boolean if non zero, use strict verification.
558 * @ingroup hx509_verify
562 hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx
, int boolean
)
565 ctx
->flags
|= HX509_VERIFY_CTX_F_REQUIRE_RFC3280
;
567 ctx
->flags
&= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280
;
571 * Allow using the operating system builtin trust anchors if no other
572 * trust anchors are configured.
574 * @param ctx a verification context
575 * @param boolean if non zero, useing the operating systems builtin
579 * @return An hx509 error code, see hx509_get_error_string().
581 * @ingroup hx509_cert
585 hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx
, int boolean
)
588 ctx
->flags
&= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS
;
590 ctx
->flags
|= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS
;
593 static const Extension
*
594 find_extension(const Certificate
*cert
, const heim_oid
*oid
, int *idx
)
596 const TBSCertificate
*c
= &cert
->tbsCertificate
;
598 if (c
->version
== NULL
|| *c
->version
< 2 || c
->extensions
== NULL
)
601 for (;*idx
< c
->extensions
->len
; (*idx
)++) {
602 if (der_heim_oid_cmp(&c
->extensions
->val
[*idx
].extnID
, oid
) == 0)
603 return &c
->extensions
->val
[(*idx
)++];
609 find_extension_auth_key_id(const Certificate
*subject
,
610 AuthorityKeyIdentifier
*ai
)
616 memset(ai
, 0, sizeof(*ai
));
618 e
= find_extension(subject
, oid_id_x509_ce_authorityKeyIdentifier(), &i
);
620 return HX509_EXTENSION_NOT_FOUND
;
622 return decode_AuthorityKeyIdentifier(e
->extnValue
.data
,
628 _hx509_find_extension_subject_key_id(const Certificate
*issuer
,
629 SubjectKeyIdentifier
*si
)
635 memset(si
, 0, sizeof(*si
));
637 e
= find_extension(issuer
, oid_id_x509_ce_subjectKeyIdentifier(), &i
);
639 return HX509_EXTENSION_NOT_FOUND
;
641 return decode_SubjectKeyIdentifier(e
->extnValue
.data
,
647 find_extension_name_constraints(const Certificate
*subject
,
654 memset(nc
, 0, sizeof(*nc
));
656 e
= find_extension(subject
, oid_id_x509_ce_nameConstraints(), &i
);
658 return HX509_EXTENSION_NOT_FOUND
;
660 return decode_NameConstraints(e
->extnValue
.data
,
666 find_extension_subject_alt_name(const Certificate
*cert
, int *i
,
672 memset(sa
, 0, sizeof(*sa
));
674 e
= find_extension(cert
, oid_id_x509_ce_subjectAltName(), i
);
676 return HX509_EXTENSION_NOT_FOUND
;
678 return decode_GeneralNames(e
->extnValue
.data
,
684 find_extension_eku(const Certificate
*cert
, ExtKeyUsage
*eku
)
690 memset(eku
, 0, sizeof(*eku
));
692 e
= find_extension(cert
, oid_id_x509_ce_extKeyUsage(), &i
);
694 return HX509_EXTENSION_NOT_FOUND
;
696 return decode_ExtKeyUsage(e
->extnValue
.data
,
702 add_to_list(hx509_octet_string_list
*list
, const heim_octet_string
*entry
)
707 p
= realloc(list
->val
, (list
->len
+ 1) * sizeof(list
->val
[0]));
711 ret
= der_copy_octet_string(entry
, &list
->val
[list
->len
]);
719 * Free a list of octet strings returned by another hx509 library
722 * @param list list to be freed.
724 * @ingroup hx509_misc
728 hx509_free_octet_string_list(hx509_octet_string_list
*list
)
731 for (i
= 0; i
< list
->len
; i
++)
732 der_free_octet_string(&list
->val
[i
]);
739 * Return a list of subjectAltNames specified by oid in the
740 * certificate. On error the
742 * The returned list of octet string should be freed with
743 * hx509_free_octet_string_list().
745 * @param context A hx509 context.
746 * @param cert a hx509 certificate object.
747 * @param oid an oid to for SubjectAltName.
748 * @param list list of matching SubjectAltName.
750 * @return An hx509 error code, see hx509_get_error_string().
752 * @ingroup hx509_cert
756 hx509_cert_find_subjectAltName_otherName(hx509_context context
,
759 hx509_octet_string_list
*list
)
769 ret
= find_extension_subject_alt_name(_hx509_get_cert(cert
), &i
, &sa
);
771 if (ret
== HX509_EXTENSION_NOT_FOUND
) {
774 } else if (ret
!= 0) {
775 hx509_set_error_string(context
, 0, ret
, "Error searching for SAN");
776 hx509_free_octet_string_list(list
);
780 for (j
= 0; j
< sa
.len
; j
++) {
781 if (sa
.val
[j
].element
== choice_GeneralName_otherName
&&
782 der_heim_oid_cmp(&sa
.val
[j
].u
.otherName
.type_id
, oid
) == 0)
784 ret
= add_to_list(list
, &sa
.val
[j
].u
.otherName
.value
);
786 hx509_set_error_string(context
, 0, ret
,
787 "Error adding an exra SAN to "
789 hx509_free_octet_string_list(list
);
790 free_GeneralNames(&sa
);
795 free_GeneralNames(&sa
);
802 check_key_usage(hx509_context context
, const Certificate
*cert
,
803 unsigned flags
, int req_present
)
811 if (_hx509_cert_get_version(cert
) < 3)
814 e
= find_extension(cert
, oid_id_x509_ce_keyUsage(), &i
);
817 hx509_set_error_string(context
, 0, HX509_KU_CERT_MISSING
,
818 "Required extension key "
819 "usage missing from certifiate");
820 return HX509_KU_CERT_MISSING
;
825 ret
= decode_KeyUsage(e
->extnValue
.data
, e
->extnValue
.length
, &ku
, &size
);
828 ku_flags
= KeyUsage2int(ku
);
829 if ((ku_flags
& flags
) != flags
) {
830 unsigned missing
= (~ku_flags
) & flags
;
831 char buf
[256], *name
;
833 unparse_flags(missing
, asn1_KeyUsage_units(), buf
, sizeof(buf
));
834 _hx509_unparse_Name(&cert
->tbsCertificate
.subject
, &name
);
835 hx509_set_error_string(context
, 0, HX509_KU_CERT_MISSING
,
836 "Key usage %s required but missing "
837 "from certifiate %s", buf
, name
);
839 return HX509_KU_CERT_MISSING
;
845 * Return 0 on matching key usage 'flags' for 'cert', otherwise return
846 * an error code. If 'req_present' the existance is required of the
847 * KeyUsage extension.
851 _hx509_check_key_usage(hx509_context context
, hx509_cert cert
,
852 unsigned flags
, int req_present
)
854 return check_key_usage(context
, _hx509_get_cert(cert
), flags
, req_present
);
857 enum certtype
{ PROXY_CERT
, EE_CERT
, CA_CERT
};
860 check_basic_constraints(hx509_context context
, const Certificate
*cert
,
861 enum certtype type
, int depth
)
868 if (_hx509_cert_get_version(cert
) < 3)
871 e
= find_extension(cert
, oid_id_x509_ce_basicConstraints(), &i
);
879 ret
= _hx509_unparse_Name(&cert
->tbsCertificate
.subject
, &name
);
881 hx509_set_error_string(context
, 0, HX509_EXTENSION_NOT_FOUND
,
882 "basicConstraints missing from "
883 "CA certifiacte %s", name
);
885 return HX509_EXTENSION_NOT_FOUND
;
890 ret
= decode_BasicConstraints(e
->extnValue
.data
,
891 e
->extnValue
.length
, &bc
,
897 if (bc
.cA
!= NULL
&& *bc
.cA
)
898 ret
= HX509_PARENT_IS_CA
;
904 if (bc
.cA
== NULL
|| !*bc
.cA
)
905 ret
= HX509_PARENT_NOT_CA
;
906 else if (bc
.pathLenConstraint
)
907 if (depth
- 1 > *bc
.pathLenConstraint
)
908 ret
= HX509_CA_PATH_TOO_DEEP
;
911 free_BasicConstraints(&bc
);
916 _hx509_cert_is_parent_cmp(const Certificate
*subject
,
917 const Certificate
*issuer
,
918 int allow_self_signed
)
921 AuthorityKeyIdentifier ai
;
922 SubjectKeyIdentifier si
;
925 diff
= _hx509_name_cmp(&issuer
->tbsCertificate
.subject
,
926 &subject
->tbsCertificate
.issuer
);
930 memset(&ai
, 0, sizeof(ai
));
931 memset(&si
, 0, sizeof(si
));
934 * Try to find AuthorityKeyIdentifier, if it's not present in the
935 * subject certificate nor the parent.
938 ret_ai
= find_extension_auth_key_id(subject
, &ai
);
939 if (ret_ai
&& ret_ai
!= HX509_EXTENSION_NOT_FOUND
)
941 ret_si
= _hx509_find_extension_subject_key_id(issuer
, &si
);
942 if (ret_si
&& ret_si
!= HX509_EXTENSION_NOT_FOUND
)
945 if (ret_si
&& ret_ai
)
950 if (allow_self_signed
) {
953 } else if (ai
.keyIdentifier
) {
959 if (ai
.keyIdentifier
== NULL
) {
962 if (ai
.authorityCertIssuer
== NULL
)
964 if (ai
.authorityCertSerialNumber
== NULL
)
967 diff
= der_heim_integer_cmp(ai
.authorityCertSerialNumber
,
968 &issuer
->tbsCertificate
.serialNumber
);
971 if (ai
.authorityCertIssuer
->len
!= 1)
973 if (ai
.authorityCertIssuer
->val
[0].element
!= choice_GeneralName_directoryName
)
977 ai
.authorityCertIssuer
->val
[0].u
.directoryName
.element
;
979 ai
.authorityCertIssuer
->val
[0].u
.directoryName
.u
.rdnSequence
;
981 diff
= _hx509_name_cmp(&issuer
->tbsCertificate
.subject
,
987 diff
= der_heim_octet_string_cmp(ai
.keyIdentifier
, &si
);
992 free_AuthorityKeyIdentifier(&ai
);
993 free_SubjectKeyIdentifier(&si
);
998 certificate_is_anchor(hx509_context context
,
999 hx509_certs trust_anchors
,
1000 const hx509_cert cert
)
1006 if (trust_anchors
== NULL
)
1009 _hx509_query_clear(&q
);
1011 q
.match
= HX509_QUERY_MATCH_CERTIFICATE
;
1012 q
.certificate
= _hx509_get_cert(cert
);
1014 ret
= hx509_certs_find(context
, trust_anchors
, &q
, &c
);
1021 certificate_is_self_signed(const Certificate
*cert
)
1023 return _hx509_name_cmp(&cert
->tbsCertificate
.subject
,
1024 &cert
->tbsCertificate
.issuer
) == 0;
1028 * The subjectName is "null" when it's empty set of relative DBs.
1032 subject_null_p(const Certificate
*c
)
1034 return c
->tbsCertificate
.subject
.u
.rdnSequence
.len
== 0;
1039 find_parent(hx509_context context
,
1041 hx509_certs trust_anchors
,
1047 AuthorityKeyIdentifier ai
;
1052 memset(&ai
, 0, sizeof(ai
));
1054 _hx509_query_clear(&q
);
1056 if (!subject_null_p(current
->data
)) {
1057 q
.match
|= HX509_QUERY_FIND_ISSUER_CERT
;
1058 q
.subject
= _hx509_get_cert(current
);
1060 ret
= find_extension_auth_key_id(current
->data
, &ai
);
1062 hx509_set_error_string(context
, 0, HX509_CERTIFICATE_MALFORMED
,
1063 "Subjectless certificate missing AuthKeyID");
1064 return HX509_CERTIFICATE_MALFORMED
;
1067 if (ai
.keyIdentifier
== NULL
) {
1068 free_AuthorityKeyIdentifier(&ai
);
1069 hx509_set_error_string(context
, 0, HX509_CERTIFICATE_MALFORMED
,
1070 "Subjectless certificate missing keyIdentifier "
1071 "inside AuthKeyID");
1072 return HX509_CERTIFICATE_MALFORMED
;
1075 q
.subject_id
= ai
.keyIdentifier
;
1076 q
.match
= HX509_QUERY_MATCH_SUBJECT_KEY_ID
;
1080 q
.match
|= HX509_QUERY_NO_MATCH_PATH
;
1083 q
.timenow
= time_now
;
1084 q
.match
|= HX509_QUERY_MATCH_TIME
;
1086 ret
= hx509_certs_find(context
, pool
, &q
, parent
);
1088 free_AuthorityKeyIdentifier(&ai
);
1091 q
.match
&= ~HX509_QUERY_MATCH_TIME
;
1094 if (trust_anchors
) {
1095 ret
= hx509_certs_find(context
, trust_anchors
, &q
, parent
);
1097 free_AuthorityKeyIdentifier(&ai
);
1101 free_AuthorityKeyIdentifier(&ai
);
1107 ret
= hx509_cert_get_subject(current
, &name
);
1109 hx509_clear_error_string(context
);
1110 return HX509_ISSUER_NOT_FOUND
;
1112 ret
= hx509_name_to_string(name
, &str
);
1113 hx509_name_free(&name
);
1115 hx509_clear_error_string(context
);
1116 return HX509_ISSUER_NOT_FOUND
;
1119 hx509_set_error_string(context
, 0, HX509_ISSUER_NOT_FOUND
,
1120 "Failed to find issuer for "
1121 "certificate with subject: '%s'", str
);
1124 return HX509_ISSUER_NOT_FOUND
;
1132 is_proxy_cert(hx509_context context
,
1133 const Certificate
*cert
,
1134 ProxyCertInfo
*rinfo
)
1142 memset(rinfo
, 0, sizeof(*rinfo
));
1144 e
= find_extension(cert
, oid_id_pkix_pe_proxyCertInfo(), &i
);
1146 hx509_clear_error_string(context
);
1147 return HX509_EXTENSION_NOT_FOUND
;
1150 ret
= decode_ProxyCertInfo(e
->extnValue
.data
,
1151 e
->extnValue
.length
,
1155 hx509_clear_error_string(context
);
1158 if (size
!= e
->extnValue
.length
) {
1159 free_ProxyCertInfo(&info
);
1160 hx509_clear_error_string(context
);
1161 return HX509_EXTRA_DATA_AFTER_STRUCTURE
;
1164 free_ProxyCertInfo(&info
);
1172 * Path operations are like MEMORY based keyset, but with exposed
1173 * internal so we can do easy searches.
1177 _hx509_path_append(hx509_context context
, hx509_path
*path
, hx509_cert cert
)
1180 val
= realloc(path
->val
, (path
->len
+ 1) * sizeof(path
->val
[0]));
1182 hx509_set_error_string(context
, 0, ENOMEM
, "out of memory");
1187 path
->val
[path
->len
] = hx509_cert_ref(cert
);
1194 _hx509_path_free(hx509_path
*path
)
1198 for (i
= 0; i
< path
->len
; i
++)
1199 hx509_cert_free(path
->val
[i
]);
1206 * Find path by looking up issuer for the top certificate and continue
1207 * until an anchor certificate is found or max limit is found. A
1208 * certificate never included twice in the path.
1210 * If the trust anchors are not given, calculate optimistic path, just
1211 * follow the chain upward until we no longer find a parent or we hit
1212 * the max path limit. In this case, a failure will always be returned
1213 * depending on what error condition is hit first.
1215 * The path includes a path from the top certificate to the anchor
1218 * The caller needs to free `path´ both on successful built path and
1223 _hx509_calculate_path(hx509_context context
,
1226 hx509_certs anchors
,
1227 unsigned int max_depth
,
1232 hx509_cert parent
, current
;
1236 max_depth
= HX509_VERIFY_MAX_DEPTH
;
1238 ret
= _hx509_path_append(context
, path
, cert
);
1242 current
= hx509_cert_ref(cert
);
1244 while (!certificate_is_anchor(context
, anchors
, current
)) {
1246 ret
= find_parent(context
, time_now
, anchors
, path
,
1247 pool
, current
, &parent
);
1248 hx509_cert_free(current
);
1252 ret
= _hx509_path_append(context
, path
, parent
);
1257 if (path
->len
> max_depth
) {
1258 hx509_cert_free(current
);
1259 hx509_set_error_string(context
, 0, HX509_PATH_TOO_LONG
,
1260 "Path too long while bulding "
1261 "certificate chain");
1262 return HX509_PATH_TOO_LONG
;
1266 if ((flags
& HX509_CALCULATE_PATH_NO_ANCHOR
) &&
1268 certificate_is_anchor(context
, anchors
, path
->val
[path
->len
- 1]))
1270 hx509_cert_free(path
->val
[path
->len
- 1]);
1274 hx509_cert_free(current
);
1279 AlgorithmIdentifier_cmp(const AlgorithmIdentifier
*p
,
1280 const AlgorithmIdentifier
*q
)
1283 diff
= der_heim_oid_cmp(&p
->algorithm
, &q
->algorithm
);
1286 if (p
->parameters
) {
1288 return heim_any_cmp(p
->parameters
,
1301 _hx509_Certificate_cmp(const Certificate
*p
, const Certificate
*q
)
1304 diff
= der_heim_bit_string_cmp(&p
->signatureValue
, &q
->signatureValue
);
1307 diff
= AlgorithmIdentifier_cmp(&p
->signatureAlgorithm
,
1308 &q
->signatureAlgorithm
);
1311 diff
= der_heim_octet_string_cmp(&p
->tbsCertificate
._save
,
1312 &q
->tbsCertificate
._save
);
1317 * Compare to hx509 certificate object, useful for sorting.
1319 * @param p a hx509 certificate object.
1320 * @param q a hx509 certificate object.
1322 * @return 0 the objects are the same, returns > 0 is p is "larger"
1323 * then q, < 0 if p is "smaller" then q.
1325 * @ingroup hx509_cert
1329 hx509_cert_cmp(hx509_cert p
, hx509_cert q
)
1331 return _hx509_Certificate_cmp(p
->data
, q
->data
);
1335 * Return the name of the issuer of the hx509 certificate.
1337 * @param p a hx509 certificate object.
1338 * @param name a pointer to a hx509 name, should be freed by
1339 * hx509_name_free().
1341 * @return An hx509 error code, see hx509_get_error_string().
1343 * @ingroup hx509_cert
1347 hx509_cert_get_issuer(hx509_cert p
, hx509_name
*name
)
1349 return _hx509_name_from_Name(&p
->data
->tbsCertificate
.issuer
, name
);
1353 * Return the name of the subject of the hx509 certificate.
1355 * @param p a hx509 certificate object.
1356 * @param name a pointer to a hx509 name, should be freed by
1357 * hx509_name_free(). See also hx509_cert_get_base_subject().
1359 * @return An hx509 error code, see hx509_get_error_string().
1361 * @ingroup hx509_cert
1365 hx509_cert_get_subject(hx509_cert p
, hx509_name
*name
)
1367 return _hx509_name_from_Name(&p
->data
->tbsCertificate
.subject
, name
);
1371 * Return the name of the base subject of the hx509 certificate. If
1372 * the certiicate is a verified proxy certificate, the this function
1373 * return the base certificate (root of the proxy chain). If the proxy
1374 * certificate is not verified with the base certificate
1375 * HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned.
1377 * @param context a hx509 context.
1378 * @param c a hx509 certificate object.
1379 * @param name a pointer to a hx509 name, should be freed by
1380 * hx509_name_free(). See also hx509_cert_get_subject().
1382 * @return An hx509 error code, see hx509_get_error_string().
1384 * @ingroup hx509_cert
1388 hx509_cert_get_base_subject(hx509_context context
, hx509_cert c
,
1392 return hx509_name_copy(context
, c
->basename
, name
);
1393 if (is_proxy_cert(context
, c
->data
, NULL
) == 0) {
1394 int ret
= HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED
;
1395 hx509_set_error_string(context
, 0, ret
,
1396 "Proxy certificate have not been "
1397 "canonicalize yet, no base name");
1400 return _hx509_name_from_Name(&c
->data
->tbsCertificate
.subject
, name
);
1404 * Get serial number of the certificate.
1406 * @param p a hx509 certificate object.
1407 * @param i serial number, should be freed ith der_free_heim_integer().
1409 * @return An hx509 error code, see hx509_get_error_string().
1411 * @ingroup hx509_cert
1415 hx509_cert_get_serialnumber(hx509_cert p
, heim_integer
*i
)
1417 return der_copy_heim_integer(&p
->data
->tbsCertificate
.serialNumber
, i
);
1421 * Get notBefore time of the certificate.
1423 * @param p a hx509 certificate object.
1425 * @return return not before time
1427 * @ingroup hx509_cert
1431 hx509_cert_get_notBefore(hx509_cert p
)
1433 return _hx509_Time2time_t(&p
->data
->tbsCertificate
.validity
.notBefore
);
1437 * Get notAfter time of the certificate.
1439 * @param p a hx509 certificate object.
1441 * @return return not after time.
1443 * @ingroup hx509_cert
1447 hx509_cert_get_notAfter(hx509_cert p
)
1449 return _hx509_Time2time_t(&p
->data
->tbsCertificate
.validity
.notAfter
);
1453 * Get the SubjectPublicKeyInfo structure from the hx509 certificate.
1455 * @param p a hx509 certificate object.
1456 * @param spki SubjectPublicKeyInfo, should be freed with
1457 * free_SubjectPublicKeyInfo().
1459 * @return An hx509 error code, see hx509_get_error_string().
1461 * @ingroup hx509_cert
1465 hx509_cert_get_SPKI(hx509_cert p
, SubjectPublicKeyInfo
*spki
)
1467 return copy_SubjectPublicKeyInfo(&p
->data
->tbsCertificate
.subjectPublicKeyInfo
,
1472 _hx509_cert_private_key(hx509_cert p
)
1474 return p
->private_key
;
1478 _hx509_cert_private_key_exportable(hx509_cert p
)
1480 if (p
->private_key
== NULL
)
1482 return _hx509_private_key_exportable(p
->private_key
);
1486 _hx509_cert_private_decrypt(hx509_context context
,
1487 const heim_octet_string
*ciphertext
,
1488 const heim_oid
*encryption_oid
,
1490 heim_octet_string
*cleartext
)
1492 cleartext
->data
= NULL
;
1493 cleartext
->length
= 0;
1495 if (p
->private_key
== NULL
) {
1496 hx509_set_error_string(context
, 0, HX509_PRIVATE_KEY_MISSING
,
1497 "Private key missing");
1498 return HX509_PRIVATE_KEY_MISSING
;
1501 return _hx509_private_key_private_decrypt(context
,
1509 _hx509_cert_public_encrypt(hx509_context context
,
1510 const heim_octet_string
*cleartext
,
1512 heim_oid
*encryption_oid
,
1513 heim_octet_string
*ciphertext
)
1515 return _hx509_public_encrypt(context
,
1517 encryption_oid
, ciphertext
);
1525 _hx509_Time2time_t(const Time
*t
)
1527 switch(t
->element
) {
1528 case choice_Time_utcTime
:
1529 return t
->u
.utcTime
;
1530 case choice_Time_generalTime
:
1531 return t
->u
.generalTime
;
1541 init_name_constraints(hx509_name_constraints
*nc
)
1543 memset(nc
, 0, sizeof(*nc
));
1548 add_name_constraints(hx509_context context
, const Certificate
*c
, int not_ca
,
1549 hx509_name_constraints
*nc
)
1551 NameConstraints tnc
;
1554 ret
= find_extension_name_constraints(c
, &tnc
);
1555 if (ret
== HX509_EXTENSION_NOT_FOUND
)
1558 hx509_set_error_string(context
, 0, ret
, "Failed getting NameConstraints");
1560 } else if (not_ca
) {
1561 ret
= HX509_VERIFY_CONSTRAINTS
;
1562 hx509_set_error_string(context
, 0, ret
, "Not a CA and "
1563 "have NameConstraints");
1565 NameConstraints
*val
;
1566 val
= realloc(nc
->val
, sizeof(nc
->val
[0]) * (nc
->len
+ 1));
1568 hx509_clear_error_string(context
);
1573 ret
= copy_NameConstraints(&tnc
, &nc
->val
[nc
->len
]);
1575 hx509_clear_error_string(context
);
1581 free_NameConstraints(&tnc
);
1586 match_RDN(const RelativeDistinguishedName
*c
,
1587 const RelativeDistinguishedName
*n
)
1591 if (c
->len
!= n
->len
)
1592 return HX509_NAME_CONSTRAINT_ERROR
;
1594 for (i
= 0; i
< n
->len
; i
++) {
1595 if (der_heim_oid_cmp(&c
->val
[i
].type
, &n
->val
[i
].type
) != 0)
1596 return HX509_NAME_CONSTRAINT_ERROR
;
1597 if (_hx509_name_ds_cmp(&c
->val
[i
].value
, &n
->val
[i
].value
) != 0)
1598 return HX509_NAME_CONSTRAINT_ERROR
;
1604 match_X501Name(const Name
*c
, const Name
*n
)
1608 if (c
->element
!= choice_Name_rdnSequence
1609 || n
->element
!= choice_Name_rdnSequence
)
1611 if (c
->u
.rdnSequence
.len
> n
->u
.rdnSequence
.len
)
1612 return HX509_NAME_CONSTRAINT_ERROR
;
1613 for (i
= 0; i
< c
->u
.rdnSequence
.len
; i
++) {
1614 ret
= match_RDN(&c
->u
.rdnSequence
.val
[i
], &n
->u
.rdnSequence
.val
[i
]);
1623 match_general_name(const GeneralName
*c
, const GeneralName
*n
, int *match
)
1626 * Name constraints only apply to the same name type, see RFC3280,
1629 assert(c
->element
== n
->element
);
1631 switch(c
->element
) {
1632 case choice_GeneralName_otherName
:
1633 if (der_heim_oid_cmp(&c
->u
.otherName
.type_id
,
1634 &n
->u
.otherName
.type_id
) != 0)
1635 return HX509_NAME_CONSTRAINT_ERROR
;
1636 if (heim_any_cmp(&c
->u
.otherName
.value
,
1637 &n
->u
.otherName
.value
) != 0)
1638 return HX509_NAME_CONSTRAINT_ERROR
;
1641 case choice_GeneralName_rfc822Name
: {
1644 s
= strchr(c
->u
.rfc822Name
, '@');
1646 if (strcasecmp(c
->u
.rfc822Name
, n
->u
.rfc822Name
) != 0)
1647 return HX509_NAME_CONSTRAINT_ERROR
;
1649 s
= strchr(n
->u
.rfc822Name
, '@');
1651 return HX509_NAME_CONSTRAINT_ERROR
;
1652 len1
= strlen(c
->u
.rfc822Name
);
1653 len2
= strlen(s
+ 1);
1655 return HX509_NAME_CONSTRAINT_ERROR
;
1656 if (strcasecmp(s
+ 1 + len2
- len1
, c
->u
.rfc822Name
) != 0)
1657 return HX509_NAME_CONSTRAINT_ERROR
;
1658 if (len1
< len2
&& s
[len2
- len1
+ 1] != '.')
1659 return HX509_NAME_CONSTRAINT_ERROR
;
1664 case choice_GeneralName_dNSName
: {
1667 lenc
= strlen(c
->u
.dNSName
);
1668 lenn
= strlen(n
->u
.dNSName
);
1670 return HX509_NAME_CONSTRAINT_ERROR
;
1671 if (strcasecmp(&n
->u
.dNSName
[lenn
- lenc
], c
->u
.dNSName
) != 0)
1672 return HX509_NAME_CONSTRAINT_ERROR
;
1673 if (lenc
!= lenn
&& n
->u
.dNSName
[lenn
- lenc
- 1] != '.')
1674 return HX509_NAME_CONSTRAINT_ERROR
;
1678 case choice_GeneralName_directoryName
: {
1679 Name c_name
, n_name
;
1682 c_name
._save
.data
= NULL
;
1683 c_name
._save
.length
= 0;
1684 c_name
.element
= c
->u
.directoryName
.element
;
1685 c_name
.u
.rdnSequence
= c
->u
.directoryName
.u
.rdnSequence
;
1687 n_name
._save
.data
= NULL
;
1688 n_name
._save
.length
= 0;
1689 n_name
.element
= n
->u
.directoryName
.element
;
1690 n_name
.u
.rdnSequence
= n
->u
.directoryName
.u
.rdnSequence
;
1692 ret
= match_X501Name(&c_name
, &n_name
);
1697 case choice_GeneralName_uniformResourceIdentifier
:
1698 case choice_GeneralName_iPAddress
:
1699 case choice_GeneralName_registeredID
:
1701 return HX509_NAME_CONSTRAINT_ERROR
;
1706 match_alt_name(const GeneralName
*n
, const Certificate
*c
,
1707 int *same
, int *match
)
1714 ret
= find_extension_subject_alt_name(c
, &i
, &sa
);
1715 if (ret
== HX509_EXTENSION_NOT_FOUND
) {
1718 } else if (ret
!= 0)
1721 for (j
= 0; j
< sa
.len
; j
++) {
1722 if (n
->element
== sa
.val
[j
].element
) {
1724 ret
= match_general_name(n
, &sa
.val
[j
], match
);
1727 free_GeneralNames(&sa
);
1734 match_tree(const GeneralSubtrees
*t
, const Certificate
*c
, int *match
)
1736 int name
, alt_name
, same
;
1740 name
= alt_name
= same
= *match
= 0;
1741 for (i
= 0; i
< t
->len
; i
++) {
1742 if (t
->val
[i
].minimum
&& t
->val
[i
].maximum
)
1746 * If the constraint apply to directoryNames, test is with
1747 * subjectName of the certificate if the certificate have a
1748 * non-null (empty) subjectName.
1751 if (t
->val
[i
].base
.element
== choice_GeneralName_directoryName
1752 && !subject_null_p(c
))
1754 GeneralName certname
;
1756 memset(&certname
, 0, sizeof(certname
));
1757 certname
.element
= choice_GeneralName_directoryName
;
1758 certname
.u
.directoryName
.element
=
1759 c
->tbsCertificate
.subject
.element
;
1760 certname
.u
.directoryName
.u
.rdnSequence
=
1761 c
->tbsCertificate
.subject
.u
.rdnSequence
;
1763 ret
= match_general_name(&t
->val
[i
].base
, &certname
, &name
);
1766 /* Handle subjectAltNames, this is icky since they
1767 * restrictions only apply if the subjectAltName is of the
1768 * same type. So if there have been a match of type, require
1769 * altname to be set.
1771 ret
= match_alt_name(&t
->val
[i
].base
, c
, &same
, &alt_name
);
1773 if (name
&& (!same
|| alt_name
))
1779 check_name_constraints(hx509_context context
,
1780 const hx509_name_constraints
*nc
,
1781 const Certificate
*c
)
1786 for (i
= 0 ; i
< nc
->len
; i
++) {
1789 if (nc
->val
[i
].permittedSubtrees
) {
1790 GeneralSubtrees_SET(&gs
, nc
->val
[i
].permittedSubtrees
);
1791 ret
= match_tree(&gs
, c
, &match
);
1793 hx509_clear_error_string(context
);
1796 /* allow null subjectNames, they wont matches anything */
1797 if (match
== 0 && !subject_null_p(c
)) {
1798 hx509_set_error_string(context
, 0, HX509_VERIFY_CONSTRAINTS
,
1799 "Error verify constraints, "
1800 "certificate didn't match any "
1801 "permitted subtree");
1802 return HX509_VERIFY_CONSTRAINTS
;
1805 if (nc
->val
[i
].excludedSubtrees
) {
1806 GeneralSubtrees_SET(&gs
, nc
->val
[i
].excludedSubtrees
);
1807 ret
= match_tree(&gs
, c
, &match
);
1809 hx509_clear_error_string(context
);
1813 hx509_set_error_string(context
, 0, HX509_VERIFY_CONSTRAINTS
,
1814 "Error verify constraints, "
1815 "certificate included in excluded "
1817 return HX509_VERIFY_CONSTRAINTS
;
1825 free_name_constraints(hx509_name_constraints
*nc
)
1829 for (i
= 0 ; i
< nc
->len
; i
++)
1830 free_NameConstraints(&nc
->val
[i
]);
1835 * Build and verify the path for the certificate to the trust anchor
1836 * specified in the verify context. The path is constructed from the
1837 * certificate, the pool and the trust anchors.
1839 * @param context A hx509 context.
1840 * @param ctx A hx509 verification context.
1841 * @param cert the certificate to build the path from.
1842 * @param pool A keyset of certificates to build the chain from.
1844 * @return An hx509 error code, see hx509_get_error_string().
1846 * @ingroup hx509_verify
1850 hx509_verify_path(hx509_context context
,
1851 hx509_verify_ctx ctx
,
1855 hx509_name_constraints nc
;
1858 const AlgorithmIdentifier
*alg_id
;
1860 int ret
, i
, proxy_cert_depth
, selfsigned_depth
;
1863 hx509_certs anchors
= NULL
;
1865 memset(&proxy_issuer
, 0, sizeof(proxy_issuer
));
1867 ret
= init_name_constraints(&nc
);
1874 if ((ctx
->flags
& HX509_VERIFY_CTX_F_TIME_SET
) == 0)
1875 ctx
->time_now
= time(NULL
);
1880 if (ctx
->trust_anchors
)
1881 anchors
= _hx509_certs_ref(ctx
->trust_anchors
);
1882 else if (context
->default_trust_anchors
&& ALLOW_DEF_TA(ctx
))
1883 anchors
= _hx509_certs_ref(context
->default_trust_anchors
);
1885 ret
= hx509_certs_init(context
, "MEMORY:no-TA", 0, NULL
, &anchors
);
1891 * Calculate the path from the certificate user presented to the
1894 ret
= _hx509_calculate_path(context
, 0, ctx
->time_now
,
1895 anchors
, ctx
->max_depth
,
1901 alg_id
= path
.val
[path
->len
- 1]->data
->tbsCertificate
.signature
;
1905 * Check CA and proxy certificate chain from the top of the
1906 * certificate chain. Also check certificate is valid with respect
1907 * to the current time.
1911 proxy_cert_depth
= 0;
1912 selfsigned_depth
= 0;
1914 if (ctx
->flags
& HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
)
1919 for (i
= 0; i
< path
.len
; i
++) {
1923 c
= _hx509_get_cert(path
.val
[i
]);
1926 * Lets do some basic check on issuer like
1927 * keyUsage.keyCertSign and basicConstraints.cA bit depending
1928 * on what type of certificate this is.
1933 /* XXX make constants for keyusage */
1934 ret
= check_key_usage(context
, c
, 1 << 5,
1935 REQUIRE_RFC3280(ctx
) ? TRUE
: FALSE
);
1937 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
1938 "Key usage missing from CA certificate");
1942 if (i
+ 1 != path
.len
&& certificate_is_self_signed(c
))
1949 if (is_proxy_cert(context
, c
, &info
) == 0) {
1952 if (info
.pCPathLenConstraint
!= NULL
&&
1953 *info
.pCPathLenConstraint
< i
)
1955 free_ProxyCertInfo(&info
);
1956 ret
= HX509_PATH_TOO_LONG
;
1957 hx509_set_error_string(context
, 0, ret
,
1958 "Proxy certificate chain "
1959 "longer then allowed");
1962 /* XXX MUST check info.proxyPolicy */
1963 free_ProxyCertInfo(&info
);
1966 if (find_extension(c
, oid_id_x509_ce_subjectAltName(), &j
)) {
1967 ret
= HX509_PROXY_CERT_INVALID
;
1968 hx509_set_error_string(context
, 0, ret
,
1969 "Proxy certificate have explicity "
1970 "forbidden subjectAltName");
1975 if (find_extension(c
, oid_id_x509_ce_issuerAltName(), &j
)) {
1976 ret
= HX509_PROXY_CERT_INVALID
;
1977 hx509_set_error_string(context
, 0, ret
,
1978 "Proxy certificate have explicity "
1979 "forbidden issuerAltName");
1984 * The subject name of the proxy certificate should be
1985 * CN=XXX,<proxy issuer>, prune of CN and check if its
1986 * the same over the whole chain of proxy certs and
1987 * then check with the EE cert when we get to it.
1990 if (proxy_cert_depth
) {
1991 ret
= _hx509_name_cmp(&proxy_issuer
, &c
->tbsCertificate
.subject
);
1993 ret
= HX509_PROXY_CERT_NAME_WRONG
;
1994 hx509_set_error_string(context
, 0, ret
,
1995 "Base proxy name not right");
2000 free_Name(&proxy_issuer
);
2002 ret
= copy_Name(&c
->tbsCertificate
.subject
, &proxy_issuer
);
2004 hx509_clear_error_string(context
);
2008 j
= proxy_issuer
.u
.rdnSequence
.len
;
2009 if (proxy_issuer
.u
.rdnSequence
.len
< 2
2010 || proxy_issuer
.u
.rdnSequence
.val
[j
- 1].len
> 1
2011 || der_heim_oid_cmp(&proxy_issuer
.u
.rdnSequence
.val
[j
- 1].val
[0].type
,
2012 oid_id_at_commonName()))
2014 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2015 hx509_set_error_string(context
, 0, ret
,
2016 "Proxy name too short or "
2017 "does not have Common name "
2022 free_RelativeDistinguishedName(&proxy_issuer
.u
.rdnSequence
.val
[j
- 1]);
2023 proxy_issuer
.u
.rdnSequence
.len
-= 1;
2025 ret
= _hx509_name_cmp(&proxy_issuer
, &c
->tbsCertificate
.issuer
);
2027 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2028 hx509_set_error_string(context
, 0, ret
,
2029 "Proxy issuer name not as expected");
2036 * Now we are done with the proxy certificates, this
2037 * cert was an EE cert and we we will fall though to
2038 * EE checking below.
2046 * If there where any proxy certificates in the chain
2047 * (proxy_cert_depth > 0), check that the proxy issuer
2048 * matched proxy certificates "base" subject.
2050 if (proxy_cert_depth
) {
2052 ret
= _hx509_name_cmp(&proxy_issuer
,
2053 &c
->tbsCertificate
.subject
);
2055 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2056 hx509_clear_error_string(context
);
2060 hx509_name_free(&cert
->basename
);
2062 ret
= _hx509_name_from_Name(&proxy_issuer
, &cert
->basename
);
2064 hx509_clear_error_string(context
);
2072 ret
= check_basic_constraints(context
, c
, type
,
2073 i
- proxy_cert_depth
- selfsigned_depth
);
2078 * Don't check the trust anchors expiration time since they
2079 * are transported out of band, from RFC3820.
2081 if (i
+ 1 != path
.len
|| CHECK_TA(ctx
)) {
2083 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
2084 if (t
> ctx
->time_now
) {
2085 ret
= HX509_CERT_USED_BEFORE_TIME
;
2086 hx509_clear_error_string(context
);
2089 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notAfter
);
2090 if (t
< ctx
->time_now
) {
2091 ret
= HX509_CERT_USED_AFTER_TIME
;
2092 hx509_clear_error_string(context
);
2097 if (type
== EE_CERT
)
2099 else if (type
== PROXY_CERT
)
2104 * Verify constraints, do this backward so path constraints are
2105 * checked in the right order.
2108 for (ret
= 0, i
= path
.len
- 1; i
>= 0; i
--) {
2111 c
= _hx509_get_cert(path
.val
[i
]);
2113 /* verify name constraints, not for selfsigned and anchor */
2114 if (!certificate_is_self_signed(c
) || i
+ 1 != path
.len
) {
2115 ret
= check_name_constraints(context
, &nc
, c
);
2120 ret
= add_name_constraints(context
, c
, i
== 0, &nc
);
2124 /* XXX verify all other silly constraints */
2129 * Verify that no certificates has been revoked.
2132 if (ctx
->revoke_ctx
) {
2135 ret
= hx509_certs_init(context
, "MEMORY:revoke-certs", 0,
2140 for (i
= 0; i
< path
.len
; i
++) {
2141 ret
= hx509_certs_add(context
, certs
, path
.val
[i
]);
2143 hx509_certs_free(&certs
);
2147 ret
= hx509_certs_merge(context
, certs
, pool
);
2149 hx509_certs_free(&certs
);
2153 for (i
= 0; i
< path
.len
- 1; i
++) {
2154 int parent
= (i
< path
.len
- 1) ? i
+ 1 : i
;
2156 ret
= hx509_revoke_verify(context
,
2163 hx509_certs_free(&certs
);
2167 hx509_certs_free(&certs
);
2171 for (i
= path
.len
- 1; i
>= 0; i
--) {
2172 _hx509_print_cert_subject(path
.val
[i
]);
2177 * Verify signatures, do this backward so public key working
2178 * parameter is passed up from the anchor up though the chain.
2181 for (i
= path
.len
- 1; i
>= 0; i
--) {
2182 Certificate
*signer
, *c
;
2184 c
= _hx509_get_cert(path
.val
[i
]);
2186 /* is last in chain (trust anchor) */
2187 if (i
+ 1 == path
.len
) {
2188 signer
= path
.val
[i
]->data
;
2190 /* if trust anchor is not self signed, don't check sig */
2191 if (!certificate_is_self_signed(signer
))
2194 /* take next certificate in chain */
2195 signer
= path
.val
[i
+ 1]->data
;
2198 /* verify signatureValue */
2199 ret
= _hx509_verify_signature_bitstring(context
,
2201 &c
->signatureAlgorithm
,
2202 &c
->tbsCertificate
._save
,
2203 &c
->signatureValue
);
2205 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
2206 "Failed to verify signature of certificate");
2212 hx509_certs_free(&anchors
);
2213 free_Name(&proxy_issuer
);
2214 free_name_constraints(&nc
);
2215 _hx509_path_free(&path
);
2221 * Verify a signature made using the private key of an certificate.
2223 * @param context A hx509 context.
2224 * @param signer the certificate that made the signature.
2225 * @param alg algorthm that was used to sign the data.
2226 * @param data the data that was signed.
2227 * @param sig the sigature to verify.
2229 * @return An hx509 error code, see hx509_get_error_string().
2231 * @ingroup hx509_crypto
2235 hx509_verify_signature(hx509_context context
,
2236 const hx509_cert signer
,
2237 const AlgorithmIdentifier
*alg
,
2238 const heim_octet_string
*data
,
2239 const heim_octet_string
*sig
)
2241 return _hx509_verify_signature(context
, signer
->data
, alg
, data
, sig
);
2246 * Verify that the certificate is allowed to be used for the hostname
2249 * @param context A hx509 context.
2250 * @param cert the certificate to match with
2251 * @param flags Flags to modify the behavior:
2252 * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok
2253 * @param type type of hostname:
2254 * - HX509_HN_HOSTNAME for plain hostname.
2255 * - HX509_HN_DNSSRV for DNS SRV names.
2256 * @param hostname the hostname to check
2257 * @param sa address of the host
2258 * @param sa_size length of address
2260 * @return An hx509 error code, see hx509_get_error_string().
2262 * @ingroup hx509_cert
2266 hx509_verify_hostname(hx509_context context
,
2267 const hx509_cert cert
,
2269 hx509_hostname_type type
,
2270 const char *hostname
,
2271 const struct sockaddr
*sa
,
2272 /* XXX krb5_socklen_t */ int sa_size
)
2277 if (sa
&& sa_size
<= 0)
2280 memset(&san
, 0, sizeof(san
));
2284 ret
= find_extension_subject_alt_name(cert
->data
, &i
, &san
);
2285 if (ret
== HX509_EXTENSION_NOT_FOUND
) {
2288 } else if (ret
!= 0)
2291 for (j
= 0; j
< san
.len
; j
++) {
2292 switch (san
.val
[j
].element
) {
2293 case choice_GeneralName_dNSName
:
2294 if (strcasecmp(san
.val
[j
].u
.dNSName
, hostname
) == 0) {
2295 free_GeneralNames(&san
);
2303 free_GeneralNames(&san
);
2307 Name
*name
= &cert
->data
->tbsCertificate
.subject
;
2309 /* match if first component is a CN= */
2310 if (name
->u
.rdnSequence
.len
> 0
2311 && name
->u
.rdnSequence
.val
[0].len
== 1
2312 && der_heim_oid_cmp(&name
->u
.rdnSequence
.val
[0].val
[0].type
,
2313 oid_id_at_commonName()) == 0)
2315 DirectoryString
*ds
= &name
->u
.rdnSequence
.val
[0].val
[0].value
;
2317 switch (ds
->element
) {
2318 case choice_DirectoryString_printableString
:
2319 if (strcasecmp(ds
->u
.printableString
, hostname
) == 0)
2322 case choice_DirectoryString_ia5String
:
2323 if (strcasecmp(ds
->u
.ia5String
, hostname
) == 0)
2326 case choice_DirectoryString_utf8String
:
2327 if (strcasecmp(ds
->u
.utf8String
, hostname
) == 0)
2335 if ((flags
& HX509_VHN_F_ALLOW_NO_MATCH
) == 0)
2336 ret
= HX509_NAME_CONSTRAINT_ERROR
;
2342 _hx509_set_cert_attribute(hx509_context context
,
2344 const heim_oid
*oid
,
2345 const heim_octet_string
*attr
)
2347 hx509_cert_attribute a
;
2350 if (hx509_cert_get_attribute(cert
, oid
) != NULL
)
2353 d
= realloc(cert
->attrs
.val
,
2354 sizeof(cert
->attrs
.val
[0]) * (cert
->attrs
.len
+ 1));
2356 hx509_clear_error_string(context
);
2359 cert
->attrs
.val
= d
;
2361 a
= malloc(sizeof(*a
));
2365 der_copy_octet_string(attr
, &a
->data
);
2366 der_copy_oid(oid
, &a
->oid
);
2368 cert
->attrs
.val
[cert
->attrs
.len
] = a
;
2375 * Get an external attribute for the certificate, examples are
2376 * friendly name and id.
2378 * @param cert hx509 certificate object to search
2379 * @param oid an oid to search for.
2381 * @return an hx509_cert_attribute, only valid as long as the
2382 * certificate is referenced.
2384 * @ingroup hx509_cert
2387 hx509_cert_attribute
2388 hx509_cert_get_attribute(hx509_cert cert
, const heim_oid
*oid
)
2391 for (i
= 0; i
< cert
->attrs
.len
; i
++)
2392 if (der_heim_oid_cmp(oid
, &cert
->attrs
.val
[i
]->oid
) == 0)
2393 return cert
->attrs
.val
[i
];
2398 * Set the friendly name on the certificate.
2400 * @param cert The certificate to set the friendly name on
2401 * @param name Friendly name.
2403 * @return An hx509 error code, see hx509_get_error_string().
2405 * @ingroup hx509_cert
2409 hx509_cert_set_friendly_name(hx509_cert cert
, const char *name
)
2411 if (cert
->friendlyname
)
2412 free(cert
->friendlyname
);
2413 cert
->friendlyname
= strdup(name
);
2414 if (cert
->friendlyname
== NULL
)
2420 * Get friendly name of the certificate.
2422 * @param cert cert to get the friendly name from.
2424 * @return an friendly name or NULL if there is. The friendly name is
2425 * only valid as long as the certificate is referenced.
2427 * @ingroup hx509_cert
2431 hx509_cert_get_friendly_name(hx509_cert cert
)
2433 hx509_cert_attribute a
;
2434 PKCS9_friendlyName n
;
2438 if (cert
->friendlyname
)
2439 return cert
->friendlyname
;
2441 a
= hx509_cert_get_attribute(cert
, oid_id_pkcs_9_at_friendlyName());
2443 /* XXX use subject name ? */
2447 ret
= decode_PKCS9_friendlyName(a
->data
.data
, a
->data
.length
, &n
, &sz
);
2452 free_PKCS9_friendlyName(&n
);
2456 cert
->friendlyname
= malloc(n
.val
[0].length
+ 1);
2457 if (cert
->friendlyname
== NULL
) {
2458 free_PKCS9_friendlyName(&n
);
2462 for (i
= 0; i
< n
.val
[0].length
; i
++) {
2463 if (n
.val
[0].data
[i
] <= 0xff)
2464 cert
->friendlyname
[i
] = n
.val
[0].data
[i
] & 0xff;
2466 cert
->friendlyname
[i
] = 'X';
2468 cert
->friendlyname
[i
] = '\0';
2469 free_PKCS9_friendlyName(&n
);
2471 return cert
->friendlyname
;
2475 _hx509_query_clear(hx509_query
*q
)
2477 memset(q
, 0, sizeof(*q
));
2481 * Allocate an query controller. Free using hx509_query_free().
2483 * @param context A hx509 context.
2484 * @param q return pointer to a hx509_query.
2486 * @return An hx509 error code, see hx509_get_error_string().
2488 * @ingroup hx509_cert
2492 hx509_query_alloc(hx509_context context
, hx509_query
**q
)
2494 *q
= calloc(1, sizeof(**q
));
2501 * Set match options for the hx509 query controller.
2503 * @param q query controller.
2504 * @param option options to control the query controller.
2506 * @return An hx509 error code, see hx509_get_error_string().
2508 * @ingroup hx509_cert
2512 hx509_query_match_option(hx509_query
*q
, hx509_query_option option
)
2515 case HX509_QUERY_OPTION_PRIVATE_KEY
:
2516 q
->match
|= HX509_QUERY_PRIVATE_KEY
;
2518 case HX509_QUERY_OPTION_KU_ENCIPHERMENT
:
2519 q
->match
|= HX509_QUERY_KU_ENCIPHERMENT
;
2521 case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE
:
2522 q
->match
|= HX509_QUERY_KU_DIGITALSIGNATURE
;
2524 case HX509_QUERY_OPTION_KU_KEYCERTSIGN
:
2525 q
->match
|= HX509_QUERY_KU_KEYCERTSIGN
;
2527 case HX509_QUERY_OPTION_END
:
2534 * Set the issuer and serial number of match in the query
2535 * controller. The function make copies of the isser and serial number.
2537 * @param q a hx509 query controller
2538 * @param issuer issuer to search for
2539 * @param serialNumber the serialNumber of the issuer.
2541 * @return An hx509 error code, see hx509_get_error_string().
2543 * @ingroup hx509_cert
2547 hx509_query_match_issuer_serial(hx509_query
*q
,
2549 const heim_integer
*serialNumber
)
2553 der_free_heim_integer(q
->serial
);
2556 q
->serial
= malloc(sizeof(*q
->serial
));
2557 if (q
->serial
== NULL
)
2559 ret
= der_copy_heim_integer(serialNumber
, q
->serial
);
2565 if (q
->issuer_name
) {
2566 free_Name(q
->issuer_name
);
2567 free(q
->issuer_name
);
2569 q
->issuer_name
= malloc(sizeof(*q
->issuer_name
));
2570 if (q
->issuer_name
== NULL
)
2572 ret
= copy_Name(issuer
, q
->issuer_name
);
2574 free(q
->issuer_name
);
2575 q
->issuer_name
= NULL
;
2578 q
->match
|= HX509_QUERY_MATCH_SERIALNUMBER
|HX509_QUERY_MATCH_ISSUER_NAME
;
2583 * Set the query controller to match on a friendly name
2585 * @param q a hx509 query controller.
2586 * @param name a friendly name to match on
2588 * @return An hx509 error code, see hx509_get_error_string().
2590 * @ingroup hx509_cert
2594 hx509_query_match_friendly_name(hx509_query
*q
, const char *name
)
2596 if (q
->friendlyname
)
2597 free(q
->friendlyname
);
2598 q
->friendlyname
= strdup(name
);
2599 if (q
->friendlyname
== NULL
)
2601 q
->match
|= HX509_QUERY_MATCH_FRIENDLY_NAME
;
2606 * Set the query controller to match using a specific match function.
2608 * @param q a hx509 query controller.
2609 * @param func function to use for matching, if the argument is NULL,
2610 * the match function is removed.
2611 * @param ctx context passed to the function.
2613 * @return An hx509 error code, see hx509_get_error_string().
2615 * @ingroup hx509_cert
2619 hx509_query_match_cmp_func(hx509_query
*q
,
2620 int (*func
)(void *, hx509_cert
),
2624 q
->match
|= HX509_QUERY_MATCH_FUNCTION
;
2626 q
->match
&= ~HX509_QUERY_MATCH_FUNCTION
;
2628 q
->cmp_func_ctx
= ctx
;
2633 * Free the query controller.
2635 * @param context A hx509 context.
2636 * @param q a pointer to the query controller.
2638 * @ingroup hx509_cert
2642 hx509_query_free(hx509_context context
, hx509_query
*q
)
2645 der_free_heim_integer(q
->serial
);
2649 if (q
->issuer_name
) {
2650 free_Name(q
->issuer_name
);
2651 free(q
->issuer_name
);
2652 q
->issuer_name
= NULL
;
2655 free(q
->friendlyname
);
2656 memset(q
, 0, sizeof(*q
));
2662 _hx509_query_match_cert(hx509_context context
, const hx509_query
*q
, hx509_cert cert
)
2664 Certificate
*c
= _hx509_get_cert(cert
);
2666 _hx509_query_statistic(context
, 1, q
);
2668 if ((q
->match
& HX509_QUERY_FIND_ISSUER_CERT
) &&
2669 _hx509_cert_is_parent_cmp(q
->subject
, c
, 0) != 0)
2672 if ((q
->match
& HX509_QUERY_MATCH_CERTIFICATE
) &&
2673 _hx509_Certificate_cmp(q
->certificate
, c
) != 0)
2676 if ((q
->match
& HX509_QUERY_MATCH_SERIALNUMBER
)
2677 && der_heim_integer_cmp(&c
->tbsCertificate
.serialNumber
, q
->serial
) != 0)
2680 if ((q
->match
& HX509_QUERY_MATCH_ISSUER_NAME
)
2681 && _hx509_name_cmp(&c
->tbsCertificate
.issuer
, q
->issuer_name
) != 0)
2684 if ((q
->match
& HX509_QUERY_MATCH_SUBJECT_NAME
)
2685 && _hx509_name_cmp(&c
->tbsCertificate
.subject
, q
->subject_name
) != 0)
2688 if (q
->match
& HX509_QUERY_MATCH_SUBJECT_KEY_ID
) {
2689 SubjectKeyIdentifier si
;
2692 ret
= _hx509_find_extension_subject_key_id(c
, &si
);
2694 if (der_heim_octet_string_cmp(&si
, q
->subject_id
) != 0)
2696 free_SubjectKeyIdentifier(&si
);
2701 if ((q
->match
& HX509_QUERY_MATCH_ISSUER_ID
))
2703 if ((q
->match
& HX509_QUERY_PRIVATE_KEY
) &&
2704 _hx509_cert_private_key(cert
) == NULL
)
2709 if (q
->match
& HX509_QUERY_KU_DIGITALSIGNATURE
)
2711 if (q
->match
& HX509_QUERY_KU_NONREPUDIATION
)
2713 if (q
->match
& HX509_QUERY_KU_ENCIPHERMENT
)
2715 if (q
->match
& HX509_QUERY_KU_DATAENCIPHERMENT
)
2717 if (q
->match
& HX509_QUERY_KU_KEYAGREEMENT
)
2719 if (q
->match
& HX509_QUERY_KU_KEYCERTSIGN
)
2721 if (q
->match
& HX509_QUERY_KU_CRLSIGN
)
2723 if (ku
&& check_key_usage(context
, c
, ku
, TRUE
))
2726 if ((q
->match
& HX509_QUERY_ANCHOR
))
2729 if (q
->match
& HX509_QUERY_MATCH_LOCAL_KEY_ID
) {
2730 hx509_cert_attribute a
;
2732 a
= hx509_cert_get_attribute(cert
, oid_id_pkcs_9_at_localKeyId());
2735 if (der_heim_octet_string_cmp(&a
->data
, q
->local_key_id
) != 0)
2739 if (q
->match
& HX509_QUERY_NO_MATCH_PATH
) {
2742 for (i
= 0; i
< q
->path
->len
; i
++)
2743 if (hx509_cert_cmp(q
->path
->val
[i
], cert
) == 0)
2746 if (q
->match
& HX509_QUERY_MATCH_FRIENDLY_NAME
) {
2747 const char *name
= hx509_cert_get_friendly_name(cert
);
2750 if (strcasecmp(q
->friendlyname
, name
) != 0)
2753 if (q
->match
& HX509_QUERY_MATCH_FUNCTION
) {
2754 int ret
= (*q
->cmp_func
)(q
->cmp_func_ctx
, cert
);
2759 if (q
->match
& HX509_QUERY_MATCH_KEY_HASH_SHA1
) {
2760 heim_octet_string os
;
2763 os
.data
= c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.data
;
2765 c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.length
/ 8;
2767 ret
= _hx509_verify_signature(context
,
2769 hx509_signature_sha1(),
2776 if (q
->match
& HX509_QUERY_MATCH_TIME
) {
2778 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
2781 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notAfter
);
2786 if (q
->match
& ~HX509_QUERY_MASK
)
2793 * Set a statistic file for the query statistics.
2795 * @param context A hx509 context.
2796 * @param fn statistics file name
2798 * @ingroup hx509_cert
2802 hx509_query_statistic_file(hx509_context context
, const char *fn
)
2804 if (context
->querystat
)
2805 free(context
->querystat
);
2806 context
->querystat
= strdup(fn
);
2810 _hx509_query_statistic(hx509_context context
, int type
, const hx509_query
*q
)
2813 if (context
->querystat
== NULL
)
2815 f
= fopen(context
->querystat
, "a");
2818 fprintf(f
, "%d %d\n", type
, q
->match
);
2822 static const char *statname
[] = {
2824 "match serialnumber",
2825 "match issuer name",
2826 "match subject name",
2827 "match subject key id",
2831 "ku digitalsignature",
2834 "ku nonrepudiation",
2836 "ku dataencipherment",
2838 "match certificate",
2839 "match local key id",
2841 "match friendly name",
2843 "match key hash sha1",
2848 unsigned long stats
;
2854 stat_sort(const void *a
, const void *b
)
2856 const struct stat_el
*ae
= a
;
2857 const struct stat_el
*be
= b
;
2858 return be
->stats
- ae
->stats
;
2862 * Unparse the statistics file and print the result on a FILE descriptor.
2864 * @param context A hx509 context.
2865 * @param printtype tyep to print
2866 * @param out the FILE to write the data on.
2868 * @ingroup hx509_cert
2872 hx509_query_unparse_stats(hx509_context context
, int printtype
, FILE *out
)
2876 int type
, mask
, i
, num
;
2877 unsigned long multiqueries
= 0, totalqueries
= 0;
2878 struct stat_el stats
[32];
2880 if (context
->querystat
== NULL
)
2882 f
= fopen(context
->querystat
, "r");
2884 fprintf(out
, "No statistic file %s: %s.\n",
2885 context
->querystat
, strerror(errno
));
2889 for (i
= 0; i
< sizeof(stats
)/sizeof(stats
[0]); i
++) {
2894 while (fscanf(f
, "%d %d\n", &type
, &mask
) == 2) {
2895 if (type
!= printtype
)
2898 while (mask
&& i
< sizeof(stats
)/sizeof(stats
[0])) {
2912 qsort(stats
, sizeof(stats
)/sizeof(stats
[0]), sizeof(stats
[0]), stat_sort
);
2916 errx(1, "out of memory");
2918 rtbl_set_separator (t
, " ");
2920 rtbl_add_column_by_id (t
, 0, "Name", 0);
2921 rtbl_add_column_by_id (t
, 1, "Counter", 0);
2924 for (i
= 0; i
< sizeof(stats
)/sizeof(stats
[0]); i
++) {
2927 if (stats
[i
].index
< sizeof(statname
)/sizeof(statname
[0]))
2928 rtbl_add_column_entry_by_id (t
, 0, statname
[stats
[i
].index
]);
2930 snprintf(str
, sizeof(str
), "%d", stats
[i
].index
);
2931 rtbl_add_column_entry_by_id (t
, 0, str
);
2933 snprintf(str
, sizeof(str
), "%lu", stats
[i
].stats
);
2934 rtbl_add_column_entry_by_id (t
, 1, str
);
2937 rtbl_format(t
, out
);
2940 fprintf(out
, "\nQueries: multi %lu total %lu\n",
2941 multiqueries
, totalqueries
);
2945 * Check the extended key usage on the hx509 certificate.
2947 * @param context A hx509 context.
2948 * @param cert A hx509 context.
2949 * @param eku the EKU to check for
2950 * @param allow_any_eku if the any EKU is set, allow that to be a
2953 * @return An hx509 error code, see hx509_get_error_string().
2955 * @ingroup hx509_cert
2959 hx509_cert_check_eku(hx509_context context
, hx509_cert cert
,
2960 const heim_oid
*eku
, int allow_any_eku
)
2965 ret
= find_extension_eku(_hx509_get_cert(cert
), &e
);
2967 hx509_clear_error_string(context
);
2971 for (i
= 0; i
< e
.len
; i
++) {
2972 if (der_heim_oid_cmp(eku
, &e
.val
[i
]) == 0) {
2973 free_ExtKeyUsage(&e
);
2976 if (allow_any_eku
) {
2978 if (der_heim_oid_cmp(id_any_eku
, &e
.val
[i
]) == 0) {
2979 free_ExtKeyUsage(&e
);
2985 free_ExtKeyUsage(&e
);
2986 hx509_clear_error_string(context
);
2987 return HX509_CERTIFICATE_MISSING_EKU
;
2991 _hx509_cert_get_keyusage(hx509_context context
,
3000 memset(ku
, 0, sizeof(*ku
));
3002 cert
= _hx509_get_cert(c
);
3004 if (_hx509_cert_get_version(cert
) < 3)
3007 e
= find_extension(cert
, oid_id_x509_ce_keyUsage(), &i
);
3009 return HX509_KU_CERT_MISSING
;
3011 ret
= decode_KeyUsage(e
->extnValue
.data
, e
->extnValue
.length
, ku
, &size
);
3018 _hx509_cert_get_eku(hx509_context context
,
3024 memset(e
, 0, sizeof(*e
));
3026 ret
= find_extension_eku(_hx509_get_cert(cert
), e
);
3027 if (ret
&& ret
!= HX509_EXTENSION_NOT_FOUND
) {
3028 hx509_clear_error_string(context
);
3035 * Encodes the hx509 certificate as a DER encode binary.
3037 * @param context A hx509 context.
3038 * @param c the certificate to encode.
3039 * @param os the encode certificate, set to NULL, 0 on case of error.
3041 * @return An hx509 error code, see hx509_get_error_string().
3043 * @ingroup hx509_cert
3047 hx509_cert_binary(hx509_context context
, hx509_cert c
, heim_octet_string
*os
)
3055 ASN1_MALLOC_ENCODE(Certificate
, os
->data
, os
->length
,
3056 _hx509_get_cert(c
), &size
, ret
);
3062 if (os
->length
!= size
)
3063 _hx509_abort("internal ASN.1 encoder error");
3069 * Last to avoid lost __attribute__s due to #undef.
3072 #undef __attribute__
3073 #define __attribute__(X)
3076 _hx509_abort(const char *fmt
, ...)
3077 __attribute__ ((noreturn
, format (printf
, 1, 2)))