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 free_Certificate(&t);
287 hx509_set_error_string(context, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE,
288 "Extra data after certificate");
289 return HX509_EXTRA_DATA_AFTER_STRUCTURE;
292 ret = hx509_cert_init(context, &t, cert);
293 free_Certificate(&t);
298 _hx509_cert_set_release(hx509_cert cert,
299 _hx509_cert_release_func release,
302 cert->release = release;
307 /* Doesn't make a copy of `private_key'. */
310 _hx509_cert_assign_key(hx509_cert cert, hx509_private_key private_key)
312 if (cert->private_key)
313 hx509_private_key_free(&cert->private_key);
314 cert->private_key = _hx509_private_key_ref(private_key);
319 * Free reference to the hx509 certificate object, if the refcounter
320 * reaches 0, the object if freed. Its allowed to pass in NULL.
322 * @param cert the cert to free.
324 * @ingroup hx509_cert
328 hx509_cert_free(hx509_cert cert)
336 _hx509_abort("cert refcount <= 0 on free");
341 (cert->release)(cert, cert->ctx);
343 if (cert->private_key)
344 hx509_private_key_free(&cert->private_key);
346 free_Certificate(cert->data);
349 for (i = 0; i < cert->attrs.len; i++) {
350 der_free_octet_string(&cert->attrs.val[i]->data);
351 der_free_oid(&cert->attrs.val[i]->oid);
352 free(cert->attrs.val[i]);
354 free(cert->attrs.val);
355 free(cert->friendlyname);
357 hx509_name_free(&cert->basename);
358 memset(cert, 0, sizeof(*cert));
363 * Add a reference to a hx509 certificate object.
365 * @param cert a pointer to an hx509 certificate object.
367 * @return the same object as is passed in.
369 * @ingroup hx509_cert
373 hx509_cert_ref(hx509_cert cert)
378 _hx509_abort("cert refcount <= 0");
381 _hx509_abort("cert refcount == 0");
386 * Allocate an verification context that is used fo control the
387 * verification process.
389 * @param context A hx509 context.
390 * @param ctx returns a pointer to a hx509_verify_ctx object.
392 * @return An hx509 error code, see hx509_get_error_string().
394 * @ingroup hx509_verify
398 hx509_verify_init_ctx(hx509_context context, hx509_verify_ctx *ctx)
402 c = calloc(1, sizeof(*c));
406 c->max_depth = HX509_VERIFY_MAX_DEPTH;
414 * Free an hx509 verification context.
416 * @param ctx the context to be freed.
418 * @ingroup hx509_verify
422 hx509_verify_destroy_ctx(hx509_verify_ctx ctx)
425 hx509_certs_free(&ctx->trust_anchors);
426 hx509_revoke_free(&ctx->revoke_ctx);
427 memset(ctx, 0, sizeof(*ctx));
433 * Set the trust anchors in the verification context, makes an
434 * reference to the keyset, so the consumer can free the keyset
435 * independent of the destruction of the verification context (ctx).
436 * If there already is a keyset attached, it's released.
438 * @param ctx a verification context
439 * @param set a keyset containing the trust anchors.
441 * @ingroup hx509_verify
445 hx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set)
447 if (ctx->trust_anchors)
448 hx509_certs_free(&ctx->trust_anchors);
449 ctx->trust_anchors = hx509_certs_ref(set);
453 * Attach an revocation context to the verfication context, , makes an
454 * reference to the revoke context, so the consumer can free the
455 * revoke context independent of the destruction of the verification
456 * context. If there is no revoke context, the verification process is
457 * NOT going to check any verification status.
459 * @param ctx a verification context.
460 * @param revoke_ctx a revoke context.
462 * @ingroup hx509_verify
466 hx509_verify_attach_revoke(hx509_verify_ctx ctx, hx509_revoke_ctx revoke_ctx)
469 hx509_revoke_free(&ctx->revoke_ctx);
470 ctx->revoke_ctx = _hx509_revoke_ref(revoke_ctx);
474 * Set the clock time the the verification process is going to
475 * use. Used to check certificate in the past and future time. If not
476 * set the current time will be used.
478 * @param ctx a verification context.
479 * @param t the time the verifiation is using.
482 * @ingroup hx509_verify
486 hx509_verify_set_time(hx509_verify_ctx ctx, time_t t)
488 ctx->flags |= HX509_VERIFY_CTX_F_TIME_SET;
493 _hx509_verify_get_time(hx509_verify_ctx ctx)
495 return ctx->time_now;
499 * Set the maximum depth of the certificate chain that the path
500 * builder is going to try.
502 * @param ctx a verification context
503 * @param max_depth maxium depth of the certificate chain, include
506 * @ingroup hx509_verify
510 hx509_verify_set_max_depth(hx509_verify_ctx ctx, unsigned int max_depth)
512 ctx->max_depth = max_depth;
516 * Allow or deny the use of proxy certificates
518 * @param ctx a verification context
519 * @param boolean if non zero, allow proxy certificates.
521 * @ingroup hx509_verify
525 hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean)
528 ctx->flags |= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
530 ctx->flags &= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
534 * Select strict RFC3280 verification of certificiates. This means
535 * checking key usage on CA certificates, this will make version 1
536 * certificiates unuseable.
538 * @param ctx a verification context
539 * @param boolean if non zero, use strict verification.
541 * @ingroup hx509_verify
545 hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean)
548 ctx->flags |= HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
550 ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
554 * Allow using the operating system builtin trust anchors if no other
555 * trust anchors are configured.
557 * @param ctx a verification context
558 * @param boolean if non zero, useing the operating systems builtin
562 * @return An hx509 error code, see hx509_get_error_string().
564 * @ingroup hx509_cert
568 hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean)
571 ctx->flags &= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
573 ctx->flags |= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
577 hx509_verify_ctx_f_allow_best_before_signature_algs(hx509_context ctx,
581 ctx->flags &= ~HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
583 ctx->flags |= HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
586 static const Extension *
587 find_extension(const Certificate *cert, const heim_oid *oid, size_t *idx)
589 const TBSCertificate *c = &cert->tbsCertificate;
591 if (c->version == NULL || *c->version < 2 || c->extensions == NULL)
594 for (;*idx < c->extensions->len; (*idx)++) {
595 if (der_heim_oid_cmp(&c->extensions->val[*idx].extnID, oid) == 0)
596 return &c->extensions->val[(*idx)++];
602 find_extension_auth_key_id(const Certificate *subject,
603 AuthorityKeyIdentifier *ai)
609 memset(ai, 0, sizeof(*ai));
611 e = find_extension(subject, &asn1_oid_id_x509_ce_authorityKeyIdentifier, &i);
613 return HX509_EXTENSION_NOT_FOUND;
615 return decode_AuthorityKeyIdentifier(e->extnValue.data,
621 _hx509_find_extension_subject_key_id(const Certificate *issuer,
622 SubjectKeyIdentifier *si)
628 memset(si, 0, sizeof(*si));
630 e = find_extension(issuer, &asn1_oid_id_x509_ce_subjectKeyIdentifier, &i);
632 return HX509_EXTENSION_NOT_FOUND;
634 return decode_SubjectKeyIdentifier(e->extnValue.data,
640 find_extension_name_constraints(const Certificate *subject,
647 memset(nc, 0, sizeof(*nc));
649 e = find_extension(subject, &asn1_oid_id_x509_ce_nameConstraints, &i);
651 return HX509_EXTENSION_NOT_FOUND;
653 return decode_NameConstraints(e->extnValue.data,
659 find_extension_subject_alt_name(const Certificate *cert, size_t *i,
665 memset(sa, 0, sizeof(*sa));
667 e = find_extension(cert, &asn1_oid_id_x509_ce_subjectAltName, i);
669 return HX509_EXTENSION_NOT_FOUND;
671 return decode_GeneralNames(e->extnValue.data,
677 find_extension_eku(const Certificate *cert, ExtKeyUsage *eku)
683 memset(eku, 0, sizeof(*eku));
685 e = find_extension(cert, &asn1_oid_id_x509_ce_extKeyUsage, &i);
687 return HX509_EXTENSION_NOT_FOUND;
689 return decode_ExtKeyUsage(e->extnValue.data,
695 add_to_list(hx509_octet_string_list *list, const heim_octet_string *entry)
700 p = realloc(list->val, (list->len + 1) * sizeof(list->val[0]));
704 ret = der_copy_octet_string(entry, &list->val[list->len]);
712 * Free a list of octet strings returned by another hx509 library
715 * @param list list to be freed.
717 * @ingroup hx509_misc
721 hx509_free_octet_string_list(hx509_octet_string_list *list)
724 for (i = 0; i < list->len; i++)
725 der_free_octet_string(&list->val[i]);
732 * Return a list of subjectAltNames specified by oid in the
733 * certificate. On error the
735 * The returned list of octet string should be freed with
736 * hx509_free_octet_string_list().
738 * @param context A hx509 context.
739 * @param cert a hx509 certificate object.
740 * @param oid an oid to for SubjectAltName.
741 * @param list list of matching SubjectAltName.
743 * @return An hx509 error code, see hx509_get_error_string().
745 * @ingroup hx509_cert
749 hx509_cert_find_subjectAltName_otherName(hx509_context context,
752 hx509_octet_string_list *list)
763 ret = find_extension_subject_alt_name(_hx509_get_cert(cert), &i, &sa);
765 if (ret == HX509_EXTENSION_NOT_FOUND) {
767 } else if (ret != 0) {
768 hx509_set_error_string(context, 0, ret, "Error searching for SAN");
769 hx509_free_octet_string_list(list);
773 for (j = 0; j < sa.len; j++) {
774 if (sa.val[j].element == choice_GeneralName_otherName &&
775 der_heim_oid_cmp(&sa.val[j].u.otherName.type_id, oid) == 0)
777 ret = add_to_list(list, &sa.val[j].u.otherName.value);
779 hx509_set_error_string(context, 0, ret,
780 "Error adding an exra SAN to "
782 hx509_free_octet_string_list(list);
783 free_GeneralNames(&sa);
788 free_GeneralNames(&sa);
794 check_key_usage(hx509_context context, const Certificate *cert,
795 unsigned flags, int req_present)
804 if (_hx509_cert_get_version(cert) < 3)
807 e = find_extension(cert, &asn1_oid_id_x509_ce_keyUsage, &i);
810 hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
811 "Required extension key "
812 "usage missing from certifiate");
813 return HX509_KU_CERT_MISSING;
818 ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &size);
821 ku_flags = KeyUsage2int(ku);
822 if ((ku_flags & flags) != flags) {
823 unsigned missing = (~ku_flags) & flags;
824 char buf[256], *name;
826 unparse_flags(missing, asn1_KeyUsage_units(), buf, sizeof(buf));
827 _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
828 hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
829 "Key usage %s required but missing "
830 "from certifiate %s", buf, name);
832 return HX509_KU_CERT_MISSING;
838 * Return 0 on matching key usage 'flags' for 'cert', otherwise return
839 * an error code. If 'req_present' the existance is required of the
840 * KeyUsage extension.
844 _hx509_check_key_usage(hx509_context context, hx509_cert cert,
845 unsigned flags, int req_present)
847 return check_key_usage(context, _hx509_get_cert(cert), flags, req_present);
850 enum certtype { PROXY_CERT, EE_CERT, CA_CERT };
853 check_basic_constraints(hx509_context context, const Certificate *cert,
854 enum certtype type, size_t depth)
862 if (_hx509_cert_get_version(cert) < 3)
865 e = find_extension(cert, &asn1_oid_id_x509_ce_basicConstraints, &i);
873 ret = _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
875 hx509_set_error_string(context, 0, HX509_EXTENSION_NOT_FOUND,
876 "basicConstraints missing from "
877 "CA certifiacte %s", name);
879 return HX509_EXTENSION_NOT_FOUND;
884 ret = decode_BasicConstraints(e->extnValue.data,
885 e->extnValue.length, &bc,
891 if (bc.cA != NULL && *bc.cA)
892 ret = HX509_PARENT_IS_CA;
898 if (bc.cA == NULL || !*bc.cA)
899 ret = HX509_PARENT_NOT_CA;
900 else if (bc.pathLenConstraint)
901 if (depth - 1 > *bc.pathLenConstraint)
902 ret = HX509_CA_PATH_TOO_DEEP;
905 free_BasicConstraints(&bc);
910 _hx509_cert_is_parent_cmp(const Certificate *subject,
911 const Certificate *issuer,
912 int allow_self_signed)
915 AuthorityKeyIdentifier ai;
916 SubjectKeyIdentifier si;
917 int ret_ai, ret_si, ret;
919 ret = _hx509_name_cmp(&issuer->tbsCertificate.subject,
920 &subject->tbsCertificate.issuer,
927 memset(&ai, 0, sizeof(ai));
928 memset(&si, 0, sizeof(si));
931 * Try to find AuthorityKeyIdentifier, if it's not present in the
932 * subject certificate nor the parent.
935 ret_ai = find_extension_auth_key_id(subject, &ai);
936 if (ret_ai && ret_ai != HX509_EXTENSION_NOT_FOUND)
938 ret_si = _hx509_find_extension_subject_key_id(issuer, &si);
939 if (ret_si && ret_si != HX509_EXTENSION_NOT_FOUND)
942 if (ret_si && ret_ai)
947 if (allow_self_signed) {
950 } else if (ai.keyIdentifier) {
956 if (ai.keyIdentifier == NULL) {
959 if (ai.authorityCertIssuer == NULL)
961 if (ai.authorityCertSerialNumber == NULL)
964 diff = der_heim_integer_cmp(ai.authorityCertSerialNumber,
965 &issuer->tbsCertificate.serialNumber);
968 if (ai.authorityCertIssuer->len != 1)
970 if (ai.authorityCertIssuer->val[0].element != choice_GeneralName_directoryName)
974 ai.authorityCertIssuer->val[0].u.directoryName.element;
976 ai.authorityCertIssuer->val[0].u.directoryName.u.rdnSequence;
978 ret = _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(hx509_context context,
1022 const Certificate *cert,
1026 ret = _hx509_name_cmp(&cert->tbsCertificate.subject,
1027 &cert->tbsCertificate.issuer, &diff);
1028 *self_signed = (diff == 0);
1030 hx509_set_error_string(context, 0, ret,
1031 "Failed to check if self signed");
1033 ret = _hx509_self_signed_valid(context, &cert->signatureAlgorithm);
1039 * The subjectName is "null" when it's empty set of relative DBs.
1043 subject_null_p(const Certificate *c)
1045 return c->tbsCertificate.subject.u.rdnSequence.len == 0;
1050 find_parent(hx509_context context,
1052 hx509_certs trust_anchors,
1058 AuthorityKeyIdentifier ai;
1063 memset(&ai, 0, sizeof(ai));
1065 _hx509_query_clear(&q);
1067 if (!subject_null_p(current->data)) {
1068 q.match |= HX509_QUERY_FIND_ISSUER_CERT;
1069 q.subject = _hx509_get_cert(current);
1071 ret = find_extension_auth_key_id(current->data, &ai);
1073 hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
1074 "Subjectless certificate missing AuthKeyID");
1075 return HX509_CERTIFICATE_MALFORMED;
1078 if (ai.keyIdentifier == NULL) {
1079 free_AuthorityKeyIdentifier(&ai);
1080 hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
1081 "Subjectless certificate missing keyIdentifier "
1082 "inside AuthKeyID");
1083 return HX509_CERTIFICATE_MALFORMED;
1086 q.subject_id = ai.keyIdentifier;
1087 q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID;
1091 q.match |= HX509_QUERY_NO_MATCH_PATH;
1094 q.timenow = time_now;
1095 q.match |= HX509_QUERY_MATCH_TIME;
1097 ret = hx509_certs_find(context, pool, &q, parent);
1099 free_AuthorityKeyIdentifier(&ai);
1102 q.match &= ~HX509_QUERY_MATCH_TIME;
1105 if (trust_anchors) {
1106 ret = hx509_certs_find(context, trust_anchors, &q, parent);
1108 free_AuthorityKeyIdentifier(&ai);
1112 free_AuthorityKeyIdentifier(&ai);
1118 ret = hx509_cert_get_subject(current, &name);
1120 hx509_clear_error_string(context);
1121 return HX509_ISSUER_NOT_FOUND;
1123 ret = hx509_name_to_string(name, &str);
1124 hx509_name_free(&name);
1126 hx509_clear_error_string(context);
1127 return HX509_ISSUER_NOT_FOUND;
1130 hx509_set_error_string(context, 0, HX509_ISSUER_NOT_FOUND,
1131 "Failed to find issuer for "
1132 "certificate with subject: '%s'", str);
1135 return HX509_ISSUER_NOT_FOUND;
1143 is_proxy_cert(hx509_context context,
1144 const Certificate *cert,
1145 ProxyCertInfo *rinfo)
1154 memset(rinfo, 0, sizeof(*rinfo));
1156 e = find_extension(cert, &asn1_oid_id_pkix_pe_proxyCertInfo, &i);
1158 hx509_clear_error_string(context);
1159 return HX509_EXTENSION_NOT_FOUND;
1162 ret = decode_ProxyCertInfo(e->extnValue.data,
1163 e->extnValue.length,
1167 hx509_clear_error_string(context);
1170 if (size != e->extnValue.length) {
1171 free_ProxyCertInfo(&info);
1172 hx509_clear_error_string(context);
1173 return HX509_EXTRA_DATA_AFTER_STRUCTURE;
1176 free_ProxyCertInfo(&info);
1184 * Path operations are like MEMORY based keyset, but with exposed
1185 * internal so we can do easy searches.
1189 _hx509_path_append(hx509_context context, hx509_path *path, hx509_cert cert)
1192 val = realloc(path->val, (path->len + 1) * sizeof(path->val[0]));
1194 hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1199 path->val[path->len] = hx509_cert_ref(cert);
1206 _hx509_path_free(hx509_path *path)
1210 for (i = 0; i < path->len; i++)
1211 hx509_cert_free(path->val[i]);
1218 * Find path by looking up issuer for the top certificate and continue
1219 * until an anchor certificate is found or max limit is found. A
1220 * certificate never included twice in the path.
1222 * If the trust anchors are not given, calculate optimistic path, just
1223 * follow the chain upward until we no longer find a parent or we hit
1224 * the max path limit. In this case, a failure will always be returned
1225 * depending on what error condition is hit first.
1227 * The path includes a path from the top certificate to the anchor
1230 * The caller needs to free `path´ both on successful built path and
1235 _hx509_calculate_path(hx509_context context,
1238 hx509_certs anchors,
1239 unsigned int max_depth,
1244 hx509_cert parent, current;
1248 max_depth = HX509_VERIFY_MAX_DEPTH;
1250 ret = _hx509_path_append(context, path, cert);
1254 current = hx509_cert_ref(cert);
1256 while (!certificate_is_anchor(context, anchors, current)) {
1258 ret = find_parent(context, time_now, anchors, path,
1259 pool, current, &parent);
1260 hx509_cert_free(current);
1264 ret = _hx509_path_append(context, path, parent);
1269 if (path->len > max_depth) {
1270 hx509_cert_free(current);
1271 hx509_set_error_string(context, 0, HX509_PATH_TOO_LONG,
1272 "Path too long while bulding "
1273 "certificate chain");
1274 return HX509_PATH_TOO_LONG;
1278 if ((flags & HX509_CALCULATE_PATH_NO_ANCHOR) &&
1280 certificate_is_anchor(context, anchors, path->val[path->len - 1]))
1282 hx509_cert_free(path->val[path->len - 1]);
1286 hx509_cert_free(current);
1291 _hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier *p,
1292 const AlgorithmIdentifier *q)
1295 diff = der_heim_oid_cmp(&p->algorithm, &q->algorithm);
1298 if (p->parameters) {
1300 return heim_any_cmp(p->parameters,
1313 _hx509_Certificate_cmp(const Certificate *p, const Certificate *q)
1316 diff = der_heim_bit_string_cmp(&p->signatureValue, &q->signatureValue);
1319 diff = _hx509_AlgorithmIdentifier_cmp(&p->signatureAlgorithm,
1320 &q->signatureAlgorithm);
1323 diff = der_heim_octet_string_cmp(&p->tbsCertificate._save,
1324 &q->tbsCertificate._save);
1329 * Compare to hx509 certificate object, useful for sorting.
1331 * @param p a hx509 certificate object.
1332 * @param q a hx509 certificate object.
1334 * @return 0 the objects are the same, returns > 0 is p is "larger"
1335 * then q, < 0 if p is "smaller" then q.
1337 * @ingroup hx509_cert
1341 hx509_cert_cmp(hx509_cert p, hx509_cert q)
1343 return _hx509_Certificate_cmp(p->data, q->data);
1347 * Return the name of the issuer of the hx509 certificate.
1349 * @param p a hx509 certificate object.
1350 * @param name a pointer to a hx509 name, should be freed by
1351 * hx509_name_free().
1353 * @return An hx509 error code, see hx509_get_error_string().
1355 * @ingroup hx509_cert
1359 hx509_cert_get_issuer(hx509_cert p, hx509_name *name)
1361 return _hx509_name_from_Name(&p->data->tbsCertificate.issuer, name);
1365 * Return the name of the subject of the hx509 certificate.
1367 * @param p a hx509 certificate object.
1368 * @param name a pointer to a hx509 name, should be freed by
1369 * hx509_name_free(). See also hx509_cert_get_base_subject().
1371 * @return An hx509 error code, see hx509_get_error_string().
1373 * @ingroup hx509_cert
1377 hx509_cert_get_subject(hx509_cert p, hx509_name *name)
1379 return _hx509_name_from_Name(&p->data->tbsCertificate.subject, name);
1383 * Return the name of the base subject of the hx509 certificate. If
1384 * the certiicate is a verified proxy certificate, the this function
1385 * return the base certificate (root of the proxy chain). If the proxy
1386 * certificate is not verified with the base certificate
1387 * HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned.
1389 * @param context a hx509 context.
1390 * @param c a hx509 certificate object.
1391 * @param name a pointer to a hx509 name, should be freed by
1392 * hx509_name_free(). See also hx509_cert_get_subject().
1394 * @return An hx509 error code, see hx509_get_error_string().
1396 * @ingroup hx509_cert
1400 hx509_cert_get_base_subject(hx509_context context, hx509_cert c,
1404 return hx509_name_copy(context, c->basename, name);
1405 if (is_proxy_cert(context, c->data, NULL) == 0) {
1406 int ret = HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED;
1407 hx509_set_error_string(context, 0, ret,
1408 "Proxy certificate have not been "
1409 "canonicalize yet, no base name");
1412 return _hx509_name_from_Name(&c->data->tbsCertificate.subject, name);
1416 * Get serial number of the certificate.
1418 * @param p a hx509 certificate object.
1419 * @param i serial number, should be freed ith der_free_heim_integer().
1421 * @return An hx509 error code, see hx509_get_error_string().
1423 * @ingroup hx509_cert
1427 hx509_cert_get_serialnumber(hx509_cert p, heim_integer *i)
1429 return der_copy_heim_integer(&p->data->tbsCertificate.serialNumber, i);
1433 * Get notBefore time of the certificate.
1435 * @param p a hx509 certificate object.
1437 * @return return not before time
1439 * @ingroup hx509_cert
1443 hx509_cert_get_notBefore(hx509_cert p)
1445 return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notBefore);
1449 * Get notAfter time of the certificate.
1451 * @param p a hx509 certificate object.
1453 * @return return not after time.
1455 * @ingroup hx509_cert
1459 hx509_cert_get_notAfter(hx509_cert p)
1461 return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notAfter);
1465 * Get the SubjectPublicKeyInfo structure from the hx509 certificate.
1467 * @param context a hx509 context.
1468 * @param p a hx509 certificate object.
1469 * @param spki SubjectPublicKeyInfo, should be freed with
1470 * free_SubjectPublicKeyInfo().
1472 * @return An hx509 error code, see hx509_get_error_string().
1474 * @ingroup hx509_cert
1478 hx509_cert_get_SPKI(hx509_context context, hx509_cert p, SubjectPublicKeyInfo *spki)
1482 ret = copy_SubjectPublicKeyInfo(&p->data->tbsCertificate.subjectPublicKeyInfo, spki);
1484 hx509_set_error_string(context, 0, ret, "Failed to copy SPKI");
1489 * Get the AlgorithmIdentifier from the hx509 certificate.
1491 * @param context a hx509 context.
1492 * @param p a hx509 certificate object.
1493 * @param alg AlgorithmIdentifier, should be freed with
1494 * free_AlgorithmIdentifier(). The algorithmidentifier is
1495 * typicly rsaEncryption, or id-ecPublicKey, or some other
1496 * public key mechanism.
1498 * @return An hx509 error code, see hx509_get_error_string().
1500 * @ingroup hx509_cert
1504 hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context,
1506 AlgorithmIdentifier *alg)
1510 ret = copy_AlgorithmIdentifier(&p->data->tbsCertificate.subjectPublicKeyInfo.algorithm, alg);
1512 hx509_set_error_string(context, 0, ret,
1513 "Failed to copy SPKI AlgorithmIdentifier");
1518 get_x_unique_id(hx509_context context, const char *name,
1519 const heim_bit_string *cert, heim_bit_string *subject)
1524 ret = HX509_EXTENSION_NOT_FOUND;
1525 hx509_set_error_string(context, 0, ret, "%s unique id doesn't exists", name);
1528 ret = der_copy_bit_string(cert, subject);
1530 hx509_set_error_string(context, 0, ret, "malloc out of memory", name);
1537 * Get a copy of the Issuer Unique ID
1539 * @param context a hx509_context
1540 * @param p a hx509 certificate
1541 * @param issuer the issuer id returned, free with der_free_bit_string()
1543 * @return An hx509 error code, see hx509_get_error_string(). The
1544 * error code HX509_EXTENSION_NOT_FOUND is returned if the certificate
1545 * doesn't have a issuerUniqueID
1547 * @ingroup hx509_cert
1551 hx509_cert_get_issuer_unique_id(hx509_context context, hx509_cert p, heim_bit_string *issuer)
1553 return get_x_unique_id(context, "issuer", p->data->tbsCertificate.issuerUniqueID, issuer);
1557 * Get a copy of the Subect Unique ID
1559 * @param context a hx509_context
1560 * @param p a hx509 certificate
1561 * @param subject the subject id returned, free with der_free_bit_string()
1563 * @return An hx509 error code, see hx509_get_error_string(). The
1564 * error code HX509_EXTENSION_NOT_FOUND is returned if the certificate
1565 * doesn't have a subjectUniqueID
1567 * @ingroup hx509_cert
1571 hx509_cert_get_subject_unique_id(hx509_context context, hx509_cert p, heim_bit_string *subject)
1573 return get_x_unique_id(context, "subject", p->data->tbsCertificate.subjectUniqueID, subject);
1578 _hx509_cert_private_key(hx509_cert p)
1580 return p->private_key;
1584 hx509_cert_have_private_key(hx509_cert p)
1586 return p->private_key ? 1 : 0;
1591 _hx509_cert_private_key_exportable(hx509_cert p)
1593 if (p->private_key == NULL)
1595 return _hx509_private_key_exportable(p->private_key);
1599 _hx509_cert_private_decrypt(hx509_context context,
1600 const heim_octet_string *ciphertext,
1601 const heim_oid *encryption_oid,
1603 heim_octet_string *cleartext)
1605 cleartext->data = NULL;
1606 cleartext->length = 0;
1608 if (p->private_key == NULL) {
1609 hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
1610 "Private key missing");
1611 return HX509_PRIVATE_KEY_MISSING;
1614 return hx509_private_key_private_decrypt(context,
1622 hx509_cert_public_encrypt(hx509_context context,
1623 const heim_octet_string *cleartext,
1625 heim_oid *encryption_oid,
1626 heim_octet_string *ciphertext)
1628 return _hx509_public_encrypt(context,
1630 encryption_oid, ciphertext);
1638 _hx509_Time2time_t(const Time *t)
1640 switch(t->element) {
1641 case choice_Time_utcTime:
1642 return t->u.utcTime;
1643 case choice_Time_generalTime:
1644 return t->u.generalTime;
1654 init_name_constraints(hx509_name_constraints *nc)
1656 memset(nc, 0, sizeof(*nc));
1661 add_name_constraints(hx509_context context, const Certificate *c, int not_ca,
1662 hx509_name_constraints *nc)
1664 NameConstraints tnc;
1667 ret = find_extension_name_constraints(c, &tnc);
1668 if (ret == HX509_EXTENSION_NOT_FOUND)
1671 hx509_set_error_string(context, 0, ret, "Failed getting NameConstraints");
1673 } else if (not_ca) {
1674 ret = HX509_VERIFY_CONSTRAINTS;
1675 hx509_set_error_string(context, 0, ret, "Not a CA and "
1676 "have NameConstraints");
1678 NameConstraints *val;
1679 val = realloc(nc->val, sizeof(nc->val[0]) * (nc->len + 1));
1681 hx509_clear_error_string(context);
1686 ret = copy_NameConstraints(&tnc, &nc->val[nc->len]);
1688 hx509_clear_error_string(context);
1694 free_NameConstraints(&tnc);
1699 match_RDN(const RelativeDistinguishedName *c,
1700 const RelativeDistinguishedName *n)
1704 if (c->len != n->len)
1705 return HX509_NAME_CONSTRAINT_ERROR;
1707 for (i = 0; i < n->len; i++) {
1710 if (der_heim_oid_cmp(&c->val[i].type, &n->val[i].type) != 0)
1711 return HX509_NAME_CONSTRAINT_ERROR;
1712 ret = _hx509_name_ds_cmp(&c->val[i].value, &n->val[i].value, &diff);
1716 return HX509_NAME_CONSTRAINT_ERROR;
1722 match_X501Name(const Name *c, const Name *n)
1727 if (c->element != choice_Name_rdnSequence
1728 || n->element != choice_Name_rdnSequence)
1730 if (c->u.rdnSequence.len > n->u.rdnSequence.len)
1731 return HX509_NAME_CONSTRAINT_ERROR;
1732 for (i = 0; i < c->u.rdnSequence.len; i++) {
1733 ret = match_RDN(&c->u.rdnSequence.val[i], &n->u.rdnSequence.val[i]);
1742 match_general_name(const GeneralName *c, const GeneralName *n, int *match)
1745 * Name constraints only apply to the same name type, see RFC3280,
1748 assert(c->element == n->element);
1750 switch(c->element) {
1751 case choice_GeneralName_otherName:
1752 if (der_heim_oid_cmp(&c->u.otherName.type_id,
1753 &n->u.otherName.type_id) != 0)
1754 return HX509_NAME_CONSTRAINT_ERROR;
1755 if (heim_any_cmp(&c->u.otherName.value,
1756 &n->u.otherName.value) != 0)
1757 return HX509_NAME_CONSTRAINT_ERROR;
1760 case choice_GeneralName_rfc822Name: {
1763 s = memchr(c->u.rfc822Name.data, '@', c->u.rfc822Name.length);
1765 if (der_printable_string_cmp(&c->u.rfc822Name, &n->u.rfc822Name) != 0)
1766 return HX509_NAME_CONSTRAINT_ERROR;
1768 s = memchr(n->u.rfc822Name.data, '@', n->u.rfc822Name.length);
1770 return HX509_NAME_CONSTRAINT_ERROR;
1771 len1 = c->u.rfc822Name.length;
1772 len2 = n->u.rfc822Name.length -
1773 (s - ((char *)n->u.rfc822Name.data));
1775 return HX509_NAME_CONSTRAINT_ERROR;
1776 if (memcmp(s + 1 + len2 - len1, c->u.rfc822Name.data, len1) != 0)
1777 return HX509_NAME_CONSTRAINT_ERROR;
1778 if (len1 < len2 && s[len2 - len1 + 1] != '.')
1779 return HX509_NAME_CONSTRAINT_ERROR;
1784 case choice_GeneralName_dNSName: {
1788 lenc = c->u.dNSName.length;
1789 lenn = n->u.dNSName.length;
1791 return HX509_NAME_CONSTRAINT_ERROR;
1792 ptr = n->u.dNSName.data;
1793 if (memcmp(&ptr[lenn - lenc], c->u.dNSName.data, lenc) != 0)
1794 return HX509_NAME_CONSTRAINT_ERROR;
1795 if (lenn != lenc && ptr[lenn - lenc - 1] != '.')
1796 return HX509_NAME_CONSTRAINT_ERROR;
1800 case choice_GeneralName_directoryName: {
1801 Name c_name, n_name;
1804 c_name._save.data = NULL;
1805 c_name._save.length = 0;
1806 c_name.element = c->u.directoryName.element;
1807 c_name.u.rdnSequence = c->u.directoryName.u.rdnSequence;
1809 n_name._save.data = NULL;
1810 n_name._save.length = 0;
1811 n_name.element = n->u.directoryName.element;
1812 n_name.u.rdnSequence = n->u.directoryName.u.rdnSequence;
1814 ret = match_X501Name(&c_name, &n_name);
1819 case choice_GeneralName_uniformResourceIdentifier:
1820 case choice_GeneralName_iPAddress:
1821 case choice_GeneralName_registeredID:
1823 return HX509_NAME_CONSTRAINT_ERROR;
1828 match_alt_name(const GeneralName *n, const Certificate *c,
1829 int *same, int *match)
1837 ret = find_extension_subject_alt_name(c, &i, &sa);
1838 if (ret == HX509_EXTENSION_NOT_FOUND) {
1841 } else if (ret != 0)
1844 for (j = 0; j < sa.len; j++) {
1845 if (n->element == sa.val[j].element) {
1847 ret = match_general_name(n, &sa.val[j], match);
1850 free_GeneralNames(&sa);
1857 match_tree(const GeneralSubtrees *t, const Certificate *c, int *match)
1859 int name, alt_name, same;
1863 name = alt_name = same = *match = 0;
1864 for (i = 0; i < t->len; i++) {
1865 if (t->val[i].minimum && t->val[i].maximum)
1869 * If the constraint apply to directoryNames, test is with
1870 * subjectName of the certificate if the certificate have a
1871 * non-null (empty) subjectName.
1874 if (t->val[i].base.element == choice_GeneralName_directoryName
1875 && !subject_null_p(c))
1877 GeneralName certname;
1879 memset(&certname, 0, sizeof(certname));
1880 certname.element = choice_GeneralName_directoryName;
1881 certname.u.directoryName.element =
1882 c->tbsCertificate.subject.element;
1883 certname.u.directoryName.u.rdnSequence =
1884 c->tbsCertificate.subject.u.rdnSequence;
1886 ret = match_general_name(&t->val[i].base, &certname, &name);
1889 /* Handle subjectAltNames, this is icky since they
1890 * restrictions only apply if the subjectAltName is of the
1891 * same type. So if there have been a match of type, require
1892 * altname to be set.
1894 ret = match_alt_name(&t->val[i].base, c, &same, &alt_name);
1896 if (name && (!same || alt_name))
1902 check_name_constraints(hx509_context context,
1903 const hx509_name_constraints *nc,
1904 const Certificate *c)
1909 for (i = 0 ; i < nc->len; i++) {
1912 if (nc->val[i].permittedSubtrees) {
1913 GeneralSubtrees_SET(&gs, nc->val[i].permittedSubtrees);
1914 ret = match_tree(&gs, c, &match);
1916 hx509_clear_error_string(context);
1919 /* allow null subjectNames, they wont matches anything */
1920 if (match == 0 && !subject_null_p(c)) {
1921 hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS,
1922 "Error verify constraints, "
1923 "certificate didn't match any "
1924 "permitted subtree");
1925 return HX509_VERIFY_CONSTRAINTS;
1928 if (nc->val[i].excludedSubtrees) {
1929 GeneralSubtrees_SET(&gs, nc->val[i].excludedSubtrees);
1930 ret = match_tree(&gs, c, &match);
1932 hx509_clear_error_string(context);
1936 hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS,
1937 "Error verify constraints, "
1938 "certificate included in excluded "
1940 return HX509_VERIFY_CONSTRAINTS;
1948 free_name_constraints(hx509_name_constraints *nc)
1952 for (i = 0 ; i < nc->len; i++)
1953 free_NameConstraints(&nc->val[i]);
1958 * Build and verify the path for the certificate to the trust anchor
1959 * specified in the verify context. The path is constructed from the
1960 * certificate, the pool and the trust anchors.
1962 * @param context A hx509 context.
1963 * @param ctx A hx509 verification context.
1964 * @param cert the certificate to build the path from.
1965 * @param pool A keyset of certificates to build the chain from.
1967 * @return An hx509 error code, see hx509_get_error_string().
1969 * @ingroup hx509_verify
1973 hx509_verify_path(hx509_context context,
1974 hx509_verify_ctx ctx,
1978 hx509_name_constraints nc;
1980 int ret, proxy_cert_depth, selfsigned_depth, diff;
1984 hx509_certs anchors = NULL;
1986 memset(&proxy_issuer, 0, sizeof(proxy_issuer));
1988 ret = init_name_constraints(&nc);
1995 if ((ctx->flags & HX509_VERIFY_CTX_F_TIME_SET) == 0)
1996 ctx->time_now = time(NULL);
2001 if (ctx->trust_anchors)
2002 anchors = hx509_certs_ref(ctx->trust_anchors);
2003 else if (context->default_trust_anchors && ALLOW_DEF_TA(ctx))
2004 anchors = hx509_certs_ref(context->default_trust_anchors);
2006 ret = hx509_certs_init(context, "MEMORY:no-TA", 0, NULL, &anchors);
2012 * Calculate the path from the certificate user presented to the
2015 ret = _hx509_calculate_path(context, 0, ctx->time_now,
2016 anchors, ctx->max_depth,
2022 * Check CA and proxy certificate chain from the top of the
2023 * certificate chain. Also check certificate is valid with respect
2024 * to the current time.
2028 proxy_cert_depth = 0;
2029 selfsigned_depth = 0;
2031 if (ctx->flags & HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE)
2036 for (i = 0; i < path.len; i++) {
2040 c = _hx509_get_cert(path.val[i]);
2043 * Lets do some basic check on issuer like
2044 * keyUsage.keyCertSign and basicConstraints.cA bit depending
2045 * on what type of certificate this is.
2051 /* XXX make constants for keyusage */
2052 ret = check_key_usage(context, c, 1 << 5,
2053 REQUIRE_RFC3280(ctx) ? TRUE : FALSE);
2055 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
2056 "Key usage missing from CA certificate");
2060 /* self signed cert doesn't add to path length */
2061 if (i + 1 != path.len) {
2064 ret = certificate_is_self_signed(context, c, &selfsigned);
2075 if (is_proxy_cert(context, c, &info) == 0) {
2078 if (info.pCPathLenConstraint != NULL &&
2079 *info.pCPathLenConstraint < i)
2081 free_ProxyCertInfo(&info);
2082 ret = HX509_PATH_TOO_LONG;
2083 hx509_set_error_string(context, 0, ret,
2084 "Proxy certificate chain "
2085 "longer then allowed");
2088 /* XXX MUST check info.proxyPolicy */
2089 free_ProxyCertInfo(&info);
2092 if (find_extension(c, &asn1_oid_id_x509_ce_subjectAltName, &j)) {
2093 ret = HX509_PROXY_CERT_INVALID;
2094 hx509_set_error_string(context, 0, ret,
2095 "Proxy certificate have explicity "
2096 "forbidden subjectAltName");
2101 if (find_extension(c, &asn1_oid_id_x509_ce_issuerAltName, &j)) {
2102 ret = HX509_PROXY_CERT_INVALID;
2103 hx509_set_error_string(context, 0, ret,
2104 "Proxy certificate have explicity "
2105 "forbidden issuerAltName");
2110 * The subject name of the proxy certificate should be
2111 * CN=XXX,<proxy issuer>, prune of CN and check if its
2112 * the same over the whole chain of proxy certs and
2113 * then check with the EE cert when we get to it.
2116 if (proxy_cert_depth) {
2117 ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.subject, &diff);
2119 hx509_set_error_string(context, 0, ret, "Out of memory");
2123 ret = HX509_PROXY_CERT_NAME_WRONG;
2124 hx509_set_error_string(context, 0, ret,
2125 "Base proxy name not right");
2130 free_Name(&proxy_issuer);
2132 ret = copy_Name(&c->tbsCertificate.subject, &proxy_issuer);
2134 hx509_clear_error_string(context);
2138 j = proxy_issuer.u.rdnSequence.len;
2139 if (proxy_issuer.u.rdnSequence.len < 2
2140 || proxy_issuer.u.rdnSequence.val[j - 1].len > 1
2141 || der_heim_oid_cmp(&proxy_issuer.u.rdnSequence.val[j - 1].val[0].type,
2142 &asn1_oid_id_at_commonName))
2144 ret = HX509_PROXY_CERT_NAME_WRONG;
2145 hx509_set_error_string(context, 0, ret,
2146 "Proxy name too short or "
2147 "does not have Common name "
2152 free_RelativeDistinguishedName(&proxy_issuer.u.rdnSequence.val[j - 1]);
2153 proxy_issuer.u.rdnSequence.len -= 1;
2155 ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.issuer, &diff);
2157 hx509_set_error_string(context, 0, ret, "Out of memory");
2161 ret = HX509_PROXY_CERT_NAME_WRONG;
2162 hx509_set_error_string(context, 0, ret,
2163 "Proxy issuer name not as expected");
2170 * Now we are done with the proxy certificates, this
2171 * cert was an EE cert and we we will fall though to
2172 * EE checking below.
2180 * If there where any proxy certificates in the chain
2181 * (proxy_cert_depth > 0), check that the proxy issuer
2182 * matched proxy certificates "base" subject.
2184 if (proxy_cert_depth) {
2186 ret = _hx509_name_cmp(&proxy_issuer,
2187 &c->tbsCertificate.subject, &diff);
2189 hx509_set_error_string(context, 0, ret, "out of memory");
2193 ret = HX509_PROXY_CERT_NAME_WRONG;
2194 hx509_clear_error_string(context);
2198 hx509_name_free(&cert->basename);
2200 ret = _hx509_name_from_Name(&proxy_issuer, &cert->basename);
2202 hx509_clear_error_string(context);
2210 ret = check_basic_constraints(context, c, type,
2211 i - proxy_cert_depth - selfsigned_depth);
2216 * Don't check the trust anchors expiration time since they
2217 * are transported out of band, from RFC3820.
2219 if (i + 1 != path.len || CHECK_TA(ctx)) {
2221 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2222 if (t > ctx->time_now) {
2223 ret = HX509_CERT_USED_BEFORE_TIME;
2224 hx509_clear_error_string(context);
2227 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
2228 if (t < ctx->time_now) {
2229 ret = HX509_CERT_USED_AFTER_TIME;
2230 hx509_clear_error_string(context);
2235 if (type == EE_CERT)
2237 else if (type == PROXY_CERT)
2242 * Verify constraints, do this backward so path constraints are
2243 * checked in the right order.
2246 for (ret = 0, k = path.len; k > 0; k--) {
2251 c = _hx509_get_cert(path.val[i]);
2253 ret = certificate_is_self_signed(context, c, &selfsigned);
2257 /* verify name constraints, not for selfsigned and anchor */
2258 if (!selfsigned || i + 1 != path.len) {
2259 ret = check_name_constraints(context, &nc, c);
2264 ret = add_name_constraints(context, c, i == 0, &nc);
2268 /* XXX verify all other silly constraints */
2273 * Verify that no certificates has been revoked.
2276 if (ctx->revoke_ctx) {
2279 ret = hx509_certs_init(context, "MEMORY:revoke-certs", 0,
2284 for (i = 0; i < path.len; i++) {
2285 ret = hx509_certs_add(context, certs, path.val[i]);
2287 hx509_certs_free(&certs);
2291 ret = hx509_certs_merge(context, certs, pool);
2293 hx509_certs_free(&certs);
2297 for (i = 0; i < path.len - 1; i++) {
2298 size_t parent = (i < path.len - 1) ? i + 1 : i;
2300 ret = hx509_revoke_verify(context,
2307 hx509_certs_free(&certs);
2311 hx509_certs_free(&certs);
2315 * Verify signatures, do this backward so public key working
2316 * parameter is passed up from the anchor up though the chain.
2319 for (k = path.len; k > 0; k--) {
2324 c = _hx509_get_cert(path.val[i]);
2326 /* is last in chain (trust anchor) */
2327 if (i + 1 == path.len) {
2330 signer = path.val[i];
2332 ret = certificate_is_self_signed(context, signer->data, &selfsigned);
2336 /* if trust anchor is not self signed, don't check sig */
2340 /* take next certificate in chain */
2341 signer = path.val[i + 1];
2344 /* verify signatureValue */
2345 ret = _hx509_verify_signature_bitstring(context,
2347 &c->signatureAlgorithm,
2348 &c->tbsCertificate._save,
2349 &c->signatureValue);
2351 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
2352 "Failed to verify signature of certificate");
2356 * Verify that the sigature algorithm "best-before" date is
2357 * before the creation date of the certificate, do this for
2358 * trust anchors too, since any trust anchor that is created
2359 * after a algorithm is known to be bad deserved to be invalid.
2361 * Skip the leaf certificate for now...
2364 if (i != 0 && (ctx->flags & HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK) == 0) {
2366 _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2367 ret = _hx509_signature_best_before(context,
2368 &c->signatureAlgorithm,
2376 hx509_certs_free(&anchors);
2377 free_Name(&proxy_issuer);
2378 free_name_constraints(&nc);
2379 _hx509_path_free(&path);
2385 * Verify a signature made using the private key of an certificate.
2387 * @param context A hx509 context.
2388 * @param signer the certificate that made the signature.
2389 * @param alg algorthm that was used to sign the data.
2390 * @param data the data that was signed.
2391 * @param sig the sigature to verify.
2393 * @return An hx509 error code, see hx509_get_error_string().
2395 * @ingroup hx509_crypto
2399 hx509_verify_signature(hx509_context context,
2400 const hx509_cert signer,
2401 const AlgorithmIdentifier *alg,
2402 const heim_octet_string *data,
2403 const heim_octet_string *sig)
2405 return _hx509_verify_signature(context, signer, alg, data, sig);
2409 _hx509_verify_signature_bitstring(hx509_context context,
2410 const hx509_cert signer,
2411 const AlgorithmIdentifier *alg,
2412 const heim_octet_string *data,
2413 const heim_bit_string *sig)
2415 heim_octet_string os;
2417 if (sig->length & 7) {
2418 hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT,
2419 "signature not multiple of 8 bits");
2420 return HX509_CRYPTO_SIG_INVALID_FORMAT;
2423 os.data = sig->data;
2424 os.length = sig->length / 8;
2426 return _hx509_verify_signature(context, signer, alg, data, &os);
2432 * Verify that the certificate is allowed to be used for the hostname
2435 * @param context A hx509 context.
2436 * @param cert the certificate to match with
2437 * @param flags Flags to modify the behavior:
2438 * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok
2439 * @param type type of hostname:
2440 * - HX509_HN_HOSTNAME for plain hostname.
2441 * - HX509_HN_DNSSRV for DNS SRV names.
2442 * @param hostname the hostname to check
2443 * @param sa address of the host
2444 * @param sa_size length of address
2446 * @return An hx509 error code, see hx509_get_error_string().
2448 * @ingroup hx509_cert
2452 hx509_verify_hostname(hx509_context context,
2453 const hx509_cert cert,
2455 hx509_hostname_type type,
2456 const char *hostname,
2457 const struct sockaddr *sa,
2458 /* XXX krb5_socklen_t */ int sa_size)
2465 if (sa && sa_size <= 0)
2468 memset(&san, 0, sizeof(san));
2472 ret = find_extension_subject_alt_name(cert->data, &i, &san);
2473 if (ret == HX509_EXTENSION_NOT_FOUND)
2476 return HX509_PARSING_NAME_FAILED;
2478 for (j = 0; j < san.len; j++) {
2479 switch (san.val[j].element) {
2480 case choice_GeneralName_dNSName: {
2481 heim_printable_string hn;
2482 hn.data = rk_UNCONST(hostname);
2483 hn.length = strlen(hostname);
2485 if (der_printable_string_cmp(&san.val[j].u.dNSName, &hn) == 0) {
2486 free_GeneralNames(&san);
2495 free_GeneralNames(&san);
2498 name = &cert->data->tbsCertificate.subject;
2500 /* Find first CN= in the name, and try to match the hostname on that */
2501 for (ret = 0, k = name->u.rdnSequence.len; ret == 0 && k > 0; k--) {
2503 for (j = 0; ret == 0 && j < name->u.rdnSequence.val[i].len; j++) {
2504 AttributeTypeAndValue *n = &name->u.rdnSequence.val[i].val[j];
2506 if (der_heim_oid_cmp(&n->type, &asn1_oid_id_at_commonName) == 0) {
2507 DirectoryString *ds = &n->value;
2508 switch (ds->element) {
2509 case choice_DirectoryString_printableString: {
2510 heim_printable_string hn;
2511 hn.data = rk_UNCONST(hostname);
2512 hn.length = strlen(hostname);
2514 if (der_printable_string_cmp(&ds->u.printableString, &hn) == 0)
2518 case choice_DirectoryString_ia5String: {
2520 hn.data = rk_UNCONST(hostname);
2521 hn.length = strlen(hostname);
2523 if (der_ia5_string_cmp(&ds->u.ia5String, &hn) == 0)
2527 case choice_DirectoryString_utf8String:
2528 if (strcasecmp(ds->u.utf8String, hostname) == 0)
2533 ret = HX509_NAME_CONSTRAINT_ERROR;
2538 if ((flags & HX509_VHN_F_ALLOW_NO_MATCH) == 0)
2539 ret = HX509_NAME_CONSTRAINT_ERROR;
2545 _hx509_set_cert_attribute(hx509_context context,
2547 const heim_oid *oid,
2548 const heim_octet_string *attr)
2550 hx509_cert_attribute a;
2553 if (hx509_cert_get_attribute(cert, oid) != NULL)
2556 d = realloc(cert->attrs.val,
2557 sizeof(cert->attrs.val[0]) * (cert->attrs.len + 1));
2559 hx509_clear_error_string(context);
2562 cert->attrs.val = d;
2564 a = malloc(sizeof(*a));
2568 der_copy_octet_string(attr, &a->data);
2569 der_copy_oid(oid, &a->oid);
2571 cert->attrs.val[cert->attrs.len] = a;
2578 * Get an external attribute for the certificate, examples are
2579 * friendly name and id.
2581 * @param cert hx509 certificate object to search
2582 * @param oid an oid to search for.
2584 * @return an hx509_cert_attribute, only valid as long as the
2585 * certificate is referenced.
2587 * @ingroup hx509_cert
2590 hx509_cert_attribute
2591 hx509_cert_get_attribute(hx509_cert cert, const heim_oid *oid)
2594 for (i = 0; i < cert->attrs.len; i++)
2595 if (der_heim_oid_cmp(oid, &cert->attrs.val[i]->oid) == 0)
2596 return cert->attrs.val[i];
2601 * Set the friendly name on the certificate.
2603 * @param cert The certificate to set the friendly name on
2604 * @param name Friendly name.
2606 * @return An hx509 error code, see hx509_get_error_string().
2608 * @ingroup hx509_cert
2612 hx509_cert_set_friendly_name(hx509_cert cert, const char *name)
2614 if (cert->friendlyname)
2615 free(cert->friendlyname);
2616 cert->friendlyname = strdup(name);
2617 if (cert->friendlyname == NULL)
2623 * Get friendly name of the certificate.
2625 * @param cert cert to get the friendly name from.
2627 * @return an friendly name or NULL if there is. The friendly name is
2628 * only valid as long as the certificate is referenced.
2630 * @ingroup hx509_cert
2634 hx509_cert_get_friendly_name(hx509_cert cert)
2636 hx509_cert_attribute a;
2637 PKCS9_friendlyName n;
2642 if (cert->friendlyname)
2643 return cert->friendlyname;
2645 a = hx509_cert_get_attribute(cert, &asn1_oid_id_pkcs_9_at_friendlyName);
2649 ret = hx509_cert_get_subject(cert, &name);
2652 ret = hx509_name_to_string(name, &cert->friendlyname);
2653 hx509_name_free(&name);
2656 return cert->friendlyname;
2659 ret = decode_PKCS9_friendlyName(a->data.data, a->data.length, &n, &sz);
2664 free_PKCS9_friendlyName(&n);
2668 cert->friendlyname = malloc(n.val[0].length + 1);
2669 if (cert->friendlyname == NULL) {
2670 free_PKCS9_friendlyName(&n);
2674 for (i = 0; i < n.val[0].length; i++) {
2675 if (n.val[0].data[i] <= 0xff)
2676 cert->friendlyname[i] = n.val[0].data[i] & 0xff;
2678 cert->friendlyname[i] = 'X';
2680 cert->friendlyname[i] = '\0';
2681 free_PKCS9_friendlyName(&n);
2683 return cert->friendlyname;
2687 _hx509_query_clear(hx509_query *q)
2689 memset(q, 0, sizeof(*q));
2693 * Allocate an query controller. Free using hx509_query_free().
2695 * @param context A hx509 context.
2696 * @param q return pointer to a hx509_query.
2698 * @return An hx509 error code, see hx509_get_error_string().
2700 * @ingroup hx509_cert
2704 hx509_query_alloc(hx509_context context, hx509_query **q)
2706 *q = calloc(1, sizeof(**q));
2714 * Set match options for the hx509 query controller.
2716 * @param q query controller.
2717 * @param option options to control the query controller.
2719 * @return An hx509 error code, see hx509_get_error_string().
2721 * @ingroup hx509_cert
2725 hx509_query_match_option(hx509_query *q, hx509_query_option option)
2728 case HX509_QUERY_OPTION_PRIVATE_KEY:
2729 q->match |= HX509_QUERY_PRIVATE_KEY;
2731 case HX509_QUERY_OPTION_KU_ENCIPHERMENT:
2732 q->match |= HX509_QUERY_KU_ENCIPHERMENT;
2734 case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE:
2735 q->match |= HX509_QUERY_KU_DIGITALSIGNATURE;
2737 case HX509_QUERY_OPTION_KU_KEYCERTSIGN:
2738 q->match |= HX509_QUERY_KU_KEYCERTSIGN;
2740 case HX509_QUERY_OPTION_END:
2747 * Set the issuer and serial number of match in the query
2748 * controller. The function make copies of the isser and serial number.
2750 * @param q a hx509 query controller
2751 * @param issuer issuer to search for
2752 * @param serialNumber the serialNumber of the issuer.
2754 * @return An hx509 error code, see hx509_get_error_string().
2756 * @ingroup hx509_cert
2760 hx509_query_match_issuer_serial(hx509_query *q,
2762 const heim_integer *serialNumber)
2766 der_free_heim_integer(q->serial);
2769 q->serial = malloc(sizeof(*q->serial));
2770 if (q->serial == NULL)
2772 ret = der_copy_heim_integer(serialNumber, q->serial);
2778 if (q->issuer_name) {
2779 free_Name(q->issuer_name);
2780 free(q->issuer_name);
2782 q->issuer_name = malloc(sizeof(*q->issuer_name));
2783 if (q->issuer_name == NULL)
2785 ret = copy_Name(issuer, q->issuer_name);
2787 free(q->issuer_name);
2788 q->issuer_name = NULL;
2791 q->match |= HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME;
2796 * Set the query controller to match on a friendly name
2798 * @param q a hx509 query controller.
2799 * @param name a friendly name to match on
2801 * @return An hx509 error code, see hx509_get_error_string().
2803 * @ingroup hx509_cert
2807 hx509_query_match_friendly_name(hx509_query *q, const char *name)
2809 if (q->friendlyname)
2810 free(q->friendlyname);
2811 q->friendlyname = strdup(name);
2812 if (q->friendlyname == NULL)
2814 q->match |= HX509_QUERY_MATCH_FRIENDLY_NAME;
2819 * Set the query controller to require an one specific EKU (extended
2820 * key usage). Any previous EKU matching is overwitten. If NULL is
2821 * passed in as the eku, the EKU requirement is reset.
2823 * @param q a hx509 query controller.
2824 * @param eku an EKU to match on.
2826 * @return An hx509 error code, see hx509_get_error_string().
2828 * @ingroup hx509_cert
2832 hx509_query_match_eku(hx509_query *q, const heim_oid *eku)
2838 der_free_oid(q->eku);
2842 q->match &= ~HX509_QUERY_MATCH_EKU;
2845 der_free_oid(q->eku);
2847 q->eku = calloc(1, sizeof(*q->eku));
2851 ret = der_copy_oid(eku, q->eku);
2857 q->match |= HX509_QUERY_MATCH_EKU;
2863 hx509_query_match_expr(hx509_context context, hx509_query *q, const char *expr)
2866 _hx509_expr_free(q->expr);
2871 q->match &= ~HX509_QUERY_MATCH_EXPR;
2873 q->expr = _hx509_expr_parse(expr);
2875 q->match |= HX509_QUERY_MATCH_EXPR;
2882 * Set the query controller to match using a specific match function.
2884 * @param q a hx509 query controller.
2885 * @param func function to use for matching, if the argument is NULL,
2886 * the match function is removed.
2887 * @param ctx context passed to the function.
2889 * @return An hx509 error code, see hx509_get_error_string().
2891 * @ingroup hx509_cert
2895 hx509_query_match_cmp_func(hx509_query *q,
2896 int (*func)(hx509_context, hx509_cert, void *),
2900 q->match |= HX509_QUERY_MATCH_FUNCTION;
2902 q->match &= ~HX509_QUERY_MATCH_FUNCTION;
2904 q->cmp_func_ctx = ctx;
2909 * Free the query controller.
2911 * @param context A hx509 context.
2912 * @param q a pointer to the query controller.
2914 * @ingroup hx509_cert
2918 hx509_query_free(hx509_context context, hx509_query *q)
2924 der_free_heim_integer(q->serial);
2927 if (q->issuer_name) {
2928 free_Name(q->issuer_name);
2929 free(q->issuer_name);
2932 der_free_oid(q->eku);
2935 if (q->friendlyname)
2936 free(q->friendlyname);
2938 _hx509_expr_free(q->expr);
2940 memset(q, 0, sizeof(*q));
2945 _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert cert)
2947 Certificate *c = _hx509_get_cert(cert);
2950 _hx509_query_statistic(context, 1, q);
2952 if ((q->match & HX509_QUERY_FIND_ISSUER_CERT) &&
2953 _hx509_cert_is_parent_cmp(q->subject, c, 0) != 0)
2956 if ((q->match & HX509_QUERY_MATCH_CERTIFICATE) &&
2957 _hx509_Certificate_cmp(q->certificate, c) != 0)
2960 if ((q->match & HX509_QUERY_MATCH_SERIALNUMBER)
2961 && der_heim_integer_cmp(&c->tbsCertificate.serialNumber, q->serial) != 0)
2964 if (q->match & HX509_QUERY_MATCH_ISSUER_NAME) {
2965 ret = _hx509_name_cmp(&c->tbsCertificate.issuer, q->issuer_name, &diff);
2970 if (q->match & HX509_QUERY_MATCH_SUBJECT_NAME) {
2971 ret = _hx509_name_cmp(&c->tbsCertificate.subject, q->subject_name, &diff);
2976 if (q->match & HX509_QUERY_MATCH_SUBJECT_KEY_ID) {
2977 SubjectKeyIdentifier si;
2979 ret = _hx509_find_extension_subject_key_id(c, &si);
2981 if (der_heim_octet_string_cmp(&si, q->subject_id) != 0)
2983 free_SubjectKeyIdentifier(&si);
2988 if ((q->match & HX509_QUERY_MATCH_ISSUER_ID))
2990 if ((q->match & HX509_QUERY_PRIVATE_KEY) &&
2991 _hx509_cert_private_key(cert) == NULL)
2996 if (q->match & HX509_QUERY_KU_DIGITALSIGNATURE)
2998 if (q->match & HX509_QUERY_KU_NONREPUDIATION)
3000 if (q->match & HX509_QUERY_KU_ENCIPHERMENT)
3002 if (q->match & HX509_QUERY_KU_DATAENCIPHERMENT)
3004 if (q->match & HX509_QUERY_KU_KEYAGREEMENT)
3006 if (q->match & HX509_QUERY_KU_KEYCERTSIGN)
3008 if (q->match & HX509_QUERY_KU_CRLSIGN)
3010 if (ku && check_key_usage(context, c, ku, TRUE))
3013 if ((q->match & HX509_QUERY_ANCHOR))
3016 if (q->match & HX509_QUERY_MATCH_LOCAL_KEY_ID) {
3017 hx509_cert_attribute a;
3019 a = hx509_cert_get_attribute(cert, &asn1_oid_id_pkcs_9_at_localKeyId);
3022 if (der_heim_octet_string_cmp(&a->data, q->local_key_id) != 0)
3026 if (q->match & HX509_QUERY_NO_MATCH_PATH) {
3029 for (i = 0; i < q->path->len; i++)
3030 if (hx509_cert_cmp(q->path->val[i], cert) == 0)
3033 if (q->match & HX509_QUERY_MATCH_FRIENDLY_NAME) {
3034 const char *name = hx509_cert_get_friendly_name(cert);
3037 if (strcasecmp(q->friendlyname, name) != 0)
3040 if (q->match & HX509_QUERY_MATCH_FUNCTION) {
3041 ret = (*q->cmp_func)(context, cert, q->cmp_func_ctx);
3046 if (q->match & HX509_QUERY_MATCH_KEY_HASH_SHA1) {
3047 heim_octet_string os;
3049 os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
3051 c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
3053 ret = _hx509_verify_signature(context,
3055 hx509_signature_sha1(),
3062 if (q->match & HX509_QUERY_MATCH_TIME) {
3064 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
3067 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
3072 /* If an EKU is required, check the cert for it. */
3073 if ((q->match & HX509_QUERY_MATCH_EKU) &&
3074 hx509_cert_check_eku(context, cert, q->eku, 0))
3077 if ((q->match & HX509_QUERY_MATCH_EXPR)) {
3078 hx509_env env = NULL;
3080 ret = _hx509_cert_to_env(context, cert, &env);
3084 ret = _hx509_expr_eval(context, env, q->expr);
3085 hx509_env_free(&env);
3090 if (q->match & ~HX509_QUERY_MASK)
3097 * Set a statistic file for the query statistics.
3099 * @param context A hx509 context.
3100 * @param fn statistics file name
3102 * @ingroup hx509_cert
3106 hx509_query_statistic_file(hx509_context context, const char *fn)
3108 if (context->querystat)
3109 free(context->querystat);
3110 context->querystat = strdup(fn);
3114 _hx509_query_statistic(hx509_context context, int type, const hx509_query *q)
3117 if (context->querystat == NULL)
3119 f = fopen(context->querystat, "a");
3123 fprintf(f, "%d %d\n", type, q->match);
3127 static const char *statname[] = {
3129 "match serialnumber",
3130 "match issuer name",
3131 "match subject name",
3132 "match subject key id",
3136 "ku digitalsignature",
3139 "ku nonrepudiation",
3141 "ku dataencipherment",
3143 "match certificate",
3144 "match local key id",
3146 "match friendly name",
3148 "match key hash sha1",
3153 unsigned long stats;
3159 stat_sort(const void *a, const void *b)
3161 const struct stat_el *ae = a;
3162 const struct stat_el *be = b;
3163 return be->stats - ae->stats;
3167 * Unparse the statistics file and print the result on a FILE descriptor.
3169 * @param context A hx509 context.
3170 * @param printtype tyep to print
3171 * @param out the FILE to write the data on.
3173 * @ingroup hx509_cert
3177 hx509_query_unparse_stats(hx509_context context, int printtype, FILE *out)
3181 int type, mask, num;
3183 unsigned long multiqueries = 0, totalqueries = 0;
3184 struct stat_el stats[32];
3186 if (context->querystat == NULL)
3188 f = fopen(context->querystat, "r");
3190 fprintf(out, "No statistic file %s: %s.\n",
3191 context->querystat, strerror(errno));
3196 for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
3201 while (fscanf(f, "%d %d\n", &type, &mask) == 2) {
3202 if (type != printtype)
3205 while (mask && i < sizeof(stats)/sizeof(stats[0])) {
3219 qsort(stats, sizeof(stats)/sizeof(stats[0]), sizeof(stats[0]), stat_sort);
3223 errx(1, "out of memory");
3225 rtbl_set_separator (t, " ");
3227 rtbl_add_column_by_id (t, 0, "Name", 0);
3228 rtbl_add_column_by_id (t, 1, "Counter", 0);
3231 for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
3234 if (stats[i].index < sizeof(statname)/sizeof(statname[0]))
3235 rtbl_add_column_entry_by_id (t, 0, statname[stats[i].index]);
3237 snprintf(str, sizeof(str), "%d", stats[i].index);
3238 rtbl_add_column_entry_by_id (t, 0, str);
3240 snprintf(str, sizeof(str), "%lu", stats[i].stats);
3241 rtbl_add_column_entry_by_id (t, 1, str);
3244 rtbl_format(t, out);
3247 fprintf(out, "\nQueries: multi %lu total %lu\n",
3248 multiqueries, totalqueries);
3252 * Check the extended key usage on the hx509 certificate.
3254 * @param context A hx509 context.
3255 * @param cert A hx509 context.
3256 * @param eku the EKU to check for
3257 * @param allow_any_eku if the any EKU is set, allow that to be a
3260 * @return An hx509 error code, see hx509_get_error_string().
3262 * @ingroup hx509_cert
3266 hx509_cert_check_eku(hx509_context context, hx509_cert cert,
3267 const heim_oid *eku, int allow_any_eku)
3273 ret = find_extension_eku(_hx509_get_cert(cert), &e);
3275 hx509_clear_error_string(context);
3279 for (i = 0; i < e.len; i++) {
3280 if (der_heim_oid_cmp(eku, &e.val[i]) == 0) {
3281 free_ExtKeyUsage(&e);
3284 if (allow_any_eku) {
3286 if (der_heim_oid_cmp(id_any_eku, &e.val[i]) == 0) {
3287 free_ExtKeyUsage(&e);
3293 free_ExtKeyUsage(&e);
3294 hx509_clear_error_string(context);
3295 return HX509_CERTIFICATE_MISSING_EKU;
3299 _hx509_cert_get_keyusage(hx509_context context,
3309 memset(ku, 0, sizeof(*ku));
3311 cert = _hx509_get_cert(c);
3313 if (_hx509_cert_get_version(cert) < 3)
3316 e = find_extension(cert, &asn1_oid_id_x509_ce_keyUsage, &i);
3318 return HX509_KU_CERT_MISSING;
3320 ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, ku, &size);
3327 _hx509_cert_get_eku(hx509_context context,
3333 memset(e, 0, sizeof(*e));
3335 ret = find_extension_eku(_hx509_get_cert(cert), e);
3336 if (ret && ret != HX509_EXTENSION_NOT_FOUND) {
3337 hx509_clear_error_string(context);
3344 * Encodes the hx509 certificate as a DER encode binary.
3346 * @param context A hx509 context.
3347 * @param c the certificate to encode.
3348 * @param os the encode certificate, set to NULL, 0 on case of
3349 * error. Free the os->data with hx509_xfree().
3351 * @return An hx509 error code, see hx509_get_error_string().
3353 * @ingroup hx509_cert
3357 hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os)
3365 ASN1_MALLOC_ENCODE(Certificate, os->data, os->length,
3366 _hx509_get_cert(c), &size, ret);
3372 if (os->length != size)
3373 _hx509_abort("internal ASN.1 encoder error");
3379 * Last to avoid lost __attribute__s due to #undef.
3382 #undef __attribute__
3383 #define __attribute__(X)
3386 _hx509_abort(const char *fmt, ...)
3387 __attribute__ ((noreturn, format (printf, 1, 2)))
3399 * Free a data element allocated in the library.
3401 * @param ptr data to be freed.
3403 * @ingroup hx509_misc
3407 hx509_xfree(void *ptr)
3417 _hx509_cert_to_env(hx509_context context, hx509_cert cert, hx509_env *env)
3423 hx509_env envcert = NULL;
3428 asprintf(&buf, "%d", _hx509_cert_get_version(_hx509_get_cert(cert)));
3429 ret = hx509_env_add(context, &envcert, "version", buf);
3435 ret = hx509_cert_get_subject(cert, &name);
3439 ret = hx509_name_to_string(name, &buf);
3441 hx509_name_free(&name);
3445 ret = hx509_env_add(context, &envcert, "subject", buf);
3446 hx509_name_free(&name);
3451 ret = hx509_cert_get_issuer(cert, &name);
3455 ret = hx509_name_to_string(name, &buf);
3456 hx509_name_free(&name);
3460 ret = hx509_env_add(context, &envcert, "issuer", buf);
3467 ret = _hx509_cert_get_eku(context, cert, &eku);
3468 if (ret == HX509_EXTENSION_NOT_FOUND)
3474 hx509_env enveku = NULL;
3476 for (i = 0; i < eku.len; i++) {
3478 ret = der_print_heim_oid(&eku.val[i], '.', &buf);
3480 free_ExtKeyUsage(&eku);
3481 hx509_env_free(&enveku);
3484 ret = hx509_env_add(context, &enveku, buf, "oid-name-here");
3487 free_ExtKeyUsage(&eku);
3488 hx509_env_free(&enveku);
3492 free_ExtKeyUsage(&eku);
3494 ret = hx509_env_add_binding(context, &envcert, "eku", enveku);
3496 hx509_env_free(&enveku);
3502 Certificate *c = _hx509_get_cert(cert);
3503 heim_octet_string os, sig;
3504 hx509_env envhash = NULL;
3506 os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
3508 c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
3510 ret = _hx509_create_signature(context,
3512 hx509_signature_sha1(),
3519 ret = hex_encode(sig.data, sig.length, &buf);
3520 der_free_octet_string(&sig);
3523 hx509_set_error_string(context, 0, ret,
3528 ret = hx509_env_add(context, &envhash, "sha1", buf);
3533 ret = hx509_env_add_binding(context, &envcert, "hash", envhash);
3535 hx509_env_free(&envhash);
3540 ret = hx509_env_add_binding(context, env, "certificate", envcert);
3547 hx509_env_free(&envcert);
3552 * Print a simple representation of a certificate
3554 * @param context A hx509 context, can be NULL
3555 * @param cert certificate to print
3556 * @param out the stdio output stream, if NULL, stdout is used
3558 * @return An hx509 error code
3560 * @ingroup hx509_cert
3564 hx509_print_cert(hx509_context context, hx509_cert cert, FILE *out)
3573 ret = hx509_cert_get_issuer(cert, &name);
3576 hx509_name_to_string(name, &str);
3577 hx509_name_free(&name);
3578 fprintf(out, " issuer: \"%s\"\n", str);
3581 ret = hx509_cert_get_subject(cert, &name);
3584 hx509_name_to_string(name, &str);
3585 hx509_name_free(&name);
3586 fprintf(out, " subject: \"%s\"\n", str);
3590 heim_integer serialNumber;
3592 ret = hx509_cert_get_serialnumber(cert, &serialNumber);
3595 ret = der_print_hex_heim_integer(&serialNumber, &str);
3598 der_free_heim_integer(&serialNumber);
3599 fprintf(out, " serial: %s\n", str);
3603 printf(" keyusage: ");
3604 ret = hx509_cert_keyusage_print(context, cert, &str);
3606 fprintf(out, "%s\n", str);