2 * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include "crypto-headers.h"
39 * @page page_cert The basic certificate
41 * The basic hx509 cerificate object in hx509 is hx509_cert. The
42 * hx509_cert object is representing one X509/PKIX certificate and
43 * associated attributes; like private key, friendly name, etc.
45 * A hx509_cert object is usully found via the keyset interfaces (@ref
46 * page_keyset), but its also possible to create a certificate
47 * directly from a parsed object with hx509_cert_init() and
48 * hx509_cert_init_data().
50 * See the library functions here: @ref hx509_cert
53 struct hx509_verify_ctx_data {
54 hx509_certs trust_anchors;
56 #define HX509_VERIFY_CTX_F_TIME_SET 1
57 #define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE 2
58 #define HX509_VERIFY_CTX_F_REQUIRE_RFC3280 4
59 #define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS 8
60 #define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS 16
61 #define HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK 32
63 unsigned int max_depth;
64 #define HX509_VERIFY_MAX_DEPTH 30
65 hx509_revoke_ctx revoke_ctx;
68 #define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280)
69 #define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS)
70 #define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0)
72 struct _hx509_cert_attrs {
74 hx509_cert_attribute *val;
77 struct hx509_cert_data {
81 hx509_private_key private_key;
82 struct _hx509_cert_attrs attrs;
84 _hx509_cert_release_func release;
88 typedef struct hx509_name_constraints {
91 } hx509_name_constraints;
93 #define GeneralSubtrees_SET(g,var) \
94 (g)->len = (var)->len, (g)->val = (var)->val;
97 * Creates a hx509 context that most functions in the library
98 * uses. The context is only allowed to be used by one thread at each
99 * moment. Free the context with hx509_context_free().
101 * @param context Returns a pointer to new hx509 context.
103 * @return Returns an hx509 error code.
109 hx509_context_init(hx509_context *context)
111 *context = calloc(1, sizeof(**context));
112 if (*context == NULL)
115 _hx509_ks_null_register(*context);
116 _hx509_ks_mem_register(*context);
117 _hx509_ks_file_register(*context);
118 _hx509_ks_pkcs12_register(*context);
119 _hx509_ks_pkcs11_register(*context);
120 _hx509_ks_dir_register(*context);
121 _hx509_ks_keychain_register(*context);
123 ENGINE_add_conf_module();
124 OpenSSL_add_all_algorithms();
126 (*context)->ocsp_time_diff = HX509_DEFAULT_OCSP_TIME_DIFF;
128 initialize_hx_error_table_r(&(*context)->et_list);
129 initialize_asn1_error_table_r(&(*context)->et_list);
131 #ifdef HX509_DEFAULT_ANCHORS
132 (void)hx509_certs_init(*context, HX509_DEFAULT_ANCHORS, 0,
133 NULL, &(*context)->default_trust_anchors);
140 * Selects if the hx509_revoke_verify() function is going to require
141 * the existans of a revokation method (OCSP, CRL) or not. Note that
142 * hx509_verify_path(), hx509_cms_verify_signed(), and other function
143 * call hx509_revoke_verify().
145 * @param context hx509 context to change the flag for.
146 * @param flag zero, revokation method required, non zero missing
147 * revokation method ok
149 * @ingroup hx509_verify
153 hx509_context_set_missing_revoke(hx509_context context, int flag)
156 context->flags |= HX509_CTX_VERIFY_MISSING_OK;
158 context->flags &= ~HX509_CTX_VERIFY_MISSING_OK;
162 * Free the context allocated by hx509_context_init().
164 * @param context context to be freed.
170 hx509_context_free(hx509_context *context)
172 hx509_clear_error_string(*context);
173 if ((*context)->ks_ops) {
174 free((*context)->ks_ops);
175 (*context)->ks_ops = NULL;
177 (*context)->ks_num_ops = 0;
178 free_error_table ((*context)->et_list);
179 if ((*context)->querystat)
180 free((*context)->querystat);
181 memset(*context, 0, sizeof(**context));
191 _hx509_get_cert(hx509_cert cert)
201 _hx509_cert_get_version(const Certificate *t)
203 return t->tbsCertificate.version ? *t->tbsCertificate.version + 1 : 1;
207 * Allocate and init an hx509 certificate object from the decoded
210 * @param context A hx509 context.
214 * @return Returns an hx509 error code.
216 * @ingroup hx509_cert
220 hx509_cert_init(hx509_context context, const Certificate *c, hx509_cert *cert)
224 *cert = malloc(sizeof(**cert));
228 (*cert)->friendlyname = NULL;
229 (*cert)->attrs.len = 0;
230 (*cert)->attrs.val = NULL;
231 (*cert)->private_key = NULL;
232 (*cert)->basename = NULL;
233 (*cert)->release = NULL;
236 (*cert)->data = calloc(1, sizeof(*(*cert)->data));
237 if ((*cert)->data == NULL) {
241 ret = copy_Certificate(c, (*cert)->data);
251 * Just like hx509_cert_init(), but instead of a decode certificate
252 * takes an pointer and length to a memory region that contains a
253 * DER/BER encoded certificate.
255 * If the memory region doesn't contain just the certificate and
256 * nothing more the function will fail with
257 * HX509_EXTRA_DATA_AFTER_STRUCTURE.
259 * @param context A hx509 context.
260 * @param ptr pointer to memory region containing encoded certificate.
261 * @param len length of memory region.
262 * @param cert a return pointer to a hx509 certificate object, will
263 * contain NULL on error.
265 * @return An hx509 error code, see hx509_get_error_string().
267 * @ingroup hx509_cert
271 hx509_cert_init_data(hx509_context context,
280 ret = decode_Certificate(ptr, len, &t, &size);
282 hx509_set_error_string(context, 0, ret, "Failed to decode certificate");
286 hx509_set_error_string(context, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE,
287 "Extra data after certificate");
288 return HX509_EXTRA_DATA_AFTER_STRUCTURE;
291 ret = hx509_cert_init(context, &t, cert);
292 free_Certificate(&t);
297 _hx509_cert_set_release(hx509_cert cert,
298 _hx509_cert_release_func release,
301 cert->release = release;
306 /* Doesn't make a copy of `private_key'. */
309 _hx509_cert_assign_key(hx509_cert cert, hx509_private_key private_key)
311 if (cert->private_key)
312 _hx509_private_key_free(&cert->private_key);
313 cert->private_key = _hx509_private_key_ref(private_key);
318 * Free reference to the hx509 certificate object, if the refcounter
319 * reaches 0, the object if freed. Its allowed to pass in NULL.
321 * @param cert the cert to free.
323 * @ingroup hx509_cert
327 hx509_cert_free(hx509_cert cert)
335 _hx509_abort("cert refcount <= 0 on free");
340 (cert->release)(cert, cert->ctx);
342 if (cert->private_key)
343 _hx509_private_key_free(&cert->private_key);
345 free_Certificate(cert->data);
348 for (i = 0; i < cert->attrs.len; i++) {
349 der_free_octet_string(&cert->attrs.val[i]->data);
350 der_free_oid(&cert->attrs.val[i]->oid);
351 free(cert->attrs.val[i]);
353 free(cert->attrs.val);
354 free(cert->friendlyname);
356 hx509_name_free(&cert->basename);
357 memset(cert, 0, sizeof(cert));
362 * Add a reference to a hx509 certificate object.
364 * @param cert a pointer to an hx509 certificate object.
366 * @return the same object as is passed in.
368 * @ingroup hx509_cert
372 hx509_cert_ref(hx509_cert cert)
377 _hx509_abort("cert refcount <= 0");
380 _hx509_abort("cert refcount == 0");
385 * Allocate an verification context that is used fo control the
386 * verification process.
388 * @param context A hx509 context.
389 * @param ctx returns a pointer to a hx509_verify_ctx object.
391 * @return An hx509 error code, see hx509_get_error_string().
393 * @ingroup hx509_verify
397 hx509_verify_init_ctx(hx509_context context, hx509_verify_ctx *ctx)
401 c = calloc(1, sizeof(*c));
405 c->max_depth = HX509_VERIFY_MAX_DEPTH;
413 * Free an hx509 verification context.
415 * @param ctx the context to be freed.
417 * @ingroup hx509_verify
421 hx509_verify_destroy_ctx(hx509_verify_ctx ctx)
424 hx509_certs_free(&ctx->trust_anchors);
425 hx509_revoke_free(&ctx->revoke_ctx);
426 memset(ctx, 0, sizeof(*ctx));
432 * Set the trust anchors in the verification context, makes an
433 * reference to the keyset, so the consumer can free the keyset
434 * independent of the destruction of the verification context (ctx).
436 * @param ctx a verification context
437 * @param set a keyset containing the trust anchors.
439 * @ingroup hx509_verify
443 hx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set)
445 ctx->trust_anchors = _hx509_certs_ref(set);
449 * Attach an revocation context to the verfication context, , makes an
450 * reference to the revoke context, so the consumer can free the
451 * revoke context independent of the destruction of the verification
452 * context. If there is no revoke context, the verification process is
453 * NOT going to check any verification status.
455 * @param ctx a verification context.
456 * @param revoke_ctx a revoke context.
458 * @ingroup hx509_verify
462 hx509_verify_attach_revoke(hx509_verify_ctx ctx, hx509_revoke_ctx revoke_ctx)
465 hx509_revoke_free(&ctx->revoke_ctx);
466 ctx->revoke_ctx = _hx509_revoke_ref(revoke_ctx);
470 * Set the clock time the the verification process is going to
471 * use. Used to check certificate in the past and future time. If not
472 * set the current time will be used.
474 * @param ctx a verification context.
475 * @param t the time the verifiation is using.
478 * @ingroup hx509_verify
482 hx509_verify_set_time(hx509_verify_ctx ctx, time_t t)
484 ctx->flags |= HX509_VERIFY_CTX_F_TIME_SET;
489 _hx509_verify_get_time(hx509_verify_ctx ctx)
491 return ctx->time_now;
495 * Set the maximum depth of the certificate chain that the path
496 * builder is going to try.
498 * @param ctx a verification context
499 * @param max_depth maxium depth of the certificate chain, include
502 * @ingroup hx509_verify
506 hx509_verify_set_max_depth(hx509_verify_ctx ctx, unsigned int max_depth)
508 ctx->max_depth = max_depth;
512 * Allow or deny the use of proxy certificates
514 * @param ctx a verification context
515 * @param boolean if non zero, allow proxy certificates.
517 * @ingroup hx509_verify
521 hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean)
524 ctx->flags |= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
526 ctx->flags &= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
530 * Select strict RFC3280 verification of certificiates. This means
531 * checking key usage on CA certificates, this will make version 1
532 * certificiates unuseable.
534 * @param ctx a verification context
535 * @param boolean if non zero, use strict verification.
537 * @ingroup hx509_verify
541 hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean)
544 ctx->flags |= HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
546 ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
550 * Allow using the operating system builtin trust anchors if no other
551 * trust anchors are configured.
553 * @param ctx a verification context
554 * @param boolean if non zero, useing the operating systems builtin
558 * @return An hx509 error code, see hx509_get_error_string().
560 * @ingroup hx509_cert
564 hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean)
567 ctx->flags &= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
569 ctx->flags |= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
573 hx509_verify_ctx_f_allow_best_before_signature_algs(hx509_context ctx,
577 ctx->flags &= ~HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
579 ctx->flags |= HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
582 static const Extension *
583 find_extension(const Certificate *cert, const heim_oid *oid, int *idx)
585 const TBSCertificate *c = &cert->tbsCertificate;
587 if (c->version == NULL || *c->version < 2 || c->extensions == NULL)
590 for (;*idx < c->extensions->len; (*idx)++) {
591 if (der_heim_oid_cmp(&c->extensions->val[*idx].extnID, oid) == 0)
592 return &c->extensions->val[(*idx)++];
598 find_extension_auth_key_id(const Certificate *subject,
599 AuthorityKeyIdentifier *ai)
605 memset(ai, 0, sizeof(*ai));
607 e = find_extension(subject, oid_id_x509_ce_authorityKeyIdentifier(), &i);
609 return HX509_EXTENSION_NOT_FOUND;
611 return decode_AuthorityKeyIdentifier(e->extnValue.data,
617 _hx509_find_extension_subject_key_id(const Certificate *issuer,
618 SubjectKeyIdentifier *si)
624 memset(si, 0, sizeof(*si));
626 e = find_extension(issuer, oid_id_x509_ce_subjectKeyIdentifier(), &i);
628 return HX509_EXTENSION_NOT_FOUND;
630 return decode_SubjectKeyIdentifier(e->extnValue.data,
636 find_extension_name_constraints(const Certificate *subject,
643 memset(nc, 0, sizeof(*nc));
645 e = find_extension(subject, oid_id_x509_ce_nameConstraints(), &i);
647 return HX509_EXTENSION_NOT_FOUND;
649 return decode_NameConstraints(e->extnValue.data,
655 find_extension_subject_alt_name(const Certificate *cert, int *i,
661 memset(sa, 0, sizeof(*sa));
663 e = find_extension(cert, oid_id_x509_ce_subjectAltName(), i);
665 return HX509_EXTENSION_NOT_FOUND;
667 return decode_GeneralNames(e->extnValue.data,
673 find_extension_eku(const Certificate *cert, ExtKeyUsage *eku)
679 memset(eku, 0, sizeof(*eku));
681 e = find_extension(cert, oid_id_x509_ce_extKeyUsage(), &i);
683 return HX509_EXTENSION_NOT_FOUND;
685 return decode_ExtKeyUsage(e->extnValue.data,
691 add_to_list(hx509_octet_string_list *list, const heim_octet_string *entry)
696 p = realloc(list->val, (list->len + 1) * sizeof(list->val[0]));
700 ret = der_copy_octet_string(entry, &list->val[list->len]);
708 * Free a list of octet strings returned by another hx509 library
711 * @param list list to be freed.
713 * @ingroup hx509_misc
717 hx509_free_octet_string_list(hx509_octet_string_list *list)
720 for (i = 0; i < list->len; i++)
721 der_free_octet_string(&list->val[i]);
728 * Return a list of subjectAltNames specified by oid in the
729 * certificate. On error the
731 * The returned list of octet string should be freed with
732 * hx509_free_octet_string_list().
734 * @param context A hx509 context.
735 * @param cert a hx509 certificate object.
736 * @param oid an oid to for SubjectAltName.
737 * @param list list of matching SubjectAltName.
739 * @return An hx509 error code, see hx509_get_error_string().
741 * @ingroup hx509_cert
745 hx509_cert_find_subjectAltName_otherName(hx509_context context,
748 hx509_octet_string_list *list)
758 ret = find_extension_subject_alt_name(_hx509_get_cert(cert), &i, &sa);
760 if (ret == HX509_EXTENSION_NOT_FOUND) {
763 } else if (ret != 0) {
764 hx509_set_error_string(context, 0, ret, "Error searching for SAN");
765 hx509_free_octet_string_list(list);
769 for (j = 0; j < sa.len; j++) {
770 if (sa.val[j].element == choice_GeneralName_otherName &&
771 der_heim_oid_cmp(&sa.val[j].u.otherName.type_id, oid) == 0)
773 ret = add_to_list(list, &sa.val[j].u.otherName.value);
775 hx509_set_error_string(context, 0, ret,
776 "Error adding an exra SAN to "
778 hx509_free_octet_string_list(list);
779 free_GeneralNames(&sa);
784 free_GeneralNames(&sa);
791 check_key_usage(hx509_context context, const Certificate *cert,
792 unsigned flags, int req_present)
800 if (_hx509_cert_get_version(cert) < 3)
803 e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
806 hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
807 "Required extension key "
808 "usage missing from certifiate");
809 return HX509_KU_CERT_MISSING;
814 ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &size);
817 ku_flags = KeyUsage2int(ku);
818 if ((ku_flags & flags) != flags) {
819 unsigned missing = (~ku_flags) & flags;
820 char buf[256], *name;
822 unparse_flags(missing, asn1_KeyUsage_units(), buf, sizeof(buf));
823 _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
824 hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
825 "Key usage %s required but missing "
826 "from certifiate %s", buf, name);
828 return HX509_KU_CERT_MISSING;
834 * Return 0 on matching key usage 'flags' for 'cert', otherwise return
835 * an error code. If 'req_present' the existance is required of the
836 * KeyUsage extension.
840 _hx509_check_key_usage(hx509_context context, hx509_cert cert,
841 unsigned flags, int req_present)
843 return check_key_usage(context, _hx509_get_cert(cert), flags, req_present);
846 enum certtype { PROXY_CERT, EE_CERT, CA_CERT };
849 check_basic_constraints(hx509_context context, const Certificate *cert,
850 enum certtype type, int depth)
857 if (_hx509_cert_get_version(cert) < 3)
860 e = find_extension(cert, oid_id_x509_ce_basicConstraints(), &i);
868 ret = _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
870 hx509_set_error_string(context, 0, HX509_EXTENSION_NOT_FOUND,
871 "basicConstraints missing from "
872 "CA certifiacte %s", name);
874 return HX509_EXTENSION_NOT_FOUND;
879 ret = decode_BasicConstraints(e->extnValue.data,
880 e->extnValue.length, &bc,
886 if (bc.cA != NULL && *bc.cA)
887 ret = HX509_PARENT_IS_CA;
893 if (bc.cA == NULL || !*bc.cA)
894 ret = HX509_PARENT_NOT_CA;
895 else if (bc.pathLenConstraint)
896 if (depth - 1 > *bc.pathLenConstraint)
897 ret = HX509_CA_PATH_TOO_DEEP;
900 free_BasicConstraints(&bc);
905 _hx509_cert_is_parent_cmp(const Certificate *subject,
906 const Certificate *issuer,
907 int allow_self_signed)
910 AuthorityKeyIdentifier ai;
911 SubjectKeyIdentifier si;
912 int ret_ai, ret_si, ret;
914 ret = _hx509_name_cmp(&issuer->tbsCertificate.subject,
915 &subject->tbsCertificate.issuer,
922 memset(&ai, 0, sizeof(ai));
923 memset(&si, 0, sizeof(si));
926 * Try to find AuthorityKeyIdentifier, if it's not present in the
927 * subject certificate nor the parent.
930 ret_ai = find_extension_auth_key_id(subject, &ai);
931 if (ret_ai && ret_ai != HX509_EXTENSION_NOT_FOUND)
933 ret_si = _hx509_find_extension_subject_key_id(issuer, &si);
934 if (ret_si && ret_si != HX509_EXTENSION_NOT_FOUND)
937 if (ret_si && ret_ai)
942 if (allow_self_signed) {
945 } else if (ai.keyIdentifier) {
951 if (ai.keyIdentifier == NULL) {
954 if (ai.authorityCertIssuer == NULL)
956 if (ai.authorityCertSerialNumber == NULL)
959 diff = der_heim_integer_cmp(ai.authorityCertSerialNumber,
960 &issuer->tbsCertificate.serialNumber);
963 if (ai.authorityCertIssuer->len != 1)
965 if (ai.authorityCertIssuer->val[0].element != choice_GeneralName_directoryName)
969 ai.authorityCertIssuer->val[0].u.directoryName.element;
971 ai.authorityCertIssuer->val[0].u.directoryName.u.rdnSequence;
973 ret = _hx509_name_cmp(&issuer->tbsCertificate.subject,
982 diff = der_heim_octet_string_cmp(ai.keyIdentifier, &si);
987 free_AuthorityKeyIdentifier(&ai);
988 free_SubjectKeyIdentifier(&si);
993 certificate_is_anchor(hx509_context context,
994 hx509_certs trust_anchors,
995 const hx509_cert cert)
1001 if (trust_anchors == NULL)
1004 _hx509_query_clear(&q);
1006 q.match = HX509_QUERY_MATCH_CERTIFICATE;
1007 q.certificate = _hx509_get_cert(cert);
1009 ret = hx509_certs_find(context, trust_anchors, &q, &c);
1016 certificate_is_self_signed(hx509_context context,
1017 const Certificate *cert,
1021 ret = _hx509_name_cmp(&cert->tbsCertificate.subject,
1022 &cert->tbsCertificate.issuer, &diff);
1023 *self_signed = (diff == 0);
1025 hx509_set_error_string(context, 0, ret,
1026 "Failed to check if self signed");
1031 * The subjectName is "null" when it's empty set of relative DBs.
1035 subject_null_p(const Certificate *c)
1037 return c->tbsCertificate.subject.u.rdnSequence.len == 0;
1042 find_parent(hx509_context context,
1044 hx509_certs trust_anchors,
1050 AuthorityKeyIdentifier ai;
1055 memset(&ai, 0, sizeof(ai));
1057 _hx509_query_clear(&q);
1059 if (!subject_null_p(current->data)) {
1060 q.match |= HX509_QUERY_FIND_ISSUER_CERT;
1061 q.subject = _hx509_get_cert(current);
1063 ret = find_extension_auth_key_id(current->data, &ai);
1065 hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
1066 "Subjectless certificate missing AuthKeyID");
1067 return HX509_CERTIFICATE_MALFORMED;
1070 if (ai.keyIdentifier == NULL) {
1071 free_AuthorityKeyIdentifier(&ai);
1072 hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
1073 "Subjectless certificate missing keyIdentifier "
1074 "inside AuthKeyID");
1075 return HX509_CERTIFICATE_MALFORMED;
1078 q.subject_id = ai.keyIdentifier;
1079 q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID;
1083 q.match |= HX509_QUERY_NO_MATCH_PATH;
1086 q.timenow = time_now;
1087 q.match |= HX509_QUERY_MATCH_TIME;
1089 ret = hx509_certs_find(context, pool, &q, parent);
1091 free_AuthorityKeyIdentifier(&ai);
1094 q.match &= ~HX509_QUERY_MATCH_TIME;
1097 if (trust_anchors) {
1098 ret = hx509_certs_find(context, trust_anchors, &q, parent);
1100 free_AuthorityKeyIdentifier(&ai);
1104 free_AuthorityKeyIdentifier(&ai);
1110 ret = hx509_cert_get_subject(current, &name);
1112 hx509_clear_error_string(context);
1113 return HX509_ISSUER_NOT_FOUND;
1115 ret = hx509_name_to_string(name, &str);
1116 hx509_name_free(&name);
1118 hx509_clear_error_string(context);
1119 return HX509_ISSUER_NOT_FOUND;
1122 hx509_set_error_string(context, 0, HX509_ISSUER_NOT_FOUND,
1123 "Failed to find issuer for "
1124 "certificate with subject: '%s'", str);
1127 return HX509_ISSUER_NOT_FOUND;
1135 is_proxy_cert(hx509_context context,
1136 const Certificate *cert,
1137 ProxyCertInfo *rinfo)
1145 memset(rinfo, 0, sizeof(*rinfo));
1147 e = find_extension(cert, oid_id_pkix_pe_proxyCertInfo(), &i);
1149 hx509_clear_error_string(context);
1150 return HX509_EXTENSION_NOT_FOUND;
1153 ret = decode_ProxyCertInfo(e->extnValue.data,
1154 e->extnValue.length,
1158 hx509_clear_error_string(context);
1161 if (size != e->extnValue.length) {
1162 free_ProxyCertInfo(&info);
1163 hx509_clear_error_string(context);
1164 return HX509_EXTRA_DATA_AFTER_STRUCTURE;
1167 free_ProxyCertInfo(&info);
1175 * Path operations are like MEMORY based keyset, but with exposed
1176 * internal so we can do easy searches.
1180 _hx509_path_append(hx509_context context, hx509_path *path, hx509_cert cert)
1183 val = realloc(path->val, (path->len + 1) * sizeof(path->val[0]));
1185 hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1190 path->val[path->len] = hx509_cert_ref(cert);
1197 _hx509_path_free(hx509_path *path)
1201 for (i = 0; i < path->len; i++)
1202 hx509_cert_free(path->val[i]);
1209 * Find path by looking up issuer for the top certificate and continue
1210 * until an anchor certificate is found or max limit is found. A
1211 * certificate never included twice in the path.
1213 * If the trust anchors are not given, calculate optimistic path, just
1214 * follow the chain upward until we no longer find a parent or we hit
1215 * the max path limit. In this case, a failure will always be returned
1216 * depending on what error condition is hit first.
1218 * The path includes a path from the top certificate to the anchor
1221 * The caller needs to free `path´ both on successful built path and
1226 _hx509_calculate_path(hx509_context context,
1229 hx509_certs anchors,
1230 unsigned int max_depth,
1235 hx509_cert parent, current;
1239 max_depth = HX509_VERIFY_MAX_DEPTH;
1241 ret = _hx509_path_append(context, path, cert);
1245 current = hx509_cert_ref(cert);
1247 while (!certificate_is_anchor(context, anchors, current)) {
1249 ret = find_parent(context, time_now, anchors, path,
1250 pool, current, &parent);
1251 hx509_cert_free(current);
1255 ret = _hx509_path_append(context, path, parent);
1260 if (path->len > max_depth) {
1261 hx509_cert_free(current);
1262 hx509_set_error_string(context, 0, HX509_PATH_TOO_LONG,
1263 "Path too long while bulding "
1264 "certificate chain");
1265 return HX509_PATH_TOO_LONG;
1269 if ((flags & HX509_CALCULATE_PATH_NO_ANCHOR) &&
1271 certificate_is_anchor(context, anchors, path->val[path->len - 1]))
1273 hx509_cert_free(path->val[path->len - 1]);
1277 hx509_cert_free(current);
1282 _hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier *p,
1283 const AlgorithmIdentifier *q)
1286 diff = der_heim_oid_cmp(&p->algorithm, &q->algorithm);
1289 if (p->parameters) {
1291 return heim_any_cmp(p->parameters,
1304 _hx509_Certificate_cmp(const Certificate *p, const Certificate *q)
1307 diff = der_heim_bit_string_cmp(&p->signatureValue, &q->signatureValue);
1310 diff = _hx509_AlgorithmIdentifier_cmp(&p->signatureAlgorithm,
1311 &q->signatureAlgorithm);
1314 diff = der_heim_octet_string_cmp(&p->tbsCertificate._save,
1315 &q->tbsCertificate._save);
1320 * Compare to hx509 certificate object, useful for sorting.
1322 * @param p a hx509 certificate object.
1323 * @param q a hx509 certificate object.
1325 * @return 0 the objects are the same, returns > 0 is p is "larger"
1326 * then q, < 0 if p is "smaller" then q.
1328 * @ingroup hx509_cert
1332 hx509_cert_cmp(hx509_cert p, hx509_cert q)
1334 return _hx509_Certificate_cmp(p->data, q->data);
1338 * Return the name of the issuer of the hx509 certificate.
1340 * @param p a hx509 certificate object.
1341 * @param name a pointer to a hx509 name, should be freed by
1342 * hx509_name_free().
1344 * @return An hx509 error code, see hx509_get_error_string().
1346 * @ingroup hx509_cert
1350 hx509_cert_get_issuer(hx509_cert p, hx509_name *name)
1352 return _hx509_name_from_Name(&p->data->tbsCertificate.issuer, name);
1356 * Return the name of the subject of the hx509 certificate.
1358 * @param p a hx509 certificate object.
1359 * @param name a pointer to a hx509 name, should be freed by
1360 * hx509_name_free(). See also hx509_cert_get_base_subject().
1362 * @return An hx509 error code, see hx509_get_error_string().
1364 * @ingroup hx509_cert
1368 hx509_cert_get_subject(hx509_cert p, hx509_name *name)
1370 return _hx509_name_from_Name(&p->data->tbsCertificate.subject, name);
1374 * Return the name of the base subject of the hx509 certificate. If
1375 * the certiicate is a verified proxy certificate, the this function
1376 * return the base certificate (root of the proxy chain). If the proxy
1377 * certificate is not verified with the base certificate
1378 * HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned.
1380 * @param context a hx509 context.
1381 * @param c a hx509 certificate object.
1382 * @param name a pointer to a hx509 name, should be freed by
1383 * hx509_name_free(). See also hx509_cert_get_subject().
1385 * @return An hx509 error code, see hx509_get_error_string().
1387 * @ingroup hx509_cert
1391 hx509_cert_get_base_subject(hx509_context context, hx509_cert c,
1395 return hx509_name_copy(context, c->basename, name);
1396 if (is_proxy_cert(context, c->data, NULL) == 0) {
1397 int ret = HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED;
1398 hx509_set_error_string(context, 0, ret,
1399 "Proxy certificate have not been "
1400 "canonicalize yet, no base name");
1403 return _hx509_name_from_Name(&c->data->tbsCertificate.subject, name);
1407 * Get serial number of the certificate.
1409 * @param p a hx509 certificate object.
1410 * @param i serial number, should be freed ith der_free_heim_integer().
1412 * @return An hx509 error code, see hx509_get_error_string().
1414 * @ingroup hx509_cert
1418 hx509_cert_get_serialnumber(hx509_cert p, heim_integer *i)
1420 return der_copy_heim_integer(&p->data->tbsCertificate.serialNumber, i);
1424 * Get notBefore time of the certificate.
1426 * @param p a hx509 certificate object.
1428 * @return return not before time
1430 * @ingroup hx509_cert
1434 hx509_cert_get_notBefore(hx509_cert p)
1436 return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notBefore);
1440 * Get notAfter time of the certificate.
1442 * @param p a hx509 certificate object.
1444 * @return return not after time.
1446 * @ingroup hx509_cert
1450 hx509_cert_get_notAfter(hx509_cert p)
1452 return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notAfter);
1456 * Get the SubjectPublicKeyInfo structure from the hx509 certificate.
1458 * @param context a hx509 context.
1459 * @param p a hx509 certificate object.
1460 * @param spki SubjectPublicKeyInfo, should be freed with
1461 * free_SubjectPublicKeyInfo().
1463 * @return An hx509 error code, see hx509_get_error_string().
1465 * @ingroup hx509_cert
1469 hx509_cert_get_SPKI(hx509_context context, hx509_cert p, SubjectPublicKeyInfo *spki)
1473 ret = copy_SubjectPublicKeyInfo(&p->data->tbsCertificate.subjectPublicKeyInfo, spki);
1475 hx509_set_error_string(context, 0, ret, "Failed to copy SPKI");
1480 * Get the AlgorithmIdentifier from the hx509 certificate.
1482 * @param context a hx509 context.
1483 * @param p a hx509 certificate object.
1484 * @param alg AlgorithmIdentifier, should be freed with
1485 * free_AlgorithmIdentifier(). The algorithmidentifier is
1486 * typicly rsaEncryption, or id-ecPublicKey, or some other
1487 * public key mechanism.
1489 * @return An hx509 error code, see hx509_get_error_string().
1491 * @ingroup hx509_cert
1495 hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context,
1497 AlgorithmIdentifier *alg)
1501 ret = copy_AlgorithmIdentifier(&p->data->tbsCertificate.subjectPublicKeyInfo.algorithm, alg);
1503 hx509_set_error_string(context, 0, ret,
1504 "Failed to copy SPKI AlgorithmIdentifier");
1510 _hx509_cert_private_key(hx509_cert p)
1512 return p->private_key;
1516 hx509_cert_have_private_key(hx509_cert p)
1518 return p->private_key ? 1 : 0;
1523 _hx509_cert_private_key_exportable(hx509_cert p)
1525 if (p->private_key == NULL)
1527 return _hx509_private_key_exportable(p->private_key);
1531 _hx509_cert_private_decrypt(hx509_context context,
1532 const heim_octet_string *ciphertext,
1533 const heim_oid *encryption_oid,
1535 heim_octet_string *cleartext)
1537 cleartext->data = NULL;
1538 cleartext->length = 0;
1540 if (p->private_key == NULL) {
1541 hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
1542 "Private key missing");
1543 return HX509_PRIVATE_KEY_MISSING;
1546 return _hx509_private_key_private_decrypt(context,
1554 _hx509_cert_public_encrypt(hx509_context context,
1555 const heim_octet_string *cleartext,
1557 heim_oid *encryption_oid,
1558 heim_octet_string *ciphertext)
1560 return _hx509_public_encrypt(context,
1562 encryption_oid, ciphertext);
1570 _hx509_Time2time_t(const Time *t)
1572 switch(t->element) {
1573 case choice_Time_utcTime:
1574 return t->u.utcTime;
1575 case choice_Time_generalTime:
1576 return t->u.generalTime;
1586 init_name_constraints(hx509_name_constraints *nc)
1588 memset(nc, 0, sizeof(*nc));
1593 add_name_constraints(hx509_context context, const Certificate *c, int not_ca,
1594 hx509_name_constraints *nc)
1596 NameConstraints tnc;
1599 ret = find_extension_name_constraints(c, &tnc);
1600 if (ret == HX509_EXTENSION_NOT_FOUND)
1603 hx509_set_error_string(context, 0, ret, "Failed getting NameConstraints");
1605 } else if (not_ca) {
1606 ret = HX509_VERIFY_CONSTRAINTS;
1607 hx509_set_error_string(context, 0, ret, "Not a CA and "
1608 "have NameConstraints");
1610 NameConstraints *val;
1611 val = realloc(nc->val, sizeof(nc->val[0]) * (nc->len + 1));
1613 hx509_clear_error_string(context);
1618 ret = copy_NameConstraints(&tnc, &nc->val[nc->len]);
1620 hx509_clear_error_string(context);
1626 free_NameConstraints(&tnc);
1631 match_RDN(const RelativeDistinguishedName *c,
1632 const RelativeDistinguishedName *n)
1636 if (c->len != n->len)
1637 return HX509_NAME_CONSTRAINT_ERROR;
1639 for (i = 0; i < n->len; i++) {
1642 if (der_heim_oid_cmp(&c->val[i].type, &n->val[i].type) != 0)
1643 return HX509_NAME_CONSTRAINT_ERROR;
1644 ret = _hx509_name_ds_cmp(&c->val[i].value, &n->val[i].value, &diff);
1648 return HX509_NAME_CONSTRAINT_ERROR;
1654 match_X501Name(const Name *c, const Name *n)
1658 if (c->element != choice_Name_rdnSequence
1659 || n->element != choice_Name_rdnSequence)
1661 if (c->u.rdnSequence.len > n->u.rdnSequence.len)
1662 return HX509_NAME_CONSTRAINT_ERROR;
1663 for (i = 0; i < c->u.rdnSequence.len; i++) {
1664 ret = match_RDN(&c->u.rdnSequence.val[i], &n->u.rdnSequence.val[i]);
1673 match_general_name(const GeneralName *c, const GeneralName *n, int *match)
1676 * Name constraints only apply to the same name type, see RFC3280,
1679 assert(c->element == n->element);
1681 switch(c->element) {
1682 case choice_GeneralName_otherName:
1683 if (der_heim_oid_cmp(&c->u.otherName.type_id,
1684 &n->u.otherName.type_id) != 0)
1685 return HX509_NAME_CONSTRAINT_ERROR;
1686 if (heim_any_cmp(&c->u.otherName.value,
1687 &n->u.otherName.value) != 0)
1688 return HX509_NAME_CONSTRAINT_ERROR;
1691 case choice_GeneralName_rfc822Name: {
1694 s = strchr(c->u.rfc822Name, '@');
1696 if (strcasecmp(c->u.rfc822Name, n->u.rfc822Name) != 0)
1697 return HX509_NAME_CONSTRAINT_ERROR;
1699 s = strchr(n->u.rfc822Name, '@');
1701 return HX509_NAME_CONSTRAINT_ERROR;
1702 len1 = strlen(c->u.rfc822Name);
1703 len2 = strlen(s + 1);
1705 return HX509_NAME_CONSTRAINT_ERROR;
1706 if (strcasecmp(s + 1 + len2 - len1, c->u.rfc822Name) != 0)
1707 return HX509_NAME_CONSTRAINT_ERROR;
1708 if (len1 < len2 && s[len2 - len1 + 1] != '.')
1709 return HX509_NAME_CONSTRAINT_ERROR;
1714 case choice_GeneralName_dNSName: {
1717 lenc = strlen(c->u.dNSName);
1718 lenn = strlen(n->u.dNSName);
1720 return HX509_NAME_CONSTRAINT_ERROR;
1721 if (strcasecmp(&n->u.dNSName[lenn - lenc], c->u.dNSName) != 0)
1722 return HX509_NAME_CONSTRAINT_ERROR;
1723 if (lenc != lenn && n->u.dNSName[lenn - lenc - 1] != '.')
1724 return HX509_NAME_CONSTRAINT_ERROR;
1728 case choice_GeneralName_directoryName: {
1729 Name c_name, n_name;
1732 c_name._save.data = NULL;
1733 c_name._save.length = 0;
1734 c_name.element = c->u.directoryName.element;
1735 c_name.u.rdnSequence = c->u.directoryName.u.rdnSequence;
1737 n_name._save.data = NULL;
1738 n_name._save.length = 0;
1739 n_name.element = n->u.directoryName.element;
1740 n_name.u.rdnSequence = n->u.directoryName.u.rdnSequence;
1742 ret = match_X501Name(&c_name, &n_name);
1747 case choice_GeneralName_uniformResourceIdentifier:
1748 case choice_GeneralName_iPAddress:
1749 case choice_GeneralName_registeredID:
1751 return HX509_NAME_CONSTRAINT_ERROR;
1756 match_alt_name(const GeneralName *n, const Certificate *c,
1757 int *same, int *match)
1764 ret = find_extension_subject_alt_name(c, &i, &sa);
1765 if (ret == HX509_EXTENSION_NOT_FOUND) {
1768 } else if (ret != 0)
1771 for (j = 0; j < sa.len; j++) {
1772 if (n->element == sa.val[j].element) {
1774 ret = match_general_name(n, &sa.val[j], match);
1777 free_GeneralNames(&sa);
1784 match_tree(const GeneralSubtrees *t, const Certificate *c, int *match)
1786 int name, alt_name, same;
1790 name = alt_name = same = *match = 0;
1791 for (i = 0; i < t->len; i++) {
1792 if (t->val[i].minimum && t->val[i].maximum)
1796 * If the constraint apply to directoryNames, test is with
1797 * subjectName of the certificate if the certificate have a
1798 * non-null (empty) subjectName.
1801 if (t->val[i].base.element == choice_GeneralName_directoryName
1802 && !subject_null_p(c))
1804 GeneralName certname;
1806 memset(&certname, 0, sizeof(certname));
1807 certname.element = choice_GeneralName_directoryName;
1808 certname.u.directoryName.element =
1809 c->tbsCertificate.subject.element;
1810 certname.u.directoryName.u.rdnSequence =
1811 c->tbsCertificate.subject.u.rdnSequence;
1813 ret = match_general_name(&t->val[i].base, &certname, &name);
1816 /* Handle subjectAltNames, this is icky since they
1817 * restrictions only apply if the subjectAltName is of the
1818 * same type. So if there have been a match of type, require
1819 * altname to be set.
1821 ret = match_alt_name(&t->val[i].base, c, &same, &alt_name);
1823 if (name && (!same || alt_name))
1829 check_name_constraints(hx509_context context,
1830 const hx509_name_constraints *nc,
1831 const Certificate *c)
1836 for (i = 0 ; i < nc->len; i++) {
1839 if (nc->val[i].permittedSubtrees) {
1840 GeneralSubtrees_SET(&gs, nc->val[i].permittedSubtrees);
1841 ret = match_tree(&gs, c, &match);
1843 hx509_clear_error_string(context);
1846 /* allow null subjectNames, they wont matches anything */
1847 if (match == 0 && !subject_null_p(c)) {
1848 hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS,
1849 "Error verify constraints, "
1850 "certificate didn't match any "
1851 "permitted subtree");
1852 return HX509_VERIFY_CONSTRAINTS;
1855 if (nc->val[i].excludedSubtrees) {
1856 GeneralSubtrees_SET(&gs, nc->val[i].excludedSubtrees);
1857 ret = match_tree(&gs, c, &match);
1859 hx509_clear_error_string(context);
1863 hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS,
1864 "Error verify constraints, "
1865 "certificate included in excluded "
1867 return HX509_VERIFY_CONSTRAINTS;
1875 free_name_constraints(hx509_name_constraints *nc)
1879 for (i = 0 ; i < nc->len; i++)
1880 free_NameConstraints(&nc->val[i]);
1885 * Build and verify the path for the certificate to the trust anchor
1886 * specified in the verify context. The path is constructed from the
1887 * certificate, the pool and the trust anchors.
1889 * @param context A hx509 context.
1890 * @param ctx A hx509 verification context.
1891 * @param cert the certificate to build the path from.
1892 * @param pool A keyset of certificates to build the chain from.
1894 * @return An hx509 error code, see hx509_get_error_string().
1896 * @ingroup hx509_verify
1900 hx509_verify_path(hx509_context context,
1901 hx509_verify_ctx ctx,
1905 hx509_name_constraints nc;
1907 int ret, i, proxy_cert_depth, selfsigned_depth, diff;
1910 hx509_certs anchors = NULL;
1912 memset(&proxy_issuer, 0, sizeof(proxy_issuer));
1914 ret = init_name_constraints(&nc);
1921 if ((ctx->flags & HX509_VERIFY_CTX_F_TIME_SET) == 0)
1922 ctx->time_now = time(NULL);
1927 if (ctx->trust_anchors)
1928 anchors = _hx509_certs_ref(ctx->trust_anchors);
1929 else if (context->default_trust_anchors && ALLOW_DEF_TA(ctx))
1930 anchors = _hx509_certs_ref(context->default_trust_anchors);
1932 ret = hx509_certs_init(context, "MEMORY:no-TA", 0, NULL, &anchors);
1938 * Calculate the path from the certificate user presented to the
1941 ret = _hx509_calculate_path(context, 0, ctx->time_now,
1942 anchors, ctx->max_depth,
1948 * Check CA and proxy certificate chain from the top of the
1949 * certificate chain. Also check certificate is valid with respect
1950 * to the current time.
1954 proxy_cert_depth = 0;
1955 selfsigned_depth = 0;
1957 if (ctx->flags & HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE)
1962 for (i = 0; i < path.len; i++) {
1966 c = _hx509_get_cert(path.val[i]);
1969 * Lets do some basic check on issuer like
1970 * keyUsage.keyCertSign and basicConstraints.cA bit depending
1971 * on what type of certificate this is.
1977 /* XXX make constants for keyusage */
1978 ret = check_key_usage(context, c, 1 << 5,
1979 REQUIRE_RFC3280(ctx) ? TRUE : FALSE);
1981 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
1982 "Key usage missing from CA certificate");
1986 /* self signed cert doesn't add to path length */
1987 if (i + 1 != path.len) {
1990 ret = certificate_is_self_signed(context, c, &selfsigned);
2001 if (is_proxy_cert(context, c, &info) == 0) {
2004 if (info.pCPathLenConstraint != NULL &&
2005 *info.pCPathLenConstraint < i)
2007 free_ProxyCertInfo(&info);
2008 ret = HX509_PATH_TOO_LONG;
2009 hx509_set_error_string(context, 0, ret,
2010 "Proxy certificate chain "
2011 "longer then allowed");
2014 /* XXX MUST check info.proxyPolicy */
2015 free_ProxyCertInfo(&info);
2018 if (find_extension(c, oid_id_x509_ce_subjectAltName(), &j)) {
2019 ret = HX509_PROXY_CERT_INVALID;
2020 hx509_set_error_string(context, 0, ret,
2021 "Proxy certificate have explicity "
2022 "forbidden subjectAltName");
2027 if (find_extension(c, oid_id_x509_ce_issuerAltName(), &j)) {
2028 ret = HX509_PROXY_CERT_INVALID;
2029 hx509_set_error_string(context, 0, ret,
2030 "Proxy certificate have explicity "
2031 "forbidden issuerAltName");
2036 * The subject name of the proxy certificate should be
2037 * CN=XXX,<proxy issuer>, prune of CN and check if its
2038 * the same over the whole chain of proxy certs and
2039 * then check with the EE cert when we get to it.
2042 if (proxy_cert_depth) {
2043 ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.subject, &diff);
2045 hx509_set_error_string(context, 0, ret, "Out of memory");
2049 ret = HX509_PROXY_CERT_NAME_WRONG;
2050 hx509_set_error_string(context, 0, ret,
2051 "Base proxy name not right");
2056 free_Name(&proxy_issuer);
2058 ret = copy_Name(&c->tbsCertificate.subject, &proxy_issuer);
2060 hx509_clear_error_string(context);
2064 j = proxy_issuer.u.rdnSequence.len;
2065 if (proxy_issuer.u.rdnSequence.len < 2
2066 || proxy_issuer.u.rdnSequence.val[j - 1].len > 1
2067 || der_heim_oid_cmp(&proxy_issuer.u.rdnSequence.val[j - 1].val[0].type,
2068 oid_id_at_commonName()))
2070 ret = HX509_PROXY_CERT_NAME_WRONG;
2071 hx509_set_error_string(context, 0, ret,
2072 "Proxy name too short or "
2073 "does not have Common name "
2078 free_RelativeDistinguishedName(&proxy_issuer.u.rdnSequence.val[j - 1]);
2079 proxy_issuer.u.rdnSequence.len -= 1;
2081 ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.issuer, &diff);
2083 hx509_set_error_string(context, 0, ret, "Out of memory");
2087 ret = HX509_PROXY_CERT_NAME_WRONG;
2088 hx509_set_error_string(context, 0, ret,
2089 "Proxy issuer name not as expected");
2096 * Now we are done with the proxy certificates, this
2097 * cert was an EE cert and we we will fall though to
2098 * EE checking below.
2106 * If there where any proxy certificates in the chain
2107 * (proxy_cert_depth > 0), check that the proxy issuer
2108 * matched proxy certificates "base" subject.
2110 if (proxy_cert_depth) {
2112 ret = _hx509_name_cmp(&proxy_issuer,
2113 &c->tbsCertificate.subject, &diff);
2115 hx509_set_error_string(context, 0, ret, "out of memory");
2119 ret = HX509_PROXY_CERT_NAME_WRONG;
2120 hx509_clear_error_string(context);
2124 hx509_name_free(&cert->basename);
2126 ret = _hx509_name_from_Name(&proxy_issuer, &cert->basename);
2128 hx509_clear_error_string(context);
2136 ret = check_basic_constraints(context, c, type,
2137 i - proxy_cert_depth - selfsigned_depth);
2142 * Don't check the trust anchors expiration time since they
2143 * are transported out of band, from RFC3820.
2145 if (i + 1 != path.len || CHECK_TA(ctx)) {
2147 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2148 if (t > ctx->time_now) {
2149 ret = HX509_CERT_USED_BEFORE_TIME;
2150 hx509_clear_error_string(context);
2153 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
2154 if (t < ctx->time_now) {
2155 ret = HX509_CERT_USED_AFTER_TIME;
2156 hx509_clear_error_string(context);
2161 if (type == EE_CERT)
2163 else if (type == PROXY_CERT)
2168 * Verify constraints, do this backward so path constraints are
2169 * checked in the right order.
2172 for (ret = 0, i = path.len - 1; i >= 0; i--) {
2176 c = _hx509_get_cert(path.val[i]);
2178 ret = certificate_is_self_signed(context, c, &selfsigned);
2182 /* verify name constraints, not for selfsigned and anchor */
2183 if (!selfsigned || i + 1 != path.len) {
2184 ret = check_name_constraints(context, &nc, c);
2189 ret = add_name_constraints(context, c, i == 0, &nc);
2193 /* XXX verify all other silly constraints */
2198 * Verify that no certificates has been revoked.
2201 if (ctx->revoke_ctx) {
2204 ret = hx509_certs_init(context, "MEMORY:revoke-certs", 0,
2209 for (i = 0; i < path.len; i++) {
2210 ret = hx509_certs_add(context, certs, path.val[i]);
2212 hx509_certs_free(&certs);
2216 ret = hx509_certs_merge(context, certs, pool);
2218 hx509_certs_free(&certs);
2222 for (i = 0; i < path.len - 1; i++) {
2223 int parent = (i < path.len - 1) ? i + 1 : i;
2225 ret = hx509_revoke_verify(context,
2232 hx509_certs_free(&certs);
2236 hx509_certs_free(&certs);
2240 * Verify signatures, do this backward so public key working
2241 * parameter is passed up from the anchor up though the chain.
2244 for (i = path.len - 1; i >= 0; i--) {
2245 Certificate *signer, *c;
2247 c = _hx509_get_cert(path.val[i]);
2249 /* is last in chain (trust anchor) */
2250 if (i + 1 == path.len) {
2253 signer = path.val[i]->data;
2255 ret = certificate_is_self_signed(context, signer, &selfsigned);
2259 /* if trust anchor is not self signed, don't check sig */
2263 /* take next certificate in chain */
2264 signer = path.val[i + 1]->data;
2267 /* verify signatureValue */
2268 ret = _hx509_verify_signature_bitstring(context,
2270 &c->signatureAlgorithm,
2271 &c->tbsCertificate._save,
2272 &c->signatureValue);
2274 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
2275 "Failed to verify signature of certificate");
2279 * Verify that the sigature algorithm "best-before" date is
2280 * before the creation date of the certificate, do this for
2281 * trust anchors too, since any trust anchor that is created
2282 * after a algorithm is known to be bad deserved to be invalid.
2284 * Skip the leaf certificate for now...
2287 if (i != 0 && (ctx->flags & HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK) == 0) {
2289 _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2290 ret = _hx509_signature_best_before(context,
2291 &c->signatureAlgorithm,
2299 hx509_certs_free(&anchors);
2300 free_Name(&proxy_issuer);
2301 free_name_constraints(&nc);
2302 _hx509_path_free(&path);
2308 * Verify a signature made using the private key of an certificate.
2310 * @param context A hx509 context.
2311 * @param signer the certificate that made the signature.
2312 * @param alg algorthm that was used to sign the data.
2313 * @param data the data that was signed.
2314 * @param sig the sigature to verify.
2316 * @return An hx509 error code, see hx509_get_error_string().
2318 * @ingroup hx509_crypto
2322 hx509_verify_signature(hx509_context context,
2323 const hx509_cert signer,
2324 const AlgorithmIdentifier *alg,
2325 const heim_octet_string *data,
2326 const heim_octet_string *sig)
2328 return _hx509_verify_signature(context, signer->data, alg, data, sig);
2333 * Verify that the certificate is allowed to be used for the hostname
2336 * @param context A hx509 context.
2337 * @param cert the certificate to match with
2338 * @param flags Flags to modify the behavior:
2339 * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok
2340 * @param type type of hostname:
2341 * - HX509_HN_HOSTNAME for plain hostname.
2342 * - HX509_HN_DNSSRV for DNS SRV names.
2343 * @param hostname the hostname to check
2344 * @param sa address of the host
2345 * @param sa_size length of address
2347 * @return An hx509 error code, see hx509_get_error_string().
2349 * @ingroup hx509_cert
2353 hx509_verify_hostname(hx509_context context,
2354 const hx509_cert cert,
2356 hx509_hostname_type type,
2357 const char *hostname,
2358 const struct sockaddr *sa,
2359 /* XXX krb5_socklen_t */ int sa_size)
2364 if (sa && sa_size <= 0)
2367 memset(&san, 0, sizeof(san));
2371 ret = find_extension_subject_alt_name(cert->data, &i, &san);
2372 if (ret == HX509_EXTENSION_NOT_FOUND) {
2375 } else if (ret != 0)
2378 for (j = 0; j < san.len; j++) {
2379 switch (san.val[j].element) {
2380 case choice_GeneralName_dNSName:
2381 if (strcasecmp(san.val[j].u.dNSName, hostname) == 0) {
2382 free_GeneralNames(&san);
2390 free_GeneralNames(&san);
2394 const Name *name = &cert->data->tbsCertificate.subject;
2396 /* match if first component is a CN= */
2397 if (name->u.rdnSequence.len > 0
2398 && name->u.rdnSequence.val[0].len == 1
2399 && der_heim_oid_cmp(&name->u.rdnSequence.val[0].val[0].type,
2400 oid_id_at_commonName()) == 0)
2402 DirectoryString *ds = &name->u.rdnSequence.val[0].val[0].value;
2404 switch (ds->element) {
2405 case choice_DirectoryString_printableString:
2406 if (strcasecmp(ds->u.printableString, hostname) == 0)
2409 case choice_DirectoryString_ia5String:
2410 if (strcasecmp(ds->u.ia5String, hostname) == 0)
2413 case choice_DirectoryString_utf8String:
2414 if (strcasecmp(ds->u.utf8String, hostname) == 0)
2422 if ((flags & HX509_VHN_F_ALLOW_NO_MATCH) == 0)
2423 ret = HX509_NAME_CONSTRAINT_ERROR;
2429 _hx509_set_cert_attribute(hx509_context context,
2431 const heim_oid *oid,
2432 const heim_octet_string *attr)
2434 hx509_cert_attribute a;
2437 if (hx509_cert_get_attribute(cert, oid) != NULL)
2440 d = realloc(cert->attrs.val,
2441 sizeof(cert->attrs.val[0]) * (cert->attrs.len + 1));
2443 hx509_clear_error_string(context);
2446 cert->attrs.val = d;
2448 a = malloc(sizeof(*a));
2452 der_copy_octet_string(attr, &a->data);
2453 der_copy_oid(oid, &a->oid);
2455 cert->attrs.val[cert->attrs.len] = a;
2462 * Get an external attribute for the certificate, examples are
2463 * friendly name and id.
2465 * @param cert hx509 certificate object to search
2466 * @param oid an oid to search for.
2468 * @return an hx509_cert_attribute, only valid as long as the
2469 * certificate is referenced.
2471 * @ingroup hx509_cert
2474 hx509_cert_attribute
2475 hx509_cert_get_attribute(hx509_cert cert, const heim_oid *oid)
2478 for (i = 0; i < cert->attrs.len; i++)
2479 if (der_heim_oid_cmp(oid, &cert->attrs.val[i]->oid) == 0)
2480 return cert->attrs.val[i];
2485 * Set the friendly name on the certificate.
2487 * @param cert The certificate to set the friendly name on
2488 * @param name Friendly name.
2490 * @return An hx509 error code, see hx509_get_error_string().
2492 * @ingroup hx509_cert
2496 hx509_cert_set_friendly_name(hx509_cert cert, const char *name)
2498 if (cert->friendlyname)
2499 free(cert->friendlyname);
2500 cert->friendlyname = strdup(name);
2501 if (cert->friendlyname == NULL)
2507 * Get friendly name of the certificate.
2509 * @param cert cert to get the friendly name from.
2511 * @return an friendly name or NULL if there is. The friendly name is
2512 * only valid as long as the certificate is referenced.
2514 * @ingroup hx509_cert
2518 hx509_cert_get_friendly_name(hx509_cert cert)
2520 hx509_cert_attribute a;
2521 PKCS9_friendlyName n;
2525 if (cert->friendlyname)
2526 return cert->friendlyname;
2528 a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_friendlyName());
2532 ret = hx509_cert_get_subject(cert, &name);
2535 ret = hx509_name_to_string(name, &cert->friendlyname);
2536 hx509_name_free(&name);
2539 return cert->friendlyname;
2542 ret = decode_PKCS9_friendlyName(a->data.data, a->data.length, &n, &sz);
2547 free_PKCS9_friendlyName(&n);
2551 cert->friendlyname = malloc(n.val[0].length + 1);
2552 if (cert->friendlyname == NULL) {
2553 free_PKCS9_friendlyName(&n);
2557 for (i = 0; i < n.val[0].length; i++) {
2558 if (n.val[0].data[i] <= 0xff)
2559 cert->friendlyname[i] = n.val[0].data[i] & 0xff;
2561 cert->friendlyname[i] = 'X';
2563 cert->friendlyname[i] = '\0';
2564 free_PKCS9_friendlyName(&n);
2566 return cert->friendlyname;
2570 _hx509_query_clear(hx509_query *q)
2572 memset(q, 0, sizeof(*q));
2576 * Allocate an query controller. Free using hx509_query_free().
2578 * @param context A hx509 context.
2579 * @param q return pointer to a hx509_query.
2581 * @return An hx509 error code, see hx509_get_error_string().
2583 * @ingroup hx509_cert
2587 hx509_query_alloc(hx509_context context, hx509_query **q)
2589 *q = calloc(1, sizeof(**q));
2597 * Set match options for the hx509 query controller.
2599 * @param q query controller.
2600 * @param option options to control the query controller.
2602 * @return An hx509 error code, see hx509_get_error_string().
2604 * @ingroup hx509_cert
2608 hx509_query_match_option(hx509_query *q, hx509_query_option option)
2611 case HX509_QUERY_OPTION_PRIVATE_KEY:
2612 q->match |= HX509_QUERY_PRIVATE_KEY;
2614 case HX509_QUERY_OPTION_KU_ENCIPHERMENT:
2615 q->match |= HX509_QUERY_KU_ENCIPHERMENT;
2617 case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE:
2618 q->match |= HX509_QUERY_KU_DIGITALSIGNATURE;
2620 case HX509_QUERY_OPTION_KU_KEYCERTSIGN:
2621 q->match |= HX509_QUERY_KU_KEYCERTSIGN;
2623 case HX509_QUERY_OPTION_END:
2630 * Set the issuer and serial number of match in the query
2631 * controller. The function make copies of the isser and serial number.
2633 * @param q a hx509 query controller
2634 * @param issuer issuer to search for
2635 * @param serialNumber the serialNumber of the issuer.
2637 * @return An hx509 error code, see hx509_get_error_string().
2639 * @ingroup hx509_cert
2643 hx509_query_match_issuer_serial(hx509_query *q,
2645 const heim_integer *serialNumber)
2649 der_free_heim_integer(q->serial);
2652 q->serial = malloc(sizeof(*q->serial));
2653 if (q->serial == NULL)
2655 ret = der_copy_heim_integer(serialNumber, q->serial);
2661 if (q->issuer_name) {
2662 free_Name(q->issuer_name);
2663 free(q->issuer_name);
2665 q->issuer_name = malloc(sizeof(*q->issuer_name));
2666 if (q->issuer_name == NULL)
2668 ret = copy_Name(issuer, q->issuer_name);
2670 free(q->issuer_name);
2671 q->issuer_name = NULL;
2674 q->match |= HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME;
2679 * Set the query controller to match on a friendly name
2681 * @param q a hx509 query controller.
2682 * @param name a friendly name to match on
2684 * @return An hx509 error code, see hx509_get_error_string().
2686 * @ingroup hx509_cert
2690 hx509_query_match_friendly_name(hx509_query *q, const char *name)
2692 if (q->friendlyname)
2693 free(q->friendlyname);
2694 q->friendlyname = strdup(name);
2695 if (q->friendlyname == NULL)
2697 q->match |= HX509_QUERY_MATCH_FRIENDLY_NAME;
2702 * Set the query controller to require an one specific EKU (extended
2703 * key usage). Any previous EKU matching is overwitten. If NULL is
2704 * passed in as the eku, the EKU requirement is reset.
2706 * @param q a hx509 query controller.
2707 * @param eku an EKU to match on.
2709 * @return An hx509 error code, see hx509_get_error_string().
2711 * @ingroup hx509_cert
2715 hx509_query_match_eku(hx509_query *q, const heim_oid *eku)
2721 der_free_oid(q->eku);
2725 q->match &= ~HX509_QUERY_MATCH_EKU;
2728 der_free_oid(q->eku);
2730 q->eku = calloc(1, sizeof(*q->eku));
2734 ret = der_copy_oid(eku, q->eku);
2740 q->match |= HX509_QUERY_MATCH_EKU;
2746 hx509_query_match_expr(hx509_context context, hx509_query *q, const char *expr)
2749 _hx509_expr_free(q->expr);
2754 q->match &= ~HX509_QUERY_MATCH_EXPR;
2756 q->expr = _hx509_expr_parse(expr);
2758 q->match |= HX509_QUERY_MATCH_EXPR;
2765 * Set the query controller to match using a specific match function.
2767 * @param q a hx509 query controller.
2768 * @param func function to use for matching, if the argument is NULL,
2769 * the match function is removed.
2770 * @param ctx context passed to the function.
2772 * @return An hx509 error code, see hx509_get_error_string().
2774 * @ingroup hx509_cert
2778 hx509_query_match_cmp_func(hx509_query *q,
2779 int (*func)(hx509_context, hx509_cert, void *),
2783 q->match |= HX509_QUERY_MATCH_FUNCTION;
2785 q->match &= ~HX509_QUERY_MATCH_FUNCTION;
2787 q->cmp_func_ctx = ctx;
2792 * Free the query controller.
2794 * @param context A hx509 context.
2795 * @param q a pointer to the query controller.
2797 * @ingroup hx509_cert
2801 hx509_query_free(hx509_context context, hx509_query *q)
2807 der_free_heim_integer(q->serial);
2810 if (q->issuer_name) {
2811 free_Name(q->issuer_name);
2812 free(q->issuer_name);
2815 der_free_oid(q->eku);
2818 if (q->friendlyname)
2819 free(q->friendlyname);
2821 _hx509_expr_free(q->expr);
2823 memset(q, 0, sizeof(*q));
2828 _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert cert)
2830 Certificate *c = _hx509_get_cert(cert);
2833 _hx509_query_statistic(context, 1, q);
2835 if ((q->match & HX509_QUERY_FIND_ISSUER_CERT) &&
2836 _hx509_cert_is_parent_cmp(q->subject, c, 0) != 0)
2839 if ((q->match & HX509_QUERY_MATCH_CERTIFICATE) &&
2840 _hx509_Certificate_cmp(q->certificate, c) != 0)
2843 if ((q->match & HX509_QUERY_MATCH_SERIALNUMBER)
2844 && der_heim_integer_cmp(&c->tbsCertificate.serialNumber, q->serial) != 0)
2847 if (q->match & HX509_QUERY_MATCH_ISSUER_NAME) {
2848 ret = _hx509_name_cmp(&c->tbsCertificate.issuer, q->issuer_name, &diff);
2853 if (q->match & HX509_QUERY_MATCH_SUBJECT_NAME) {
2854 ret = _hx509_name_cmp(&c->tbsCertificate.subject, q->subject_name, &diff);
2859 if (q->match & HX509_QUERY_MATCH_SUBJECT_KEY_ID) {
2860 SubjectKeyIdentifier si;
2862 ret = _hx509_find_extension_subject_key_id(c, &si);
2864 if (der_heim_octet_string_cmp(&si, q->subject_id) != 0)
2866 free_SubjectKeyIdentifier(&si);
2871 if ((q->match & HX509_QUERY_MATCH_ISSUER_ID))
2873 if ((q->match & HX509_QUERY_PRIVATE_KEY) &&
2874 _hx509_cert_private_key(cert) == NULL)
2879 if (q->match & HX509_QUERY_KU_DIGITALSIGNATURE)
2881 if (q->match & HX509_QUERY_KU_NONREPUDIATION)
2883 if (q->match & HX509_QUERY_KU_ENCIPHERMENT)
2885 if (q->match & HX509_QUERY_KU_DATAENCIPHERMENT)
2887 if (q->match & HX509_QUERY_KU_KEYAGREEMENT)
2889 if (q->match & HX509_QUERY_KU_KEYCERTSIGN)
2891 if (q->match & HX509_QUERY_KU_CRLSIGN)
2893 if (ku && check_key_usage(context, c, ku, TRUE))
2896 if ((q->match & HX509_QUERY_ANCHOR))
2899 if (q->match & HX509_QUERY_MATCH_LOCAL_KEY_ID) {
2900 hx509_cert_attribute a;
2902 a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_localKeyId());
2905 if (der_heim_octet_string_cmp(&a->data, q->local_key_id) != 0)
2909 if (q->match & HX509_QUERY_NO_MATCH_PATH) {
2912 for (i = 0; i < q->path->len; i++)
2913 if (hx509_cert_cmp(q->path->val[i], cert) == 0)
2916 if (q->match & HX509_QUERY_MATCH_FRIENDLY_NAME) {
2917 const char *name = hx509_cert_get_friendly_name(cert);
2920 if (strcasecmp(q->friendlyname, name) != 0)
2923 if (q->match & HX509_QUERY_MATCH_FUNCTION) {
2924 ret = (*q->cmp_func)(context, cert, q->cmp_func_ctx);
2929 if (q->match & HX509_QUERY_MATCH_KEY_HASH_SHA1) {
2930 heim_octet_string os;
2932 os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
2934 c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
2936 ret = _hx509_verify_signature(context,
2938 hx509_signature_sha1(),
2945 if (q->match & HX509_QUERY_MATCH_TIME) {
2947 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2950 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
2955 /* If an EKU is required, check the cert for it. */
2956 if ((q->match & HX509_QUERY_MATCH_EKU) &&
2957 hx509_cert_check_eku(context, cert, q->eku, 0))
2960 if ((q->match & HX509_QUERY_MATCH_EXPR)) {
2961 hx509_env env = NULL;
2963 ret = _hx509_cert_to_env(context, cert, &env);
2967 ret = _hx509_expr_eval(context, env, q->expr);
2968 hx509_env_free(&env);
2973 if (q->match & ~HX509_QUERY_MASK)
2980 * Set a statistic file for the query statistics.
2982 * @param context A hx509 context.
2983 * @param fn statistics file name
2985 * @ingroup hx509_cert
2989 hx509_query_statistic_file(hx509_context context, const char *fn)
2991 if (context->querystat)
2992 free(context->querystat);
2993 context->querystat = strdup(fn);
2997 _hx509_query_statistic(hx509_context context, int type, const hx509_query *q)
3000 if (context->querystat == NULL)
3002 f = fopen(context->querystat, "a");
3006 fprintf(f, "%d %d\n", type, q->match);
3010 static const char *statname[] = {
3012 "match serialnumber",
3013 "match issuer name",
3014 "match subject name",
3015 "match subject key id",
3019 "ku digitalsignature",
3022 "ku nonrepudiation",
3024 "ku dataencipherment",
3026 "match certificate",
3027 "match local key id",
3029 "match friendly name",
3031 "match key hash sha1",
3036 unsigned long stats;
3042 stat_sort(const void *a, const void *b)
3044 const struct stat_el *ae = a;
3045 const struct stat_el *be = b;
3046 return be->stats - ae->stats;
3050 * Unparse the statistics file and print the result on a FILE descriptor.
3052 * @param context A hx509 context.
3053 * @param printtype tyep to print
3054 * @param out the FILE to write the data on.
3056 * @ingroup hx509_cert
3060 hx509_query_unparse_stats(hx509_context context, int printtype, FILE *out)
3064 int type, mask, i, num;
3065 unsigned long multiqueries = 0, totalqueries = 0;
3066 struct stat_el stats[32];
3068 if (context->querystat == NULL)
3070 f = fopen(context->querystat, "r");
3072 fprintf(out, "No statistic file %s: %s.\n",
3073 context->querystat, strerror(errno));
3078 for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
3083 while (fscanf(f, "%d %d\n", &type, &mask) == 2) {
3084 if (type != printtype)
3087 while (mask && i < sizeof(stats)/sizeof(stats[0])) {
3101 qsort(stats, sizeof(stats)/sizeof(stats[0]), sizeof(stats[0]), stat_sort);
3105 errx(1, "out of memory");
3107 rtbl_set_separator (t, " ");
3109 rtbl_add_column_by_id (t, 0, "Name", 0);
3110 rtbl_add_column_by_id (t, 1, "Counter", 0);
3113 for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
3116 if (stats[i].index < sizeof(statname)/sizeof(statname[0]))
3117 rtbl_add_column_entry_by_id (t, 0, statname[stats[i].index]);
3119 snprintf(str, sizeof(str), "%d", stats[i].index);
3120 rtbl_add_column_entry_by_id (t, 0, str);
3122 snprintf(str, sizeof(str), "%lu", stats[i].stats);
3123 rtbl_add_column_entry_by_id (t, 1, str);
3126 rtbl_format(t, out);
3129 fprintf(out, "\nQueries: multi %lu total %lu\n",
3130 multiqueries, totalqueries);
3134 * Check the extended key usage on the hx509 certificate.
3136 * @param context A hx509 context.
3137 * @param cert A hx509 context.
3138 * @param eku the EKU to check for
3139 * @param allow_any_eku if the any EKU is set, allow that to be a
3142 * @return An hx509 error code, see hx509_get_error_string().
3144 * @ingroup hx509_cert
3148 hx509_cert_check_eku(hx509_context context, hx509_cert cert,
3149 const heim_oid *eku, int allow_any_eku)
3154 ret = find_extension_eku(_hx509_get_cert(cert), &e);
3156 hx509_clear_error_string(context);
3160 for (i = 0; i < e.len; i++) {
3161 if (der_heim_oid_cmp(eku, &e.val[i]) == 0) {
3162 free_ExtKeyUsage(&e);
3165 if (allow_any_eku) {
3167 if (der_heim_oid_cmp(id_any_eku, &e.val[i]) == 0) {
3168 free_ExtKeyUsage(&e);
3174 free_ExtKeyUsage(&e);
3175 hx509_clear_error_string(context);
3176 return HX509_CERTIFICATE_MISSING_EKU;
3180 _hx509_cert_get_keyusage(hx509_context context,
3189 memset(ku, 0, sizeof(*ku));
3191 cert = _hx509_get_cert(c);
3193 if (_hx509_cert_get_version(cert) < 3)
3196 e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
3198 return HX509_KU_CERT_MISSING;
3200 ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, ku, &size);
3207 _hx509_cert_get_eku(hx509_context context,
3213 memset(e, 0, sizeof(*e));
3215 ret = find_extension_eku(_hx509_get_cert(cert), e);
3216 if (ret && ret != HX509_EXTENSION_NOT_FOUND) {
3217 hx509_clear_error_string(context);
3224 * Encodes the hx509 certificate as a DER encode binary.
3226 * @param context A hx509 context.
3227 * @param c the certificate to encode.
3228 * @param os the encode certificate, set to NULL, 0 on case of
3229 * error. Free the returned structure with hx509_xfree().
3231 * @return An hx509 error code, see hx509_get_error_string().
3233 * @ingroup hx509_cert
3237 hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os)
3245 ASN1_MALLOC_ENCODE(Certificate, os->data, os->length,
3246 _hx509_get_cert(c), &size, ret);
3252 if (os->length != size)
3253 _hx509_abort("internal ASN.1 encoder error");
3259 * Last to avoid lost __attribute__s due to #undef.
3262 #undef __attribute__
3263 #define __attribute__(X)
3266 _hx509_abort(const char *fmt, ...)
3267 __attribute__ ((noreturn, format (printf, 1, 2)))
3279 * Free a data element allocated in the library.
3281 * @param ptr data to be freed.
3283 * @ingroup hx509_misc
3287 hx509_xfree(void *ptr)
3297 _hx509_cert_to_env(hx509_context context, hx509_cert cert, hx509_env *env)
3303 hx509_env envcert = NULL;
3308 asprintf(&buf, "%d", _hx509_cert_get_version(_hx509_get_cert(cert)));
3309 ret = hx509_env_add(context, &envcert, "version", buf);
3315 ret = hx509_cert_get_subject(cert, &name);
3319 ret = hx509_name_to_string(name, &buf);
3321 hx509_name_free(&name);
3325 ret = hx509_env_add(context, &envcert, "subject", buf);
3326 hx509_name_free(&name);
3331 ret = hx509_cert_get_issuer(cert, &name);
3335 ret = hx509_name_to_string(name, &buf);
3336 hx509_name_free(&name);
3340 ret = hx509_env_add(context, &envcert, "issuer", buf);
3347 ret = _hx509_cert_get_eku(context, cert, &eku);
3348 if (ret == HX509_EXTENSION_NOT_FOUND)
3354 hx509_env enveku = NULL;
3356 for (i = 0; i < eku.len; i++) {
3358 ret = der_print_heim_oid(&eku.val[i], '.', &buf);
3360 free_ExtKeyUsage(&eku);
3361 hx509_env_free(&enveku);
3364 ret = hx509_env_add(context, &enveku, buf, "oid-name-here");
3367 free_ExtKeyUsage(&eku);
3368 hx509_env_free(&enveku);
3372 free_ExtKeyUsage(&eku);
3374 ret = hx509_env_add_binding(context, &envcert, "eku", enveku);
3376 hx509_env_free(&enveku);
3382 Certificate *c = _hx509_get_cert(cert);
3383 heim_octet_string os, sig;
3384 hx509_env envhash = NULL;
3387 os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
3389 c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
3391 ret = _hx509_create_signature(context,
3393 hx509_signature_sha1(),
3400 ret = hex_encode(sig.data, sig.length, &buf);
3401 der_free_octet_string(&sig);
3404 hx509_set_error_string(context, 0, ret,
3409 ret = hx509_env_add(context, &envhash, "sha1", buf);
3414 ret = hx509_env_add_binding(context, &envcert, "hash", envhash);
3416 hx509_env_free(&envhash);
3421 ret = hx509_env_add_binding(context, env, "certificate", envcert);
3428 hx509_env_free(&envcert);