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 RCSID("$Id: cert.c 20915 2007-06-05 03:58:56Z lha $");
36 #include "crypto-headers.h"
39 struct hx509_verify_ctx_data {
40 hx509_certs trust_anchors;
42 #define HX509_VERIFY_CTX_F_TIME_SET 1
43 #define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE 2
44 #define HX509_VERIFY_CTX_F_REQUIRE_RFC3280 4
45 #define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS 8
47 unsigned int max_depth;
48 #define HX509_VERIFY_MAX_DEPTH 30
49 hx509_revoke_ctx revoke_ctx;
52 #define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280)
53 #define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS)
55 struct _hx509_cert_attrs {
57 hx509_cert_attribute *val;
60 struct hx509_cert_data {
64 hx509_private_key private_key;
65 struct _hx509_cert_attrs attrs;
67 _hx509_cert_release_func release;
71 typedef struct hx509_name_constraints {
74 } hx509_name_constraints;
76 #define GeneralSubtrees_SET(g,var) \
77 (g)->len = (var)->len, (g)->val = (var)->val;
84 _hx509_abort(const char *fmt, ...)
100 hx509_context_init(hx509_context *context)
102 *context = calloc(1, sizeof(**context));
103 if (*context == NULL)
106 _hx509_ks_null_register(*context);
107 _hx509_ks_mem_register(*context);
108 _hx509_ks_file_register(*context);
109 _hx509_ks_pkcs12_register(*context);
110 _hx509_ks_pkcs11_register(*context);
111 _hx509_ks_dir_register(*context);
112 _hx509_ks_keychain_register(*context);
114 ENGINE_add_conf_module();
115 OpenSSL_add_all_algorithms();
117 (*context)->ocsp_time_diff = HX509_DEFAULT_OCSP_TIME_DIFF;
119 initialize_hx_error_table_r(&(*context)->et_list);
120 initialize_asn1_error_table_r(&(*context)->et_list);
122 #ifdef HX509_DEFAULT_ANCHORS
123 (void)hx509_certs_init(*context, HX509_DEFAULT_ANCHORS, 0,
124 NULL, &(*context)->default_trust_anchors);
131 hx509_context_set_missing_revoke(hx509_context context, int flag)
134 context->flags |= HX509_CTX_VERIFY_MISSING_OK;
136 context->flags &= ~HX509_CTX_VERIFY_MISSING_OK;
140 hx509_context_free(hx509_context *context)
142 hx509_clear_error_string(*context);
143 if ((*context)->ks_ops) {
144 free((*context)->ks_ops);
145 (*context)->ks_ops = NULL;
147 (*context)->ks_num_ops = 0;
148 free_error_table ((*context)->et_list);
149 if ((*context)->querystat)
150 free((*context)->querystat);
151 memset(*context, 0, sizeof(**context));
162 _hx509_get_cert(hx509_cert cert)
173 _hx509_print_cert_subject(hx509_cert cert)
179 ret = hx509_cert_get_subject(cert, &name);
183 ret = hx509_name_to_string(name, &subject_name);
184 hx509_name_free(&name);
188 printf("name: %s\n", subject_name);
199 _hx509_cert_get_version(const Certificate *t)
201 return t->tbsCertificate.version ? *t->tbsCertificate.version + 1 : 1;
205 hx509_cert_init(hx509_context context, const Certificate *c, hx509_cert *cert)
209 *cert = malloc(sizeof(**cert));
213 (*cert)->friendlyname = NULL;
214 (*cert)->attrs.len = 0;
215 (*cert)->attrs.val = NULL;
216 (*cert)->private_key = NULL;
217 (*cert)->basename = NULL;
218 (*cert)->release = NULL;
221 (*cert)->data = calloc(1, sizeof(*(*cert)->data));
222 if ((*cert)->data == NULL) {
226 ret = copy_Certificate(c, (*cert)->data);
235 _hx509_cert_set_release(hx509_cert cert,
236 _hx509_cert_release_func release,
239 cert->release = release;
244 /* Doesn't make a copy of `private_key'. */
247 _hx509_cert_assign_key(hx509_cert cert, hx509_private_key private_key)
249 if (cert->private_key)
250 _hx509_private_key_free(&cert->private_key);
251 cert->private_key = _hx509_private_key_ref(private_key);
256 hx509_cert_free(hx509_cert cert)
264 _hx509_abort("refcount <= 0");
269 (cert->release)(cert, cert->ctx);
271 if (cert->private_key)
272 _hx509_private_key_free(&cert->private_key);
274 free_Certificate(cert->data);
277 for (i = 0; i < cert->attrs.len; i++) {
278 der_free_octet_string(&cert->attrs.val[i]->data);
279 der_free_oid(&cert->attrs.val[i]->oid);
280 free(cert->attrs.val[i]);
282 free(cert->attrs.val);
283 free(cert->friendlyname);
285 hx509_name_free(&cert->basename);
286 memset(cert, 0, sizeof(cert));
291 hx509_cert_ref(hx509_cert cert)
294 _hx509_abort("refcount <= 0");
297 _hx509_abort("refcount == 0");
302 hx509_verify_init_ctx(hx509_context context, hx509_verify_ctx *ctx)
306 c = calloc(1, sizeof(*c));
310 c->max_depth = HX509_VERIFY_MAX_DEPTH;
318 hx509_verify_destroy_ctx(hx509_verify_ctx ctx)
321 memset(ctx, 0, sizeof(*ctx));
326 hx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set)
328 ctx->trust_anchors = set;
332 hx509_verify_attach_revoke(hx509_verify_ctx ctx, hx509_revoke_ctx revoke_ctx)
334 ctx->revoke_ctx = revoke_ctx;
338 hx509_verify_set_time(hx509_verify_ctx ctx, time_t t)
340 ctx->flags |= HX509_VERIFY_CTX_F_TIME_SET;
345 hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean)
348 ctx->flags |= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
350 ctx->flags &= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
354 hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean)
357 ctx->flags |= HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
359 ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
362 static const Extension *
363 find_extension(const Certificate *cert, const heim_oid *oid, int *idx)
365 const TBSCertificate *c = &cert->tbsCertificate;
367 if (c->version == NULL || *c->version < 2 || c->extensions == NULL)
370 for (;*idx < c->extensions->len; (*idx)++) {
371 if (der_heim_oid_cmp(&c->extensions->val[*idx].extnID, oid) == 0)
372 return &c->extensions->val[(*idx)++];
378 find_extension_auth_key_id(const Certificate *subject,
379 AuthorityKeyIdentifier *ai)
385 memset(ai, 0, sizeof(*ai));
387 e = find_extension(subject, oid_id_x509_ce_authorityKeyIdentifier(), &i);
389 return HX509_EXTENSION_NOT_FOUND;
391 return decode_AuthorityKeyIdentifier(e->extnValue.data,
397 _hx509_find_extension_subject_key_id(const Certificate *issuer,
398 SubjectKeyIdentifier *si)
404 memset(si, 0, sizeof(*si));
406 e = find_extension(issuer, oid_id_x509_ce_subjectKeyIdentifier(), &i);
408 return HX509_EXTENSION_NOT_FOUND;
410 return decode_SubjectKeyIdentifier(e->extnValue.data,
416 find_extension_name_constraints(const Certificate *subject,
423 memset(nc, 0, sizeof(*nc));
425 e = find_extension(subject, oid_id_x509_ce_nameConstraints(), &i);
427 return HX509_EXTENSION_NOT_FOUND;
429 return decode_NameConstraints(e->extnValue.data,
435 find_extension_subject_alt_name(const Certificate *cert, int *i,
441 memset(sa, 0, sizeof(*sa));
443 e = find_extension(cert, oid_id_x509_ce_subjectAltName(), i);
445 return HX509_EXTENSION_NOT_FOUND;
447 return decode_GeneralNames(e->extnValue.data,
453 find_extension_eku(const Certificate *cert, ExtKeyUsage *eku)
459 memset(eku, 0, sizeof(*eku));
461 e = find_extension(cert, oid_id_x509_ce_extKeyUsage(), &i);
463 return HX509_EXTENSION_NOT_FOUND;
465 return decode_ExtKeyUsage(e->extnValue.data,
471 add_to_list(hx509_octet_string_list *list, const heim_octet_string *entry)
476 p = realloc(list->val, (list->len + 1) * sizeof(list->val[0]));
480 ret = der_copy_octet_string(entry, &list->val[list->len]);
488 hx509_free_octet_string_list(hx509_octet_string_list *list)
491 for (i = 0; i < list->len; i++)
492 der_free_octet_string(&list->val[i]);
499 hx509_cert_find_subjectAltName_otherName(hx509_cert cert,
501 hx509_octet_string_list *list)
511 ret = find_extension_subject_alt_name(_hx509_get_cert(cert), &i, &sa);
513 if (ret == HX509_EXTENSION_NOT_FOUND) {
520 for (j = 0; j < sa.len; j++) {
521 if (sa.val[j].element == choice_GeneralName_otherName &&
522 der_heim_oid_cmp(&sa.val[j].u.otherName.type_id, oid) == 0)
524 ret = add_to_list(list, &sa.val[j].u.otherName.value);
526 free_GeneralNames(&sa);
531 free_GeneralNames(&sa);
538 check_key_usage(hx509_context context, const Certificate *cert,
539 unsigned flags, int req_present)
547 if (_hx509_cert_get_version(cert) < 3)
550 e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
553 hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
554 "Required extension key "
555 "usage missing from certifiate");
556 return HX509_KU_CERT_MISSING;
561 ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &size);
564 ku_flags = KeyUsage2int(ku);
565 if ((ku_flags & flags) != flags) {
566 unsigned missing = (~ku_flags) & flags;
567 char buf[256], *name;
569 unparse_flags(missing, asn1_KeyUsage_units(), buf, sizeof(buf));
570 _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
571 hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
572 "Key usage %s required but missing "
573 "from certifiate %s", buf, name);
575 return HX509_KU_CERT_MISSING;
581 _hx509_check_key_usage(hx509_context context, hx509_cert cert,
582 unsigned flags, int req_present)
584 return check_key_usage(context, _hx509_get_cert(cert), flags, req_present);
587 enum certtype { PROXY_CERT, EE_CERT, CA_CERT };
590 check_basic_constraints(hx509_context context, const Certificate *cert,
591 enum certtype type, int depth)
598 if (_hx509_cert_get_version(cert) < 3)
601 e = find_extension(cert, oid_id_x509_ce_basicConstraints(), &i);
609 ret = _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
611 hx509_set_error_string(context, 0, HX509_EXTENSION_NOT_FOUND,
612 "basicConstraints missing from "
613 "CA certifiacte %s", name);
615 return HX509_EXTENSION_NOT_FOUND;
620 ret = decode_BasicConstraints(e->extnValue.data,
621 e->extnValue.length, &bc,
627 if (bc.cA != NULL && *bc.cA)
628 ret = HX509_PARENT_IS_CA;
634 if (bc.cA == NULL || !*bc.cA)
635 ret = HX509_PARENT_NOT_CA;
636 else if (bc.pathLenConstraint)
637 if (depth - 1 > *bc.pathLenConstraint)
638 ret = HX509_CA_PATH_TOO_DEEP;
641 free_BasicConstraints(&bc);
646 _hx509_cert_is_parent_cmp(const Certificate *subject,
647 const Certificate *issuer,
648 int allow_self_signed)
651 AuthorityKeyIdentifier ai;
652 SubjectKeyIdentifier si;
655 diff = _hx509_name_cmp(&issuer->tbsCertificate.subject,
656 &subject->tbsCertificate.issuer);
660 memset(&ai, 0, sizeof(ai));
661 memset(&si, 0, sizeof(si));
664 * Try to find AuthorityKeyIdentifier, if its not present in the
665 * subject certificate nor the parent.
668 ret_ai = find_extension_auth_key_id(subject, &ai);
669 if (ret_ai && ret_ai != HX509_EXTENSION_NOT_FOUND)
671 ret_si = _hx509_find_extension_subject_key_id(issuer, &si);
672 if (ret_si && ret_si != HX509_EXTENSION_NOT_FOUND)
675 if (ret_si && ret_ai)
680 if (allow_self_signed) {
683 } else if (ai.keyIdentifier) {
689 if (ai.keyIdentifier == NULL) {
692 if (ai.authorityCertIssuer == NULL)
694 if (ai.authorityCertSerialNumber == NULL)
697 diff = der_heim_integer_cmp(ai.authorityCertSerialNumber,
698 &issuer->tbsCertificate.serialNumber);
701 if (ai.authorityCertIssuer->len != 1)
703 if (ai.authorityCertIssuer->val[0].element != choice_GeneralName_directoryName)
707 ai.authorityCertIssuer->val[0].u.directoryName.element;
709 ai.authorityCertIssuer->val[0].u.directoryName.u.rdnSequence;
711 diff = _hx509_name_cmp(&issuer->tbsCertificate.subject,
717 diff = der_heim_octet_string_cmp(ai.keyIdentifier, &si);
722 free_AuthorityKeyIdentifier(&ai);
723 free_SubjectKeyIdentifier(&si);
728 certificate_is_anchor(hx509_context context,
729 hx509_certs trust_anchors,
730 const hx509_cert cert)
736 if (trust_anchors == NULL)
739 _hx509_query_clear(&q);
741 q.match = HX509_QUERY_MATCH_CERTIFICATE;
742 q.certificate = _hx509_get_cert(cert);
744 ret = hx509_certs_find(context, trust_anchors, &q, &c);
751 certificate_is_self_signed(const Certificate *cert)
753 return _hx509_cert_is_parent_cmp(cert, cert, 1) == 0;
757 * The subjectName is "null" when its empty set of relative DBs.
761 subject_null_p(const Certificate *c)
763 return c->tbsCertificate.subject.u.rdnSequence.len == 0;
768 find_parent(hx509_context context,
770 hx509_certs trust_anchors,
776 AuthorityKeyIdentifier ai;
781 memset(&ai, 0, sizeof(ai));
783 _hx509_query_clear(&q);
785 if (!subject_null_p(current->data)) {
786 q.match |= HX509_QUERY_FIND_ISSUER_CERT;
787 q.subject = _hx509_get_cert(current);
789 ret = find_extension_auth_key_id(current->data, &ai);
791 hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
792 "Subjectless certificate missing AuthKeyID");
793 return HX509_CERTIFICATE_MALFORMED;
796 if (ai.keyIdentifier == NULL) {
797 free_AuthorityKeyIdentifier(&ai);
798 hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
799 "Subjectless certificate missing keyIdentifier "
801 return HX509_CERTIFICATE_MALFORMED;
804 q.subject_id = ai.keyIdentifier;
805 q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID;
809 q.match |= HX509_QUERY_NO_MATCH_PATH;
812 q.timenow = time_now;
813 q.match |= HX509_QUERY_MATCH_TIME;
815 ret = hx509_certs_find(context, pool, &q, parent);
817 free_AuthorityKeyIdentifier(&ai);
820 q.match &= ~HX509_QUERY_MATCH_TIME;
824 ret = hx509_certs_find(context, trust_anchors, &q, parent);
826 free_AuthorityKeyIdentifier(&ai);
830 free_AuthorityKeyIdentifier(&ai);
836 ret = hx509_cert_get_subject(current, &name);
838 hx509_clear_error_string(context);
839 return HX509_ISSUER_NOT_FOUND;
841 ret = hx509_name_to_string(name, &str);
842 hx509_name_free(&name);
844 hx509_clear_error_string(context);
845 return HX509_ISSUER_NOT_FOUND;
848 hx509_set_error_string(context, 0, HX509_ISSUER_NOT_FOUND,
849 "Failed to find issuer for "
850 "certificate with subject: '%s'", str);
853 return HX509_ISSUER_NOT_FOUND;
861 is_proxy_cert(hx509_context context,
862 const Certificate *cert,
863 ProxyCertInfo *rinfo)
871 memset(rinfo, 0, sizeof(*rinfo));
873 e = find_extension(cert, oid_id_pe_proxyCertInfo(), &i);
875 hx509_clear_error_string(context);
876 return HX509_EXTENSION_NOT_FOUND;
879 ret = decode_ProxyCertInfo(e->extnValue.data,
884 hx509_clear_error_string(context);
887 if (size != e->extnValue.length) {
888 free_ProxyCertInfo(&info);
889 hx509_clear_error_string(context);
890 return HX509_EXTRA_DATA_AFTER_STRUCTURE;
893 free_ProxyCertInfo(&info);
901 * Path operations are like MEMORY based keyset, but with exposed
902 * internal so we can do easy searches.
906 _hx509_path_append(hx509_context context, hx509_path *path, hx509_cert cert)
909 val = realloc(path->val, (path->len + 1) * sizeof(path->val[0]));
911 hx509_set_error_string(context, 0, ENOMEM, "out of memory");
916 path->val[path->len] = hx509_cert_ref(cert);
923 _hx509_path_free(hx509_path *path)
927 for (i = 0; i < path->len; i++)
928 hx509_cert_free(path->val[i]);
935 * Find path by looking up issuer for the top certificate and continue
936 * until an anchor certificate is found or max limit is found. A
937 * certificate never included twice in the path.
939 * If the trust anchors are not given, calculate optimistic path, just
940 * follow the chain upward until we no longer find a parent or we hit
941 * the max path limit. In this case, a failure will always be returned
942 * depending on what error condition is hit first.
944 * The path includes a path from the top certificate to the anchor
947 * The caller needs to free `path´ both on successful built path and
952 _hx509_calculate_path(hx509_context context,
956 unsigned int max_depth,
961 hx509_cert parent, current;
965 max_depth = HX509_VERIFY_MAX_DEPTH;
967 ret = _hx509_path_append(context, path, cert);
971 current = hx509_cert_ref(cert);
973 while (!certificate_is_anchor(context, anchors, current)) {
975 ret = find_parent(context, time_now, anchors, path,
976 pool, current, &parent);
977 hx509_cert_free(current);
981 ret = _hx509_path_append(context, path, parent);
986 if (path->len > max_depth) {
987 hx509_cert_free(current);
988 hx509_set_error_string(context, 0, HX509_PATH_TOO_LONG,
989 "Path too long while bulding "
990 "certificate chain");
991 return HX509_PATH_TOO_LONG;
995 if ((flags & HX509_CALCULATE_PATH_NO_ANCHOR) &&
997 certificate_is_anchor(context, anchors, path->val[path->len - 1]))
999 hx509_cert_free(path->val[path->len - 1]);
1003 hx509_cert_free(current);
1008 AlgorithmIdentifier_cmp(const AlgorithmIdentifier *p,
1009 const AlgorithmIdentifier *q)
1012 diff = der_heim_oid_cmp(&p->algorithm, &q->algorithm);
1015 if (p->parameters) {
1017 return heim_any_cmp(p->parameters,
1030 _hx509_Certificate_cmp(const Certificate *p, const Certificate *q)
1033 diff = der_heim_bit_string_cmp(&p->signatureValue, &q->signatureValue);
1036 diff = AlgorithmIdentifier_cmp(&p->signatureAlgorithm,
1037 &q->signatureAlgorithm);
1040 diff = der_heim_octet_string_cmp(&p->tbsCertificate._save,
1041 &q->tbsCertificate._save);
1046 hx509_cert_cmp(hx509_cert p, hx509_cert q)
1048 return _hx509_Certificate_cmp(p->data, q->data);
1052 hx509_cert_get_issuer(hx509_cert p, hx509_name *name)
1054 return _hx509_name_from_Name(&p->data->tbsCertificate.issuer, name);
1058 hx509_cert_get_subject(hx509_cert p, hx509_name *name)
1060 return _hx509_name_from_Name(&p->data->tbsCertificate.subject, name);
1064 hx509_cert_get_base_subject(hx509_context context, hx509_cert c,
1068 return hx509_name_copy(context, c->basename, name);
1069 if (is_proxy_cert(context, c->data, NULL) == 0) {
1070 int ret = HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED;
1071 hx509_set_error_string(context, 0, ret,
1072 "Proxy certificate have not been "
1073 "canonicalize yet, no base name");
1076 return _hx509_name_from_Name(&c->data->tbsCertificate.subject, name);
1080 hx509_cert_get_serialnumber(hx509_cert p, heim_integer *i)
1082 return der_copy_heim_integer(&p->data->tbsCertificate.serialNumber, i);
1086 hx509_cert_get_notBefore(hx509_cert p)
1088 return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notBefore);
1092 hx509_cert_get_notAfter(hx509_cert p)
1094 return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notAfter);
1098 hx509_cert_get_SPKI(hx509_cert p, SubjectPublicKeyInfo *spki)
1100 return copy_SubjectPublicKeyInfo(&p->data->tbsCertificate.subjectPublicKeyInfo,
1105 _hx509_cert_private_key(hx509_cert p)
1107 return p->private_key;
1111 _hx509_cert_private_key_exportable(hx509_cert p)
1113 if (p->private_key == NULL)
1115 return _hx509_private_key_exportable(p->private_key);
1119 _hx509_cert_private_decrypt(hx509_context context,
1120 const heim_octet_string *ciphertext,
1121 const heim_oid *encryption_oid,
1123 heim_octet_string *cleartext)
1125 cleartext->data = NULL;
1126 cleartext->length = 0;
1128 if (p->private_key == NULL) {
1129 hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
1130 "Private key missing");
1131 return HX509_PRIVATE_KEY_MISSING;
1134 return _hx509_private_key_private_decrypt(context,
1142 _hx509_cert_public_encrypt(hx509_context context,
1143 const heim_octet_string *cleartext,
1145 heim_oid *encryption_oid,
1146 heim_octet_string *ciphertext)
1148 return _hx509_public_encrypt(context,
1150 encryption_oid, ciphertext);
1158 _hx509_Time2time_t(const Time *t)
1160 switch(t->element) {
1161 case choice_Time_utcTime:
1162 return t->u.utcTime;
1163 case choice_Time_generalTime:
1164 return t->u.generalTime;
1174 init_name_constraints(hx509_name_constraints *nc)
1176 memset(nc, 0, sizeof(*nc));
1181 add_name_constraints(hx509_context context, const Certificate *c, int not_ca,
1182 hx509_name_constraints *nc)
1184 NameConstraints tnc;
1187 ret = find_extension_name_constraints(c, &tnc);
1188 if (ret == HX509_EXTENSION_NOT_FOUND)
1191 hx509_set_error_string(context, 0, ret, "Failed getting NameConstraints");
1193 } else if (not_ca) {
1194 ret = HX509_VERIFY_CONSTRAINTS;
1195 hx509_set_error_string(context, 0, ret, "Not a CA and "
1196 "have NameConstraints");
1198 NameConstraints *val;
1199 val = realloc(nc->val, sizeof(nc->val[0]) * (nc->len + 1));
1201 hx509_clear_error_string(context);
1206 ret = copy_NameConstraints(&tnc, &nc->val[nc->len]);
1208 hx509_clear_error_string(context);
1214 free_NameConstraints(&tnc);
1219 match_RDN(const RelativeDistinguishedName *c,
1220 const RelativeDistinguishedName *n)
1224 if (c->len != n->len)
1225 return HX509_NAME_CONSTRAINT_ERROR;
1227 for (i = 0; i < n->len; i++) {
1228 if (der_heim_oid_cmp(&c->val[i].type, &n->val[i].type) != 0)
1229 return HX509_NAME_CONSTRAINT_ERROR;
1230 if (_hx509_name_ds_cmp(&c->val[i].value, &n->val[i].value) != 0)
1231 return HX509_NAME_CONSTRAINT_ERROR;
1237 match_X501Name(const Name *c, const Name *n)
1241 if (c->element != choice_Name_rdnSequence
1242 || n->element != choice_Name_rdnSequence)
1244 if (c->u.rdnSequence.len > n->u.rdnSequence.len)
1245 return HX509_NAME_CONSTRAINT_ERROR;
1246 for (i = 0; i < c->u.rdnSequence.len; i++) {
1247 ret = match_RDN(&c->u.rdnSequence.val[i], &n->u.rdnSequence.val[i]);
1256 match_general_name(const GeneralName *c, const GeneralName *n, int *match)
1259 * Name constraints only apply to the same name type, see RFC3280,
1262 assert(c->element == n->element);
1264 switch(c->element) {
1265 case choice_GeneralName_otherName:
1266 if (der_heim_oid_cmp(&c->u.otherName.type_id,
1267 &n->u.otherName.type_id) != 0)
1268 return HX509_NAME_CONSTRAINT_ERROR;
1269 if (heim_any_cmp(&c->u.otherName.value,
1270 &n->u.otherName.value) != 0)
1271 return HX509_NAME_CONSTRAINT_ERROR;
1274 case choice_GeneralName_rfc822Name: {
1277 s = strchr(c->u.rfc822Name, '@');
1279 if (strcasecmp(c->u.rfc822Name, n->u.rfc822Name) != 0)
1280 return HX509_NAME_CONSTRAINT_ERROR;
1282 s = strchr(n->u.rfc822Name, '@');
1284 return HX509_NAME_CONSTRAINT_ERROR;
1285 len1 = strlen(c->u.rfc822Name);
1286 len2 = strlen(s + 1);
1288 return HX509_NAME_CONSTRAINT_ERROR;
1289 if (strcasecmp(s + 1 + len2 - len1, c->u.rfc822Name) != 0)
1290 return HX509_NAME_CONSTRAINT_ERROR;
1291 if (len1 < len2 && s[len2 - len1] != '.')
1292 return HX509_NAME_CONSTRAINT_ERROR;
1297 case choice_GeneralName_dNSName: {
1300 len1 = strlen(c->u.dNSName);
1301 len2 = strlen(n->u.dNSName);
1303 return HX509_NAME_CONSTRAINT_ERROR;
1304 if (strcasecmp(&n->u.dNSName[len2 - len1], c->u.dNSName) != 0)
1305 return HX509_NAME_CONSTRAINT_ERROR;
1309 case choice_GeneralName_directoryName: {
1310 Name c_name, n_name;
1313 c_name._save.data = NULL;
1314 c_name._save.length = 0;
1315 c_name.element = c->u.directoryName.element;
1316 c_name.u.rdnSequence = c->u.directoryName.u.rdnSequence;
1318 n_name._save.data = NULL;
1319 n_name._save.length = 0;
1320 n_name.element = n->u.directoryName.element;
1321 n_name.u.rdnSequence = n->u.directoryName.u.rdnSequence;
1323 ret = match_X501Name(&c_name, &n_name);
1328 case choice_GeneralName_uniformResourceIdentifier:
1329 case choice_GeneralName_iPAddress:
1330 case choice_GeneralName_registeredID:
1332 return HX509_NAME_CONSTRAINT_ERROR;
1337 match_alt_name(const GeneralName *n, const Certificate *c,
1338 int *same, int *match)
1345 ret = find_extension_subject_alt_name(c, &i, &sa);
1346 if (ret == HX509_EXTENSION_NOT_FOUND) {
1349 } else if (ret != 0)
1352 for (j = 0; j < sa.len; j++) {
1353 if (n->element == sa.val[j].element) {
1355 ret = match_general_name(n, &sa.val[j], match);
1358 free_GeneralNames(&sa);
1366 match_tree(const GeneralSubtrees *t, const Certificate *c, int *match)
1368 int name, alt_name, same;
1372 name = alt_name = same = *match = 0;
1373 for (i = 0; i < t->len; i++) {
1374 if (t->val[i].minimum && t->val[i].maximum)
1378 * If the constraint apply to directoryNames, test is with
1379 * subjectName of the certificate if the certificate have a
1380 * non-null (empty) subjectName.
1383 if (t->val[i].base.element == choice_GeneralName_directoryName
1384 && !subject_null_p(c))
1386 GeneralName certname;
1388 memset(&certname, 0, sizeof(certname));
1389 certname.element = choice_GeneralName_directoryName;
1390 certname.u.directoryName.element =
1391 c->tbsCertificate.subject.element;
1392 certname.u.directoryName.u.rdnSequence =
1393 c->tbsCertificate.subject.u.rdnSequence;
1395 ret = match_general_name(&t->val[i].base, &certname, &name);
1398 /* Handle subjectAltNames, this is icky since they
1399 * restrictions only apply if the subjectAltName is of the
1400 * same type. So if there have been a match of type, require
1401 * altname to be set.
1403 ret = match_alt_name(&t->val[i].base, c, &same, &alt_name);
1405 if (name && (!same || alt_name))
1411 check_name_constraints(hx509_context context,
1412 const hx509_name_constraints *nc,
1413 const Certificate *c)
1418 for (i = 0 ; i < nc->len; i++) {
1421 if (nc->val[i].permittedSubtrees) {
1422 GeneralSubtrees_SET(&gs, nc->val[i].permittedSubtrees);
1423 ret = match_tree(&gs, c, &match);
1425 hx509_clear_error_string(context);
1428 /* allow null subjectNames, they wont matches anything */
1429 if (match == 0 && !subject_null_p(c)) {
1430 hx509_clear_error_string(context);
1431 return HX509_VERIFY_CONSTRAINTS;
1434 if (nc->val[i].excludedSubtrees) {
1435 GeneralSubtrees_SET(&gs, nc->val[i].excludedSubtrees);
1436 ret = match_tree(&gs, c, &match);
1438 hx509_clear_error_string(context);
1442 hx509_clear_error_string(context);
1443 return HX509_VERIFY_CONSTRAINTS;
1451 free_name_constraints(hx509_name_constraints *nc)
1455 for (i = 0 ; i < nc->len; i++)
1456 free_NameConstraints(&nc->val[i]);
1461 hx509_verify_path(hx509_context context,
1462 hx509_verify_ctx ctx,
1466 hx509_name_constraints nc;
1469 const AlgorithmIdentifier *alg_id;
1471 int ret, i, proxy_cert_depth;
1474 hx509_certs anchors = NULL;
1476 memset(&proxy_issuer, 0, sizeof(proxy_issuer));
1478 ret = init_name_constraints(&nc);
1485 if ((ctx->flags & HX509_VERIFY_CTX_F_TIME_SET) == 0)
1486 ctx->time_now = time(NULL);
1491 ret = hx509_certs_init(context, "MEMORY:trust-anchors", 0, NULL, &anchors);
1494 ret = hx509_certs_merge(context, anchors, ctx->trust_anchors);
1497 ret = hx509_certs_merge(context, anchors, context->default_trust_anchors);
1502 * Calculate the path from the certificate user presented to the
1505 ret = _hx509_calculate_path(context, 0, ctx->time_now,
1506 anchors, ctx->max_depth,
1512 alg_id = path.val[path->len - 1]->data->tbsCertificate.signature;
1516 * Check CA and proxy certificate chain from the top of the
1517 * certificate chain. Also check certificate is valid with respect
1518 * to the current time.
1522 proxy_cert_depth = 0;
1524 if (ctx->flags & HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE)
1529 for (i = 0; i < path.len; i++) {
1533 c = _hx509_get_cert(path.val[i]);
1536 * Lets do some basic check on issuer like
1537 * keyUsage.keyCertSign and basicConstraints.cA bit depending
1538 * on what type of certificate this is.
1543 /* XXX make constants for keyusage */
1544 ret = check_key_usage(context, c, 1 << 5,
1545 REQUIRE_RFC3280(ctx) ? TRUE : FALSE);
1547 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
1548 "Key usage missing from CA certificate");
1555 if (is_proxy_cert(context, c, &info) == 0) {
1558 if (info.pCPathLenConstraint != NULL &&
1559 *info.pCPathLenConstraint < i)
1561 free_ProxyCertInfo(&info);
1562 ret = HX509_PATH_TOO_LONG;
1563 hx509_set_error_string(context, 0, ret,
1564 "Proxy certificate chain "
1565 "longer then allowed");
1568 /* XXX MUST check info.proxyPolicy */
1569 free_ProxyCertInfo(&info);
1572 if (find_extension(c, oid_id_x509_ce_subjectAltName(), &j)) {
1573 ret = HX509_PROXY_CERT_INVALID;
1574 hx509_set_error_string(context, 0, ret,
1575 "Proxy certificate have explicity "
1576 "forbidden subjectAltName");
1581 if (find_extension(c, oid_id_x509_ce_issuerAltName(), &j)) {
1582 ret = HX509_PROXY_CERT_INVALID;
1583 hx509_set_error_string(context, 0, ret,
1584 "Proxy certificate have explicity "
1585 "forbidden issuerAltName");
1590 * The subject name of the proxy certificate should be
1591 * CN=XXX,<proxy issuer>, prune of CN and check if its
1592 * the same over the whole chain of proxy certs and
1593 * then check with the EE cert when we get to it.
1596 if (proxy_cert_depth) {
1597 ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.subject);
1599 ret = HX509_PROXY_CERT_NAME_WRONG;
1600 hx509_set_error_string(context, 0, ret,
1601 "Base proxy name not right");
1606 free_Name(&proxy_issuer);
1608 ret = copy_Name(&c->tbsCertificate.subject, &proxy_issuer);
1610 hx509_clear_error_string(context);
1614 j = proxy_issuer.u.rdnSequence.len;
1615 if (proxy_issuer.u.rdnSequence.len < 2
1616 || proxy_issuer.u.rdnSequence.val[j - 1].len > 1
1617 || der_heim_oid_cmp(&proxy_issuer.u.rdnSequence.val[j - 1].val[0].type,
1618 oid_id_at_commonName()))
1620 ret = HX509_PROXY_CERT_NAME_WRONG;
1621 hx509_set_error_string(context, 0, ret,
1622 "Proxy name too short or "
1623 "does not have Common name "
1628 free_RelativeDistinguishedName(&proxy_issuer.u.rdnSequence.val[j - 1]);
1629 proxy_issuer.u.rdnSequence.len -= 1;
1631 ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.issuer);
1633 ret = HX509_PROXY_CERT_NAME_WRONG;
1634 hx509_set_error_string(context, 0, ret,
1635 "Proxy issuer name not as expected");
1642 * Now we are done with the proxy certificates, this
1643 * cert was an EE cert and we we will fall though to
1644 * EE checking below.
1652 * If there where any proxy certificates in the chain
1653 * (proxy_cert_depth > 0), check that the proxy issuer
1654 * matched proxy certificates "base" subject.
1656 if (proxy_cert_depth) {
1658 ret = _hx509_name_cmp(&proxy_issuer,
1659 &c->tbsCertificate.subject);
1661 ret = HX509_PROXY_CERT_NAME_WRONG;
1662 hx509_clear_error_string(context);
1666 hx509_name_free(&cert->basename);
1668 ret = _hx509_name_from_Name(&proxy_issuer, &cert->basename);
1670 hx509_clear_error_string(context);
1678 ret = check_basic_constraints(context, c, type, i - proxy_cert_depth);
1683 * Don't check the trust anchors expiration time since they
1684 * are transported out of band, from RFC3820.
1686 if (i + 1 != path.len || CHECK_TA(ctx)) {
1688 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
1689 if (t > ctx->time_now) {
1690 ret = HX509_CERT_USED_BEFORE_TIME;
1691 hx509_clear_error_string(context);
1694 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
1695 if (t < ctx->time_now) {
1696 ret = HX509_CERT_USED_AFTER_TIME;
1697 hx509_clear_error_string(context);
1702 if (type == EE_CERT)
1704 else if (type == PROXY_CERT)
1709 * Verify constraints, do this backward so path constraints are
1710 * checked in the right order.
1713 for (ret = 0, i = path.len - 1; i >= 0; i--) {
1716 c = _hx509_get_cert(path.val[i]);
1719 /* check that algorithm and parameters is the same */
1720 /* XXX this is wrong */
1721 ret = alg_cmp(&c->tbsCertificate.signature, alg_id);
1723 hx509_clear_error_string(context);
1724 ret = HX509_PATH_ALGORITHM_CHANGED;
1729 /* verify name constraints, not for selfsigned and anchor */
1730 if (!certificate_is_self_signed(c) || i == path.len - 1) {
1731 ret = check_name_constraints(context, &nc, c);
1736 ret = add_name_constraints(context, c, i == 0, &nc);
1740 /* XXX verify all other silly constraints */
1745 * Verify that no certificates has been revoked.
1748 if (ctx->revoke_ctx) {
1751 ret = hx509_certs_init(context, "MEMORY:revoke-certs", 0,
1756 for (i = 0; i < path.len; i++) {
1757 ret = hx509_certs_add(context, certs, path.val[i]);
1759 hx509_certs_free(&certs);
1763 ret = hx509_certs_merge(context, certs, pool);
1765 hx509_certs_free(&certs);
1769 for (i = 0; i < path.len - 1; i++) {
1770 int parent = (i < path.len - 1) ? i + 1 : i;
1772 ret = hx509_revoke_verify(context,
1779 hx509_certs_free(&certs);
1783 hx509_certs_free(&certs);
1787 for (i = path.len - 1; i >= 0; i--) {
1788 _hx509_print_cert_subject(path.val[i]);
1793 * Verify signatures, do this backward so public key working
1794 * parameter is passed up from the anchor up though the chain.
1797 for (i = path.len - 1; i >= 0; i--) {
1798 Certificate *signer, *c;
1800 c = _hx509_get_cert(path.val[i]);
1802 /* is last in chain (trust anchor) */
1803 if (i == path.len - 1) {
1804 signer = path.val[i]->data;
1806 /* if trust anchor is not self signed, don't check sig */
1807 if (!certificate_is_self_signed(signer))
1810 /* take next certificate in chain */
1811 signer = path.val[i + 1]->data;
1814 /* verify signatureValue */
1815 ret = _hx509_verify_signature_bitstring(context,
1817 &c->signatureAlgorithm,
1818 &c->tbsCertificate._save,
1819 &c->signatureValue);
1821 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
1822 "Failed to verify signature of certificate");
1828 hx509_certs_free(&anchors);
1829 free_Name(&proxy_issuer);
1830 free_name_constraints(&nc);
1831 _hx509_path_free(&path);
1837 hx509_verify_signature(hx509_context context,
1838 const hx509_cert signer,
1839 const AlgorithmIdentifier *alg,
1840 const heim_octet_string *data,
1841 const heim_octet_string *sig)
1843 return _hx509_verify_signature(context, signer->data, alg, data, sig);
1847 hx509_verify_hostname(hx509_context context,
1848 const hx509_cert cert,
1850 const char *hostname,
1851 const struct sockaddr *sa,
1852 /* XXX krb5_socklen_t */ int sa_size)
1854 if (sa && sa_size <= 0)
1860 _hx509_set_cert_attribute(hx509_context context,
1862 const heim_oid *oid,
1863 const heim_octet_string *attr)
1865 hx509_cert_attribute a;
1868 if (hx509_cert_get_attribute(cert, oid) != NULL)
1871 d = realloc(cert->attrs.val,
1872 sizeof(cert->attrs.val[0]) * (cert->attrs.len + 1));
1874 hx509_clear_error_string(context);
1877 cert->attrs.val = d;
1879 a = malloc(sizeof(*a));
1883 der_copy_octet_string(attr, &a->data);
1884 der_copy_oid(oid, &a->oid);
1886 cert->attrs.val[cert->attrs.len] = a;
1892 hx509_cert_attribute
1893 hx509_cert_get_attribute(hx509_cert cert, const heim_oid *oid)
1896 for (i = 0; i < cert->attrs.len; i++)
1897 if (der_heim_oid_cmp(oid, &cert->attrs.val[i]->oid) == 0)
1898 return cert->attrs.val[i];
1903 hx509_cert_set_friendly_name(hx509_cert cert, const char *name)
1905 if (cert->friendlyname)
1906 free(cert->friendlyname);
1907 cert->friendlyname = strdup(name);
1908 if (cert->friendlyname == NULL)
1915 hx509_cert_get_friendly_name(hx509_cert cert)
1917 hx509_cert_attribute a;
1918 PKCS9_friendlyName n;
1922 if (cert->friendlyname)
1923 return cert->friendlyname;
1925 a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_friendlyName());
1927 /* XXX use subject name ? */
1931 ret = decode_PKCS9_friendlyName(a->data.data, a->data.length, &n, &sz);
1936 free_PKCS9_friendlyName(&n);
1940 cert->friendlyname = malloc(n.val[0].length + 1);
1941 if (cert->friendlyname == NULL) {
1942 free_PKCS9_friendlyName(&n);
1946 for (i = 0; i < n.val[0].length; i++) {
1947 if (n.val[0].data[i] <= 0xff)
1948 cert->friendlyname[i] = n.val[0].data[i] & 0xff;
1950 cert->friendlyname[i] = 'X';
1952 cert->friendlyname[i] = '\0';
1953 free_PKCS9_friendlyName(&n);
1955 return cert->friendlyname;
1959 _hx509_query_clear(hx509_query *q)
1961 memset(q, 0, sizeof(*q));
1965 hx509_query_alloc(hx509_context context, hx509_query **q)
1967 *q = calloc(1, sizeof(**q));
1974 hx509_query_match_option(hx509_query *q, hx509_query_option option)
1977 case HX509_QUERY_OPTION_PRIVATE_KEY:
1978 q->match |= HX509_QUERY_PRIVATE_KEY;
1980 case HX509_QUERY_OPTION_KU_ENCIPHERMENT:
1981 q->match |= HX509_QUERY_KU_ENCIPHERMENT;
1983 case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE:
1984 q->match |= HX509_QUERY_KU_DIGITALSIGNATURE;
1986 case HX509_QUERY_OPTION_KU_KEYCERTSIGN:
1987 q->match |= HX509_QUERY_KU_KEYCERTSIGN;
1989 case HX509_QUERY_OPTION_END:
1996 hx509_query_match_issuer_serial(hx509_query *q,
1998 const heim_integer *serialNumber)
2002 der_free_heim_integer(q->serial);
2005 q->serial = malloc(sizeof(*q->serial));
2006 if (q->serial == NULL)
2008 ret = der_copy_heim_integer(serialNumber, q->serial);
2014 if (q->issuer_name) {
2015 free_Name(q->issuer_name);
2016 free(q->issuer_name);
2018 q->issuer_name = malloc(sizeof(*q->issuer_name));
2019 if (q->issuer_name == NULL)
2021 ret = copy_Name(issuer, q->issuer_name);
2023 free(q->issuer_name);
2024 q->issuer_name = NULL;
2027 q->match |= HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME;
2033 hx509_query_match_friendly_name(hx509_query *q, const char *name)
2035 if (q->friendlyname)
2036 free(q->friendlyname);
2037 q->friendlyname = strdup(name);
2038 if (q->friendlyname == NULL)
2040 q->match |= HX509_QUERY_MATCH_FRIENDLY_NAME;
2045 hx509_query_match_cmp_func(hx509_query *q,
2046 int (*func)(void *, hx509_cert),
2050 q->match |= HX509_QUERY_MATCH_FUNCTION;
2052 q->match &= ~HX509_QUERY_MATCH_FUNCTION;
2054 q->cmp_func_ctx = ctx;
2060 hx509_query_free(hx509_context context, hx509_query *q)
2063 der_free_heim_integer(q->serial);
2067 if (q->issuer_name) {
2068 free_Name(q->issuer_name);
2069 free(q->issuer_name);
2070 q->issuer_name = NULL;
2073 free(q->friendlyname);
2074 memset(q, 0, sizeof(*q));
2080 _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert cert)
2082 Certificate *c = _hx509_get_cert(cert);
2084 _hx509_query_statistic(context, 1, q);
2086 if ((q->match & HX509_QUERY_FIND_ISSUER_CERT) &&
2087 _hx509_cert_is_parent_cmp(q->subject, c, 0) != 0)
2090 if ((q->match & HX509_QUERY_MATCH_CERTIFICATE) &&
2091 _hx509_Certificate_cmp(q->certificate, c) != 0)
2094 if ((q->match & HX509_QUERY_MATCH_SERIALNUMBER)
2095 && der_heim_integer_cmp(&c->tbsCertificate.serialNumber, q->serial) != 0)
2098 if ((q->match & HX509_QUERY_MATCH_ISSUER_NAME)
2099 && _hx509_name_cmp(&c->tbsCertificate.issuer, q->issuer_name) != 0)
2102 if ((q->match & HX509_QUERY_MATCH_SUBJECT_NAME)
2103 && _hx509_name_cmp(&c->tbsCertificate.subject, q->subject_name) != 0)
2106 if (q->match & HX509_QUERY_MATCH_SUBJECT_KEY_ID) {
2107 SubjectKeyIdentifier si;
2110 ret = _hx509_find_extension_subject_key_id(c, &si);
2112 if (der_heim_octet_string_cmp(&si, q->subject_id) != 0)
2114 free_SubjectKeyIdentifier(&si);
2119 if ((q->match & HX509_QUERY_MATCH_ISSUER_ID))
2121 if ((q->match & HX509_QUERY_PRIVATE_KEY) &&
2122 _hx509_cert_private_key(cert) == NULL)
2127 if (q->match & HX509_QUERY_KU_DIGITALSIGNATURE)
2129 if (q->match & HX509_QUERY_KU_NONREPUDIATION)
2131 if (q->match & HX509_QUERY_KU_ENCIPHERMENT)
2133 if (q->match & HX509_QUERY_KU_DATAENCIPHERMENT)
2135 if (q->match & HX509_QUERY_KU_KEYAGREEMENT)
2137 if (q->match & HX509_QUERY_KU_KEYCERTSIGN)
2139 if (q->match & HX509_QUERY_KU_CRLSIGN)
2141 if (ku && check_key_usage(context, c, ku, TRUE))
2144 if ((q->match & HX509_QUERY_ANCHOR))
2147 if (q->match & HX509_QUERY_MATCH_LOCAL_KEY_ID) {
2148 hx509_cert_attribute a;
2150 a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_localKeyId());
2153 if (der_heim_octet_string_cmp(&a->data, q->local_key_id) != 0)
2157 if (q->match & HX509_QUERY_NO_MATCH_PATH) {
2160 for (i = 0; i < q->path->len; i++)
2161 if (hx509_cert_cmp(q->path->val[i], cert) == 0)
2164 if (q->match & HX509_QUERY_MATCH_FRIENDLY_NAME) {
2165 const char *name = hx509_cert_get_friendly_name(cert);
2168 if (strcasecmp(q->friendlyname, name) != 0)
2171 if (q->match & HX509_QUERY_MATCH_FUNCTION) {
2172 int ret = (*q->cmp_func)(q->cmp_func_ctx, cert);
2177 if (q->match & HX509_QUERY_MATCH_KEY_HASH_SHA1) {
2178 heim_octet_string os;
2181 os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
2183 c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
2185 ret = _hx509_verify_signature(context,
2187 hx509_signature_sha1(),
2194 if (q->match & HX509_QUERY_MATCH_TIME) {
2196 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2199 t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
2204 if (q->match & ~HX509_QUERY_MASK)
2211 hx509_query_statistic_file(hx509_context context, const char *fn)
2213 if (context->querystat)
2214 free(context->querystat);
2215 context->querystat = strdup(fn);
2219 _hx509_query_statistic(hx509_context context, int type, const hx509_query *q)
2222 if (context->querystat == NULL)
2224 f = fopen(context->querystat, "a");
2227 fprintf(f, "%d %d\n", type, q->match);
2231 static const char *statname[] = {
2233 "match serialnumber",
2234 "match issuer name",
2235 "match subject name",
2236 "match subject key id",
2240 "ku digitalsignature",
2243 "ku nonrepudiation",
2245 "ku dataencipherment",
2247 "match certificate",
2248 "match local key id",
2250 "match friendly name",
2252 "match key hash sha1",
2257 unsigned long stats;
2263 stat_sort(const void *a, const void *b)
2265 const struct stat_el *ae = a;
2266 const struct stat_el *be = b;
2267 return be->stats - ae->stats;
2271 hx509_query_unparse_stats(hx509_context context, int printtype, FILE *out)
2275 int type, mask, i, num;
2276 unsigned long multiqueries = 0, totalqueries = 0;
2277 struct stat_el stats[32];
2279 if (context->querystat == NULL)
2281 f = fopen(context->querystat, "r");
2283 fprintf(out, "No statistic file %s: %s.\n",
2284 context->querystat, strerror(errno));
2288 for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
2293 while (fscanf(f, "%d %d\n", &type, &mask) == 2) {
2294 if (type != printtype)
2297 while (mask && i < sizeof(stats)/sizeof(stats[0])) {
2311 qsort(stats, sizeof(stats)/sizeof(stats[0]), sizeof(stats[0]), stat_sort);
2315 errx(1, "out of memory");
2317 rtbl_set_separator (t, " ");
2319 rtbl_add_column_by_id (t, 0, "Name", 0);
2320 rtbl_add_column_by_id (t, 1, "Counter", 0);
2323 for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
2326 if (stats[i].index < sizeof(statname)/sizeof(statname[0]))
2327 rtbl_add_column_entry_by_id (t, 0, statname[stats[i].index]);
2329 snprintf(str, sizeof(str), "%d", stats[i].index);
2330 rtbl_add_column_entry_by_id (t, 0, str);
2332 snprintf(str, sizeof(str), "%lu", stats[i].stats);
2333 rtbl_add_column_entry_by_id (t, 1, str);
2336 rtbl_format(t, out);
2339 fprintf(out, "\nQueries: multi %lu total %lu\n",
2340 multiqueries, totalqueries);
2344 hx509_cert_check_eku(hx509_context context, hx509_cert cert,
2345 const heim_oid *eku, int allow_any_eku)
2350 ret = find_extension_eku(_hx509_get_cert(cert), &e);
2352 hx509_clear_error_string(context);
2356 for (i = 0; i < e.len; i++) {
2357 if (der_heim_oid_cmp(eku, &e.val[i]) == 0) {
2358 free_ExtKeyUsage(&e);
2361 if (allow_any_eku) {
2363 if (der_heim_oid_cmp(id_any_eku, &e.val[i]) == 0) {
2364 free_ExtKeyUsage(&e);
2370 free_ExtKeyUsage(&e);
2371 hx509_clear_error_string(context);
2372 return HX509_CERTIFICATE_MISSING_EKU;
2376 _hx509_cert_get_keyusage(hx509_context context,
2385 memset(ku, 0, sizeof(*ku));
2387 cert = _hx509_get_cert(c);
2389 if (_hx509_cert_get_version(cert) < 3)
2392 e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
2394 return HX509_KU_CERT_MISSING;
2396 ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, ku, &size);
2403 _hx509_cert_get_eku(hx509_context context,
2409 memset(e, 0, sizeof(*e));
2411 ret = find_extension_eku(_hx509_get_cert(cert), e);
2412 if (ret && ret != HX509_EXTENSION_NOT_FOUND) {
2413 hx509_clear_error_string(context);
2420 hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os)
2428 ASN1_MALLOC_ENCODE(Certificate, os->data, os->length,
2429 _hx509_get_cert(c), &size, ret);
2432 if (os->length != size)
2433 _hx509_abort("internal ASN.1 encoder error");