2 * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include "crypto-headers.h"
40 * @page page_cert The basic certificate
42 * The basic hx509 cerificate object in hx509 is hx509_cert. The
43 * hx509_cert object is representing one X509/PKIX certificate and
44 * associated attributes; like private key, friendly name, etc.
46 * A hx509_cert object is usully found via the keyset interfaces (@ref
47 * page_keyset), but its also possible to create a certificate
48 * directly from a parsed object with hx509_cert_init() and
49 * hx509_cert_init_data().
51 * See the library functions here: @ref hx509_cert
54 struct hx509_verify_ctx_data {
55 hx509_certs trust_anchors;
57 #define HX509_VERIFY_CTX_F_TIME_SET 1
58 #define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE 2
59 #define HX509_VERIFY_CTX_F_REQUIRE_RFC3280 4
60 #define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS 8
61 #define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS 16
63 unsigned int max_depth;
64 #define HX509_VERIFY_MAX_DEPTH 30
65 hx509_revoke_ctx revoke_ctx;
68 #define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280)
69 #define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS)
70 #define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0)
72 struct _hx509_cert_attrs {
74 hx509_cert_attribute *val;
77 struct hx509_cert_data {
81 hx509_private_key private_key;
82 struct _hx509_cert_attrs attrs;
84 _hx509_cert_release_func release;
88 typedef struct hx509_name_constraints {
91 } hx509_name_constraints;
93 #define GeneralSubtrees_SET(g,var) \
94 (g)->len = (var)->len, (g)->val = (var)->val;
97 * Creates a hx509 context that most functions in the library
98 * uses. The context is only allowed to be used by one thread at each
99 * moment. Free the context with hx509_context_free().
101 * @param context Returns a pointer to new hx509 context.
103 * @return Returns an hx509 error code.
109 hx509_context_init(hx509_context *context)
111 *context = calloc(1, sizeof(**context));
112 if (*context == NULL)
115 _hx509_ks_null_register(*context);
116 _hx509_ks_mem_register(*context);
117 _hx509_ks_file_register(*context);
118 _hx509_ks_pkcs12_register(*context);
119 _hx509_ks_pkcs11_register(*context);
120 _hx509_ks_dir_register(*context);
121 _hx509_ks_keychain_register(*context);
123 ENGINE_add_conf_module();
124 OpenSSL_add_all_algorithms();
126 (*context)->ocsp_time_diff = HX509_DEFAULT_OCSP_TIME_DIFF;
128 initialize_hx_error_table_r(&(*context)->et_list);
129 initialize_asn1_error_table_r(&(*context)->et_list);
131 #ifdef HX509_DEFAULT_ANCHORS
132 (void)hx509_certs_init(*context, HX509_DEFAULT_ANCHORS, 0,
133 NULL, &(*context)->default_trust_anchors);
140 * Selects if the hx509_revoke_verify() function is going to require
141 * the existans of a revokation method (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;
572 static const Extension *
573 find_extension(const Certificate *cert, const heim_oid *oid, int *idx)
575 const TBSCertificate *c = &cert->tbsCertificate;
577 if (c->version == NULL || *c->version < 2 || c->extensions == NULL)
580 for (;*idx < c->extensions->len; (*idx)++) {
581 if (der_heim_oid_cmp(&c->extensions->val[*idx].extnID, oid) == 0)
582 return &c->extensions->val[(*idx)++];
588 find_extension_auth_key_id(const Certificate *subject,
589 AuthorityKeyIdentifier *ai)
595 memset(ai, 0, sizeof(*ai));
597 e = find_extension(subject, oid_id_x509_ce_authorityKeyIdentifier(), &i);
599 return HX509_EXTENSION_NOT_FOUND;
601 return decode_AuthorityKeyIdentifier(e->extnValue.data,
607 _hx509_find_extension_subject_key_id(const Certificate *issuer,
608 SubjectKeyIdentifier *si)
614 memset(si, 0, sizeof(*si));
616 e = find_extension(issuer, oid_id_x509_ce_subjectKeyIdentifier(), &i);
618 return HX509_EXTENSION_NOT_FOUND;
620 return decode_SubjectKeyIdentifier(e->extnValue.data,
626 find_extension_name_constraints(const Certificate *subject,
633 memset(nc, 0, sizeof(*nc));
635 e = find_extension(subject, oid_id_x509_ce_nameConstraints(), &i);
637 return HX509_EXTENSION_NOT_FOUND;
639 return decode_NameConstraints(e->extnValue.data,
645 find_extension_subject_alt_name(const Certificate *cert, int *i,
651 memset(sa, 0, sizeof(*sa));
653 e = find_extension(cert, oid_id_x509_ce_subjectAltName(), i);
655 return HX509_EXTENSION_NOT_FOUND;
657 return decode_GeneralNames(e->extnValue.data,
663 find_extension_eku(const Certificate *cert, ExtKeyUsage *eku)
669 memset(eku, 0, sizeof(*eku));
671 e = find_extension(cert, oid_id_x509_ce_extKeyUsage(), &i);
673 return HX509_EXTENSION_NOT_FOUND;
675 return decode_ExtKeyUsage(e->extnValue.data,
681 add_to_list(hx509_octet_string_list *list, const heim_octet_string *entry)
686 p = realloc(list->val, (list->len + 1) * sizeof(list->val[0]));
690 ret = der_copy_octet_string(entry, &list->val[list->len]);
698 * Free a list of octet strings returned by another hx509 library
701 * @param list list to be freed.
703 * @ingroup hx509_misc
707 hx509_free_octet_string_list(hx509_octet_string_list *list)
710 for (i = 0; i < list->len; i++)
711 der_free_octet_string(&list->val[i]);
718 * Return a list of subjectAltNames specified by oid in the
719 * certificate. On error the
721 * The returned list of octet string should be freed with
722 * hx509_free_octet_string_list().
724 * @param context A hx509 context.
725 * @param cert a hx509 certificate object.
726 * @param oid an oid to for SubjectAltName.
727 * @param list list of matching SubjectAltName.
729 * @return An hx509 error code, see hx509_get_error_string().
731 * @ingroup hx509_cert
735 hx509_cert_find_subjectAltName_otherName(hx509_context context,
738 hx509_octet_string_list *list)
748 ret = find_extension_subject_alt_name(_hx509_get_cert(cert), &i, &sa);
750 if (ret == HX509_EXTENSION_NOT_FOUND) {
753 } else if (ret != 0) {
754 hx509_set_error_string(context, 0, ret, "Error searching for SAN");
755 hx509_free_octet_string_list(list);
759 for (j = 0; j < sa.len; j++) {
760 if (sa.val[j].element == choice_GeneralName_otherName &&
761 der_heim_oid_cmp(&sa.val[j].u.otherName.type_id, oid) == 0)
763 ret = add_to_list(list, &sa.val[j].u.otherName.value);
765 hx509_set_error_string(context, 0, ret,
766 "Error adding an exra SAN to "
768 hx509_free_octet_string_list(list);
769 free_GeneralNames(&sa);
774 free_GeneralNames(&sa);
781 check_key_usage(hx509_context context, const Certificate *cert,
782 unsigned flags, int req_present)
790 if (_hx509_cert_get_version(cert) < 3)
793 e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
796 hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
797 "Required extension key "
798 "usage missing from certifiate");
799 return HX509_KU_CERT_MISSING;
804 ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &size);
807 ku_flags = KeyUsage2int(ku);
808 if ((ku_flags & flags) != flags) {
809 unsigned missing = (~ku_flags) & flags;
810 char buf[256], *name;
812 unparse_flags(missing, asn1_KeyUsage_units(), buf, sizeof(buf));
813 _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
814 hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
815 "Key usage %s required but missing "
816 "from certifiate %s", buf, name);
818 return HX509_KU_CERT_MISSING;
824 * Return 0 on matching key usage 'flags' for 'cert', otherwise return
825 * an error code. If 'req_present' the existance is required of the
826 * KeyUsage extension.
830 _hx509_check_key_usage(hx509_context context, hx509_cert cert,
831 unsigned flags, int req_present)
833 return check_key_usage(context, _hx509_get_cert(cert), flags, req_present);
836 enum certtype { PROXY_CERT, EE_CERT, CA_CERT };
839 check_basic_constraints(hx509_context context, const Certificate *cert,
840 enum certtype type, int depth)
847 if (_hx509_cert_get_version(cert) < 3)
850 e = find_extension(cert, oid_id_x509_ce_basicConstraints(), &i);
858 ret = _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
860 hx509_set_error_string(context, 0, HX509_EXTENSION_NOT_FOUND,
861 "basicConstraints missing from "
862 "CA certifiacte %s", name);
864 return HX509_EXTENSION_NOT_FOUND;
869 ret = decode_BasicConstraints(e->extnValue.data,
870 e->extnValue.length, &bc,
876 if (bc.cA != NULL && *bc.cA)
877 ret = HX509_PARENT_IS_CA;
883 if (bc.cA == NULL || !*bc.cA)
884 ret = HX509_PARENT_NOT_CA;
885 else if (bc.pathLenConstraint)
886 if (depth - 1 > *bc.pathLenConstraint)
887 ret = HX509_CA_PATH_TOO_DEEP;
890 free_BasicConstraints(&bc);
895 _hx509_cert_is_parent_cmp(const Certificate *subject,
896 const Certificate *issuer,
897 int allow_self_signed)
900 AuthorityKeyIdentifier ai;
901 SubjectKeyIdentifier si;
902 int ret_ai, ret_si, ret;
904 ret = _hx509_name_cmp(&issuer->tbsCertificate.subject,
905 &subject->tbsCertificate.issuer,
912 memset(&ai, 0, sizeof(ai));
913 memset(&si, 0, sizeof(si));
916 * Try to find AuthorityKeyIdentifier, if it's not present in the
917 * subject certificate nor the parent.
920 ret_ai = find_extension_auth_key_id(subject, &ai);
921 if (ret_ai && ret_ai != HX509_EXTENSION_NOT_FOUND)
923 ret_si = _hx509_find_extension_subject_key_id(issuer, &si);
924 if (ret_si && ret_si != HX509_EXTENSION_NOT_FOUND)
927 if (ret_si && ret_ai)
932 if (allow_self_signed) {
935 } else if (ai.keyIdentifier) {
941 if (ai.keyIdentifier == NULL) {
944 if (ai.authorityCertIssuer == NULL)
946 if (ai.authorityCertSerialNumber == NULL)
949 diff = der_heim_integer_cmp(ai.authorityCertSerialNumber,
950 &issuer->tbsCertificate.serialNumber);
953 if (ai.authorityCertIssuer->len != 1)
955 if (ai.authorityCertIssuer->val[0].element != choice_GeneralName_directoryName)
959 ai.authorityCertIssuer->val[0].u.directoryName.element;
961 ai.authorityCertIssuer->val[0].u.directoryName.u.rdnSequence;
963 ret = _hx509_name_cmp(&issuer->tbsCertificate.subject,
972 diff = der_heim_octet_string_cmp(ai.keyIdentifier, &si);
977 free_AuthorityKeyIdentifier(&ai);
978 free_SubjectKeyIdentifier(&si);
983 certificate_is_anchor(hx509_context context,
984 hx509_certs trust_anchors,
985 const hx509_cert cert)
991 if (trust_anchors == NULL)
994 _hx509_query_clear(&q);
996 q.match = HX509_QUERY_MATCH_CERTIFICATE;
997 q.certificate = _hx509_get_cert(cert);
999 ret = hx509_certs_find(context, trust_anchors, &q, &c);
1006 certificate_is_self_signed(hx509_context context,
1007 const Certificate *cert,
1011 ret = _hx509_name_cmp(&cert->tbsCertificate.subject,
1012 &cert->tbsCertificate.issuer, &diff);
1013 *self_signed = (diff == 0);
1015 hx509_set_error_string(context, 0, ret,
1016 "Failed to check if self signed");
1021 * The subjectName is "null" when it's empty set of relative DBs.
1025 subject_null_p(const Certificate *c)
1027 return c->tbsCertificate.subject.u.rdnSequence.len == 0;
1032 find_parent(hx509_context context,
1034 hx509_certs trust_anchors,
1040 AuthorityKeyIdentifier ai;
1045 memset(&ai, 0, sizeof(ai));
1047 _hx509_query_clear(&q);
1049 if (!subject_null_p(current->data)) {
1050 q.match |= HX509_QUERY_FIND_ISSUER_CERT;
1051 q.subject = _hx509_get_cert(current);
1053 ret = find_extension_auth_key_id(current->data, &ai);
1055 hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
1056 "Subjectless certificate missing AuthKeyID");
1057 return HX509_CERTIFICATE_MALFORMED;
1060 if (ai.keyIdentifier == NULL) {
1061 free_AuthorityKeyIdentifier(&ai);
1062 hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
1063 "Subjectless certificate missing keyIdentifier "
1064 "inside AuthKeyID");
1065 return HX509_CERTIFICATE_MALFORMED;
1068 q.subject_id = ai.keyIdentifier;
1069 q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID;
1073 q.match |= HX509_QUERY_NO_MATCH_PATH;
1076 q.timenow = time_now;
1077 q.match |= HX509_QUERY_MATCH_TIME;
1079 ret = hx509_certs_find(context, pool, &q, parent);
1081 free_AuthorityKeyIdentifier(&ai);
1084 q.match &= ~HX509_QUERY_MATCH_TIME;
1087 if (trust_anchors) {
1088 ret = hx509_certs_find(context, trust_anchors, &q, parent);
1090 free_AuthorityKeyIdentifier(&ai);
1094 free_AuthorityKeyIdentifier(&ai);
1100 ret = hx509_cert_get_subject(current, &name);
1102 hx509_clear_error_string(context);
1103 return HX509_ISSUER_NOT_FOUND;
1105 ret = hx509_name_to_string(name, &str);
1106 hx509_name_free(&name);
1108 hx509_clear_error_string(context);
1109 return HX509_ISSUER_NOT_FOUND;
1112 hx509_set_error_string(context, 0, HX509_ISSUER_NOT_FOUND,
1113 "Failed to find issuer for "
1114 "certificate with subject: '%s'", str);
1117 return HX509_ISSUER_NOT_FOUND;
1125 is_proxy_cert(hx509_context context,
1126 const Certificate *cert,
1127 ProxyCertInfo *rinfo)
1135 memset(rinfo, 0, sizeof(*rinfo));
1137 e = find_extension(cert, oid_id_pkix_pe_proxyCertInfo(), &i);
1139 hx509_clear_error_string(context);
1140 return HX509_EXTENSION_NOT_FOUND;
1143 ret = decode_ProxyCertInfo(e->extnValue.data,
1144 e->extnValue.length,
1148 hx509_clear_error_string(context);
1151 if (size != e->extnValue.length) {
1152 free_ProxyCertInfo(&info);
1153 hx509_clear_error_string(context);
1154 return HX509_EXTRA_DATA_AFTER_STRUCTURE;
1157 free_ProxyCertInfo(&info);
1165 * Path operations are like MEMORY based keyset, but with exposed
1166 * internal so we can do easy searches.
1170 _hx509_path_append(hx509_context context, hx509_path *path, hx509_cert cert)
1173 val = realloc(path->val, (path->len + 1) * sizeof(path->val[0]));
1175 hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1180 path->val[path->len] = hx509_cert_ref(cert);
1187 _hx509_path_free(hx509_path *path)
1191 for (i = 0; i < path->len; i++)
1192 hx509_cert_free(path->val[i]);
1199 * Find path by looking up issuer for the top certificate and continue
1200 * until an anchor certificate is found or max limit is found. A
1201 * certificate never included twice in the path.
1203 * If the trust anchors are not given, calculate optimistic path, just
1204 * follow the chain upward until we no longer find a parent or we hit
1205 * the max path limit. In this case, a failure will always be returned
1206 * depending on what error condition is hit first.
1208 * The path includes a path from the top certificate to the anchor
1211 * The caller needs to free `path´ both on successful built path and
1216 _hx509_calculate_path(hx509_context context,
1219 hx509_certs anchors,
1220 unsigned int max_depth,
1225 hx509_cert parent, current;
1229 max_depth = HX509_VERIFY_MAX_DEPTH;
1231 ret = _hx509_path_append(context, path, cert);
1235 current = hx509_cert_ref(cert);
1237 while (!certificate_is_anchor(context, anchors, current)) {
1239 ret = find_parent(context, time_now, anchors, path,
1240 pool, current, &parent);
1241 hx509_cert_free(current);
1245 ret = _hx509_path_append(context, path, parent);
1250 if (path->len > max_depth) {
1251 hx509_cert_free(current);
1252 hx509_set_error_string(context, 0, HX509_PATH_TOO_LONG,
1253 "Path too long while bulding "
1254 "certificate chain");
1255 return HX509_PATH_TOO_LONG;
1259 if ((flags & HX509_CALCULATE_PATH_NO_ANCHOR) &&
1261 certificate_is_anchor(context, anchors, path->val[path->len - 1]))
1263 hx509_cert_free(path->val[path->len - 1]);
1267 hx509_cert_free(current);
1272 _hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier *p,
1273 const AlgorithmIdentifier *q)
1276 diff = der_heim_oid_cmp(&p->algorithm, &q->algorithm);
1279 if (p->parameters) {
1281 return heim_any_cmp(p->parameters,
1294 _hx509_Certificate_cmp(const Certificate *p, const Certificate *q)
1297 diff = der_heim_bit_string_cmp(&p->signatureValue, &q->signatureValue);
1300 diff = _hx509_AlgorithmIdentifier_cmp(&p->signatureAlgorithm,
1301 &q->signatureAlgorithm);
1304 diff = der_heim_octet_string_cmp(&p->tbsCertificate._save,
1305 &q->tbsCertificate._save);
1310 * Compare to hx509 certificate object, useful for sorting.
1312 * @param p a hx509 certificate object.
1313 * @param q a hx509 certificate object.
1315 * @return 0 the objects are the same, returns > 0 is p is "larger"
1316 * then q, < 0 if p is "smaller" then q.
1318 * @ingroup hx509_cert
1322 hx509_cert_cmp(hx509_cert p, hx509_cert q)
1324 return _hx509_Certificate_cmp(p->data, q->data);
1328 * Return the name of the issuer of the hx509 certificate.
1330 * @param p a hx509 certificate object.
1331 * @param name a pointer to a hx509 name, should be freed by
1332 * hx509_name_free().
1334 * @return An hx509 error code, see hx509_get_error_string().
1336 * @ingroup hx509_cert
1340 hx509_cert_get_issuer(hx509_cert p, hx509_name *name)
1342 return _hx509_name_from_Name(&p->data->tbsCertificate.issuer, name);
1346 * Return the name of the subject of the hx509 certificate.
1348 * @param p a hx509 certificate object.
1349 * @param name a pointer to a hx509 name, should be freed by
1350 * hx509_name_free(). See also hx509_cert_get_base_subject().
1352 * @return An hx509 error code, see hx509_get_error_string().
1354 * @ingroup hx509_cert
1358 hx509_cert_get_subject(hx509_cert p, hx509_name *name)
1360 return _hx509_name_from_Name(&p->data->tbsCertificate.subject, name);
1364 * Return the name of the base subject of the hx509 certificate. If
1365 * the certiicate is a verified proxy certificate, the this function
1366 * return the base certificate (root of the proxy chain). If the proxy
1367 * certificate is not verified with the base certificate
1368 * HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned.
1370 * @param context a hx509 context.
1371 * @param c a hx509 certificate object.
1372 * @param name a pointer to a hx509 name, should be freed by
1373 * hx509_name_free(). See also hx509_cert_get_subject().
1375 * @return An hx509 error code, see hx509_get_error_string().
1377 * @ingroup hx509_cert
1381 hx509_cert_get_base_subject(hx509_context context, hx509_cert c,
1385 return hx509_name_copy(context, c->basename, name);
1386 if (is_proxy_cert(context, c->data, NULL) == 0) {
1387 int ret = HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED;
1388 hx509_set_error_string(context, 0, ret,
1389 "Proxy certificate have not been "
1390 "canonicalize yet, no base name");
1393 return _hx509_name_from_Name(&c->data->tbsCertificate.subject, name);
1397 * Get serial number of the certificate.
1399 * @param p a hx509 certificate object.
1400 * @param i serial number, should be freed ith der_free_heim_integer().
1402 * @return An hx509 error code, see hx509_get_error_string().
1404 * @ingroup hx509_cert
1408 hx509_cert_get_serialnumber(hx509_cert p, heim_integer *i)
1410 return der_copy_heim_integer(&p->data->tbsCertificate.serialNumber, i);
1414 * Get notBefore time of the certificate.
1416 * @param p a hx509 certificate object.
1418 * @return return not before time
1420 * @ingroup hx509_cert
1424 hx509_cert_get_notBefore(hx509_cert p)
1426 return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notBefore);
1430 * Get notAfter time of the certificate.
1432 * @param p a hx509 certificate object.
1434 * @return return not after time.
1436 * @ingroup hx509_cert
1440 hx509_cert_get_notAfter(hx509_cert p)
1442 return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notAfter);
1446 * Get the SubjectPublicKeyInfo structure from the hx509 certificate.
1448 * @param context a hx509 context.
1449 * @param p a hx509 certificate object.
1450 * @param spki SubjectPublicKeyInfo, should be freed with
1451 * free_SubjectPublicKeyInfo().
1453 * @return An hx509 error code, see hx509_get_error_string().
1455 * @ingroup hx509_cert
1459 hx509_cert_get_SPKI(hx509_context context, hx509_cert p, SubjectPublicKeyInfo *spki)
1463 ret = copy_SubjectPublicKeyInfo(&p->data->tbsCertificate.subjectPublicKeyInfo, spki);
1465 hx509_set_error_string(context, 0, ret, "Failed to copy SPKI");
1470 * Get the AlgorithmIdentifier from the hx509 certificate.
1472 * @param context a hx509 context.
1473 * @param p a hx509 certificate object.
1474 * @param alg AlgorithmIdentifier, should be freed with
1475 * free_AlgorithmIdentifier().
1477 * @return An hx509 error code, see hx509_get_error_string().
1479 * @ingroup hx509_cert
1483 hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context,
1485 AlgorithmIdentifier *alg)
1489 ret = copy_AlgorithmIdentifier(&p->data->tbsCertificate.subjectPublicKeyInfo.algorithm, alg);
1491 hx509_set_error_string(context, 0, ret,
1492 "Failed to copy SPKI AlgorithmIdentifier");
1498 _hx509_cert_private_key(hx509_cert p)
1500 return p->private_key;
1504 hx509_cert_have_private_key(hx509_cert p)
1506 return p->private_key ? 1 : 0;
1511 _hx509_cert_private_key_exportable(hx509_cert p)
1513 if (p->private_key == NULL)
1515 return _hx509_private_key_exportable(p->private_key);
1519 _hx509_cert_private_decrypt(hx509_context context,
1520 const heim_octet_string *ciphertext,
1521 const heim_oid *encryption_oid,
1523 heim_octet_string *cleartext)
1525 cleartext->data = NULL;
1526 cleartext->length = 0;
1528 if (p->private_key == NULL) {
1529 hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
1530 "Private key missing");
1531 return HX509_PRIVATE_KEY_MISSING;
1534 return _hx509_private_key_private_decrypt(context,
1542 _hx509_cert_public_encrypt(hx509_context context,
1543 const heim_octet_string *cleartext,
1545 heim_oid *encryption_oid,
1546 heim_octet_string *ciphertext)
1548 return _hx509_public_encrypt(context,
1550 encryption_oid, ciphertext);
1558 _hx509_Time2time_t(const Time *t)
1560 switch(t->element) {
1561 case choice_Time_utcTime:
1562 return t->u.utcTime;
1563 case choice_Time_generalTime:
1564 return t->u.generalTime;
1574 init_name_constraints(hx509_name_constraints *nc)
1576 memset(nc, 0, sizeof(*nc));
1581 add_name_constraints(hx509_context context, const Certificate *c, int not_ca,
1582 hx509_name_constraints *nc)
1584 NameConstraints tnc;
1587 ret = find_extension_name_constraints(c, &tnc);
1588 if (ret == HX509_EXTENSION_NOT_FOUND)
1591 hx509_set_error_string(context, 0, ret, "Failed getting NameConstraints");
1593 } else if (not_ca) {
1594 ret = HX509_VERIFY_CONSTRAINTS;
1595 hx509_set_error_string(context, 0, ret, "Not a CA and "
1596 "have NameConstraints");
1598 NameConstraints *val;
1599 val = realloc(nc->val, sizeof(nc->val[0]) * (nc->len + 1));
1601 hx509_clear_error_string(context);
1606 ret = copy_NameConstraints(&tnc, &nc->val[nc->len]);
1608 hx509_clear_error_string(context);
1614 free_NameConstraints(&tnc);
1619 match_RDN(const RelativeDistinguishedName *c,
1620 const RelativeDistinguishedName *n)
1624 if (c->len != n->len)
1625 return HX509_NAME_CONSTRAINT_ERROR;
1627 for (i = 0; i < n->len; i++) {
1630 if (der_heim_oid_cmp(&c->val[i].type, &n->val[i].type) != 0)
1631 return HX509_NAME_CONSTRAINT_ERROR;
1632 ret = _hx509_name_ds_cmp(&c->val[i].value, &n->val[i].value, &diff);
1636 return HX509_NAME_CONSTRAINT_ERROR;
1642 match_X501Name(const Name *c, const Name *n)
1646 if (c->element != choice_Name_rdnSequence
1647 || n->element != choice_Name_rdnSequence)
1649 if (c->u.rdnSequence.len > n->u.rdnSequence.len)
1650 return HX509_NAME_CONSTRAINT_ERROR;
1651 for (i = 0; i < c->u.rdnSequence.len; i++) {
1652 ret = match_RDN(&c->u.rdnSequence.val[i], &n->u.rdnSequence.val[i]);
1661 match_general_name(const GeneralName *c, const GeneralName *n, int *match)
1664 * Name constraints only apply to the same name type, see RFC3280,
1667 assert(c->element == n->element);
1669 switch(c->element) {
1670 case choice_GeneralName_otherName:
1671 if (der_heim_oid_cmp(&c->u.otherName.type_id,
1672 &n->u.otherName.type_id) != 0)
1673 return HX509_NAME_CONSTRAINT_ERROR;
1674 if (heim_any_cmp(&c->u.otherName.value,
1675 &n->u.otherName.value) != 0)
1676 return HX509_NAME_CONSTRAINT_ERROR;
1679 case choice_GeneralName_rfc822Name: {
1682 s = strchr(c->u.rfc822Name, '@');
1684 if (strcasecmp(c->u.rfc822Name, n->u.rfc822Name) != 0)
1685 return HX509_NAME_CONSTRAINT_ERROR;
1687 s = strchr(n->u.rfc822Name, '@');
1689 return HX509_NAME_CONSTRAINT_ERROR;
1690 len1 = strlen(c->u.rfc822Name);
1691 len2 = strlen(s + 1);
1693 return HX509_NAME_CONSTRAINT_ERROR;
1694 if (strcasecmp(s + 1 + len2 - len1, c->u.rfc822Name) != 0)
1695 return HX509_NAME_CONSTRAINT_ERROR;
1696 if (len1 < len2 && s[len2 - len1 + 1] != '.')
1697 return HX509_NAME_CONSTRAINT_ERROR;
1702 case choice_GeneralName_dNSName: {
1705 lenc = strlen(c->u.dNSName);
1706 lenn = strlen(n->u.dNSName);
1708 return HX509_NAME_CONSTRAINT_ERROR;
1709 if (strcasecmp(&n->u.dNSName[lenn - lenc], c->u.dNSName) != 0)
1710 return HX509_NAME_CONSTRAINT_ERROR;
1711 if (lenc != lenn && n->u.dNSName[lenn - lenc - 1] != '.')
1712 return HX509_NAME_CONSTRAINT_ERROR;
1716 case choice_GeneralName_directoryName: {
1717 Name c_name, n_name;
1720 c_name._save.data = NULL;
1721 c_name._save.length = 0;
1722 c_name.element = c->u.directoryName.element;
1723 c_name.u.rdnSequence = c->u.directoryName.u.rdnSequence;
1725 n_name._save.data = NULL;
1726 n_name._save.length = 0;
1727 n_name.element = n->u.directoryName.element;
1728 n_name.u.rdnSequence = n->u.directoryName.u.rdnSequence;
1730 ret = match_X501Name(&c_name, &n_name);
1735 case choice_GeneralName_uniformResourceIdentifier:
1736 case choice_GeneralName_iPAddress:
1737 case choice_GeneralName_registeredID:
1739 return HX509_NAME_CONSTRAINT_ERROR;
1744 match_alt_name(const GeneralName *n, const Certificate *c,
1745 int *same, int *match)
1752 ret = find_extension_subject_alt_name(c, &i, &sa);
1753 if (ret == HX509_EXTENSION_NOT_FOUND) {
1756 } else if (ret != 0)
1759 for (j = 0; j < sa.len; j++) {
1760 if (n->element == sa.val[j].element) {
1762 ret = match_general_name(n, &sa.val[j], match);
1765 free_GeneralNames(&sa);
1772 match_tree(const GeneralSubtrees *t, const Certificate *c, int *match)
1774 int name, alt_name, same;
1778 name = alt_name = same = *match = 0;
1779 for (i = 0; i < t->len; i++) {
1780 if (t->val[i].minimum && t->val[i].maximum)
1784 * If the constraint apply to directoryNames, test is with
1785 * subjectName of the certificate if the certificate have a
1786 * non-null (empty) subjectName.
1789 if (t->val[i].base.element == choice_GeneralName_directoryName
1790 && !subject_null_p(c))
1792 GeneralName certname;
1794 memset(&certname, 0, sizeof(certname));
1795 certname.element = choice_GeneralName_directoryName;
1796 certname.u.directoryName.element =
1797 c->tbsCertificate.subject.element;
1798 certname.u.directoryName.u.rdnSequence =
1799 c->tbsCertificate.subject.u.rdnSequence;
1801 ret = match_general_name(&t->val[i].base, &certname, &name);
1804 /* Handle subjectAltNames, this is icky since they
1805 * restrictions only apply if the subjectAltName is of the
1806 * same type. So if there have been a match of type, require
1807 * altname to be set.
1809 ret = match_alt_name(&t->val[i].base, c, &same, &alt_name);
1811 if (name && (!same || alt_name))
1817 check_name_constraints(hx509_context context,
1818 const hx509_name_constraints *nc,
1819 const Certificate *c)
1824 for (i = 0 ; i < nc->len; i++) {
1827 if (nc->val[i].permittedSubtrees) {
1828 GeneralSubtrees_SET(&gs, nc->val[i].permittedSubtrees);
1829 ret = match_tree(&gs, c, &match);
1831 hx509_clear_error_string(context);
1834 /* allow null subjectNames, they wont matches anything */
1835 if (match == 0 && !subject_null_p(c)) {
1836 hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS,
1837 "Error verify constraints, "
1838 "certificate didn't match any "
1839 "permitted subtree");
1840 return HX509_VERIFY_CONSTRAINTS;
1843 if (nc->val[i].excludedSubtrees) {
1844 GeneralSubtrees_SET(&gs, nc->val[i].excludedSubtrees);
1845 ret = match_tree(&gs, c, &match);
1847 hx509_clear_error_string(context);
1851 hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS,
1852 "Error verify constraints, "
1853 "certificate included in excluded "
1855 return HX509_VERIFY_CONSTRAINTS;
1863 free_name_constraints(hx509_name_constraints *nc)
1867 for (i = 0 ; i < nc->len; i++)
1868 free_NameConstraints(&nc->val[i]);
1873 * Build and verify the path for the certificate to the trust anchor
1874 * specified in the verify context. The path is constructed from the
1875 * certificate, the pool and the trust anchors.
1877 * @param context A hx509 context.
1878 * @param ctx A hx509 verification context.
1879 * @param cert the certificate to build the path from.
1880 * @param pool A keyset of certificates to build the chain from.
1882 * @return An hx509 error code, see hx509_get_error_string().
1884 * @ingroup hx509_verify
1888 hx509_verify_path(hx509_context context,
1889 hx509_verify_ctx ctx,
1893 hx509_name_constraints nc;
1895 int ret, i, proxy_cert_depth, selfsigned_depth, diff;
1898 hx509_certs anchors = NULL;
1900 memset(&proxy_issuer, 0, sizeof(proxy_issuer));
1902 ret = init_name_constraints(&nc);
1909 if ((ctx->flags & HX509_VERIFY_CTX_F_TIME_SET) == 0)
1910 ctx->time_now = time(NULL);
1915 if (ctx->trust_anchors)
1916 anchors = _hx509_certs_ref(ctx->trust_anchors);
1917 else if (context->default_trust_anchors && ALLOW_DEF_TA(ctx))
1918 anchors = _hx509_certs_ref(context->default_trust_anchors);
1920 ret = hx509_certs_init(context, "MEMORY:no-TA", 0, NULL, &anchors);
1926 * Calculate the path from the certificate user presented to the
1929 ret = _hx509_calculate_path(context, 0, ctx->time_now,
1930 anchors, ctx->max_depth,
1936 * Check CA and proxy certificate chain from the top of the
1937 * certificate chain. Also check certificate is valid with respect
1938 * to the current time.
1942 proxy_cert_depth = 0;
1943 selfsigned_depth = 0;
1945 if (ctx->flags & HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE)
1950 for (i = 0; i < path.len; i++) {
1954 c = _hx509_get_cert(path.val[i]);
1957 * Lets do some basic check on issuer like
1958 * keyUsage.keyCertSign and basicConstraints.cA bit depending
1959 * on what type of certificate this is.
1965 /* XXX make constants for keyusage */
1966 ret = check_key_usage(context, c, 1 << 5,
1967 REQUIRE_RFC3280(ctx) ? TRUE : FALSE);
1969 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
1970 "Key usage missing from CA certificate");
1974 /* self signed cert doesn't add to path length */
1975 if (i + 1 != path.len) {
1978 ret = certificate_is_self_signed(context, c, &selfsigned);
1989 if (is_proxy_cert(context, c, &info) == 0) {
1992 if (info.pCPathLenConstraint != NULL &&
1993 *info.pCPathLenConstraint < i)
1995 free_ProxyCertInfo(&info);
1996 ret = HX509_PATH_TOO_LONG;
1997 hx509_set_error_string(context, 0, ret,
1998 "Proxy certificate chain "
1999 "longer then allowed");
2002 /* XXX MUST check info.proxyPolicy */
2003 free_ProxyCertInfo(&info);
2006 if (find_extension(c, oid_id_x509_ce_subjectAltName(), &j)) {
2007 ret = HX509_PROXY_CERT_INVALID;
2008 hx509_set_error_string(context, 0, ret,
2009 "Proxy certificate have explicity "
2010 "forbidden subjectAltName");
2015 if (find_extension(c, oid_id_x509_ce_issuerAltName(), &j)) {
2016 ret = HX509_PROXY_CERT_INVALID;
2017 hx509_set_error_string(context, 0, ret,
2018 "Proxy certificate have explicity "
2019 "forbidden issuerAltName");
2024 * The subject name of the proxy certificate should be
2025 * CN=XXX,<proxy issuer>, prune of CN and check if its
2026 * the same over the whole chain of proxy certs and
2027 * then check with the EE cert when we get to it.
2030 if (proxy_cert_depth) {
2031 ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.subject, &diff);
2033 hx509_set_error_string(context, 0, ret, "Out of memory");
2037 ret = HX509_PROXY_CERT_NAME_WRONG;
2038 hx509_set_error_string(context, 0, ret,
2039 "Base proxy name not right");
2044 free_Name(&proxy_issuer);
2046 ret = copy_Name(&c->tbsCertificate.subject, &proxy_issuer);
2048 hx509_clear_error_string(context);
2052 j = proxy_issuer.u.rdnSequence.len;
2053 if (proxy_issuer.u.rdnSequence.len < 2
2054 || proxy_issuer.u.rdnSequence.val[j - 1].len > 1
2055 || der_heim_oid_cmp(&proxy_issuer.u.rdnSequence.val[j - 1].val[0].type,
2056 oid_id_at_commonName()))
2058 ret = HX509_PROXY_CERT_NAME_WRONG;
2059 hx509_set_error_string(context, 0, ret,
2060 "Proxy name too short or "
2061 "does not have Common name "
2066 free_RelativeDistinguishedName(&proxy_issuer.u.rdnSequence.val[j - 1]);
2067 proxy_issuer.u.rdnSequence.len -= 1;
2069 ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.issuer, &diff);
2071 hx509_set_error_string(context, 0, ret, "Out of memory");
2075 ret = HX509_PROXY_CERT_NAME_WRONG;
2076 hx509_set_error_string(context, 0, ret,
2077 "Proxy issuer name not as expected");
2084 * Now we are done with the proxy certificates, this
2085 * cert was an EE cert and we we will fall though to
2086 * EE checking below.
2094 * If there where any proxy certificates in the chain
2095 * (proxy_cert_depth > 0), check that the proxy issuer
2096 * matched proxy certificates "base" subject.
2098 if (proxy_cert_depth) {
2100 ret = _hx509_name_cmp(&proxy_issuer,
2101 &c->tbsCertificate.subject, &diff);
2103 hx509_set_error_string(context, 0, ret, "out of memory");
2107 ret = HX509_PROXY_CERT_NAME_WRONG;
2108 hx509_clear_error_string(context);
2112 hx509_name_free(&cert->basename);
2114 ret = _hx509_name_from_Name(&proxy_issuer, &cert->basename);
2116 hx509_clear_error_string(context);
2124 ret = check_basic_constraints(context, c, type,
2125 i - proxy_cert_depth - selfsigned_depth);
2130 * Don't check the trust anchors expiration time since they
2131 * are transported out of band, from RFC3820.
2133 if (i + 1 != path.len || CHECK_TA(ctx)) {
2135 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2136 if (t > ctx->time_now) {
2137 ret = HX509_CERT_USED_BEFORE_TIME;
2138 hx509_clear_error_string(context);
2141 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
2142 if (t < ctx->time_now) {
2143 ret = HX509_CERT_USED_AFTER_TIME;
2144 hx509_clear_error_string(context);
2149 if (type == EE_CERT)
2151 else if (type == PROXY_CERT)
2156 * Verify constraints, do this backward so path constraints are
2157 * checked in the right order.
2160 for (ret = 0, i = path.len - 1; i >= 0; i--) {
2164 c = _hx509_get_cert(path.val[i]);
2166 ret = certificate_is_self_signed(context, c, &selfsigned);
2170 /* verify name constraints, not for selfsigned and anchor */
2171 if (!selfsigned || i + 1 != path.len) {
2172 ret = check_name_constraints(context, &nc, c);
2177 ret = add_name_constraints(context, c, i == 0, &nc);
2181 /* XXX verify all other silly constraints */
2186 * Verify that no certificates has been revoked.
2189 if (ctx->revoke_ctx) {
2192 ret = hx509_certs_init(context, "MEMORY:revoke-certs", 0,
2197 for (i = 0; i < path.len; i++) {
2198 ret = hx509_certs_add(context, certs, path.val[i]);
2200 hx509_certs_free(&certs);
2204 ret = hx509_certs_merge(context, certs, pool);
2206 hx509_certs_free(&certs);
2210 for (i = 0; i < path.len - 1; i++) {
2211 int parent = (i < path.len - 1) ? i + 1 : i;
2213 ret = hx509_revoke_verify(context,
2220 hx509_certs_free(&certs);
2224 hx509_certs_free(&certs);
2228 * Verify signatures, do this backward so public key working
2229 * parameter is passed up from the anchor up though the chain.
2232 for (i = path.len - 1; i >= 0; i--) {
2233 Certificate *signer, *c;
2235 c = _hx509_get_cert(path.val[i]);
2237 /* is last in chain (trust anchor) */
2238 if (i + 1 == path.len) {
2241 signer = path.val[i]->data;
2243 ret = certificate_is_self_signed(context, signer, &selfsigned);
2247 /* if trust anchor is not self signed, don't check sig */
2251 /* take next certificate in chain */
2252 signer = path.val[i + 1]->data;
2255 /* verify signatureValue */
2256 ret = _hx509_verify_signature_bitstring(context,
2258 &c->signatureAlgorithm,
2259 &c->tbsCertificate._save,
2260 &c->signatureValue);
2262 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
2263 "Failed to verify signature of certificate");
2269 hx509_certs_free(&anchors);
2270 free_Name(&proxy_issuer);
2271 free_name_constraints(&nc);
2272 _hx509_path_free(&path);
2278 * Verify a signature made using the private key of an certificate.
2280 * @param context A hx509 context.
2281 * @param signer the certificate that made the signature.
2282 * @param alg algorthm that was used to sign the data.
2283 * @param data the data that was signed.
2284 * @param sig the sigature to verify.
2286 * @return An hx509 error code, see hx509_get_error_string().
2288 * @ingroup hx509_crypto
2292 hx509_verify_signature(hx509_context context,
2293 const hx509_cert signer,
2294 const AlgorithmIdentifier *alg,
2295 const heim_octet_string *data,
2296 const heim_octet_string *sig)
2298 return _hx509_verify_signature(context, signer->data, alg, data, sig);
2303 * Verify that the certificate is allowed to be used for the hostname
2306 * @param context A hx509 context.
2307 * @param cert the certificate to match with
2308 * @param flags Flags to modify the behavior:
2309 * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok
2310 * @param type type of hostname:
2311 * - HX509_HN_HOSTNAME for plain hostname.
2312 * - HX509_HN_DNSSRV for DNS SRV names.
2313 * @param hostname the hostname to check
2314 * @param sa address of the host
2315 * @param sa_size length of address
2317 * @return An hx509 error code, see hx509_get_error_string().
2319 * @ingroup hx509_cert
2323 hx509_verify_hostname(hx509_context context,
2324 const hx509_cert cert,
2326 hx509_hostname_type type,
2327 const char *hostname,
2328 const struct sockaddr *sa,
2329 /* XXX krb5_socklen_t */ int sa_size)
2334 if (sa && sa_size <= 0)
2337 memset(&san, 0, sizeof(san));
2341 ret = find_extension_subject_alt_name(cert->data, &i, &san);
2342 if (ret == HX509_EXTENSION_NOT_FOUND) {
2345 } else if (ret != 0)
2348 for (j = 0; j < san.len; j++) {
2349 switch (san.val[j].element) {
2350 case choice_GeneralName_dNSName:
2351 if (strcasecmp(san.val[j].u.dNSName, hostname) == 0) {
2352 free_GeneralNames(&san);
2360 free_GeneralNames(&san);
2364 const Name *name = &cert->data->tbsCertificate.subject;
2366 /* match if first component is a CN= */
2367 if (name->u.rdnSequence.len > 0
2368 && name->u.rdnSequence.val[0].len == 1
2369 && der_heim_oid_cmp(&name->u.rdnSequence.val[0].val[0].type,
2370 oid_id_at_commonName()) == 0)
2372 DirectoryString *ds = &name->u.rdnSequence.val[0].val[0].value;
2374 switch (ds->element) {
2375 case choice_DirectoryString_printableString:
2376 if (strcasecmp(ds->u.printableString, hostname) == 0)
2379 case choice_DirectoryString_ia5String:
2380 if (strcasecmp(ds->u.ia5String, hostname) == 0)
2383 case choice_DirectoryString_utf8String:
2384 if (strcasecmp(ds->u.utf8String, hostname) == 0)
2392 if ((flags & HX509_VHN_F_ALLOW_NO_MATCH) == 0)
2393 ret = HX509_NAME_CONSTRAINT_ERROR;
2399 _hx509_set_cert_attribute(hx509_context context,
2401 const heim_oid *oid,
2402 const heim_octet_string *attr)
2404 hx509_cert_attribute a;
2407 if (hx509_cert_get_attribute(cert, oid) != NULL)
2410 d = realloc(cert->attrs.val,
2411 sizeof(cert->attrs.val[0]) * (cert->attrs.len + 1));
2413 hx509_clear_error_string(context);
2416 cert->attrs.val = d;
2418 a = malloc(sizeof(*a));
2422 der_copy_octet_string(attr, &a->data);
2423 der_copy_oid(oid, &a->oid);
2425 cert->attrs.val[cert->attrs.len] = a;
2432 * Get an external attribute for the certificate, examples are
2433 * friendly name and id.
2435 * @param cert hx509 certificate object to search
2436 * @param oid an oid to search for.
2438 * @return an hx509_cert_attribute, only valid as long as the
2439 * certificate is referenced.
2441 * @ingroup hx509_cert
2444 hx509_cert_attribute
2445 hx509_cert_get_attribute(hx509_cert cert, const heim_oid *oid)
2448 for (i = 0; i < cert->attrs.len; i++)
2449 if (der_heim_oid_cmp(oid, &cert->attrs.val[i]->oid) == 0)
2450 return cert->attrs.val[i];
2455 * Set the friendly name on the certificate.
2457 * @param cert The certificate to set the friendly name on
2458 * @param name Friendly name.
2460 * @return An hx509 error code, see hx509_get_error_string().
2462 * @ingroup hx509_cert
2466 hx509_cert_set_friendly_name(hx509_cert cert, const char *name)
2468 if (cert->friendlyname)
2469 free(cert->friendlyname);
2470 cert->friendlyname = strdup(name);
2471 if (cert->friendlyname == NULL)
2477 * Get friendly name of the certificate.
2479 * @param cert cert to get the friendly name from.
2481 * @return an friendly name or NULL if there is. The friendly name is
2482 * only valid as long as the certificate is referenced.
2484 * @ingroup hx509_cert
2488 hx509_cert_get_friendly_name(hx509_cert cert)
2490 hx509_cert_attribute a;
2491 PKCS9_friendlyName n;
2495 if (cert->friendlyname)
2496 return cert->friendlyname;
2498 a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_friendlyName());
2502 ret = hx509_cert_get_subject(cert, &name);
2505 ret = hx509_name_to_string(name, &cert->friendlyname);
2506 hx509_name_free(&name);
2509 return cert->friendlyname;
2512 ret = decode_PKCS9_friendlyName(a->data.data, a->data.length, &n, &sz);
2517 free_PKCS9_friendlyName(&n);
2521 cert->friendlyname = malloc(n.val[0].length + 1);
2522 if (cert->friendlyname == NULL) {
2523 free_PKCS9_friendlyName(&n);
2527 for (i = 0; i < n.val[0].length; i++) {
2528 if (n.val[0].data[i] <= 0xff)
2529 cert->friendlyname[i] = n.val[0].data[i] & 0xff;
2531 cert->friendlyname[i] = 'X';
2533 cert->friendlyname[i] = '\0';
2534 free_PKCS9_friendlyName(&n);
2536 return cert->friendlyname;
2540 _hx509_query_clear(hx509_query *q)
2542 memset(q, 0, sizeof(*q));
2546 * Allocate an query controller. Free using hx509_query_free().
2548 * @param context A hx509 context.
2549 * @param q return pointer to a hx509_query.
2551 * @return An hx509 error code, see hx509_get_error_string().
2553 * @ingroup hx509_cert
2557 hx509_query_alloc(hx509_context context, hx509_query **q)
2559 *q = calloc(1, sizeof(**q));
2567 * Set match options for the hx509 query controller.
2569 * @param q query controller.
2570 * @param option options to control the query controller.
2572 * @return An hx509 error code, see hx509_get_error_string().
2574 * @ingroup hx509_cert
2578 hx509_query_match_option(hx509_query *q, hx509_query_option option)
2581 case HX509_QUERY_OPTION_PRIVATE_KEY:
2582 q->match |= HX509_QUERY_PRIVATE_KEY;
2584 case HX509_QUERY_OPTION_KU_ENCIPHERMENT:
2585 q->match |= HX509_QUERY_KU_ENCIPHERMENT;
2587 case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE:
2588 q->match |= HX509_QUERY_KU_DIGITALSIGNATURE;
2590 case HX509_QUERY_OPTION_KU_KEYCERTSIGN:
2591 q->match |= HX509_QUERY_KU_KEYCERTSIGN;
2593 case HX509_QUERY_OPTION_END:
2600 * Set the issuer and serial number of match in the query
2601 * controller. The function make copies of the isser and serial number.
2603 * @param q a hx509 query controller
2604 * @param issuer issuer to search for
2605 * @param serialNumber the serialNumber of the issuer.
2607 * @return An hx509 error code, see hx509_get_error_string().
2609 * @ingroup hx509_cert
2613 hx509_query_match_issuer_serial(hx509_query *q,
2615 const heim_integer *serialNumber)
2619 der_free_heim_integer(q->serial);
2622 q->serial = malloc(sizeof(*q->serial));
2623 if (q->serial == NULL)
2625 ret = der_copy_heim_integer(serialNumber, q->serial);
2631 if (q->issuer_name) {
2632 free_Name(q->issuer_name);
2633 free(q->issuer_name);
2635 q->issuer_name = malloc(sizeof(*q->issuer_name));
2636 if (q->issuer_name == NULL)
2638 ret = copy_Name(issuer, q->issuer_name);
2640 free(q->issuer_name);
2641 q->issuer_name = NULL;
2644 q->match |= HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME;
2649 * Set the query controller to match on a friendly name
2651 * @param q a hx509 query controller.
2652 * @param name a friendly name to match on
2654 * @return An hx509 error code, see hx509_get_error_string().
2656 * @ingroup hx509_cert
2660 hx509_query_match_friendly_name(hx509_query *q, const char *name)
2662 if (q->friendlyname)
2663 free(q->friendlyname);
2664 q->friendlyname = strdup(name);
2665 if (q->friendlyname == NULL)
2667 q->match |= HX509_QUERY_MATCH_FRIENDLY_NAME;
2672 * Set the query controller to require an one specific EKU (extended
2673 * key usage). Any previous EKU matching is overwitten. If NULL is
2674 * passed in as the eku, the EKU requirement is reset.
2676 * @param q a hx509 query controller.
2677 * @param eku an EKU to match on.
2679 * @return An hx509 error code, see hx509_get_error_string().
2681 * @ingroup hx509_cert
2685 hx509_query_match_eku(hx509_query *q, const heim_oid *eku)
2691 der_free_oid(q->eku);
2695 q->match &= ~HX509_QUERY_MATCH_EKU;
2698 der_free_oid(q->eku);
2700 q->eku = calloc(1, sizeof(*q->eku));
2704 ret = der_copy_oid(eku, q->eku);
2710 q->match |= HX509_QUERY_MATCH_EKU;
2716 hx509_query_match_expr(hx509_context context, hx509_query *q, const char *expr)
2719 _hx509_expr_free(q->expr);
2724 q->match &= ~HX509_QUERY_MATCH_EXPR;
2726 q->expr = _hx509_expr_parse(expr);
2728 q->match |= HX509_QUERY_MATCH_EXPR;
2735 * Set the query controller to match using a specific match function.
2737 * @param q a hx509 query controller.
2738 * @param func function to use for matching, if the argument is NULL,
2739 * the match function is removed.
2740 * @param ctx context passed to the function.
2742 * @return An hx509 error code, see hx509_get_error_string().
2744 * @ingroup hx509_cert
2748 hx509_query_match_cmp_func(hx509_query *q,
2749 int (*func)(void *, hx509_cert),
2753 q->match |= HX509_QUERY_MATCH_FUNCTION;
2755 q->match &= ~HX509_QUERY_MATCH_FUNCTION;
2757 q->cmp_func_ctx = ctx;
2762 * Free the query controller.
2764 * @param context A hx509 context.
2765 * @param q a pointer to the query controller.
2767 * @ingroup hx509_cert
2771 hx509_query_free(hx509_context context, hx509_query *q)
2777 der_free_heim_integer(q->serial);
2780 if (q->issuer_name) {
2781 free_Name(q->issuer_name);
2782 free(q->issuer_name);
2785 der_free_oid(q->eku);
2788 if (q->friendlyname)
2789 free(q->friendlyname);
2791 _hx509_expr_free(q->expr);
2793 memset(q, 0, sizeof(*q));
2798 _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert cert)
2800 Certificate *c = _hx509_get_cert(cert);
2803 _hx509_query_statistic(context, 1, q);
2805 if ((q->match & HX509_QUERY_FIND_ISSUER_CERT) &&
2806 _hx509_cert_is_parent_cmp(q->subject, c, 0) != 0)
2809 if ((q->match & HX509_QUERY_MATCH_CERTIFICATE) &&
2810 _hx509_Certificate_cmp(q->certificate, c) != 0)
2813 if ((q->match & HX509_QUERY_MATCH_SERIALNUMBER)
2814 && der_heim_integer_cmp(&c->tbsCertificate.serialNumber, q->serial) != 0)
2817 if (q->match & HX509_QUERY_MATCH_ISSUER_NAME) {
2818 ret = _hx509_name_cmp(&c->tbsCertificate.issuer, q->issuer_name, &diff);
2823 if (q->match & HX509_QUERY_MATCH_SUBJECT_NAME) {
2824 ret = _hx509_name_cmp(&c->tbsCertificate.subject, q->subject_name, &diff);
2829 if (q->match & HX509_QUERY_MATCH_SUBJECT_KEY_ID) {
2830 SubjectKeyIdentifier si;
2832 ret = _hx509_find_extension_subject_key_id(c, &si);
2834 if (der_heim_octet_string_cmp(&si, q->subject_id) != 0)
2836 free_SubjectKeyIdentifier(&si);
2841 if ((q->match & HX509_QUERY_MATCH_ISSUER_ID))
2843 if ((q->match & HX509_QUERY_PRIVATE_KEY) &&
2844 _hx509_cert_private_key(cert) == NULL)
2849 if (q->match & HX509_QUERY_KU_DIGITALSIGNATURE)
2851 if (q->match & HX509_QUERY_KU_NONREPUDIATION)
2853 if (q->match & HX509_QUERY_KU_ENCIPHERMENT)
2855 if (q->match & HX509_QUERY_KU_DATAENCIPHERMENT)
2857 if (q->match & HX509_QUERY_KU_KEYAGREEMENT)
2859 if (q->match & HX509_QUERY_KU_KEYCERTSIGN)
2861 if (q->match & HX509_QUERY_KU_CRLSIGN)
2863 if (ku && check_key_usage(context, c, ku, TRUE))
2866 if ((q->match & HX509_QUERY_ANCHOR))
2869 if (q->match & HX509_QUERY_MATCH_LOCAL_KEY_ID) {
2870 hx509_cert_attribute a;
2872 a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_localKeyId());
2875 if (der_heim_octet_string_cmp(&a->data, q->local_key_id) != 0)
2879 if (q->match & HX509_QUERY_NO_MATCH_PATH) {
2882 for (i = 0; i < q->path->len; i++)
2883 if (hx509_cert_cmp(q->path->val[i], cert) == 0)
2886 if (q->match & HX509_QUERY_MATCH_FRIENDLY_NAME) {
2887 const char *name = hx509_cert_get_friendly_name(cert);
2890 if (strcasecmp(q->friendlyname, name) != 0)
2893 if (q->match & HX509_QUERY_MATCH_FUNCTION) {
2894 ret = (*q->cmp_func)(q->cmp_func_ctx, cert);
2899 if (q->match & HX509_QUERY_MATCH_KEY_HASH_SHA1) {
2900 heim_octet_string os;
2902 os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
2904 c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
2906 ret = _hx509_verify_signature(context,
2908 hx509_signature_sha1(),
2915 if (q->match & HX509_QUERY_MATCH_TIME) {
2917 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2920 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
2925 /* If an EKU is required, check the cert for it. */
2926 if ((q->match & HX509_QUERY_MATCH_EKU) &&
2927 hx509_cert_check_eku(context, cert, q->eku, 0))
2930 if ((q->match & HX509_QUERY_MATCH_EXPR)) {
2931 hx509_env env = NULL;
2933 ret = _hx509_cert_to_env(context, cert, &env);
2937 ret = _hx509_expr_eval(context, env, q->expr);
2938 hx509_env_free(&env);
2943 if (q->match & ~HX509_QUERY_MASK)
2950 * Set a statistic file for the query statistics.
2952 * @param context A hx509 context.
2953 * @param fn statistics file name
2955 * @ingroup hx509_cert
2959 hx509_query_statistic_file(hx509_context context, const char *fn)
2961 if (context->querystat)
2962 free(context->querystat);
2963 context->querystat = strdup(fn);
2967 _hx509_query_statistic(hx509_context context, int type, const hx509_query *q)
2970 if (context->querystat == NULL)
2972 f = fopen(context->querystat, "a");
2976 fprintf(f, "%d %d\n", type, q->match);
2980 static const char *statname[] = {
2982 "match serialnumber",
2983 "match issuer name",
2984 "match subject name",
2985 "match subject key id",
2989 "ku digitalsignature",
2992 "ku nonrepudiation",
2994 "ku dataencipherment",
2996 "match certificate",
2997 "match local key id",
2999 "match friendly name",
3001 "match key hash sha1",
3006 unsigned long stats;
3012 stat_sort(const void *a, const void *b)
3014 const struct stat_el *ae = a;
3015 const struct stat_el *be = b;
3016 return be->stats - ae->stats;
3020 * Unparse the statistics file and print the result on a FILE descriptor.
3022 * @param context A hx509 context.
3023 * @param printtype tyep to print
3024 * @param out the FILE to write the data on.
3026 * @ingroup hx509_cert
3030 hx509_query_unparse_stats(hx509_context context, int printtype, FILE *out)
3034 int type, mask, i, num;
3035 unsigned long multiqueries = 0, totalqueries = 0;
3036 struct stat_el stats[32];
3038 if (context->querystat == NULL)
3040 f = fopen(context->querystat, "r");
3042 fprintf(out, "No statistic file %s: %s.\n",
3043 context->querystat, strerror(errno));
3048 for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
3053 while (fscanf(f, "%d %d\n", &type, &mask) == 2) {
3054 if (type != printtype)
3057 while (mask && i < sizeof(stats)/sizeof(stats[0])) {
3071 qsort(stats, sizeof(stats)/sizeof(stats[0]), sizeof(stats[0]), stat_sort);
3075 errx(1, "out of memory");
3077 rtbl_set_separator (t, " ");
3079 rtbl_add_column_by_id (t, 0, "Name", 0);
3080 rtbl_add_column_by_id (t, 1, "Counter", 0);
3083 for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
3086 if (stats[i].index < sizeof(statname)/sizeof(statname[0]))
3087 rtbl_add_column_entry_by_id (t, 0, statname[stats[i].index]);
3089 snprintf(str, sizeof(str), "%d", stats[i].index);
3090 rtbl_add_column_entry_by_id (t, 0, str);
3092 snprintf(str, sizeof(str), "%lu", stats[i].stats);
3093 rtbl_add_column_entry_by_id (t, 1, str);
3096 rtbl_format(t, out);
3099 fprintf(out, "\nQueries: multi %lu total %lu\n",
3100 multiqueries, totalqueries);
3104 * Check the extended key usage on the hx509 certificate.
3106 * @param context A hx509 context.
3107 * @param cert A hx509 context.
3108 * @param eku the EKU to check for
3109 * @param allow_any_eku if the any EKU is set, allow that to be a
3112 * @return An hx509 error code, see hx509_get_error_string().
3114 * @ingroup hx509_cert
3118 hx509_cert_check_eku(hx509_context context, hx509_cert cert,
3119 const heim_oid *eku, int allow_any_eku)
3124 ret = find_extension_eku(_hx509_get_cert(cert), &e);
3126 hx509_clear_error_string(context);
3130 for (i = 0; i < e.len; i++) {
3131 if (der_heim_oid_cmp(eku, &e.val[i]) == 0) {
3132 free_ExtKeyUsage(&e);
3135 if (allow_any_eku) {
3137 if (der_heim_oid_cmp(id_any_eku, &e.val[i]) == 0) {
3138 free_ExtKeyUsage(&e);
3144 free_ExtKeyUsage(&e);
3145 hx509_clear_error_string(context);
3146 return HX509_CERTIFICATE_MISSING_EKU;
3150 _hx509_cert_get_keyusage(hx509_context context,
3159 memset(ku, 0, sizeof(*ku));
3161 cert = _hx509_get_cert(c);
3163 if (_hx509_cert_get_version(cert) < 3)
3166 e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
3168 return HX509_KU_CERT_MISSING;
3170 ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, ku, &size);
3177 _hx509_cert_get_eku(hx509_context context,
3183 memset(e, 0, sizeof(*e));
3185 ret = find_extension_eku(_hx509_get_cert(cert), e);
3186 if (ret && ret != HX509_EXTENSION_NOT_FOUND) {
3187 hx509_clear_error_string(context);
3194 * Encodes the hx509 certificate as a DER encode binary.
3196 * @param context A hx509 context.
3197 * @param c the certificate to encode.
3198 * @param os the encode certificate, set to NULL, 0 on case of
3199 * error. Free the returned structure with hx509_xfree().
3201 * @return An hx509 error code, see hx509_get_error_string().
3203 * @ingroup hx509_cert
3207 hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os)
3215 ASN1_MALLOC_ENCODE(Certificate, os->data, os->length,
3216 _hx509_get_cert(c), &size, ret);
3222 if (os->length != size)
3223 _hx509_abort("internal ASN.1 encoder error");
3229 * Last to avoid lost __attribute__s due to #undef.
3232 #undef __attribute__
3233 #define __attribute__(X)
3236 _hx509_abort(const char *fmt, ...)
3237 __attribute__ ((noreturn, format (printf, 1, 2)))
3249 * Free a data element allocated in the library.
3251 * @param ptr data to be freed.
3253 * @ingroup hx509_misc
3257 hx509_xfree(void *ptr)
3267 _hx509_cert_to_env(hx509_context context, hx509_cert cert, hx509_env *env)
3273 hx509_env envcert = NULL;
3278 asprintf(&buf, "%d", _hx509_cert_get_version(_hx509_get_cert(cert)));
3279 ret = hx509_env_add(context, &envcert, "version", buf);
3285 ret = hx509_cert_get_subject(cert, &name);
3289 ret = hx509_name_to_string(name, &buf);
3291 hx509_name_free(&name);
3295 ret = hx509_env_add(context, &envcert, "subject", buf);
3296 hx509_name_free(&name);
3301 ret = hx509_cert_get_issuer(cert, &name);
3305 ret = hx509_name_to_string(name, &buf);
3306 hx509_name_free(&name);
3310 ret = hx509_env_add(context, &envcert, "issuer", buf);
3317 ret = _hx509_cert_get_eku(context, cert, &eku);
3318 if (ret == HX509_EXTENSION_NOT_FOUND)
3324 hx509_env enveku = NULL;
3326 for (i = 0; i < eku.len; i++) {
3328 ret = der_print_heim_oid(&eku.val[i], '.', &buf);
3330 free_ExtKeyUsage(&eku);
3331 hx509_env_free(&enveku);
3334 ret = hx509_env_add(context, &enveku, buf, "oid-name-here");
3337 free_ExtKeyUsage(&eku);
3338 hx509_env_free(&enveku);
3342 free_ExtKeyUsage(&eku);
3344 ret = hx509_env_add_binding(context, &envcert, "eku", enveku);
3346 hx509_env_free(&enveku);
3351 ret = hx509_env_add_binding(context, env, "certificate", envcert);
3358 hx509_env_free(&envcert);