2 * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include "crypto-headers.h"
39 * @page page_cert The basic certificate
41 * The basic hx509 cerificate object in hx509 is hx509_cert. The
42 * hx509_cert object is representing one X509/PKIX certificate and
43 * associated attributes; like private key, friendly name, etc.
45 * A hx509_cert object is usully found via the keyset interfaces (@ref
46 * page_keyset), but its also possible to create a certificate
47 * directly from a parsed object with hx509_cert_init() and
48 * hx509_cert_init_data().
50 * See the library functions here: @ref hx509_cert
53 struct hx509_verify_ctx_data
{
54 hx509_certs trust_anchors
;
56 #define HX509_VERIFY_CTX_F_TIME_SET 1
57 #define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE 2
58 #define HX509_VERIFY_CTX_F_REQUIRE_RFC3280 4
59 #define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS 8
60 #define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS 16
61 #define HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK 32
63 unsigned int max_depth
;
64 #define HX509_VERIFY_MAX_DEPTH 30
65 hx509_revoke_ctx revoke_ctx
;
68 #define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280)
69 #define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS)
70 #define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0)
72 struct _hx509_cert_attrs
{
74 hx509_cert_attribute
*val
;
77 struct hx509_cert_data
{
81 hx509_private_key private_key
;
82 struct _hx509_cert_attrs attrs
;
84 _hx509_cert_release_func release
;
88 typedef struct hx509_name_constraints
{
91 } hx509_name_constraints
;
93 #define GeneralSubtrees_SET(g,var) \
94 (g)->len = (var)->len, (g)->val = (var)->val;
97 init_context_once(void *ignored
)
100 ENGINE_add_conf_module();
101 OpenSSL_add_all_algorithms();
105 * Creates a hx509 context that most functions in the library
106 * uses. The context is only allowed to be used by one thread at each
107 * moment. Free the context with hx509_context_free().
109 * @param context Returns a pointer to new hx509 context.
111 * @return Returns an hx509 error code.
117 hx509_context_init(hx509_context
*context
)
119 static heim_base_once_t init_context
= HEIM_BASE_ONCE_INIT
;
121 *context
= calloc(1, sizeof(**context
));
122 if (*context
== NULL
)
125 heim_base_once_f(&init_context
, NULL
, init_context_once
);
127 _hx509_ks_null_register(*context
);
128 _hx509_ks_mem_register(*context
);
129 _hx509_ks_file_register(*context
);
130 _hx509_ks_pkcs12_register(*context
);
131 _hx509_ks_pkcs11_register(*context
);
132 _hx509_ks_dir_register(*context
);
133 _hx509_ks_keychain_register(*context
);
135 (*context
)->ocsp_time_diff
= HX509_DEFAULT_OCSP_TIME_DIFF
;
137 initialize_hx_error_table_r(&(*context
)->et_list
);
138 initialize_asn1_error_table_r(&(*context
)->et_list
);
140 #ifdef HX509_DEFAULT_ANCHORS
141 (void)hx509_certs_init(*context
, HX509_DEFAULT_ANCHORS
, 0,
142 NULL
, &(*context
)->default_trust_anchors
);
149 * Selects if the hx509_revoke_verify() function is going to require
150 * the existans of a revokation method (OCSP, CRL) or not. Note that
151 * hx509_verify_path(), hx509_cms_verify_signed(), and other function
152 * call hx509_revoke_verify().
154 * @param context hx509 context to change the flag for.
155 * @param flag zero, revokation method required, non zero missing
156 * revokation method ok
158 * @ingroup hx509_verify
162 hx509_context_set_missing_revoke(hx509_context context
, int flag
)
165 context
->flags
|= HX509_CTX_VERIFY_MISSING_OK
;
167 context
->flags
&= ~HX509_CTX_VERIFY_MISSING_OK
;
171 * Free the context allocated by hx509_context_init().
173 * @param context context to be freed.
179 hx509_context_free(hx509_context
*context
)
181 hx509_clear_error_string(*context
);
182 if ((*context
)->ks_ops
) {
183 free((*context
)->ks_ops
);
184 (*context
)->ks_ops
= NULL
;
186 (*context
)->ks_num_ops
= 0;
187 free_error_table ((*context
)->et_list
);
188 if ((*context
)->querystat
)
189 free((*context
)->querystat
);
190 memset(*context
, 0, sizeof(**context
));
200 _hx509_get_cert(hx509_cert cert
)
210 _hx509_cert_get_version(const Certificate
*t
)
212 return t
->tbsCertificate
.version
? *t
->tbsCertificate
.version
+ 1 : 1;
216 * Allocate and init an hx509 certificate object from the decoded
219 * @param context A hx509 context.
223 * @return Returns an hx509 certificate
225 * @ingroup hx509_cert
229 hx509_cert_init(hx509_context context
, const Certificate
*c
, heim_error_t
*error
)
234 cert
= malloc(sizeof(*cert
));
237 *error
= heim_error_create_enomem();
241 cert
->friendlyname
= NULL
;
243 cert
->attrs
.val
= NULL
;
244 cert
->private_key
= NULL
;
245 cert
->basename
= NULL
;
246 cert
->release
= NULL
;
249 cert
->data
= calloc(1, sizeof(*(cert
->data
)));
250 if (cert
->data
== NULL
) {
253 *error
= heim_error_create_enomem();
256 ret
= copy_Certificate(c
, cert
->data
);
266 * Just like hx509_cert_init(), but instead of a decode certificate
267 * takes an pointer and length to a memory region that contains a
268 * DER/BER encoded certificate.
270 * If the memory region doesn't contain just the certificate and
271 * nothing more the function will fail with
272 * HX509_EXTRA_DATA_AFTER_STRUCTURE.
274 * @param context A hx509 context.
275 * @param ptr pointer to memory region containing encoded certificate.
276 * @param len length of memory region.
277 * @param error possibly returns an error
279 * @return An hx509 certificate
281 * @ingroup hx509_cert
285 hx509_cert_init_data(hx509_context context
,
295 ret
= decode_Certificate(ptr
, len
, &t
, &size
);
298 *error
= heim_error_create(ret
, "Failed to decode certificate");
302 free_Certificate(&t
);
304 *error
= heim_error_create(HX509_EXTRA_DATA_AFTER_STRUCTURE
,
305 "Extra data after certificate");
309 cert
= hx509_cert_init(context
, &t
, error
);
310 free_Certificate(&t
);
315 _hx509_cert_set_release(hx509_cert cert
,
316 _hx509_cert_release_func release
,
319 cert
->release
= release
;
324 /* Doesn't make a copy of `private_key'. */
327 _hx509_cert_assign_key(hx509_cert cert
, hx509_private_key private_key
)
329 if (cert
->private_key
)
330 hx509_private_key_free(&cert
->private_key
);
331 cert
->private_key
= _hx509_private_key_ref(private_key
);
336 * Free reference to the hx509 certificate object, if the refcounter
337 * reaches 0, the object if freed. Its allowed to pass in NULL.
339 * @param cert the cert to free.
341 * @ingroup hx509_cert
345 hx509_cert_free(hx509_cert cert
)
353 _hx509_abort("cert refcount <= 0 on free");
358 (cert
->release
)(cert
, cert
->ctx
);
360 if (cert
->private_key
)
361 hx509_private_key_free(&cert
->private_key
);
363 free_Certificate(cert
->data
);
366 for (i
= 0; i
< cert
->attrs
.len
; i
++) {
367 der_free_octet_string(&cert
->attrs
.val
[i
]->data
);
368 der_free_oid(&cert
->attrs
.val
[i
]->oid
);
369 free(cert
->attrs
.val
[i
]);
371 free(cert
->attrs
.val
);
372 free(cert
->friendlyname
);
374 hx509_name_free(&cert
->basename
);
375 memset(cert
, 0, sizeof(*cert
));
380 * Add a reference to a hx509 certificate object.
382 * @param cert a pointer to an hx509 certificate object.
384 * @return the same object as is passed in.
386 * @ingroup hx509_cert
390 hx509_cert_ref(hx509_cert cert
)
395 _hx509_abort("cert refcount <= 0");
398 _hx509_abort("cert refcount == 0");
403 * Allocate an verification context that is used fo control the
404 * verification process.
406 * @param context A hx509 context.
407 * @param ctx returns a pointer to a hx509_verify_ctx object.
409 * @return An hx509 error code, see hx509_get_error_string().
411 * @ingroup hx509_verify
415 hx509_verify_init_ctx(hx509_context context
, hx509_verify_ctx
*ctx
)
419 c
= calloc(1, sizeof(*c
));
423 c
->max_depth
= HX509_VERIFY_MAX_DEPTH
;
431 * Free an hx509 verification context.
433 * @param ctx the context to be freed.
435 * @ingroup hx509_verify
439 hx509_verify_destroy_ctx(hx509_verify_ctx ctx
)
442 hx509_certs_free(&ctx
->trust_anchors
);
443 hx509_revoke_free(&ctx
->revoke_ctx
);
444 memset(ctx
, 0, sizeof(*ctx
));
450 * Set the trust anchors in the verification context, makes an
451 * reference to the keyset, so the consumer can free the keyset
452 * independent of the destruction of the verification context (ctx).
453 * If there already is a keyset attached, it's released.
455 * @param ctx a verification context
456 * @param set a keyset containing the trust anchors.
458 * @ingroup hx509_verify
462 hx509_verify_attach_anchors(hx509_verify_ctx ctx
, hx509_certs set
)
464 if (ctx
->trust_anchors
)
465 hx509_certs_free(&ctx
->trust_anchors
);
466 ctx
->trust_anchors
= hx509_certs_ref(set
);
470 * Attach an revocation context to the verfication context, , makes an
471 * reference to the revoke context, so the consumer can free the
472 * revoke context independent of the destruction of the verification
473 * context. If there is no revoke context, the verification process is
474 * NOT going to check any verification status.
476 * @param ctx a verification context.
477 * @param revoke_ctx a revoke context.
479 * @ingroup hx509_verify
483 hx509_verify_attach_revoke(hx509_verify_ctx ctx
, hx509_revoke_ctx revoke_ctx
)
486 hx509_revoke_free(&ctx
->revoke_ctx
);
487 ctx
->revoke_ctx
= _hx509_revoke_ref(revoke_ctx
);
491 * Set the clock time the the verification process is going to
492 * use. Used to check certificate in the past and future time. If not
493 * set the current time will be used.
495 * @param ctx a verification context.
496 * @param t the time the verifiation is using.
499 * @ingroup hx509_verify
503 hx509_verify_set_time(hx509_verify_ctx ctx
, time_t t
)
505 ctx
->flags
|= HX509_VERIFY_CTX_F_TIME_SET
;
510 _hx509_verify_get_time(hx509_verify_ctx ctx
)
512 return ctx
->time_now
;
516 * Set the maximum depth of the certificate chain that the path
517 * builder is going to try.
519 * @param ctx a verification context
520 * @param max_depth maxium depth of the certificate chain, include
523 * @ingroup hx509_verify
527 hx509_verify_set_max_depth(hx509_verify_ctx ctx
, unsigned int max_depth
)
529 ctx
->max_depth
= max_depth
;
533 * Allow or deny the use of proxy certificates
535 * @param ctx a verification context
536 * @param boolean if non zero, allow proxy certificates.
538 * @ingroup hx509_verify
542 hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx
, int boolean
)
545 ctx
->flags
|= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
;
547 ctx
->flags
&= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
;
551 * Select strict RFC3280 verification of certificiates. This means
552 * checking key usage on CA certificates, this will make version 1
553 * certificiates unuseable.
555 * @param ctx a verification context
556 * @param boolean if non zero, use strict verification.
558 * @ingroup hx509_verify
562 hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx
, int boolean
)
565 ctx
->flags
|= HX509_VERIFY_CTX_F_REQUIRE_RFC3280
;
567 ctx
->flags
&= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280
;
571 * Allow using the operating system builtin trust anchors if no other
572 * trust anchors are configured.
574 * @param ctx a verification context
575 * @param boolean if non zero, useing the operating systems builtin
579 * @return An hx509 error code, see hx509_get_error_string().
581 * @ingroup hx509_cert
585 hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx
, int boolean
)
588 ctx
->flags
&= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS
;
590 ctx
->flags
|= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS
;
594 hx509_verify_ctx_f_allow_best_before_signature_algs(hx509_context ctx
,
598 ctx
->flags
&= ~HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK
;
600 ctx
->flags
|= HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK
;
603 static const Extension
*
604 find_extension(const Certificate
*cert
, const heim_oid
*oid
, size_t *idx
)
606 const TBSCertificate
*c
= &cert
->tbsCertificate
;
608 if (c
->version
== NULL
|| *c
->version
< 2 || c
->extensions
== NULL
)
611 for (;*idx
< c
->extensions
->len
; (*idx
)++) {
612 if (der_heim_oid_cmp(&c
->extensions
->val
[*idx
].extnID
, oid
) == 0)
613 return &c
->extensions
->val
[(*idx
)++];
619 find_extension_auth_key_id(const Certificate
*subject
,
620 AuthorityKeyIdentifier
*ai
)
626 memset(ai
, 0, sizeof(*ai
));
628 e
= find_extension(subject
, &asn1_oid_id_x509_ce_authorityKeyIdentifier
, &i
);
630 return HX509_EXTENSION_NOT_FOUND
;
632 return decode_AuthorityKeyIdentifier(e
->extnValue
.data
,
638 _hx509_find_extension_subject_key_id(const Certificate
*issuer
,
639 SubjectKeyIdentifier
*si
)
645 memset(si
, 0, sizeof(*si
));
647 e
= find_extension(issuer
, &asn1_oid_id_x509_ce_subjectKeyIdentifier
, &i
);
649 return HX509_EXTENSION_NOT_FOUND
;
651 return decode_SubjectKeyIdentifier(e
->extnValue
.data
,
657 find_extension_name_constraints(const Certificate
*subject
,
664 memset(nc
, 0, sizeof(*nc
));
666 e
= find_extension(subject
, &asn1_oid_id_x509_ce_nameConstraints
, &i
);
668 return HX509_EXTENSION_NOT_FOUND
;
670 return decode_NameConstraints(e
->extnValue
.data
,
676 find_extension_subject_alt_name(const Certificate
*cert
, size_t *i
,
682 memset(sa
, 0, sizeof(*sa
));
684 e
= find_extension(cert
, &asn1_oid_id_x509_ce_subjectAltName
, i
);
686 return HX509_EXTENSION_NOT_FOUND
;
688 return decode_GeneralNames(e
->extnValue
.data
,
694 find_extension_eku(const Certificate
*cert
, ExtKeyUsage
*eku
)
700 memset(eku
, 0, sizeof(*eku
));
702 e
= find_extension(cert
, &asn1_oid_id_x509_ce_extKeyUsage
, &i
);
704 return HX509_EXTENSION_NOT_FOUND
;
706 return decode_ExtKeyUsage(e
->extnValue
.data
,
712 add_to_list(hx509_octet_string_list
*list
, const heim_octet_string
*entry
)
717 p
= realloc(list
->val
, (list
->len
+ 1) * sizeof(list
->val
[0]));
721 ret
= der_copy_octet_string(entry
, &list
->val
[list
->len
]);
729 * Free a list of octet strings returned by another hx509 library
732 * @param list list to be freed.
734 * @ingroup hx509_misc
738 hx509_free_octet_string_list(hx509_octet_string_list
*list
)
741 for (i
= 0; i
< list
->len
; i
++)
742 der_free_octet_string(&list
->val
[i
]);
749 * Return a list of subjectAltNames specified by oid in the
750 * certificate. On error the
752 * The returned list of octet string should be freed with
753 * hx509_free_octet_string_list().
755 * @param context A hx509 context.
756 * @param cert a hx509 certificate object.
757 * @param oid an oid to for SubjectAltName.
758 * @param list list of matching SubjectAltName.
760 * @return An hx509 error code, see hx509_get_error_string().
762 * @ingroup hx509_cert
766 hx509_cert_find_subjectAltName_otherName(hx509_context context
,
769 hx509_octet_string_list
*list
)
780 ret
= find_extension_subject_alt_name(_hx509_get_cert(cert
), &i
, &sa
);
782 if (ret
== HX509_EXTENSION_NOT_FOUND
) {
784 } else if (ret
!= 0) {
785 hx509_set_error_string(context
, 0, ret
, "Error searching for SAN");
786 hx509_free_octet_string_list(list
);
790 for (j
= 0; j
< sa
.len
; j
++) {
791 if (sa
.val
[j
].element
== choice_GeneralName_otherName
&&
792 der_heim_oid_cmp(&sa
.val
[j
].u
.otherName
.type_id
, oid
) == 0)
794 ret
= add_to_list(list
, &sa
.val
[j
].u
.otherName
.value
);
796 hx509_set_error_string(context
, 0, ret
,
797 "Error adding an exra SAN to "
799 hx509_free_octet_string_list(list
);
800 free_GeneralNames(&sa
);
805 free_GeneralNames(&sa
);
811 check_key_usage(hx509_context context
, const Certificate
*cert
,
812 unsigned flags
, int req_present
)
821 if (_hx509_cert_get_version(cert
) < 3)
824 e
= find_extension(cert
, &asn1_oid_id_x509_ce_keyUsage
, &i
);
827 hx509_set_error_string(context
, 0, HX509_KU_CERT_MISSING
,
828 "Required extension key "
829 "usage missing from certifiate");
830 return HX509_KU_CERT_MISSING
;
835 ret
= decode_KeyUsage(e
->extnValue
.data
, e
->extnValue
.length
, &ku
, &size
);
838 ku_flags
= KeyUsage2int(ku
);
839 if ((ku_flags
& flags
) != flags
) {
840 unsigned missing
= (~ku_flags
) & flags
;
841 char buf
[256], *name
;
843 unparse_flags(missing
, asn1_KeyUsage_units(), buf
, sizeof(buf
));
844 _hx509_unparse_Name(&cert
->tbsCertificate
.subject
, &name
);
845 hx509_set_error_string(context
, 0, HX509_KU_CERT_MISSING
,
846 "Key usage %s required but missing "
847 "from certifiate %s", buf
, name
);
849 return HX509_KU_CERT_MISSING
;
855 * Return 0 on matching key usage 'flags' for 'cert', otherwise return
856 * an error code. If 'req_present' the existance is required of the
857 * KeyUsage extension.
861 _hx509_check_key_usage(hx509_context context
, hx509_cert cert
,
862 unsigned flags
, int req_present
)
864 return check_key_usage(context
, _hx509_get_cert(cert
), flags
, req_present
);
867 enum certtype
{ PROXY_CERT
, EE_CERT
, CA_CERT
};
870 check_basic_constraints(hx509_context context
, const Certificate
*cert
,
871 enum certtype type
, size_t depth
)
879 if (_hx509_cert_get_version(cert
) < 3)
882 e
= find_extension(cert
, &asn1_oid_id_x509_ce_basicConstraints
, &i
);
890 ret
= _hx509_unparse_Name(&cert
->tbsCertificate
.subject
, &name
);
892 hx509_set_error_string(context
, 0, HX509_EXTENSION_NOT_FOUND
,
893 "basicConstraints missing from "
894 "CA certifiacte %s", name
);
896 return HX509_EXTENSION_NOT_FOUND
;
901 ret
= decode_BasicConstraints(e
->extnValue
.data
,
902 e
->extnValue
.length
, &bc
,
908 if (bc
.cA
!= NULL
&& *bc
.cA
)
909 ret
= HX509_PARENT_IS_CA
;
915 if (bc
.cA
== NULL
|| !*bc
.cA
)
916 ret
= HX509_PARENT_NOT_CA
;
917 else if (bc
.pathLenConstraint
)
918 if (depth
- 1 > *bc
.pathLenConstraint
)
919 ret
= HX509_CA_PATH_TOO_DEEP
;
922 free_BasicConstraints(&bc
);
927 _hx509_cert_is_parent_cmp(const Certificate
*subject
,
928 const Certificate
*issuer
,
929 int allow_self_signed
)
932 AuthorityKeyIdentifier ai
;
933 SubjectKeyIdentifier si
;
934 int ret_ai
, ret_si
, ret
;
936 ret
= _hx509_name_cmp(&issuer
->tbsCertificate
.subject
,
937 &subject
->tbsCertificate
.issuer
,
944 memset(&ai
, 0, sizeof(ai
));
945 memset(&si
, 0, sizeof(si
));
948 * Try to find AuthorityKeyIdentifier, if it's not present in the
949 * subject certificate nor the parent.
952 ret_ai
= find_extension_auth_key_id(subject
, &ai
);
953 if (ret_ai
&& ret_ai
!= HX509_EXTENSION_NOT_FOUND
)
955 ret_si
= _hx509_find_extension_subject_key_id(issuer
, &si
);
956 if (ret_si
&& ret_si
!= HX509_EXTENSION_NOT_FOUND
)
959 if (ret_si
&& ret_ai
)
964 if (allow_self_signed
) {
967 } else if (ai
.keyIdentifier
) {
973 if (ai
.keyIdentifier
== NULL
) {
976 if (ai
.authorityCertIssuer
== NULL
)
978 if (ai
.authorityCertSerialNumber
== NULL
)
981 diff
= der_heim_integer_cmp(ai
.authorityCertSerialNumber
,
982 &issuer
->tbsCertificate
.serialNumber
);
985 if (ai
.authorityCertIssuer
->len
!= 1)
987 if (ai
.authorityCertIssuer
->val
[0].element
!= choice_GeneralName_directoryName
)
990 name
.element
= (enum Name_enum
)
991 ai
.authorityCertIssuer
->val
[0].u
.directoryName
.element
;
993 ai
.authorityCertIssuer
->val
[0].u
.directoryName
.u
.rdnSequence
;
995 ret
= _hx509_name_cmp(&issuer
->tbsCertificate
.subject
,
1004 diff
= der_heim_octet_string_cmp(ai
.keyIdentifier
, &si
);
1009 free_AuthorityKeyIdentifier(&ai
);
1010 free_SubjectKeyIdentifier(&si
);
1015 certificate_is_anchor(hx509_context context
,
1016 hx509_certs trust_anchors
,
1017 const hx509_cert cert
)
1023 if (trust_anchors
== NULL
)
1026 _hx509_query_clear(&q
);
1028 q
.match
= HX509_QUERY_MATCH_CERTIFICATE
;
1029 q
.certificate
= _hx509_get_cert(cert
);
1031 ret
= hx509_certs_find(context
, trust_anchors
, &q
, &c
);
1038 certificate_is_self_signed(hx509_context context
,
1039 const Certificate
*cert
,
1043 ret
= _hx509_name_cmp(&cert
->tbsCertificate
.subject
,
1044 &cert
->tbsCertificate
.issuer
, &diff
);
1045 *self_signed
= (diff
== 0);
1047 hx509_set_error_string(context
, 0, ret
,
1048 "Failed to check if self signed");
1050 ret
= _hx509_self_signed_valid(context
, &cert
->signatureAlgorithm
);
1056 * The subjectName is "null" when it's empty set of relative DBs.
1060 subject_null_p(const Certificate
*c
)
1062 return c
->tbsCertificate
.subject
.u
.rdnSequence
.len
== 0;
1067 find_parent(hx509_context context
,
1069 hx509_certs trust_anchors
,
1075 AuthorityKeyIdentifier ai
;
1080 memset(&ai
, 0, sizeof(ai
));
1082 _hx509_query_clear(&q
);
1084 if (!subject_null_p(current
->data
)) {
1085 q
.match
|= HX509_QUERY_FIND_ISSUER_CERT
;
1086 q
.subject
= _hx509_get_cert(current
);
1088 ret
= find_extension_auth_key_id(current
->data
, &ai
);
1090 hx509_set_error_string(context
, 0, HX509_CERTIFICATE_MALFORMED
,
1091 "Subjectless certificate missing AuthKeyID");
1092 return HX509_CERTIFICATE_MALFORMED
;
1095 if (ai
.keyIdentifier
== NULL
) {
1096 free_AuthorityKeyIdentifier(&ai
);
1097 hx509_set_error_string(context
, 0, HX509_CERTIFICATE_MALFORMED
,
1098 "Subjectless certificate missing keyIdentifier "
1099 "inside AuthKeyID");
1100 return HX509_CERTIFICATE_MALFORMED
;
1103 q
.subject_id
= ai
.keyIdentifier
;
1104 q
.match
= HX509_QUERY_MATCH_SUBJECT_KEY_ID
;
1108 q
.match
|= HX509_QUERY_NO_MATCH_PATH
;
1111 q
.timenow
= time_now
;
1112 q
.match
|= HX509_QUERY_MATCH_TIME
;
1114 ret
= hx509_certs_find(context
, pool
, &q
, parent
);
1116 free_AuthorityKeyIdentifier(&ai
);
1119 q
.match
&= ~HX509_QUERY_MATCH_TIME
;
1122 if (trust_anchors
) {
1123 ret
= hx509_certs_find(context
, trust_anchors
, &q
, parent
);
1125 free_AuthorityKeyIdentifier(&ai
);
1129 free_AuthorityKeyIdentifier(&ai
);
1135 ret
= hx509_cert_get_subject(current
, &name
);
1137 hx509_clear_error_string(context
);
1138 return HX509_ISSUER_NOT_FOUND
;
1140 ret
= hx509_name_to_string(name
, &str
);
1141 hx509_name_free(&name
);
1143 hx509_clear_error_string(context
);
1144 return HX509_ISSUER_NOT_FOUND
;
1147 hx509_set_error_string(context
, 0, HX509_ISSUER_NOT_FOUND
,
1148 "Failed to find issuer for "
1149 "certificate with subject: '%s'", str
);
1152 return HX509_ISSUER_NOT_FOUND
;
1160 is_proxy_cert(hx509_context context
,
1161 const Certificate
*cert
,
1162 ProxyCertInfo
*rinfo
)
1171 memset(rinfo
, 0, sizeof(*rinfo
));
1173 e
= find_extension(cert
, &asn1_oid_id_pkix_pe_proxyCertInfo
, &i
);
1175 hx509_clear_error_string(context
);
1176 return HX509_EXTENSION_NOT_FOUND
;
1179 ret
= decode_ProxyCertInfo(e
->extnValue
.data
,
1180 e
->extnValue
.length
,
1184 hx509_clear_error_string(context
);
1187 if (size
!= e
->extnValue
.length
) {
1188 free_ProxyCertInfo(&info
);
1189 hx509_clear_error_string(context
);
1190 return HX509_EXTRA_DATA_AFTER_STRUCTURE
;
1193 free_ProxyCertInfo(&info
);
1201 * Path operations are like MEMORY based keyset, but with exposed
1202 * internal so we can do easy searches.
1206 _hx509_path_append(hx509_context context
, hx509_path
*path
, hx509_cert cert
)
1209 val
= realloc(path
->val
, (path
->len
+ 1) * sizeof(path
->val
[0]));
1211 hx509_set_error_string(context
, 0, ENOMEM
, "out of memory");
1216 path
->val
[path
->len
] = hx509_cert_ref(cert
);
1223 _hx509_path_free(hx509_path
*path
)
1227 for (i
= 0; i
< path
->len
; i
++)
1228 hx509_cert_free(path
->val
[i
]);
1235 * Find path by looking up issuer for the top certificate and continue
1236 * until an anchor certificate is found or max limit is found. A
1237 * certificate never included twice in the path.
1239 * If the trust anchors are not given, calculate optimistic path, just
1240 * follow the chain upward until we no longer find a parent or we hit
1241 * the max path limit. In this case, a failure will always be returned
1242 * depending on what error condition is hit first.
1244 * The path includes a path from the top certificate to the anchor
1247 * The caller needs to free `path´ both on successful built path and
1252 _hx509_calculate_path(hx509_context context
,
1255 hx509_certs anchors
,
1256 unsigned int max_depth
,
1261 hx509_cert parent
, current
;
1265 max_depth
= HX509_VERIFY_MAX_DEPTH
;
1267 ret
= _hx509_path_append(context
, path
, cert
);
1271 current
= hx509_cert_ref(cert
);
1273 while (!certificate_is_anchor(context
, anchors
, current
)) {
1275 ret
= find_parent(context
, time_now
, anchors
, path
,
1276 pool
, current
, &parent
);
1277 hx509_cert_free(current
);
1281 ret
= _hx509_path_append(context
, path
, parent
);
1286 if (path
->len
> max_depth
) {
1287 hx509_cert_free(current
);
1288 hx509_set_error_string(context
, 0, HX509_PATH_TOO_LONG
,
1289 "Path too long while bulding "
1290 "certificate chain");
1291 return HX509_PATH_TOO_LONG
;
1295 if ((flags
& HX509_CALCULATE_PATH_NO_ANCHOR
) &&
1297 certificate_is_anchor(context
, anchors
, path
->val
[path
->len
- 1]))
1299 hx509_cert_free(path
->val
[path
->len
- 1]);
1303 hx509_cert_free(current
);
1308 _hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier
*p
,
1309 const AlgorithmIdentifier
*q
)
1312 diff
= der_heim_oid_cmp(&p
->algorithm
, &q
->algorithm
);
1315 if (p
->parameters
) {
1317 return heim_any_cmp(p
->parameters
,
1330 _hx509_Certificate_cmp(const Certificate
*p
, const Certificate
*q
)
1333 diff
= der_heim_bit_string_cmp(&p
->signatureValue
, &q
->signatureValue
);
1336 diff
= _hx509_AlgorithmIdentifier_cmp(&p
->signatureAlgorithm
,
1337 &q
->signatureAlgorithm
);
1340 diff
= der_heim_octet_string_cmp(&p
->tbsCertificate
._save
,
1341 &q
->tbsCertificate
._save
);
1346 * Compare to hx509 certificate object, useful for sorting.
1348 * @param p a hx509 certificate object.
1349 * @param q a hx509 certificate object.
1351 * @return 0 the objects are the same, returns > 0 is p is "larger"
1352 * then q, < 0 if p is "smaller" then q.
1354 * @ingroup hx509_cert
1358 hx509_cert_cmp(hx509_cert p
, hx509_cert q
)
1360 return _hx509_Certificate_cmp(p
->data
, q
->data
);
1364 * Return the name of the issuer of the hx509 certificate.
1366 * @param p a hx509 certificate object.
1367 * @param name a pointer to a hx509 name, should be freed by
1368 * hx509_name_free().
1370 * @return An hx509 error code, see hx509_get_error_string().
1372 * @ingroup hx509_cert
1376 hx509_cert_get_issuer(hx509_cert p
, hx509_name
*name
)
1378 return _hx509_name_from_Name(&p
->data
->tbsCertificate
.issuer
, name
);
1382 * Return the name of the subject of the hx509 certificate.
1384 * @param p a hx509 certificate object.
1385 * @param name a pointer to a hx509 name, should be freed by
1386 * hx509_name_free(). See also hx509_cert_get_base_subject().
1388 * @return An hx509 error code, see hx509_get_error_string().
1390 * @ingroup hx509_cert
1394 hx509_cert_get_subject(hx509_cert p
, hx509_name
*name
)
1396 return _hx509_name_from_Name(&p
->data
->tbsCertificate
.subject
, name
);
1400 * Return the name of the base subject of the hx509 certificate. If
1401 * the certiicate is a verified proxy certificate, the this function
1402 * return the base certificate (root of the proxy chain). If the proxy
1403 * certificate is not verified with the base certificate
1404 * HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned.
1406 * @param context a hx509 context.
1407 * @param c a hx509 certificate object.
1408 * @param name a pointer to a hx509 name, should be freed by
1409 * hx509_name_free(). See also hx509_cert_get_subject().
1411 * @return An hx509 error code, see hx509_get_error_string().
1413 * @ingroup hx509_cert
1417 hx509_cert_get_base_subject(hx509_context context
, hx509_cert c
,
1421 return hx509_name_copy(context
, c
->basename
, name
);
1422 if (is_proxy_cert(context
, c
->data
, NULL
) == 0) {
1423 int ret
= HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED
;
1424 hx509_set_error_string(context
, 0, ret
,
1425 "Proxy certificate have not been "
1426 "canonicalize yet, no base name");
1429 return _hx509_name_from_Name(&c
->data
->tbsCertificate
.subject
, name
);
1433 * Get serial number of the certificate.
1435 * @param p a hx509 certificate object.
1436 * @param i serial number, should be freed ith der_free_heim_integer().
1438 * @return An hx509 error code, see hx509_get_error_string().
1440 * @ingroup hx509_cert
1444 hx509_cert_get_serialnumber(hx509_cert p
, heim_integer
*i
)
1446 return der_copy_heim_integer(&p
->data
->tbsCertificate
.serialNumber
, i
);
1450 * Get notBefore time of the certificate.
1452 * @param p a hx509 certificate object.
1454 * @return return not before time
1456 * @ingroup hx509_cert
1460 hx509_cert_get_notBefore(hx509_cert p
)
1462 return _hx509_Time2time_t(&p
->data
->tbsCertificate
.validity
.notBefore
);
1466 * Get notAfter time of the certificate.
1468 * @param p a hx509 certificate object.
1470 * @return return not after time.
1472 * @ingroup hx509_cert
1476 hx509_cert_get_notAfter(hx509_cert p
)
1478 return _hx509_Time2time_t(&p
->data
->tbsCertificate
.validity
.notAfter
);
1482 * Get the SubjectPublicKeyInfo structure from the hx509 certificate.
1484 * @param context a hx509 context.
1485 * @param p a hx509 certificate object.
1486 * @param spki SubjectPublicKeyInfo, should be freed with
1487 * free_SubjectPublicKeyInfo().
1489 * @return An hx509 error code, see hx509_get_error_string().
1491 * @ingroup hx509_cert
1495 hx509_cert_get_SPKI(hx509_context context
, hx509_cert p
, SubjectPublicKeyInfo
*spki
)
1499 ret
= copy_SubjectPublicKeyInfo(&p
->data
->tbsCertificate
.subjectPublicKeyInfo
, spki
);
1501 hx509_set_error_string(context
, 0, ret
, "Failed to copy SPKI");
1506 * Get the AlgorithmIdentifier from the hx509 certificate.
1508 * @param context a hx509 context.
1509 * @param p a hx509 certificate object.
1510 * @param alg AlgorithmIdentifier, should be freed with
1511 * free_AlgorithmIdentifier(). The algorithmidentifier is
1512 * typicly rsaEncryption, or id-ecPublicKey, or some other
1513 * public key mechanism.
1515 * @return An hx509 error code, see hx509_get_error_string().
1517 * @ingroup hx509_cert
1521 hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context
,
1523 AlgorithmIdentifier
*alg
)
1527 ret
= copy_AlgorithmIdentifier(&p
->data
->tbsCertificate
.subjectPublicKeyInfo
.algorithm
, alg
);
1529 hx509_set_error_string(context
, 0, ret
,
1530 "Failed to copy SPKI AlgorithmIdentifier");
1535 get_x_unique_id(hx509_context context
, const char *name
,
1536 const heim_bit_string
*cert
, heim_bit_string
*subject
)
1541 ret
= HX509_EXTENSION_NOT_FOUND
;
1542 hx509_set_error_string(context
, 0, ret
, "%s unique id doesn't exists", name
);
1545 ret
= der_copy_bit_string(cert
, subject
);
1547 hx509_set_error_string(context
, 0, ret
, "malloc out of memory", name
);
1554 * Get a copy of the Issuer Unique ID
1556 * @param context a hx509_context
1557 * @param p a hx509 certificate
1558 * @param issuer the issuer id returned, free with der_free_bit_string()
1560 * @return An hx509 error code, see hx509_get_error_string(). The
1561 * error code HX509_EXTENSION_NOT_FOUND is returned if the certificate
1562 * doesn't have a issuerUniqueID
1564 * @ingroup hx509_cert
1568 hx509_cert_get_issuer_unique_id(hx509_context context
, hx509_cert p
, heim_bit_string
*issuer
)
1570 return get_x_unique_id(context
, "issuer", p
->data
->tbsCertificate
.issuerUniqueID
, issuer
);
1574 * Get a copy of the Subect Unique ID
1576 * @param context a hx509_context
1577 * @param p a hx509 certificate
1578 * @param subject the subject id returned, free with der_free_bit_string()
1580 * @return An hx509 error code, see hx509_get_error_string(). The
1581 * error code HX509_EXTENSION_NOT_FOUND is returned if the certificate
1582 * doesn't have a subjectUniqueID
1584 * @ingroup hx509_cert
1588 hx509_cert_get_subject_unique_id(hx509_context context
, hx509_cert p
, heim_bit_string
*subject
)
1590 return get_x_unique_id(context
, "subject", p
->data
->tbsCertificate
.subjectUniqueID
, subject
);
1595 _hx509_cert_private_key(hx509_cert p
)
1597 return p
->private_key
;
1601 hx509_cert_have_private_key(hx509_cert p
)
1603 return p
->private_key
? 1 : 0;
1608 _hx509_cert_private_key_exportable(hx509_cert p
)
1610 if (p
->private_key
== NULL
)
1612 return _hx509_private_key_exportable(p
->private_key
);
1616 _hx509_cert_private_decrypt(hx509_context context
,
1617 const heim_octet_string
*ciphertext
,
1618 const heim_oid
*encryption_oid
,
1620 heim_octet_string
*cleartext
)
1622 cleartext
->data
= NULL
;
1623 cleartext
->length
= 0;
1625 if (p
->private_key
== NULL
) {
1626 hx509_set_error_string(context
, 0, HX509_PRIVATE_KEY_MISSING
,
1627 "Private key missing");
1628 return HX509_PRIVATE_KEY_MISSING
;
1631 return hx509_private_key_private_decrypt(context
,
1639 hx509_cert_public_encrypt(hx509_context context
,
1640 const heim_octet_string
*cleartext
,
1642 heim_oid
*encryption_oid
,
1643 heim_octet_string
*ciphertext
)
1645 return _hx509_public_encrypt(context
,
1647 encryption_oid
, ciphertext
);
1655 _hx509_Time2time_t(const Time
*t
)
1657 switch(t
->element
) {
1658 case choice_Time_utcTime
:
1659 return t
->u
.utcTime
;
1660 case choice_Time_generalTime
:
1661 return t
->u
.generalTime
;
1671 init_name_constraints(hx509_name_constraints
*nc
)
1673 memset(nc
, 0, sizeof(*nc
));
1678 add_name_constraints(hx509_context context
, const Certificate
*c
, int not_ca
,
1679 hx509_name_constraints
*nc
)
1681 NameConstraints tnc
;
1684 ret
= find_extension_name_constraints(c
, &tnc
);
1685 if (ret
== HX509_EXTENSION_NOT_FOUND
)
1688 hx509_set_error_string(context
, 0, ret
, "Failed getting NameConstraints");
1690 } else if (not_ca
) {
1691 ret
= HX509_VERIFY_CONSTRAINTS
;
1692 hx509_set_error_string(context
, 0, ret
, "Not a CA and "
1693 "have NameConstraints");
1695 NameConstraints
*val
;
1696 val
= realloc(nc
->val
, sizeof(nc
->val
[0]) * (nc
->len
+ 1));
1698 hx509_clear_error_string(context
);
1703 ret
= copy_NameConstraints(&tnc
, &nc
->val
[nc
->len
]);
1705 hx509_clear_error_string(context
);
1711 free_NameConstraints(&tnc
);
1716 match_RDN(const RelativeDistinguishedName
*c
,
1717 const RelativeDistinguishedName
*n
)
1721 if (c
->len
!= n
->len
)
1722 return HX509_NAME_CONSTRAINT_ERROR
;
1724 for (i
= 0; i
< n
->len
; i
++) {
1727 if (der_heim_oid_cmp(&c
->val
[i
].type
, &n
->val
[i
].type
) != 0)
1728 return HX509_NAME_CONSTRAINT_ERROR
;
1729 ret
= _hx509_name_ds_cmp(&c
->val
[i
].value
, &n
->val
[i
].value
, &diff
);
1733 return HX509_NAME_CONSTRAINT_ERROR
;
1739 match_X501Name(const Name
*c
, const Name
*n
)
1744 if (c
->element
!= choice_Name_rdnSequence
1745 || n
->element
!= choice_Name_rdnSequence
)
1747 if (c
->u
.rdnSequence
.len
> n
->u
.rdnSequence
.len
)
1748 return HX509_NAME_CONSTRAINT_ERROR
;
1749 for (i
= 0; i
< c
->u
.rdnSequence
.len
; i
++) {
1750 ret
= match_RDN(&c
->u
.rdnSequence
.val
[i
], &n
->u
.rdnSequence
.val
[i
]);
1759 match_general_name(const GeneralName
*c
, const GeneralName
*n
, int *match
)
1762 * Name constraints only apply to the same name type, see RFC3280,
1765 assert(c
->element
== n
->element
);
1767 switch(c
->element
) {
1768 case choice_GeneralName_otherName
:
1769 if (der_heim_oid_cmp(&c
->u
.otherName
.type_id
,
1770 &n
->u
.otherName
.type_id
) != 0)
1771 return HX509_NAME_CONSTRAINT_ERROR
;
1772 if (heim_any_cmp(&c
->u
.otherName
.value
,
1773 &n
->u
.otherName
.value
) != 0)
1774 return HX509_NAME_CONSTRAINT_ERROR
;
1777 case choice_GeneralName_rfc822Name
: {
1780 s
= memchr(c
->u
.rfc822Name
.data
, '@', c
->u
.rfc822Name
.length
);
1782 if (der_printable_string_cmp(&c
->u
.rfc822Name
, &n
->u
.rfc822Name
) != 0)
1783 return HX509_NAME_CONSTRAINT_ERROR
;
1785 s
= memchr(n
->u
.rfc822Name
.data
, '@', n
->u
.rfc822Name
.length
);
1787 return HX509_NAME_CONSTRAINT_ERROR
;
1788 len1
= c
->u
.rfc822Name
.length
;
1789 len2
= n
->u
.rfc822Name
.length
-
1790 (s
- ((char *)n
->u
.rfc822Name
.data
));
1792 return HX509_NAME_CONSTRAINT_ERROR
;
1793 if (memcmp(s
+ 1 + len2
- len1
, c
->u
.rfc822Name
.data
, len1
) != 0)
1794 return HX509_NAME_CONSTRAINT_ERROR
;
1795 if (len1
< len2
&& s
[len2
- len1
+ 1] != '.')
1796 return HX509_NAME_CONSTRAINT_ERROR
;
1801 case choice_GeneralName_dNSName
: {
1805 lenc
= c
->u
.dNSName
.length
;
1806 lenn
= n
->u
.dNSName
.length
;
1808 return HX509_NAME_CONSTRAINT_ERROR
;
1809 ptr
= n
->u
.dNSName
.data
;
1810 if (memcmp(&ptr
[lenn
- lenc
], c
->u
.dNSName
.data
, lenc
) != 0)
1811 return HX509_NAME_CONSTRAINT_ERROR
;
1812 if (lenn
!= lenc
&& ptr
[lenn
- lenc
- 1] != '.')
1813 return HX509_NAME_CONSTRAINT_ERROR
;
1817 case choice_GeneralName_directoryName
: {
1818 Name c_name
, n_name
;
1821 c_name
._save
.data
= NULL
;
1822 c_name
._save
.length
= 0;
1823 c_name
.element
= (enum Name_enum
)c
->u
.directoryName
.element
;
1824 c_name
.u
.rdnSequence
= c
->u
.directoryName
.u
.rdnSequence
;
1826 n_name
._save
.data
= NULL
;
1827 n_name
._save
.length
= 0;
1828 n_name
.element
= (enum Name_enum
)n
->u
.directoryName
.element
;
1829 n_name
.u
.rdnSequence
= n
->u
.directoryName
.u
.rdnSequence
;
1831 ret
= match_X501Name(&c_name
, &n_name
);
1836 case choice_GeneralName_uniformResourceIdentifier
:
1837 case choice_GeneralName_iPAddress
:
1838 case choice_GeneralName_registeredID
:
1840 return HX509_NAME_CONSTRAINT_ERROR
;
1845 match_alt_name(const GeneralName
*n
, const Certificate
*c
,
1846 int *same
, int *match
)
1854 ret
= find_extension_subject_alt_name(c
, &i
, &sa
);
1855 if (ret
== HX509_EXTENSION_NOT_FOUND
) {
1858 } else if (ret
!= 0)
1861 for (j
= 0; j
< sa
.len
; j
++) {
1862 if (n
->element
== sa
.val
[j
].element
) {
1864 ret
= match_general_name(n
, &sa
.val
[j
], match
);
1867 free_GeneralNames(&sa
);
1874 match_tree(const GeneralSubtrees
*t
, const Certificate
*c
, int *match
)
1876 int name
, alt_name
, same
;
1880 name
= alt_name
= same
= *match
= 0;
1881 for (i
= 0; i
< t
->len
; i
++) {
1882 if (t
->val
[i
].minimum
&& t
->val
[i
].maximum
)
1886 * If the constraint apply to directoryNames, test is with
1887 * subjectName of the certificate if the certificate have a
1888 * non-null (empty) subjectName.
1891 if (t
->val
[i
].base
.element
== choice_GeneralName_directoryName
1892 && !subject_null_p(c
))
1894 GeneralName certname
;
1896 memset(&certname
, 0, sizeof(certname
));
1897 certname
.element
= choice_GeneralName_directoryName
;
1898 certname
.u
.directoryName
.element
= (enum GeneralName_directoryName_enum
)
1899 c
->tbsCertificate
.subject
.element
;
1900 certname
.u
.directoryName
.u
.rdnSequence
=
1901 c
->tbsCertificate
.subject
.u
.rdnSequence
;
1903 ret
= match_general_name(&t
->val
[i
].base
, &certname
, &name
);
1906 /* Handle subjectAltNames, this is icky since they
1907 * restrictions only apply if the subjectAltName is of the
1908 * same type. So if there have been a match of type, require
1909 * altname to be set.
1911 ret
= match_alt_name(&t
->val
[i
].base
, c
, &same
, &alt_name
);
1913 if (name
&& (!same
|| alt_name
))
1919 check_name_constraints(hx509_context context
,
1920 const hx509_name_constraints
*nc
,
1921 const Certificate
*c
)
1926 for (i
= 0 ; i
< nc
->len
; i
++) {
1929 if (nc
->val
[i
].permittedSubtrees
) {
1930 GeneralSubtrees_SET(&gs
, nc
->val
[i
].permittedSubtrees
);
1931 ret
= match_tree(&gs
, c
, &match
);
1933 hx509_clear_error_string(context
);
1936 /* allow null subjectNames, they wont matches anything */
1937 if (match
== 0 && !subject_null_p(c
)) {
1938 hx509_set_error_string(context
, 0, HX509_VERIFY_CONSTRAINTS
,
1939 "Error verify constraints, "
1940 "certificate didn't match any "
1941 "permitted subtree");
1942 return HX509_VERIFY_CONSTRAINTS
;
1945 if (nc
->val
[i
].excludedSubtrees
) {
1946 GeneralSubtrees_SET(&gs
, nc
->val
[i
].excludedSubtrees
);
1947 ret
= match_tree(&gs
, c
, &match
);
1949 hx509_clear_error_string(context
);
1953 hx509_set_error_string(context
, 0, HX509_VERIFY_CONSTRAINTS
,
1954 "Error verify constraints, "
1955 "certificate included in excluded "
1957 return HX509_VERIFY_CONSTRAINTS
;
1965 free_name_constraints(hx509_name_constraints
*nc
)
1969 for (i
= 0 ; i
< nc
->len
; i
++)
1970 free_NameConstraints(&nc
->val
[i
]);
1975 * Build and verify the path for the certificate to the trust anchor
1976 * specified in the verify context. The path is constructed from the
1977 * certificate, the pool and the trust anchors.
1979 * @param context A hx509 context.
1980 * @param ctx A hx509 verification context.
1981 * @param cert the certificate to build the path from.
1982 * @param pool A keyset of certificates to build the chain from.
1984 * @return An hx509 error code, see hx509_get_error_string().
1986 * @ingroup hx509_verify
1990 hx509_verify_path(hx509_context context
,
1991 hx509_verify_ctx ctx
,
1995 hx509_name_constraints nc
;
1997 int ret
, proxy_cert_depth
, selfsigned_depth
, diff
;
2001 hx509_certs anchors
= NULL
;
2003 memset(&proxy_issuer
, 0, sizeof(proxy_issuer
));
2005 ret
= init_name_constraints(&nc
);
2012 if ((ctx
->flags
& HX509_VERIFY_CTX_F_TIME_SET
) == 0)
2013 ctx
->time_now
= time(NULL
);
2018 if (ctx
->trust_anchors
)
2019 anchors
= hx509_certs_ref(ctx
->trust_anchors
);
2020 else if (context
->default_trust_anchors
&& ALLOW_DEF_TA(ctx
))
2021 anchors
= hx509_certs_ref(context
->default_trust_anchors
);
2023 ret
= hx509_certs_init(context
, "MEMORY:no-TA", 0, NULL
, &anchors
);
2029 * Calculate the path from the certificate user presented to the
2032 ret
= _hx509_calculate_path(context
, 0, ctx
->time_now
,
2033 anchors
, ctx
->max_depth
,
2039 * Check CA and proxy certificate chain from the top of the
2040 * certificate chain. Also check certificate is valid with respect
2041 * to the current time.
2045 proxy_cert_depth
= 0;
2046 selfsigned_depth
= 0;
2048 if (ctx
->flags
& HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
)
2053 for (i
= 0; i
< path
.len
; i
++) {
2057 c
= _hx509_get_cert(path
.val
[i
]);
2060 * Lets do some basic check on issuer like
2061 * keyUsage.keyCertSign and basicConstraints.cA bit depending
2062 * on what type of certificate this is.
2068 /* XXX make constants for keyusage */
2069 ret
= check_key_usage(context
, c
, 1 << 5,
2070 REQUIRE_RFC3280(ctx
) ? TRUE
: FALSE
);
2072 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
2073 "Key usage missing from CA certificate");
2077 /* self signed cert doesn't add to path length */
2078 if (i
+ 1 != path
.len
) {
2081 ret
= certificate_is_self_signed(context
, c
, &selfsigned
);
2092 if (is_proxy_cert(context
, c
, &info
) == 0) {
2095 if (info
.pCPathLenConstraint
!= NULL
&&
2096 *info
.pCPathLenConstraint
< i
)
2098 free_ProxyCertInfo(&info
);
2099 ret
= HX509_PATH_TOO_LONG
;
2100 hx509_set_error_string(context
, 0, ret
,
2101 "Proxy certificate chain "
2102 "longer then allowed");
2105 /* XXX MUST check info.proxyPolicy */
2106 free_ProxyCertInfo(&info
);
2109 if (find_extension(c
, &asn1_oid_id_x509_ce_subjectAltName
, &j
)) {
2110 ret
= HX509_PROXY_CERT_INVALID
;
2111 hx509_set_error_string(context
, 0, ret
,
2112 "Proxy certificate have explicity "
2113 "forbidden subjectAltName");
2118 if (find_extension(c
, &asn1_oid_id_x509_ce_issuerAltName
, &j
)) {
2119 ret
= HX509_PROXY_CERT_INVALID
;
2120 hx509_set_error_string(context
, 0, ret
,
2121 "Proxy certificate have explicity "
2122 "forbidden issuerAltName");
2127 * The subject name of the proxy certificate should be
2128 * CN=XXX,<proxy issuer>, prune of CN and check if its
2129 * the same over the whole chain of proxy certs and
2130 * then check with the EE cert when we get to it.
2133 if (proxy_cert_depth
) {
2134 ret
= _hx509_name_cmp(&proxy_issuer
, &c
->tbsCertificate
.subject
, &diff
);
2136 hx509_set_error_string(context
, 0, ret
, "Out of memory");
2140 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2141 hx509_set_error_string(context
, 0, ret
,
2142 "Base proxy name not right");
2147 free_Name(&proxy_issuer
);
2149 ret
= copy_Name(&c
->tbsCertificate
.subject
, &proxy_issuer
);
2151 hx509_clear_error_string(context
);
2155 j
= proxy_issuer
.u
.rdnSequence
.len
;
2156 if (proxy_issuer
.u
.rdnSequence
.len
< 2
2157 || proxy_issuer
.u
.rdnSequence
.val
[j
- 1].len
> 1
2158 || der_heim_oid_cmp(&proxy_issuer
.u
.rdnSequence
.val
[j
- 1].val
[0].type
,
2159 &asn1_oid_id_at_commonName
))
2161 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2162 hx509_set_error_string(context
, 0, ret
,
2163 "Proxy name too short or "
2164 "does not have Common name "
2169 free_RelativeDistinguishedName(&proxy_issuer
.u
.rdnSequence
.val
[j
- 1]);
2170 proxy_issuer
.u
.rdnSequence
.len
-= 1;
2172 ret
= _hx509_name_cmp(&proxy_issuer
, &c
->tbsCertificate
.issuer
, &diff
);
2174 hx509_set_error_string(context
, 0, ret
, "Out of memory");
2178 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2179 hx509_set_error_string(context
, 0, ret
,
2180 "Proxy issuer name not as expected");
2187 * Now we are done with the proxy certificates, this
2188 * cert was an EE cert and we we will fall though to
2189 * EE checking below.
2197 * If there where any proxy certificates in the chain
2198 * (proxy_cert_depth > 0), check that the proxy issuer
2199 * matched proxy certificates "base" subject.
2201 if (proxy_cert_depth
) {
2203 ret
= _hx509_name_cmp(&proxy_issuer
,
2204 &c
->tbsCertificate
.subject
, &diff
);
2206 hx509_set_error_string(context
, 0, ret
, "out of memory");
2210 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2211 hx509_clear_error_string(context
);
2215 hx509_name_free(&cert
->basename
);
2217 ret
= _hx509_name_from_Name(&proxy_issuer
, &cert
->basename
);
2219 hx509_clear_error_string(context
);
2227 ret
= check_basic_constraints(context
, c
, type
,
2228 i
- proxy_cert_depth
- selfsigned_depth
);
2233 * Don't check the trust anchors expiration time since they
2234 * are transported out of band, from RFC3820.
2236 if (i
+ 1 != path
.len
|| CHECK_TA(ctx
)) {
2238 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
2239 if (t
> ctx
->time_now
) {
2240 ret
= HX509_CERT_USED_BEFORE_TIME
;
2241 hx509_clear_error_string(context
);
2244 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notAfter
);
2245 if (t
< ctx
->time_now
) {
2246 ret
= HX509_CERT_USED_AFTER_TIME
;
2247 hx509_clear_error_string(context
);
2252 if (type
== EE_CERT
)
2254 else if (type
== PROXY_CERT
)
2259 * Verify constraints, do this backward so path constraints are
2260 * checked in the right order.
2263 for (ret
= 0, k
= path
.len
; k
> 0; k
--) {
2268 c
= _hx509_get_cert(path
.val
[i
]);
2270 ret
= certificate_is_self_signed(context
, c
, &selfsigned
);
2274 /* verify name constraints, not for selfsigned and anchor */
2275 if (!selfsigned
|| i
+ 1 != path
.len
) {
2276 ret
= check_name_constraints(context
, &nc
, c
);
2281 ret
= add_name_constraints(context
, c
, i
== 0, &nc
);
2285 /* XXX verify all other silly constraints */
2290 * Verify that no certificates has been revoked.
2293 if (ctx
->revoke_ctx
) {
2296 ret
= hx509_certs_init(context
, "MEMORY:revoke-certs", 0,
2301 for (i
= 0; i
< path
.len
; i
++) {
2302 ret
= hx509_certs_add(context
, certs
, path
.val
[i
]);
2304 hx509_certs_free(&certs
);
2308 ret
= hx509_certs_merge(context
, certs
, pool
);
2310 hx509_certs_free(&certs
);
2314 for (i
= 0; i
< path
.len
- 1; i
++) {
2315 size_t parent
= (i
< path
.len
- 1) ? i
+ 1 : i
;
2317 ret
= hx509_revoke_verify(context
,
2324 hx509_certs_free(&certs
);
2328 hx509_certs_free(&certs
);
2332 * Verify signatures, do this backward so public key working
2333 * parameter is passed up from the anchor up though the chain.
2336 for (k
= path
.len
; k
> 0; k
--) {
2341 c
= _hx509_get_cert(path
.val
[i
]);
2343 /* is last in chain (trust anchor) */
2344 if (i
+ 1 == path
.len
) {
2347 signer
= path
.val
[i
];
2349 ret
= certificate_is_self_signed(context
, signer
->data
, &selfsigned
);
2353 /* if trust anchor is not self signed, don't check sig */
2357 /* take next certificate in chain */
2358 signer
= path
.val
[i
+ 1];
2361 /* verify signatureValue */
2362 ret
= _hx509_verify_signature_bitstring(context
,
2364 &c
->signatureAlgorithm
,
2365 &c
->tbsCertificate
._save
,
2366 &c
->signatureValue
);
2368 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
2369 "Failed to verify signature of certificate");
2373 * Verify that the sigature algorithm is not weak. Ignore
2374 * trust anchors since they are provisioned by the user.
2377 if (i
+ 1 != path
.len
&& (ctx
->flags
& HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK
) == 0) {
2378 ret
= _hx509_signature_is_weak(context
, &c
->signatureAlgorithm
);
2385 hx509_certs_free(&anchors
);
2386 free_Name(&proxy_issuer
);
2387 free_name_constraints(&nc
);
2388 _hx509_path_free(&path
);
2394 * Verify a signature made using the private key of an certificate.
2396 * @param context A hx509 context.
2397 * @param signer the certificate that made the signature.
2398 * @param alg algorthm that was used to sign the data.
2399 * @param data the data that was signed.
2400 * @param sig the sigature to verify.
2402 * @return An hx509 error code, see hx509_get_error_string().
2404 * @ingroup hx509_crypto
2408 hx509_verify_signature(hx509_context context
,
2409 const hx509_cert signer
,
2410 const AlgorithmIdentifier
*alg
,
2411 const heim_octet_string
*data
,
2412 const heim_octet_string
*sig
)
2414 return _hx509_verify_signature(context
, signer
, alg
, data
, sig
);
2418 _hx509_verify_signature_bitstring(hx509_context context
,
2419 const hx509_cert signer
,
2420 const AlgorithmIdentifier
*alg
,
2421 const heim_octet_string
*data
,
2422 const heim_bit_string
*sig
)
2424 heim_octet_string os
;
2426 if (sig
->length
& 7) {
2427 hx509_set_error_string(context
, 0, HX509_CRYPTO_SIG_INVALID_FORMAT
,
2428 "signature not multiple of 8 bits");
2429 return HX509_CRYPTO_SIG_INVALID_FORMAT
;
2432 os
.data
= sig
->data
;
2433 os
.length
= sig
->length
/ 8;
2435 return _hx509_verify_signature(context
, signer
, alg
, data
, &os
);
2441 * Verify that the certificate is allowed to be used for the hostname
2444 * @param context A hx509 context.
2445 * @param cert the certificate to match with
2446 * @param flags Flags to modify the behavior:
2447 * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok
2448 * @param type type of hostname:
2449 * - HX509_HN_HOSTNAME for plain hostname.
2450 * - HX509_HN_DNSSRV for DNS SRV names.
2451 * @param hostname the hostname to check
2452 * @param sa address of the host
2453 * @param sa_size length of address
2455 * @return An hx509 error code, see hx509_get_error_string().
2457 * @ingroup hx509_cert
2461 hx509_verify_hostname(hx509_context context
,
2462 const hx509_cert cert
,
2464 hx509_hostname_type type
,
2465 const char *hostname
,
2466 const struct sockaddr
*sa
,
2467 /* XXX krb5_socklen_t */ int sa_size
)
2474 if (sa
&& sa_size
<= 0)
2477 memset(&san
, 0, sizeof(san
));
2481 ret
= find_extension_subject_alt_name(cert
->data
, &i
, &san
);
2482 if (ret
== HX509_EXTENSION_NOT_FOUND
)
2485 return HX509_PARSING_NAME_FAILED
;
2487 for (j
= 0; j
< san
.len
; j
++) {
2488 switch (san
.val
[j
].element
) {
2489 case choice_GeneralName_dNSName
: {
2490 heim_printable_string hn
;
2491 hn
.data
= rk_UNCONST(hostname
);
2492 hn
.length
= strlen(hostname
);
2494 if (der_printable_string_cmp(&san
.val
[j
].u
.dNSName
, &hn
) == 0) {
2495 free_GeneralNames(&san
);
2504 free_GeneralNames(&san
);
2507 name
= &cert
->data
->tbsCertificate
.subject
;
2509 /* Find first CN= in the name, and try to match the hostname on that */
2510 for (ret
= 0, k
= name
->u
.rdnSequence
.len
; ret
== 0 && k
> 0; k
--) {
2512 for (j
= 0; ret
== 0 && j
< name
->u
.rdnSequence
.val
[i
].len
; j
++) {
2513 AttributeTypeAndValue
*n
= &name
->u
.rdnSequence
.val
[i
].val
[j
];
2515 if (der_heim_oid_cmp(&n
->type
, &asn1_oid_id_at_commonName
) == 0) {
2516 DirectoryString
*ds
= &n
->value
;
2517 switch (ds
->element
) {
2518 case choice_DirectoryString_printableString
: {
2519 heim_printable_string hn
;
2520 hn
.data
= rk_UNCONST(hostname
);
2521 hn
.length
= strlen(hostname
);
2523 if (der_printable_string_cmp(&ds
->u
.printableString
, &hn
) == 0)
2527 case choice_DirectoryString_ia5String
: {
2529 hn
.data
= rk_UNCONST(hostname
);
2530 hn
.length
= strlen(hostname
);
2532 if (der_ia5_string_cmp(&ds
->u
.ia5String
, &hn
) == 0)
2536 case choice_DirectoryString_utf8String
:
2537 if (strcasecmp(ds
->u
.utf8String
, hostname
) == 0)
2542 ret
= HX509_NAME_CONSTRAINT_ERROR
;
2547 if ((flags
& HX509_VHN_F_ALLOW_NO_MATCH
) == 0)
2548 ret
= HX509_NAME_CONSTRAINT_ERROR
;
2554 _hx509_set_cert_attribute(hx509_context context
,
2556 const heim_oid
*oid
,
2557 const heim_octet_string
*attr
)
2559 hx509_cert_attribute a
;
2562 if (hx509_cert_get_attribute(cert
, oid
) != NULL
)
2565 d
= realloc(cert
->attrs
.val
,
2566 sizeof(cert
->attrs
.val
[0]) * (cert
->attrs
.len
+ 1));
2568 hx509_clear_error_string(context
);
2571 cert
->attrs
.val
= d
;
2573 a
= malloc(sizeof(*a
));
2577 der_copy_octet_string(attr
, &a
->data
);
2578 der_copy_oid(oid
, &a
->oid
);
2580 cert
->attrs
.val
[cert
->attrs
.len
] = a
;
2587 * Get an external attribute for the certificate, examples are
2588 * friendly name and id.
2590 * @param cert hx509 certificate object to search
2591 * @param oid an oid to search for.
2593 * @return an hx509_cert_attribute, only valid as long as the
2594 * certificate is referenced.
2596 * @ingroup hx509_cert
2599 hx509_cert_attribute
2600 hx509_cert_get_attribute(hx509_cert cert
, const heim_oid
*oid
)
2603 for (i
= 0; i
< cert
->attrs
.len
; i
++)
2604 if (der_heim_oid_cmp(oid
, &cert
->attrs
.val
[i
]->oid
) == 0)
2605 return cert
->attrs
.val
[i
];
2610 * Set the friendly name on the certificate.
2612 * @param cert The certificate to set the friendly name on
2613 * @param name Friendly name.
2615 * @return An hx509 error code, see hx509_get_error_string().
2617 * @ingroup hx509_cert
2621 hx509_cert_set_friendly_name(hx509_cert cert
, const char *name
)
2623 if (cert
->friendlyname
)
2624 free(cert
->friendlyname
);
2625 cert
->friendlyname
= strdup(name
);
2626 if (cert
->friendlyname
== NULL
)
2632 * Get friendly name of the certificate.
2634 * @param cert cert to get the friendly name from.
2636 * @return an friendly name or NULL if there is. The friendly name is
2637 * only valid as long as the certificate is referenced.
2639 * @ingroup hx509_cert
2643 hx509_cert_get_friendly_name(hx509_cert cert
)
2645 hx509_cert_attribute a
;
2646 PKCS9_friendlyName n
;
2651 if (cert
->friendlyname
)
2652 return cert
->friendlyname
;
2654 a
= hx509_cert_get_attribute(cert
, &asn1_oid_id_pkcs_9_at_friendlyName
);
2658 ret
= hx509_cert_get_subject(cert
, &name
);
2661 ret
= hx509_name_to_string(name
, &cert
->friendlyname
);
2662 hx509_name_free(&name
);
2665 return cert
->friendlyname
;
2668 ret
= decode_PKCS9_friendlyName(a
->data
.data
, a
->data
.length
, &n
, &sz
);
2673 free_PKCS9_friendlyName(&n
);
2677 cert
->friendlyname
= malloc(n
.val
[0].length
+ 1);
2678 if (cert
->friendlyname
== NULL
) {
2679 free_PKCS9_friendlyName(&n
);
2683 for (i
= 0; i
< n
.val
[0].length
; i
++) {
2684 if (n
.val
[0].data
[i
] <= 0xff)
2685 cert
->friendlyname
[i
] = n
.val
[0].data
[i
] & 0xff;
2687 cert
->friendlyname
[i
] = 'X';
2689 cert
->friendlyname
[i
] = '\0';
2690 free_PKCS9_friendlyName(&n
);
2692 return cert
->friendlyname
;
2696 _hx509_query_clear(hx509_query
*q
)
2698 memset(q
, 0, sizeof(*q
));
2702 * Allocate an query controller. Free using hx509_query_free().
2704 * @param context A hx509 context.
2705 * @param q return pointer to a hx509_query.
2707 * @return An hx509 error code, see hx509_get_error_string().
2709 * @ingroup hx509_cert
2713 hx509_query_alloc(hx509_context context
, hx509_query
**q
)
2715 *q
= calloc(1, sizeof(**q
));
2723 * Set match options for the hx509 query controller.
2725 * @param q query controller.
2726 * @param option options to control the query controller.
2728 * @return An hx509 error code, see hx509_get_error_string().
2730 * @ingroup hx509_cert
2734 hx509_query_match_option(hx509_query
*q
, hx509_query_option option
)
2737 case HX509_QUERY_OPTION_PRIVATE_KEY
:
2738 q
->match
|= HX509_QUERY_PRIVATE_KEY
;
2740 case HX509_QUERY_OPTION_KU_ENCIPHERMENT
:
2741 q
->match
|= HX509_QUERY_KU_ENCIPHERMENT
;
2743 case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE
:
2744 q
->match
|= HX509_QUERY_KU_DIGITALSIGNATURE
;
2746 case HX509_QUERY_OPTION_KU_KEYCERTSIGN
:
2747 q
->match
|= HX509_QUERY_KU_KEYCERTSIGN
;
2749 case HX509_QUERY_OPTION_END
:
2756 * Set the issuer and serial number of match in the query
2757 * controller. The function make copies of the isser and serial number.
2759 * @param q a hx509 query controller
2760 * @param issuer issuer to search for
2761 * @param serialNumber the serialNumber of the issuer.
2763 * @return An hx509 error code, see hx509_get_error_string().
2765 * @ingroup hx509_cert
2769 hx509_query_match_issuer_serial(hx509_query
*q
,
2771 const heim_integer
*serialNumber
)
2775 der_free_heim_integer(q
->serial
);
2778 q
->serial
= malloc(sizeof(*q
->serial
));
2779 if (q
->serial
== NULL
)
2781 ret
= der_copy_heim_integer(serialNumber
, q
->serial
);
2787 if (q
->issuer_name
) {
2788 free_Name(q
->issuer_name
);
2789 free(q
->issuer_name
);
2791 q
->issuer_name
= malloc(sizeof(*q
->issuer_name
));
2792 if (q
->issuer_name
== NULL
)
2794 ret
= copy_Name(issuer
, q
->issuer_name
);
2796 free(q
->issuer_name
);
2797 q
->issuer_name
= NULL
;
2800 q
->match
|= HX509_QUERY_MATCH_SERIALNUMBER
|HX509_QUERY_MATCH_ISSUER_NAME
;
2805 * Set the query controller to match on a friendly name
2807 * @param q a hx509 query controller.
2808 * @param name a friendly name to match on
2810 * @return An hx509 error code, see hx509_get_error_string().
2812 * @ingroup hx509_cert
2816 hx509_query_match_friendly_name(hx509_query
*q
, const char *name
)
2818 if (q
->friendlyname
)
2819 free(q
->friendlyname
);
2820 q
->friendlyname
= strdup(name
);
2821 if (q
->friendlyname
== NULL
)
2823 q
->match
|= HX509_QUERY_MATCH_FRIENDLY_NAME
;
2828 * Set the query controller to require an one specific EKU (extended
2829 * key usage). Any previous EKU matching is overwitten. If NULL is
2830 * passed in as the eku, the EKU requirement is reset.
2832 * @param q a hx509 query controller.
2833 * @param eku an EKU to match on.
2835 * @return An hx509 error code, see hx509_get_error_string().
2837 * @ingroup hx509_cert
2841 hx509_query_match_eku(hx509_query
*q
, const heim_oid
*eku
)
2847 der_free_oid(q
->eku
);
2851 q
->match
&= ~HX509_QUERY_MATCH_EKU
;
2854 der_free_oid(q
->eku
);
2856 q
->eku
= calloc(1, sizeof(*q
->eku
));
2860 ret
= der_copy_oid(eku
, q
->eku
);
2866 q
->match
|= HX509_QUERY_MATCH_EKU
;
2872 hx509_query_match_expr(hx509_context context
, hx509_query
*q
, const char *expr
)
2875 _hx509_expr_free(q
->expr
);
2880 q
->match
&= ~HX509_QUERY_MATCH_EXPR
;
2882 q
->expr
= _hx509_expr_parse(expr
);
2884 q
->match
|= HX509_QUERY_MATCH_EXPR
;
2891 * Set the query controller to match using a specific match function.
2893 * @param q a hx509 query controller.
2894 * @param func function to use for matching, if the argument is NULL,
2895 * the match function is removed.
2896 * @param ctx context passed to the function.
2898 * @return An hx509 error code, see hx509_get_error_string().
2900 * @ingroup hx509_cert
2904 hx509_query_match_cmp_func(hx509_query
*q
,
2905 int (*func
)(hx509_context
, hx509_cert
, void *),
2909 q
->match
|= HX509_QUERY_MATCH_FUNCTION
;
2911 q
->match
&= ~HX509_QUERY_MATCH_FUNCTION
;
2913 q
->cmp_func_ctx
= ctx
;
2918 * Free the query controller.
2920 * @param context A hx509 context.
2921 * @param q a pointer to the query controller.
2923 * @ingroup hx509_cert
2927 hx509_query_free(hx509_context context
, hx509_query
*q
)
2933 der_free_heim_integer(q
->serial
);
2936 if (q
->issuer_name
) {
2937 free_Name(q
->issuer_name
);
2938 free(q
->issuer_name
);
2941 der_free_oid(q
->eku
);
2944 if (q
->friendlyname
)
2945 free(q
->friendlyname
);
2947 _hx509_expr_free(q
->expr
);
2949 memset(q
, 0, sizeof(*q
));
2954 _hx509_query_match_cert(hx509_context context
, const hx509_query
*q
, hx509_cert cert
)
2956 Certificate
*c
= _hx509_get_cert(cert
);
2959 _hx509_query_statistic(context
, 1, q
);
2961 if ((q
->match
& HX509_QUERY_FIND_ISSUER_CERT
) &&
2962 _hx509_cert_is_parent_cmp(q
->subject
, c
, 0) != 0)
2965 if ((q
->match
& HX509_QUERY_MATCH_CERTIFICATE
) &&
2966 _hx509_Certificate_cmp(q
->certificate
, c
) != 0)
2969 if ((q
->match
& HX509_QUERY_MATCH_SERIALNUMBER
)
2970 && der_heim_integer_cmp(&c
->tbsCertificate
.serialNumber
, q
->serial
) != 0)
2973 if (q
->match
& HX509_QUERY_MATCH_ISSUER_NAME
) {
2974 ret
= _hx509_name_cmp(&c
->tbsCertificate
.issuer
, q
->issuer_name
, &diff
);
2979 if (q
->match
& HX509_QUERY_MATCH_SUBJECT_NAME
) {
2980 ret
= _hx509_name_cmp(&c
->tbsCertificate
.subject
, q
->subject_name
, &diff
);
2985 if (q
->match
& HX509_QUERY_MATCH_SUBJECT_KEY_ID
) {
2986 SubjectKeyIdentifier si
;
2988 ret
= _hx509_find_extension_subject_key_id(c
, &si
);
2990 if (der_heim_octet_string_cmp(&si
, q
->subject_id
) != 0)
2992 free_SubjectKeyIdentifier(&si
);
2997 if ((q
->match
& HX509_QUERY_MATCH_ISSUER_ID
))
2999 if ((q
->match
& HX509_QUERY_PRIVATE_KEY
) &&
3000 _hx509_cert_private_key(cert
) == NULL
)
3005 if (q
->match
& HX509_QUERY_KU_DIGITALSIGNATURE
)
3007 if (q
->match
& HX509_QUERY_KU_NONREPUDIATION
)
3009 if (q
->match
& HX509_QUERY_KU_ENCIPHERMENT
)
3011 if (q
->match
& HX509_QUERY_KU_DATAENCIPHERMENT
)
3013 if (q
->match
& HX509_QUERY_KU_KEYAGREEMENT
)
3015 if (q
->match
& HX509_QUERY_KU_KEYCERTSIGN
)
3017 if (q
->match
& HX509_QUERY_KU_CRLSIGN
)
3019 if (ku
&& check_key_usage(context
, c
, ku
, TRUE
))
3022 if ((q
->match
& HX509_QUERY_ANCHOR
))
3025 if (q
->match
& HX509_QUERY_MATCH_LOCAL_KEY_ID
) {
3026 hx509_cert_attribute a
;
3028 a
= hx509_cert_get_attribute(cert
, &asn1_oid_id_pkcs_9_at_localKeyId
);
3031 if (der_heim_octet_string_cmp(&a
->data
, q
->local_key_id
) != 0)
3035 if (q
->match
& HX509_QUERY_NO_MATCH_PATH
) {
3038 for (i
= 0; i
< q
->path
->len
; i
++)
3039 if (hx509_cert_cmp(q
->path
->val
[i
], cert
) == 0)
3042 if (q
->match
& HX509_QUERY_MATCH_FRIENDLY_NAME
) {
3043 const char *name
= hx509_cert_get_friendly_name(cert
);
3046 if (strcasecmp(q
->friendlyname
, name
) != 0)
3049 if (q
->match
& HX509_QUERY_MATCH_FUNCTION
) {
3050 ret
= (*q
->cmp_func
)(context
, cert
, q
->cmp_func_ctx
);
3055 if (q
->match
& HX509_QUERY_MATCH_KEY_HASH_SHA1
) {
3056 heim_octet_string os
;
3058 os
.data
= c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.data
;
3060 c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.length
/ 8;
3062 ret
= _hx509_verify_signature(context
,
3064 hx509_signature_sha1(),
3071 if (q
->match
& HX509_QUERY_MATCH_TIME
) {
3073 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
3076 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notAfter
);
3081 /* If an EKU is required, check the cert for it. */
3082 if ((q
->match
& HX509_QUERY_MATCH_EKU
) &&
3083 hx509_cert_check_eku(context
, cert
, q
->eku
, 0))
3086 if ((q
->match
& HX509_QUERY_MATCH_EXPR
)) {
3087 hx509_env env
= NULL
;
3089 ret
= _hx509_cert_to_env(context
, cert
, &env
);
3093 ret
= _hx509_expr_eval(context
, env
, q
->expr
);
3094 hx509_env_free(&env
);
3099 if (q
->match
& ~HX509_QUERY_MASK
)
3106 * Set a statistic file for the query statistics.
3108 * @param context A hx509 context.
3109 * @param fn statistics file name
3111 * @ingroup hx509_cert
3115 hx509_query_statistic_file(hx509_context context
, const char *fn
)
3117 if (context
->querystat
)
3118 free(context
->querystat
);
3119 context
->querystat
= strdup(fn
);
3123 _hx509_query_statistic(hx509_context context
, int type
, const hx509_query
*q
)
3126 if (context
->querystat
== NULL
)
3128 f
= fopen(context
->querystat
, "a");
3132 fprintf(f
, "%d %d\n", type
, q
->match
);
3136 static const char *statname
[] = {
3138 "match serialnumber",
3139 "match issuer name",
3140 "match subject name",
3141 "match subject key id",
3145 "ku digitalsignature",
3148 "ku nonrepudiation",
3150 "ku dataencipherment",
3152 "match certificate",
3153 "match local key id",
3155 "match friendly name",
3157 "match key hash sha1",
3162 unsigned long stats
;
3168 stat_sort(const void *a
, const void *b
)
3170 const struct stat_el
*ae
= a
;
3171 const struct stat_el
*be
= b
;
3172 return be
->stats
- ae
->stats
;
3176 * Unparse the statistics file and print the result on a FILE descriptor.
3178 * @param context A hx509 context.
3179 * @param printtype tyep to print
3180 * @param out the FILE to write the data on.
3182 * @ingroup hx509_cert
3186 hx509_query_unparse_stats(hx509_context context
, int printtype
, FILE *out
)
3190 int type
, mask
, num
;
3192 unsigned long multiqueries
= 0, totalqueries
= 0;
3193 struct stat_el stats
[32];
3195 if (context
->querystat
== NULL
)
3197 f
= fopen(context
->querystat
, "r");
3199 fprintf(out
, "No statistic file %s: %s.\n",
3200 context
->querystat
, strerror(errno
));
3205 for (i
= 0; i
< sizeof(stats
)/sizeof(stats
[0]); i
++) {
3210 while (fscanf(f
, "%d %d\n", &type
, &mask
) == 2) {
3211 if (type
!= printtype
)
3214 while (mask
&& i
< sizeof(stats
)/sizeof(stats
[0])) {
3228 qsort(stats
, sizeof(stats
)/sizeof(stats
[0]), sizeof(stats
[0]), stat_sort
);
3232 errx(1, "out of memory");
3234 rtbl_set_separator (t
, " ");
3236 rtbl_add_column_by_id (t
, 0, "Name", 0);
3237 rtbl_add_column_by_id (t
, 1, "Counter", 0);
3240 for (i
= 0; i
< sizeof(stats
)/sizeof(stats
[0]); i
++) {
3243 if (stats
[i
].index
< sizeof(statname
)/sizeof(statname
[0]))
3244 rtbl_add_column_entry_by_id (t
, 0, statname
[stats
[i
].index
]);
3246 snprintf(str
, sizeof(str
), "%d", stats
[i
].index
);
3247 rtbl_add_column_entry_by_id (t
, 0, str
);
3249 snprintf(str
, sizeof(str
), "%lu", stats
[i
].stats
);
3250 rtbl_add_column_entry_by_id (t
, 1, str
);
3253 rtbl_format(t
, out
);
3256 fprintf(out
, "\nQueries: multi %lu total %lu\n",
3257 multiqueries
, totalqueries
);
3261 * Check the extended key usage on the hx509 certificate.
3263 * @param context A hx509 context.
3264 * @param cert A hx509 context.
3265 * @param eku the EKU to check for
3266 * @param allow_any_eku if the any EKU is set, allow that to be a
3269 * @return An hx509 error code, see hx509_get_error_string().
3271 * @ingroup hx509_cert
3275 hx509_cert_check_eku(hx509_context context
, hx509_cert cert
,
3276 const heim_oid
*eku
, int allow_any_eku
)
3282 ret
= find_extension_eku(_hx509_get_cert(cert
), &e
);
3284 hx509_clear_error_string(context
);
3288 for (i
= 0; i
< e
.len
; i
++) {
3289 if (der_heim_oid_cmp(eku
, &e
.val
[i
]) == 0) {
3290 free_ExtKeyUsage(&e
);
3293 if (allow_any_eku
) {
3295 if (der_heim_oid_cmp(id_any_eku
, &e
.val
[i
]) == 0) {
3296 free_ExtKeyUsage(&e
);
3302 free_ExtKeyUsage(&e
);
3303 hx509_clear_error_string(context
);
3304 return HX509_CERTIFICATE_MISSING_EKU
;
3308 _hx509_cert_get_keyusage(hx509_context context
,
3318 memset(ku
, 0, sizeof(*ku
));
3320 cert
= _hx509_get_cert(c
);
3322 if (_hx509_cert_get_version(cert
) < 3)
3325 e
= find_extension(cert
, &asn1_oid_id_x509_ce_keyUsage
, &i
);
3327 return HX509_KU_CERT_MISSING
;
3329 ret
= decode_KeyUsage(e
->extnValue
.data
, e
->extnValue
.length
, ku
, &size
);
3336 _hx509_cert_get_eku(hx509_context context
,
3342 memset(e
, 0, sizeof(*e
));
3344 ret
= find_extension_eku(_hx509_get_cert(cert
), e
);
3345 if (ret
&& ret
!= HX509_EXTENSION_NOT_FOUND
) {
3346 hx509_clear_error_string(context
);
3353 * Encodes the hx509 certificate as a DER encode binary.
3355 * @param context A hx509 context.
3356 * @param c the certificate to encode.
3357 * @param os the encode certificate, set to NULL, 0 on case of
3358 * error. Free the os->data with hx509_xfree().
3360 * @return An hx509 error code, see hx509_get_error_string().
3362 * @ingroup hx509_cert
3366 hx509_cert_binary(hx509_context context
, hx509_cert c
, heim_octet_string
*os
)
3374 ASN1_MALLOC_ENCODE(Certificate
, os
->data
, os
->length
,
3375 _hx509_get_cert(c
), &size
, ret
);
3381 if (os
->length
!= size
)
3382 _hx509_abort("internal ASN.1 encoder error");
3388 * Last to avoid lost __attribute__s due to #undef.
3391 #undef __attribute__
3392 #define __attribute__(X)
3395 _hx509_abort(const char *fmt
, ...)
3396 __attribute__ ((noreturn
, format (printf
, 1, 2)))
3408 * Free a data element allocated in the library.
3410 * @param ptr data to be freed.
3412 * @ingroup hx509_misc
3416 hx509_xfree(void *ptr
)
3426 _hx509_cert_to_env(hx509_context context
, hx509_cert cert
, hx509_env
*env
)
3432 hx509_env envcert
= NULL
;
3437 ret
= asprintf(&buf
, "%d", _hx509_cert_get_version(_hx509_get_cert(cert
)));
3440 ret
= hx509_env_add(context
, &envcert
, "version", buf
);
3446 ret
= hx509_cert_get_subject(cert
, &name
);
3450 ret
= hx509_name_to_string(name
, &buf
);
3452 hx509_name_free(&name
);
3456 ret
= hx509_env_add(context
, &envcert
, "subject", buf
);
3457 hx509_name_free(&name
);
3462 ret
= hx509_cert_get_issuer(cert
, &name
);
3466 ret
= hx509_name_to_string(name
, &buf
);
3467 hx509_name_free(&name
);
3471 ret
= hx509_env_add(context
, &envcert
, "issuer", buf
);
3478 ret
= _hx509_cert_get_eku(context
, cert
, &eku
);
3479 if (ret
== HX509_EXTENSION_NOT_FOUND
)
3485 hx509_env enveku
= NULL
;
3487 for (i
= 0; i
< eku
.len
; i
++) {
3489 ret
= der_print_heim_oid(&eku
.val
[i
], '.', &buf
);
3491 free_ExtKeyUsage(&eku
);
3492 hx509_env_free(&enveku
);
3495 ret
= hx509_env_add(context
, &enveku
, buf
, "oid-name-here");
3498 free_ExtKeyUsage(&eku
);
3499 hx509_env_free(&enveku
);
3503 free_ExtKeyUsage(&eku
);
3505 ret
= hx509_env_add_binding(context
, &envcert
, "eku", enveku
);
3507 hx509_env_free(&enveku
);
3513 Certificate
*c
= _hx509_get_cert(cert
);
3514 heim_octet_string os
, sig
;
3515 hx509_env envhash
= NULL
;
3517 os
.data
= c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.data
;
3519 c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.length
/ 8;
3521 ret
= _hx509_create_signature(context
,
3523 hx509_signature_sha1(),
3530 ret
= hex_encode(sig
.data
, sig
.length
, &buf
);
3531 der_free_octet_string(&sig
);
3534 hx509_set_error_string(context
, 0, ret
,
3539 ret
= hx509_env_add(context
, &envhash
, "sha1", buf
);
3544 ret
= hx509_env_add_binding(context
, &envcert
, "hash", envhash
);
3546 hx509_env_free(&envhash
);
3551 ret
= hx509_env_add_binding(context
, env
, "certificate", envcert
);
3558 hx509_env_free(&envcert
);
3563 * Print a simple representation of a certificate
3565 * @param context A hx509 context, can be NULL
3566 * @param cert certificate to print
3567 * @param out the stdio output stream, if NULL, stdout is used
3569 * @return An hx509 error code
3571 * @ingroup hx509_cert
3575 hx509_print_cert(hx509_context context
, hx509_cert cert
, FILE *out
)
3584 ret
= hx509_cert_get_issuer(cert
, &name
);
3587 hx509_name_to_string(name
, &str
);
3588 hx509_name_free(&name
);
3589 fprintf(out
, " issuer: \"%s\"\n", str
);
3592 ret
= hx509_cert_get_subject(cert
, &name
);
3595 hx509_name_to_string(name
, &str
);
3596 hx509_name_free(&name
);
3597 fprintf(out
, " subject: \"%s\"\n", str
);
3601 heim_integer serialNumber
;
3603 ret
= hx509_cert_get_serialnumber(cert
, &serialNumber
);
3606 ret
= der_print_hex_heim_integer(&serialNumber
, &str
);
3609 der_free_heim_integer(&serialNumber
);
3610 fprintf(out
, " serial: %s\n", str
);
3614 printf(" keyusage: ");
3615 ret
= hx509_cert_keyusage_print(context
, cert
, &str
);
3617 fprintf(out
, "%s\n", str
);