2 * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include "crypto-headers.h"
39 * @page page_cert The basic certificate
41 * The basic hx509 cerificate object in hx509 is hx509_cert. The
42 * hx509_cert object is representing one X509/PKIX certificate and
43 * associated attributes; like private key, friendly name, etc.
45 * A hx509_cert object is usully found via the keyset interfaces (@ref
46 * page_keyset), but its also possible to create a certificate
47 * directly from a parsed object with hx509_cert_init() and
48 * hx509_cert_init_data().
50 * See the library functions here: @ref hx509_cert
53 struct hx509_verify_ctx_data
{
54 hx509_certs trust_anchors
;
56 #define HX509_VERIFY_CTX_F_TIME_SET 1
57 #define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE 2
58 #define HX509_VERIFY_CTX_F_REQUIRE_RFC3280 4
59 #define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS 8
60 #define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS 16
61 #define HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK 32
63 unsigned int max_depth
;
64 #define HX509_VERIFY_MAX_DEPTH 30
65 hx509_revoke_ctx revoke_ctx
;
68 #define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280)
69 #define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS)
70 #define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0)
72 struct _hx509_cert_attrs
{
74 hx509_cert_attribute
*val
;
77 struct hx509_cert_data
{
81 hx509_private_key private_key
;
82 struct _hx509_cert_attrs attrs
;
84 _hx509_cert_release_func release
;
88 typedef struct hx509_name_constraints
{
91 } hx509_name_constraints
;
93 #define GeneralSubtrees_SET(g,var) \
94 (g)->len = (var)->len, (g)->val = (var)->val;
97 * Creates a hx509 context that most functions in the library
98 * uses. The context is only allowed to be used by one thread at each
99 * moment. Free the context with hx509_context_free().
101 * @param context Returns a pointer to new hx509 context.
103 * @return Returns an hx509 error code.
109 hx509_context_init(hx509_context
*context
)
111 *context
= calloc(1, sizeof(**context
));
112 if (*context
== NULL
)
115 _hx509_ks_null_register(*context
);
116 _hx509_ks_mem_register(*context
);
117 _hx509_ks_file_register(*context
);
118 _hx509_ks_pkcs12_register(*context
);
119 _hx509_ks_pkcs11_register(*context
);
120 _hx509_ks_dir_register(*context
);
121 _hx509_ks_keychain_register(*context
);
123 ENGINE_add_conf_module();
124 OpenSSL_add_all_algorithms();
126 (*context
)->ocsp_time_diff
= HX509_DEFAULT_OCSP_TIME_DIFF
;
128 initialize_hx_error_table_r(&(*context
)->et_list
);
129 initialize_asn1_error_table_r(&(*context
)->et_list
);
131 #ifdef HX509_DEFAULT_ANCHORS
132 (void)hx509_certs_init(*context
, HX509_DEFAULT_ANCHORS
, 0,
133 NULL
, &(*context
)->default_trust_anchors
);
140 * Selects if the hx509_revoke_verify() function is going to require
141 * the existans of a revokation method (OCSP, CRL) or not. Note that
142 * hx509_verify_path(), hx509_cms_verify_signed(), and other function
143 * call hx509_revoke_verify().
145 * @param context hx509 context to change the flag for.
146 * @param flag zero, revokation method required, non zero missing
147 * revokation method ok
149 * @ingroup hx509_verify
153 hx509_context_set_missing_revoke(hx509_context context
, int flag
)
156 context
->flags
|= HX509_CTX_VERIFY_MISSING_OK
;
158 context
->flags
&= ~HX509_CTX_VERIFY_MISSING_OK
;
162 * Free the context allocated by hx509_context_init().
164 * @param context context to be freed.
170 hx509_context_free(hx509_context
*context
)
172 hx509_clear_error_string(*context
);
173 if ((*context
)->ks_ops
) {
174 free((*context
)->ks_ops
);
175 (*context
)->ks_ops
= NULL
;
177 (*context
)->ks_num_ops
= 0;
178 free_error_table ((*context
)->et_list
);
179 if ((*context
)->querystat
)
180 free((*context
)->querystat
);
181 memset(*context
, 0, sizeof(**context
));
191 _hx509_get_cert(hx509_cert cert
)
201 _hx509_cert_get_version(const Certificate
*t
)
203 return t
->tbsCertificate
.version
? *t
->tbsCertificate
.version
+ 1 : 1;
207 * Allocate and init an hx509 certificate object from the decoded
210 * @param context A hx509 context.
214 * @return Returns an hx509 error code.
216 * @ingroup hx509_cert
220 hx509_cert_init(hx509_context context
, const Certificate
*c
, hx509_cert
*cert
)
224 *cert
= malloc(sizeof(**cert
));
228 (*cert
)->friendlyname
= NULL
;
229 (*cert
)->attrs
.len
= 0;
230 (*cert
)->attrs
.val
= NULL
;
231 (*cert
)->private_key
= NULL
;
232 (*cert
)->basename
= NULL
;
233 (*cert
)->release
= NULL
;
236 (*cert
)->data
= calloc(1, sizeof(*(*cert
)->data
));
237 if ((*cert
)->data
== NULL
) {
241 ret
= copy_Certificate(c
, (*cert
)->data
);
251 * Just like hx509_cert_init(), but instead of a decode certificate
252 * takes an pointer and length to a memory region that contains a
253 * DER/BER encoded certificate.
255 * If the memory region doesn't contain just the certificate and
256 * nothing more the function will fail with
257 * HX509_EXTRA_DATA_AFTER_STRUCTURE.
259 * @param context A hx509 context.
260 * @param ptr pointer to memory region containing encoded certificate.
261 * @param len length of memory region.
262 * @param cert a return pointer to a hx509 certificate object, will
263 * contain NULL on error.
265 * @return An hx509 error code, see hx509_get_error_string().
267 * @ingroup hx509_cert
271 hx509_cert_init_data(hx509_context context
,
280 ret
= decode_Certificate(ptr
, len
, &t
, &size
);
282 hx509_set_error_string(context
, 0, ret
, "Failed to decode certificate");
286 free_Certificate(&t
);
287 hx509_set_error_string(context
, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE
,
288 "Extra data after certificate");
289 return HX509_EXTRA_DATA_AFTER_STRUCTURE
;
292 ret
= hx509_cert_init(context
, &t
, cert
);
293 free_Certificate(&t
);
298 _hx509_cert_set_release(hx509_cert cert
,
299 _hx509_cert_release_func release
,
302 cert
->release
= release
;
307 /* Doesn't make a copy of `private_key'. */
310 _hx509_cert_assign_key(hx509_cert cert
, hx509_private_key private_key
)
312 if (cert
->private_key
)
313 _hx509_private_key_free(&cert
->private_key
);
314 cert
->private_key
= _hx509_private_key_ref(private_key
);
319 * Free reference to the hx509 certificate object, if the refcounter
320 * reaches 0, the object if freed. Its allowed to pass in NULL.
322 * @param cert the cert to free.
324 * @ingroup hx509_cert
328 hx509_cert_free(hx509_cert cert
)
336 _hx509_abort("cert refcount <= 0 on free");
341 (cert
->release
)(cert
, cert
->ctx
);
343 if (cert
->private_key
)
344 _hx509_private_key_free(&cert
->private_key
);
346 free_Certificate(cert
->data
);
349 for (i
= 0; i
< cert
->attrs
.len
; i
++) {
350 der_free_octet_string(&cert
->attrs
.val
[i
]->data
);
351 der_free_oid(&cert
->attrs
.val
[i
]->oid
);
352 free(cert
->attrs
.val
[i
]);
354 free(cert
->attrs
.val
);
355 free(cert
->friendlyname
);
357 hx509_name_free(&cert
->basename
);
358 memset(cert
, 0, sizeof(cert
));
363 * Add a reference to a hx509 certificate object.
365 * @param cert a pointer to an hx509 certificate object.
367 * @return the same object as is passed in.
369 * @ingroup hx509_cert
373 hx509_cert_ref(hx509_cert cert
)
378 _hx509_abort("cert refcount <= 0");
381 _hx509_abort("cert refcount == 0");
386 * Allocate an verification context that is used fo control the
387 * verification process.
389 * @param context A hx509 context.
390 * @param ctx returns a pointer to a hx509_verify_ctx object.
392 * @return An hx509 error code, see hx509_get_error_string().
394 * @ingroup hx509_verify
398 hx509_verify_init_ctx(hx509_context context
, hx509_verify_ctx
*ctx
)
402 c
= calloc(1, sizeof(*c
));
406 c
->max_depth
= HX509_VERIFY_MAX_DEPTH
;
414 * Free an hx509 verification context.
416 * @param ctx the context to be freed.
418 * @ingroup hx509_verify
422 hx509_verify_destroy_ctx(hx509_verify_ctx ctx
)
425 hx509_certs_free(&ctx
->trust_anchors
);
426 hx509_revoke_free(&ctx
->revoke_ctx
);
427 memset(ctx
, 0, sizeof(*ctx
));
433 * Set the trust anchors in the verification context, makes an
434 * reference to the keyset, so the consumer can free the keyset
435 * independent of the destruction of the verification context (ctx).
436 * If there already is a keyset attached, it's released.
438 * @param ctx a verification context
439 * @param set a keyset containing the trust anchors.
441 * @ingroup hx509_verify
445 hx509_verify_attach_anchors(hx509_verify_ctx ctx
, hx509_certs set
)
447 if (ctx
->trust_anchors
)
448 hx509_certs_free(&ctx
->trust_anchors
);
449 ctx
->trust_anchors
= hx509_certs_ref(set
);
453 * Attach an revocation context to the verfication context, , makes an
454 * reference to the revoke context, so the consumer can free the
455 * revoke context independent of the destruction of the verification
456 * context. If there is no revoke context, the verification process is
457 * NOT going to check any verification status.
459 * @param ctx a verification context.
460 * @param revoke_ctx a revoke context.
462 * @ingroup hx509_verify
466 hx509_verify_attach_revoke(hx509_verify_ctx ctx
, hx509_revoke_ctx revoke_ctx
)
469 hx509_revoke_free(&ctx
->revoke_ctx
);
470 ctx
->revoke_ctx
= _hx509_revoke_ref(revoke_ctx
);
474 * Set the clock time the the verification process is going to
475 * use. Used to check certificate in the past and future time. If not
476 * set the current time will be used.
478 * @param ctx a verification context.
479 * @param t the time the verifiation is using.
482 * @ingroup hx509_verify
486 hx509_verify_set_time(hx509_verify_ctx ctx
, time_t t
)
488 ctx
->flags
|= HX509_VERIFY_CTX_F_TIME_SET
;
493 _hx509_verify_get_time(hx509_verify_ctx ctx
)
495 return ctx
->time_now
;
499 * Set the maximum depth of the certificate chain that the path
500 * builder is going to try.
502 * @param ctx a verification context
503 * @param max_depth maxium depth of the certificate chain, include
506 * @ingroup hx509_verify
510 hx509_verify_set_max_depth(hx509_verify_ctx ctx
, unsigned int max_depth
)
512 ctx
->max_depth
= max_depth
;
516 * Allow or deny the use of proxy certificates
518 * @param ctx a verification context
519 * @param boolean if non zero, allow proxy certificates.
521 * @ingroup hx509_verify
525 hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx
, int boolean
)
528 ctx
->flags
|= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
;
530 ctx
->flags
&= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
;
534 * Select strict RFC3280 verification of certificiates. This means
535 * checking key usage on CA certificates, this will make version 1
536 * certificiates unuseable.
538 * @param ctx a verification context
539 * @param boolean if non zero, use strict verification.
541 * @ingroup hx509_verify
545 hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx
, int boolean
)
548 ctx
->flags
|= HX509_VERIFY_CTX_F_REQUIRE_RFC3280
;
550 ctx
->flags
&= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280
;
554 * Allow using the operating system builtin trust anchors if no other
555 * trust anchors are configured.
557 * @param ctx a verification context
558 * @param boolean if non zero, useing the operating systems builtin
562 * @return An hx509 error code, see hx509_get_error_string().
564 * @ingroup hx509_cert
568 hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx
, int boolean
)
571 ctx
->flags
&= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS
;
573 ctx
->flags
|= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS
;
577 hx509_verify_ctx_f_allow_best_before_signature_algs(hx509_context ctx
,
581 ctx
->flags
&= ~HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK
;
583 ctx
->flags
|= HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK
;
586 static const Extension
*
587 find_extension(const Certificate
*cert
, const heim_oid
*oid
, int *idx
)
589 const TBSCertificate
*c
= &cert
->tbsCertificate
;
591 if (c
->version
== NULL
|| *c
->version
< 2 || c
->extensions
== NULL
)
594 for (;*idx
< c
->extensions
->len
; (*idx
)++) {
595 if (der_heim_oid_cmp(&c
->extensions
->val
[*idx
].extnID
, oid
) == 0)
596 return &c
->extensions
->val
[(*idx
)++];
602 find_extension_auth_key_id(const Certificate
*subject
,
603 AuthorityKeyIdentifier
*ai
)
609 memset(ai
, 0, sizeof(*ai
));
611 e
= find_extension(subject
, &asn1_oid_id_x509_ce_authorityKeyIdentifier
, &i
);
613 return HX509_EXTENSION_NOT_FOUND
;
615 return decode_AuthorityKeyIdentifier(e
->extnValue
.data
,
621 _hx509_find_extension_subject_key_id(const Certificate
*issuer
,
622 SubjectKeyIdentifier
*si
)
628 memset(si
, 0, sizeof(*si
));
630 e
= find_extension(issuer
, &asn1_oid_id_x509_ce_subjectKeyIdentifier
, &i
);
632 return HX509_EXTENSION_NOT_FOUND
;
634 return decode_SubjectKeyIdentifier(e
->extnValue
.data
,
640 find_extension_name_constraints(const Certificate
*subject
,
647 memset(nc
, 0, sizeof(*nc
));
649 e
= find_extension(subject
, &asn1_oid_id_x509_ce_nameConstraints
, &i
);
651 return HX509_EXTENSION_NOT_FOUND
;
653 return decode_NameConstraints(e
->extnValue
.data
,
659 find_extension_subject_alt_name(const Certificate
*cert
, int *i
,
665 memset(sa
, 0, sizeof(*sa
));
667 e
= find_extension(cert
, &asn1_oid_id_x509_ce_subjectAltName
, i
);
669 return HX509_EXTENSION_NOT_FOUND
;
671 return decode_GeneralNames(e
->extnValue
.data
,
677 find_extension_eku(const Certificate
*cert
, ExtKeyUsage
*eku
)
683 memset(eku
, 0, sizeof(*eku
));
685 e
= find_extension(cert
, &asn1_oid_id_x509_ce_extKeyUsage
, &i
);
687 return HX509_EXTENSION_NOT_FOUND
;
689 return decode_ExtKeyUsage(e
->extnValue
.data
,
695 add_to_list(hx509_octet_string_list
*list
, const heim_octet_string
*entry
)
700 p
= realloc(list
->val
, (list
->len
+ 1) * sizeof(list
->val
[0]));
704 ret
= der_copy_octet_string(entry
, &list
->val
[list
->len
]);
712 * Free a list of octet strings returned by another hx509 library
715 * @param list list to be freed.
717 * @ingroup hx509_misc
721 hx509_free_octet_string_list(hx509_octet_string_list
*list
)
724 for (i
= 0; i
< list
->len
; i
++)
725 der_free_octet_string(&list
->val
[i
]);
732 * Return a list of subjectAltNames specified by oid in the
733 * certificate. On error the
735 * The returned list of octet string should be freed with
736 * hx509_free_octet_string_list().
738 * @param context A hx509 context.
739 * @param cert a hx509 certificate object.
740 * @param oid an oid to for SubjectAltName.
741 * @param list list of matching SubjectAltName.
743 * @return An hx509 error code, see hx509_get_error_string().
745 * @ingroup hx509_cert
749 hx509_cert_find_subjectAltName_otherName(hx509_context context
,
752 hx509_octet_string_list
*list
)
762 ret
= find_extension_subject_alt_name(_hx509_get_cert(cert
), &i
, &sa
);
764 if (ret
== HX509_EXTENSION_NOT_FOUND
) {
766 } else if (ret
!= 0) {
767 hx509_set_error_string(context
, 0, ret
, "Error searching for SAN");
768 hx509_free_octet_string_list(list
);
772 for (j
= 0; j
< sa
.len
; j
++) {
773 if (sa
.val
[j
].element
== choice_GeneralName_otherName
&&
774 der_heim_oid_cmp(&sa
.val
[j
].u
.otherName
.type_id
, oid
) == 0)
776 ret
= add_to_list(list
, &sa
.val
[j
].u
.otherName
.value
);
778 hx509_set_error_string(context
, 0, ret
,
779 "Error adding an exra SAN to "
781 hx509_free_octet_string_list(list
);
782 free_GeneralNames(&sa
);
787 free_GeneralNames(&sa
);
793 check_key_usage(hx509_context context
, const Certificate
*cert
,
794 unsigned flags
, int req_present
)
802 if (_hx509_cert_get_version(cert
) < 3)
805 e
= find_extension(cert
, &asn1_oid_id_x509_ce_keyUsage
, &i
);
808 hx509_set_error_string(context
, 0, HX509_KU_CERT_MISSING
,
809 "Required extension key "
810 "usage missing from certifiate");
811 return HX509_KU_CERT_MISSING
;
816 ret
= decode_KeyUsage(e
->extnValue
.data
, e
->extnValue
.length
, &ku
, &size
);
819 ku_flags
= KeyUsage2int(ku
);
820 if ((ku_flags
& flags
) != flags
) {
821 unsigned missing
= (~ku_flags
) & flags
;
822 char buf
[256], *name
;
824 unparse_flags(missing
, asn1_KeyUsage_units(), buf
, sizeof(buf
));
825 _hx509_unparse_Name(&cert
->tbsCertificate
.subject
, &name
);
826 hx509_set_error_string(context
, 0, HX509_KU_CERT_MISSING
,
827 "Key usage %s required but missing "
828 "from certifiate %s", buf
, name
);
830 return HX509_KU_CERT_MISSING
;
836 * Return 0 on matching key usage 'flags' for 'cert', otherwise return
837 * an error code. If 'req_present' the existance is required of the
838 * KeyUsage extension.
842 _hx509_check_key_usage(hx509_context context
, hx509_cert cert
,
843 unsigned flags
, int req_present
)
845 return check_key_usage(context
, _hx509_get_cert(cert
), flags
, req_present
);
848 enum certtype
{ PROXY_CERT
, EE_CERT
, CA_CERT
};
851 check_basic_constraints(hx509_context context
, const Certificate
*cert
,
852 enum certtype type
, int depth
)
859 if (_hx509_cert_get_version(cert
) < 3)
862 e
= find_extension(cert
, &asn1_oid_id_x509_ce_basicConstraints
, &i
);
870 ret
= _hx509_unparse_Name(&cert
->tbsCertificate
.subject
, &name
);
872 hx509_set_error_string(context
, 0, HX509_EXTENSION_NOT_FOUND
,
873 "basicConstraints missing from "
874 "CA certifiacte %s", name
);
876 return HX509_EXTENSION_NOT_FOUND
;
881 ret
= decode_BasicConstraints(e
->extnValue
.data
,
882 e
->extnValue
.length
, &bc
,
888 if (bc
.cA
!= NULL
&& *bc
.cA
)
889 ret
= HX509_PARENT_IS_CA
;
895 if (bc
.cA
== NULL
|| !*bc
.cA
)
896 ret
= HX509_PARENT_NOT_CA
;
897 else if (bc
.pathLenConstraint
)
898 if (depth
- 1 > *bc
.pathLenConstraint
)
899 ret
= HX509_CA_PATH_TOO_DEEP
;
902 free_BasicConstraints(&bc
);
907 _hx509_cert_is_parent_cmp(const Certificate
*subject
,
908 const Certificate
*issuer
,
909 int allow_self_signed
)
912 AuthorityKeyIdentifier ai
;
913 SubjectKeyIdentifier si
;
914 int ret_ai
, ret_si
, ret
;
916 ret
= _hx509_name_cmp(&issuer
->tbsCertificate
.subject
,
917 &subject
->tbsCertificate
.issuer
,
924 memset(&ai
, 0, sizeof(ai
));
925 memset(&si
, 0, sizeof(si
));
928 * Try to find AuthorityKeyIdentifier, if it's not present in the
929 * subject certificate nor the parent.
932 ret_ai
= find_extension_auth_key_id(subject
, &ai
);
933 if (ret_ai
&& ret_ai
!= HX509_EXTENSION_NOT_FOUND
)
935 ret_si
= _hx509_find_extension_subject_key_id(issuer
, &si
);
936 if (ret_si
&& ret_si
!= HX509_EXTENSION_NOT_FOUND
)
939 if (ret_si
&& ret_ai
)
944 if (allow_self_signed
) {
947 } else if (ai
.keyIdentifier
) {
953 if (ai
.keyIdentifier
== NULL
) {
956 if (ai
.authorityCertIssuer
== NULL
)
958 if (ai
.authorityCertSerialNumber
== NULL
)
961 diff
= der_heim_integer_cmp(ai
.authorityCertSerialNumber
,
962 &issuer
->tbsCertificate
.serialNumber
);
965 if (ai
.authorityCertIssuer
->len
!= 1)
967 if (ai
.authorityCertIssuer
->val
[0].element
!= choice_GeneralName_directoryName
)
971 ai
.authorityCertIssuer
->val
[0].u
.directoryName
.element
;
973 ai
.authorityCertIssuer
->val
[0].u
.directoryName
.u
.rdnSequence
;
975 ret
= _hx509_name_cmp(&issuer
->tbsCertificate
.subject
,
984 diff
= der_heim_octet_string_cmp(ai
.keyIdentifier
, &si
);
989 free_AuthorityKeyIdentifier(&ai
);
990 free_SubjectKeyIdentifier(&si
);
995 certificate_is_anchor(hx509_context context
,
996 hx509_certs trust_anchors
,
997 const hx509_cert cert
)
1003 if (trust_anchors
== NULL
)
1006 _hx509_query_clear(&q
);
1008 q
.match
= HX509_QUERY_MATCH_CERTIFICATE
;
1009 q
.certificate
= _hx509_get_cert(cert
);
1011 ret
= hx509_certs_find(context
, trust_anchors
, &q
, &c
);
1018 certificate_is_self_signed(hx509_context context
,
1019 const Certificate
*cert
,
1023 ret
= _hx509_name_cmp(&cert
->tbsCertificate
.subject
,
1024 &cert
->tbsCertificate
.issuer
, &diff
);
1025 *self_signed
= (diff
== 0);
1027 hx509_set_error_string(context
, 0, ret
,
1028 "Failed to check if self signed");
1030 ret
= _hx509_self_signed_valid(context
, &cert
->signatureAlgorithm
);
1036 * The subjectName is "null" when it's empty set of relative DBs.
1040 subject_null_p(const Certificate
*c
)
1042 return c
->tbsCertificate
.subject
.u
.rdnSequence
.len
== 0;
1047 find_parent(hx509_context context
,
1049 hx509_certs trust_anchors
,
1055 AuthorityKeyIdentifier ai
;
1060 memset(&ai
, 0, sizeof(ai
));
1062 _hx509_query_clear(&q
);
1064 if (!subject_null_p(current
->data
)) {
1065 q
.match
|= HX509_QUERY_FIND_ISSUER_CERT
;
1066 q
.subject
= _hx509_get_cert(current
);
1068 ret
= find_extension_auth_key_id(current
->data
, &ai
);
1070 hx509_set_error_string(context
, 0, HX509_CERTIFICATE_MALFORMED
,
1071 "Subjectless certificate missing AuthKeyID");
1072 return HX509_CERTIFICATE_MALFORMED
;
1075 if (ai
.keyIdentifier
== NULL
) {
1076 free_AuthorityKeyIdentifier(&ai
);
1077 hx509_set_error_string(context
, 0, HX509_CERTIFICATE_MALFORMED
,
1078 "Subjectless certificate missing keyIdentifier "
1079 "inside AuthKeyID");
1080 return HX509_CERTIFICATE_MALFORMED
;
1083 q
.subject_id
= ai
.keyIdentifier
;
1084 q
.match
= HX509_QUERY_MATCH_SUBJECT_KEY_ID
;
1088 q
.match
|= HX509_QUERY_NO_MATCH_PATH
;
1091 q
.timenow
= time_now
;
1092 q
.match
|= HX509_QUERY_MATCH_TIME
;
1094 ret
= hx509_certs_find(context
, pool
, &q
, parent
);
1096 free_AuthorityKeyIdentifier(&ai
);
1099 q
.match
&= ~HX509_QUERY_MATCH_TIME
;
1102 if (trust_anchors
) {
1103 ret
= hx509_certs_find(context
, trust_anchors
, &q
, parent
);
1105 free_AuthorityKeyIdentifier(&ai
);
1109 free_AuthorityKeyIdentifier(&ai
);
1115 ret
= hx509_cert_get_subject(current
, &name
);
1117 hx509_clear_error_string(context
);
1118 return HX509_ISSUER_NOT_FOUND
;
1120 ret
= hx509_name_to_string(name
, &str
);
1121 hx509_name_free(&name
);
1123 hx509_clear_error_string(context
);
1124 return HX509_ISSUER_NOT_FOUND
;
1127 hx509_set_error_string(context
, 0, HX509_ISSUER_NOT_FOUND
,
1128 "Failed to find issuer for "
1129 "certificate with subject: '%s'", str
);
1132 return HX509_ISSUER_NOT_FOUND
;
1140 is_proxy_cert(hx509_context context
,
1141 const Certificate
*cert
,
1142 ProxyCertInfo
*rinfo
)
1150 memset(rinfo
, 0, sizeof(*rinfo
));
1152 e
= find_extension(cert
, &asn1_oid_id_pkix_pe_proxyCertInfo
, &i
);
1154 hx509_clear_error_string(context
);
1155 return HX509_EXTENSION_NOT_FOUND
;
1158 ret
= decode_ProxyCertInfo(e
->extnValue
.data
,
1159 e
->extnValue
.length
,
1163 hx509_clear_error_string(context
);
1166 if (size
!= e
->extnValue
.length
) {
1167 free_ProxyCertInfo(&info
);
1168 hx509_clear_error_string(context
);
1169 return HX509_EXTRA_DATA_AFTER_STRUCTURE
;
1172 free_ProxyCertInfo(&info
);
1180 * Path operations are like MEMORY based keyset, but with exposed
1181 * internal so we can do easy searches.
1185 _hx509_path_append(hx509_context context
, hx509_path
*path
, hx509_cert cert
)
1188 val
= realloc(path
->val
, (path
->len
+ 1) * sizeof(path
->val
[0]));
1190 hx509_set_error_string(context
, 0, ENOMEM
, "out of memory");
1195 path
->val
[path
->len
] = hx509_cert_ref(cert
);
1202 _hx509_path_free(hx509_path
*path
)
1206 for (i
= 0; i
< path
->len
; i
++)
1207 hx509_cert_free(path
->val
[i
]);
1214 * Find path by looking up issuer for the top certificate and continue
1215 * until an anchor certificate is found or max limit is found. A
1216 * certificate never included twice in the path.
1218 * If the trust anchors are not given, calculate optimistic path, just
1219 * follow the chain upward until we no longer find a parent or we hit
1220 * the max path limit. In this case, a failure will always be returned
1221 * depending on what error condition is hit first.
1223 * The path includes a path from the top certificate to the anchor
1226 * The caller needs to free `path´ both on successful built path and
1231 _hx509_calculate_path(hx509_context context
,
1234 hx509_certs anchors
,
1235 unsigned int max_depth
,
1240 hx509_cert parent
, current
;
1244 max_depth
= HX509_VERIFY_MAX_DEPTH
;
1246 ret
= _hx509_path_append(context
, path
, cert
);
1250 current
= hx509_cert_ref(cert
);
1252 while (!certificate_is_anchor(context
, anchors
, current
)) {
1254 ret
= find_parent(context
, time_now
, anchors
, path
,
1255 pool
, current
, &parent
);
1256 hx509_cert_free(current
);
1260 ret
= _hx509_path_append(context
, path
, parent
);
1265 if (path
->len
> max_depth
) {
1266 hx509_cert_free(current
);
1267 hx509_set_error_string(context
, 0, HX509_PATH_TOO_LONG
,
1268 "Path too long while bulding "
1269 "certificate chain");
1270 return HX509_PATH_TOO_LONG
;
1274 if ((flags
& HX509_CALCULATE_PATH_NO_ANCHOR
) &&
1276 certificate_is_anchor(context
, anchors
, path
->val
[path
->len
- 1]))
1278 hx509_cert_free(path
->val
[path
->len
- 1]);
1282 hx509_cert_free(current
);
1287 _hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier
*p
,
1288 const AlgorithmIdentifier
*q
)
1291 diff
= der_heim_oid_cmp(&p
->algorithm
, &q
->algorithm
);
1294 if (p
->parameters
) {
1296 return heim_any_cmp(p
->parameters
,
1309 _hx509_Certificate_cmp(const Certificate
*p
, const Certificate
*q
)
1312 diff
= der_heim_bit_string_cmp(&p
->signatureValue
, &q
->signatureValue
);
1315 diff
= _hx509_AlgorithmIdentifier_cmp(&p
->signatureAlgorithm
,
1316 &q
->signatureAlgorithm
);
1319 diff
= der_heim_octet_string_cmp(&p
->tbsCertificate
._save
,
1320 &q
->tbsCertificate
._save
);
1325 * Compare to hx509 certificate object, useful for sorting.
1327 * @param p a hx509 certificate object.
1328 * @param q a hx509 certificate object.
1330 * @return 0 the objects are the same, returns > 0 is p is "larger"
1331 * then q, < 0 if p is "smaller" then q.
1333 * @ingroup hx509_cert
1337 hx509_cert_cmp(hx509_cert p
, hx509_cert q
)
1339 return _hx509_Certificate_cmp(p
->data
, q
->data
);
1343 * Return the name of the issuer of the hx509 certificate.
1345 * @param p a hx509 certificate object.
1346 * @param name a pointer to a hx509 name, should be freed by
1347 * hx509_name_free().
1349 * @return An hx509 error code, see hx509_get_error_string().
1351 * @ingroup hx509_cert
1355 hx509_cert_get_issuer(hx509_cert p
, hx509_name
*name
)
1357 return _hx509_name_from_Name(&p
->data
->tbsCertificate
.issuer
, name
);
1361 * Return the name of the subject of the hx509 certificate.
1363 * @param p a hx509 certificate object.
1364 * @param name a pointer to a hx509 name, should be freed by
1365 * hx509_name_free(). See also hx509_cert_get_base_subject().
1367 * @return An hx509 error code, see hx509_get_error_string().
1369 * @ingroup hx509_cert
1373 hx509_cert_get_subject(hx509_cert p
, hx509_name
*name
)
1375 return _hx509_name_from_Name(&p
->data
->tbsCertificate
.subject
, name
);
1379 * Return the name of the base subject of the hx509 certificate. If
1380 * the certiicate is a verified proxy certificate, the this function
1381 * return the base certificate (root of the proxy chain). If the proxy
1382 * certificate is not verified with the base certificate
1383 * HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned.
1385 * @param context a hx509 context.
1386 * @param c a hx509 certificate object.
1387 * @param name a pointer to a hx509 name, should be freed by
1388 * hx509_name_free(). See also hx509_cert_get_subject().
1390 * @return An hx509 error code, see hx509_get_error_string().
1392 * @ingroup hx509_cert
1396 hx509_cert_get_base_subject(hx509_context context
, hx509_cert c
,
1400 return hx509_name_copy(context
, c
->basename
, name
);
1401 if (is_proxy_cert(context
, c
->data
, NULL
) == 0) {
1402 int ret
= HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED
;
1403 hx509_set_error_string(context
, 0, ret
,
1404 "Proxy certificate have not been "
1405 "canonicalize yet, no base name");
1408 return _hx509_name_from_Name(&c
->data
->tbsCertificate
.subject
, name
);
1412 * Get serial number of the certificate.
1414 * @param p a hx509 certificate object.
1415 * @param i serial number, should be freed ith der_free_heim_integer().
1417 * @return An hx509 error code, see hx509_get_error_string().
1419 * @ingroup hx509_cert
1423 hx509_cert_get_serialnumber(hx509_cert p
, heim_integer
*i
)
1425 return der_copy_heim_integer(&p
->data
->tbsCertificate
.serialNumber
, i
);
1429 * Get notBefore time of the certificate.
1431 * @param p a hx509 certificate object.
1433 * @return return not before time
1435 * @ingroup hx509_cert
1439 hx509_cert_get_notBefore(hx509_cert p
)
1441 return _hx509_Time2time_t(&p
->data
->tbsCertificate
.validity
.notBefore
);
1445 * Get notAfter time of the certificate.
1447 * @param p a hx509 certificate object.
1449 * @return return not after time.
1451 * @ingroup hx509_cert
1455 hx509_cert_get_notAfter(hx509_cert p
)
1457 return _hx509_Time2time_t(&p
->data
->tbsCertificate
.validity
.notAfter
);
1461 * Get the SubjectPublicKeyInfo structure from the hx509 certificate.
1463 * @param context a hx509 context.
1464 * @param p a hx509 certificate object.
1465 * @param spki SubjectPublicKeyInfo, should be freed with
1466 * free_SubjectPublicKeyInfo().
1468 * @return An hx509 error code, see hx509_get_error_string().
1470 * @ingroup hx509_cert
1474 hx509_cert_get_SPKI(hx509_context context
, hx509_cert p
, SubjectPublicKeyInfo
*spki
)
1478 ret
= copy_SubjectPublicKeyInfo(&p
->data
->tbsCertificate
.subjectPublicKeyInfo
, spki
);
1480 hx509_set_error_string(context
, 0, ret
, "Failed to copy SPKI");
1485 * Get the AlgorithmIdentifier from the hx509 certificate.
1487 * @param context a hx509 context.
1488 * @param p a hx509 certificate object.
1489 * @param alg AlgorithmIdentifier, should be freed with
1490 * free_AlgorithmIdentifier(). The algorithmidentifier is
1491 * typicly rsaEncryption, or id-ecPublicKey, or some other
1492 * public key mechanism.
1494 * @return An hx509 error code, see hx509_get_error_string().
1496 * @ingroup hx509_cert
1500 hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context
,
1502 AlgorithmIdentifier
*alg
)
1506 ret
= copy_AlgorithmIdentifier(&p
->data
->tbsCertificate
.subjectPublicKeyInfo
.algorithm
, alg
);
1508 hx509_set_error_string(context
, 0, ret
,
1509 "Failed to copy SPKI AlgorithmIdentifier");
1514 get_x_unique_id(hx509_context context
, const char *name
,
1515 const heim_bit_string
*cert
, heim_bit_string
*subject
)
1520 ret
= HX509_EXTENSION_NOT_FOUND
;
1521 hx509_set_error_string(context
, 0, ret
, "%s unique id doesn't exists", name
);
1524 ret
= der_copy_bit_string(cert
, subject
);
1526 hx509_set_error_string(context
, 0, ret
, "malloc out of memory", name
);
1533 * Get a copy of the Issuer Unique ID
1535 * @param context a hx509_context
1536 * @param p a hx509 certificate
1537 * @param issuer the issuer id returned, free with der_free_bit_string()
1539 * @return An hx509 error code, see hx509_get_error_string(). The
1540 * error code HX509_EXTENSION_NOT_FOUND is returned if the certificate
1541 * doesn't have a issuerUniqueID
1543 * @ingroup hx509_cert
1547 hx509_cert_get_issuer_unique_id(hx509_context context
, hx509_cert p
, heim_bit_string
*issuer
)
1549 return get_x_unique_id(context
, "issuer", p
->data
->tbsCertificate
.issuerUniqueID
, issuer
);
1553 * Get a copy of the Subect Unique ID
1555 * @param context a hx509_context
1556 * @param p a hx509 certificate
1557 * @param subject the subject id returned, free with der_free_bit_string()
1559 * @return An hx509 error code, see hx509_get_error_string(). The
1560 * error code HX509_EXTENSION_NOT_FOUND is returned if the certificate
1561 * doesn't have a subjectUniqueID
1563 * @ingroup hx509_cert
1567 hx509_cert_get_subject_unique_id(hx509_context context
, hx509_cert p
, heim_bit_string
*subject
)
1569 return get_x_unique_id(context
, "subject", p
->data
->tbsCertificate
.subjectUniqueID
, subject
);
1574 _hx509_cert_private_key(hx509_cert p
)
1576 return p
->private_key
;
1580 hx509_cert_have_private_key(hx509_cert p
)
1582 return p
->private_key
? 1 : 0;
1587 _hx509_cert_private_key_exportable(hx509_cert p
)
1589 if (p
->private_key
== NULL
)
1591 return _hx509_private_key_exportable(p
->private_key
);
1595 _hx509_cert_private_decrypt(hx509_context context
,
1596 const heim_octet_string
*ciphertext
,
1597 const heim_oid
*encryption_oid
,
1599 heim_octet_string
*cleartext
)
1601 cleartext
->data
= NULL
;
1602 cleartext
->length
= 0;
1604 if (p
->private_key
== NULL
) {
1605 hx509_set_error_string(context
, 0, HX509_PRIVATE_KEY_MISSING
,
1606 "Private key missing");
1607 return HX509_PRIVATE_KEY_MISSING
;
1610 return _hx509_private_key_private_decrypt(context
,
1618 _hx509_cert_public_encrypt(hx509_context context
,
1619 const heim_octet_string
*cleartext
,
1621 heim_oid
*encryption_oid
,
1622 heim_octet_string
*ciphertext
)
1624 return _hx509_public_encrypt(context
,
1626 encryption_oid
, ciphertext
);
1634 _hx509_Time2time_t(const Time
*t
)
1636 switch(t
->element
) {
1637 case choice_Time_utcTime
:
1638 return t
->u
.utcTime
;
1639 case choice_Time_generalTime
:
1640 return t
->u
.generalTime
;
1650 init_name_constraints(hx509_name_constraints
*nc
)
1652 memset(nc
, 0, sizeof(*nc
));
1657 add_name_constraints(hx509_context context
, const Certificate
*c
, int not_ca
,
1658 hx509_name_constraints
*nc
)
1660 NameConstraints tnc
;
1663 ret
= find_extension_name_constraints(c
, &tnc
);
1664 if (ret
== HX509_EXTENSION_NOT_FOUND
)
1667 hx509_set_error_string(context
, 0, ret
, "Failed getting NameConstraints");
1669 } else if (not_ca
) {
1670 ret
= HX509_VERIFY_CONSTRAINTS
;
1671 hx509_set_error_string(context
, 0, ret
, "Not a CA and "
1672 "have NameConstraints");
1674 NameConstraints
*val
;
1675 val
= realloc(nc
->val
, sizeof(nc
->val
[0]) * (nc
->len
+ 1));
1677 hx509_clear_error_string(context
);
1682 ret
= copy_NameConstraints(&tnc
, &nc
->val
[nc
->len
]);
1684 hx509_clear_error_string(context
);
1690 free_NameConstraints(&tnc
);
1695 match_RDN(const RelativeDistinguishedName
*c
,
1696 const RelativeDistinguishedName
*n
)
1700 if (c
->len
!= n
->len
)
1701 return HX509_NAME_CONSTRAINT_ERROR
;
1703 for (i
= 0; i
< n
->len
; i
++) {
1706 if (der_heim_oid_cmp(&c
->val
[i
].type
, &n
->val
[i
].type
) != 0)
1707 return HX509_NAME_CONSTRAINT_ERROR
;
1708 ret
= _hx509_name_ds_cmp(&c
->val
[i
].value
, &n
->val
[i
].value
, &diff
);
1712 return HX509_NAME_CONSTRAINT_ERROR
;
1718 match_X501Name(const Name
*c
, const Name
*n
)
1722 if (c
->element
!= choice_Name_rdnSequence
1723 || n
->element
!= choice_Name_rdnSequence
)
1725 if (c
->u
.rdnSequence
.len
> n
->u
.rdnSequence
.len
)
1726 return HX509_NAME_CONSTRAINT_ERROR
;
1727 for (i
= 0; i
< c
->u
.rdnSequence
.len
; i
++) {
1728 ret
= match_RDN(&c
->u
.rdnSequence
.val
[i
], &n
->u
.rdnSequence
.val
[i
]);
1737 match_general_name(const GeneralName
*c
, const GeneralName
*n
, int *match
)
1740 * Name constraints only apply to the same name type, see RFC3280,
1743 assert(c
->element
== n
->element
);
1745 switch(c
->element
) {
1746 case choice_GeneralName_otherName
:
1747 if (der_heim_oid_cmp(&c
->u
.otherName
.type_id
,
1748 &n
->u
.otherName
.type_id
) != 0)
1749 return HX509_NAME_CONSTRAINT_ERROR
;
1750 if (heim_any_cmp(&c
->u
.otherName
.value
,
1751 &n
->u
.otherName
.value
) != 0)
1752 return HX509_NAME_CONSTRAINT_ERROR
;
1755 case choice_GeneralName_rfc822Name
: {
1758 s
= memchr(c
->u
.rfc822Name
.data
, '@', c
->u
.rfc822Name
.length
);
1760 if (der_printable_string_cmp(&c
->u
.rfc822Name
, &n
->u
.rfc822Name
) != 0)
1761 return HX509_NAME_CONSTRAINT_ERROR
;
1763 s
= memchr(n
->u
.rfc822Name
.data
, '@', n
->u
.rfc822Name
.length
);
1765 return HX509_NAME_CONSTRAINT_ERROR
;
1766 len1
= c
->u
.rfc822Name
.length
;
1767 len2
= n
->u
.rfc822Name
.length
-
1768 (s
- ((char *)n
->u
.rfc822Name
.data
));
1770 return HX509_NAME_CONSTRAINT_ERROR
;
1771 if (memcmp(s
+ 1 + len2
- len1
, c
->u
.rfc822Name
.data
, len1
) != 0)
1772 return HX509_NAME_CONSTRAINT_ERROR
;
1773 if (len1
< len2
&& s
[len2
- len1
+ 1] != '.')
1774 return HX509_NAME_CONSTRAINT_ERROR
;
1779 case choice_GeneralName_dNSName
: {
1783 lenc
= c
->u
.dNSName
.length
;
1784 lenn
= n
->u
.dNSName
.length
;
1786 return HX509_NAME_CONSTRAINT_ERROR
;
1787 ptr
= n
->u
.dNSName
.data
;
1788 if (memcmp(&ptr
[lenn
- lenc
], c
->u
.dNSName
.data
, lenc
) != 0)
1789 return HX509_NAME_CONSTRAINT_ERROR
;
1790 if (lenn
!= lenc
&& ptr
[lenn
- lenc
- 1] != '.')
1791 return HX509_NAME_CONSTRAINT_ERROR
;
1795 case choice_GeneralName_directoryName
: {
1796 Name c_name
, n_name
;
1799 c_name
._save
.data
= NULL
;
1800 c_name
._save
.length
= 0;
1801 c_name
.element
= c
->u
.directoryName
.element
;
1802 c_name
.u
.rdnSequence
= c
->u
.directoryName
.u
.rdnSequence
;
1804 n_name
._save
.data
= NULL
;
1805 n_name
._save
.length
= 0;
1806 n_name
.element
= n
->u
.directoryName
.element
;
1807 n_name
.u
.rdnSequence
= n
->u
.directoryName
.u
.rdnSequence
;
1809 ret
= match_X501Name(&c_name
, &n_name
);
1814 case choice_GeneralName_uniformResourceIdentifier
:
1815 case choice_GeneralName_iPAddress
:
1816 case choice_GeneralName_registeredID
:
1818 return HX509_NAME_CONSTRAINT_ERROR
;
1823 match_alt_name(const GeneralName
*n
, const Certificate
*c
,
1824 int *same
, int *match
)
1831 ret
= find_extension_subject_alt_name(c
, &i
, &sa
);
1832 if (ret
== HX509_EXTENSION_NOT_FOUND
) {
1835 } else if (ret
!= 0)
1838 for (j
= 0; j
< sa
.len
; j
++) {
1839 if (n
->element
== sa
.val
[j
].element
) {
1841 ret
= match_general_name(n
, &sa
.val
[j
], match
);
1844 free_GeneralNames(&sa
);
1851 match_tree(const GeneralSubtrees
*t
, const Certificate
*c
, int *match
)
1853 int name
, alt_name
, same
;
1857 name
= alt_name
= same
= *match
= 0;
1858 for (i
= 0; i
< t
->len
; i
++) {
1859 if (t
->val
[i
].minimum
&& t
->val
[i
].maximum
)
1863 * If the constraint apply to directoryNames, test is with
1864 * subjectName of the certificate if the certificate have a
1865 * non-null (empty) subjectName.
1868 if (t
->val
[i
].base
.element
== choice_GeneralName_directoryName
1869 && !subject_null_p(c
))
1871 GeneralName certname
;
1873 memset(&certname
, 0, sizeof(certname
));
1874 certname
.element
= choice_GeneralName_directoryName
;
1875 certname
.u
.directoryName
.element
=
1876 c
->tbsCertificate
.subject
.element
;
1877 certname
.u
.directoryName
.u
.rdnSequence
=
1878 c
->tbsCertificate
.subject
.u
.rdnSequence
;
1880 ret
= match_general_name(&t
->val
[i
].base
, &certname
, &name
);
1883 /* Handle subjectAltNames, this is icky since they
1884 * restrictions only apply if the subjectAltName is of the
1885 * same type. So if there have been a match of type, require
1886 * altname to be set.
1888 ret
= match_alt_name(&t
->val
[i
].base
, c
, &same
, &alt_name
);
1890 if (name
&& (!same
|| alt_name
))
1896 check_name_constraints(hx509_context context
,
1897 const hx509_name_constraints
*nc
,
1898 const Certificate
*c
)
1903 for (i
= 0 ; i
< nc
->len
; i
++) {
1906 if (nc
->val
[i
].permittedSubtrees
) {
1907 GeneralSubtrees_SET(&gs
, nc
->val
[i
].permittedSubtrees
);
1908 ret
= match_tree(&gs
, c
, &match
);
1910 hx509_clear_error_string(context
);
1913 /* allow null subjectNames, they wont matches anything */
1914 if (match
== 0 && !subject_null_p(c
)) {
1915 hx509_set_error_string(context
, 0, HX509_VERIFY_CONSTRAINTS
,
1916 "Error verify constraints, "
1917 "certificate didn't match any "
1918 "permitted subtree");
1919 return HX509_VERIFY_CONSTRAINTS
;
1922 if (nc
->val
[i
].excludedSubtrees
) {
1923 GeneralSubtrees_SET(&gs
, nc
->val
[i
].excludedSubtrees
);
1924 ret
= match_tree(&gs
, c
, &match
);
1926 hx509_clear_error_string(context
);
1930 hx509_set_error_string(context
, 0, HX509_VERIFY_CONSTRAINTS
,
1931 "Error verify constraints, "
1932 "certificate included in excluded "
1934 return HX509_VERIFY_CONSTRAINTS
;
1942 free_name_constraints(hx509_name_constraints
*nc
)
1946 for (i
= 0 ; i
< nc
->len
; i
++)
1947 free_NameConstraints(&nc
->val
[i
]);
1952 * Build and verify the path for the certificate to the trust anchor
1953 * specified in the verify context. The path is constructed from the
1954 * certificate, the pool and the trust anchors.
1956 * @param context A hx509 context.
1957 * @param ctx A hx509 verification context.
1958 * @param cert the certificate to build the path from.
1959 * @param pool A keyset of certificates to build the chain from.
1961 * @return An hx509 error code, see hx509_get_error_string().
1963 * @ingroup hx509_verify
1967 hx509_verify_path(hx509_context context
,
1968 hx509_verify_ctx ctx
,
1972 hx509_name_constraints nc
;
1974 int ret
, i
, proxy_cert_depth
, selfsigned_depth
, diff
;
1977 hx509_certs anchors
= NULL
;
1979 memset(&proxy_issuer
, 0, sizeof(proxy_issuer
));
1981 ret
= init_name_constraints(&nc
);
1988 if ((ctx
->flags
& HX509_VERIFY_CTX_F_TIME_SET
) == 0)
1989 ctx
->time_now
= time(NULL
);
1994 if (ctx
->trust_anchors
)
1995 anchors
= hx509_certs_ref(ctx
->trust_anchors
);
1996 else if (context
->default_trust_anchors
&& ALLOW_DEF_TA(ctx
))
1997 anchors
= hx509_certs_ref(context
->default_trust_anchors
);
1999 ret
= hx509_certs_init(context
, "MEMORY:no-TA", 0, NULL
, &anchors
);
2005 * Calculate the path from the certificate user presented to the
2008 ret
= _hx509_calculate_path(context
, 0, ctx
->time_now
,
2009 anchors
, ctx
->max_depth
,
2015 * Check CA and proxy certificate chain from the top of the
2016 * certificate chain. Also check certificate is valid with respect
2017 * to the current time.
2021 proxy_cert_depth
= 0;
2022 selfsigned_depth
= 0;
2024 if (ctx
->flags
& HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
)
2029 for (i
= 0; i
< path
.len
; i
++) {
2033 c
= _hx509_get_cert(path
.val
[i
]);
2036 * Lets do some basic check on issuer like
2037 * keyUsage.keyCertSign and basicConstraints.cA bit depending
2038 * on what type of certificate this is.
2044 /* XXX make constants for keyusage */
2045 ret
= check_key_usage(context
, c
, 1 << 5,
2046 REQUIRE_RFC3280(ctx
) ? TRUE
: FALSE
);
2048 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
2049 "Key usage missing from CA certificate");
2053 /* self signed cert doesn't add to path length */
2054 if (i
+ 1 != path
.len
) {
2057 ret
= certificate_is_self_signed(context
, c
, &selfsigned
);
2068 if (is_proxy_cert(context
, c
, &info
) == 0) {
2071 if (info
.pCPathLenConstraint
!= NULL
&&
2072 *info
.pCPathLenConstraint
< i
)
2074 free_ProxyCertInfo(&info
);
2075 ret
= HX509_PATH_TOO_LONG
;
2076 hx509_set_error_string(context
, 0, ret
,
2077 "Proxy certificate chain "
2078 "longer then allowed");
2081 /* XXX MUST check info.proxyPolicy */
2082 free_ProxyCertInfo(&info
);
2085 if (find_extension(c
, &asn1_oid_id_x509_ce_subjectAltName
, &j
)) {
2086 ret
= HX509_PROXY_CERT_INVALID
;
2087 hx509_set_error_string(context
, 0, ret
,
2088 "Proxy certificate have explicity "
2089 "forbidden subjectAltName");
2094 if (find_extension(c
, &asn1_oid_id_x509_ce_issuerAltName
, &j
)) {
2095 ret
= HX509_PROXY_CERT_INVALID
;
2096 hx509_set_error_string(context
, 0, ret
,
2097 "Proxy certificate have explicity "
2098 "forbidden issuerAltName");
2103 * The subject name of the proxy certificate should be
2104 * CN=XXX,<proxy issuer>, prune of CN and check if its
2105 * the same over the whole chain of proxy certs and
2106 * then check with the EE cert when we get to it.
2109 if (proxy_cert_depth
) {
2110 ret
= _hx509_name_cmp(&proxy_issuer
, &c
->tbsCertificate
.subject
, &diff
);
2112 hx509_set_error_string(context
, 0, ret
, "Out of memory");
2116 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2117 hx509_set_error_string(context
, 0, ret
,
2118 "Base proxy name not right");
2123 free_Name(&proxy_issuer
);
2125 ret
= copy_Name(&c
->tbsCertificate
.subject
, &proxy_issuer
);
2127 hx509_clear_error_string(context
);
2131 j
= proxy_issuer
.u
.rdnSequence
.len
;
2132 if (proxy_issuer
.u
.rdnSequence
.len
< 2
2133 || proxy_issuer
.u
.rdnSequence
.val
[j
- 1].len
> 1
2134 || der_heim_oid_cmp(&proxy_issuer
.u
.rdnSequence
.val
[j
- 1].val
[0].type
,
2135 &asn1_oid_id_at_commonName
))
2137 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2138 hx509_set_error_string(context
, 0, ret
,
2139 "Proxy name too short or "
2140 "does not have Common name "
2145 free_RelativeDistinguishedName(&proxy_issuer
.u
.rdnSequence
.val
[j
- 1]);
2146 proxy_issuer
.u
.rdnSequence
.len
-= 1;
2148 ret
= _hx509_name_cmp(&proxy_issuer
, &c
->tbsCertificate
.issuer
, &diff
);
2150 hx509_set_error_string(context
, 0, ret
, "Out of memory");
2154 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2155 hx509_set_error_string(context
, 0, ret
,
2156 "Proxy issuer name not as expected");
2163 * Now we are done with the proxy certificates, this
2164 * cert was an EE cert and we we will fall though to
2165 * EE checking below.
2173 * If there where any proxy certificates in the chain
2174 * (proxy_cert_depth > 0), check that the proxy issuer
2175 * matched proxy certificates "base" subject.
2177 if (proxy_cert_depth
) {
2179 ret
= _hx509_name_cmp(&proxy_issuer
,
2180 &c
->tbsCertificate
.subject
, &diff
);
2182 hx509_set_error_string(context
, 0, ret
, "out of memory");
2186 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2187 hx509_clear_error_string(context
);
2191 hx509_name_free(&cert
->basename
);
2193 ret
= _hx509_name_from_Name(&proxy_issuer
, &cert
->basename
);
2195 hx509_clear_error_string(context
);
2203 ret
= check_basic_constraints(context
, c
, type
,
2204 i
- proxy_cert_depth
- selfsigned_depth
);
2209 * Don't check the trust anchors expiration time since they
2210 * are transported out of band, from RFC3820.
2212 if (i
+ 1 != path
.len
|| CHECK_TA(ctx
)) {
2214 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
2215 if (t
> ctx
->time_now
) {
2216 ret
= HX509_CERT_USED_BEFORE_TIME
;
2217 hx509_clear_error_string(context
);
2220 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notAfter
);
2221 if (t
< ctx
->time_now
) {
2222 ret
= HX509_CERT_USED_AFTER_TIME
;
2223 hx509_clear_error_string(context
);
2228 if (type
== EE_CERT
)
2230 else if (type
== PROXY_CERT
)
2235 * Verify constraints, do this backward so path constraints are
2236 * checked in the right order.
2239 for (ret
= 0, i
= path
.len
- 1; i
>= 0; i
--) {
2243 c
= _hx509_get_cert(path
.val
[i
]);
2245 ret
= certificate_is_self_signed(context
, c
, &selfsigned
);
2249 /* verify name constraints, not for selfsigned and anchor */
2250 if (!selfsigned
|| i
+ 1 != path
.len
) {
2251 ret
= check_name_constraints(context
, &nc
, c
);
2256 ret
= add_name_constraints(context
, c
, i
== 0, &nc
);
2260 /* XXX verify all other silly constraints */
2265 * Verify that no certificates has been revoked.
2268 if (ctx
->revoke_ctx
) {
2271 ret
= hx509_certs_init(context
, "MEMORY:revoke-certs", 0,
2276 for (i
= 0; i
< path
.len
; i
++) {
2277 ret
= hx509_certs_add(context
, certs
, path
.val
[i
]);
2279 hx509_certs_free(&certs
);
2283 ret
= hx509_certs_merge(context
, certs
, pool
);
2285 hx509_certs_free(&certs
);
2289 for (i
= 0; i
< path
.len
- 1; i
++) {
2290 int parent
= (i
< path
.len
- 1) ? i
+ 1 : i
;
2292 ret
= hx509_revoke_verify(context
,
2299 hx509_certs_free(&certs
);
2303 hx509_certs_free(&certs
);
2307 * Verify signatures, do this backward so public key working
2308 * parameter is passed up from the anchor up though the chain.
2311 for (i
= path
.len
- 1; i
>= 0; i
--) {
2315 c
= _hx509_get_cert(path
.val
[i
]);
2317 /* is last in chain (trust anchor) */
2318 if (i
+ 1 == path
.len
) {
2321 signer
= path
.val
[i
];
2323 ret
= certificate_is_self_signed(context
, signer
->data
, &selfsigned
);
2327 /* if trust anchor is not self signed, don't check sig */
2331 /* take next certificate in chain */
2332 signer
= path
.val
[i
+ 1];
2335 /* verify signatureValue */
2336 ret
= _hx509_verify_signature_bitstring(context
,
2338 &c
->signatureAlgorithm
,
2339 &c
->tbsCertificate
._save
,
2340 &c
->signatureValue
);
2342 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
2343 "Failed to verify signature of certificate");
2347 * Verify that the sigature algorithm "best-before" date is
2348 * before the creation date of the certificate, do this for
2349 * trust anchors too, since any trust anchor that is created
2350 * after a algorithm is known to be bad deserved to be invalid.
2352 * Skip the leaf certificate for now...
2355 if (i
!= 0 && (ctx
->flags
& HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK
) == 0) {
2357 _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
2358 ret
= _hx509_signature_best_before(context
,
2359 &c
->signatureAlgorithm
,
2367 hx509_certs_free(&anchors
);
2368 free_Name(&proxy_issuer
);
2369 free_name_constraints(&nc
);
2370 _hx509_path_free(&path
);
2376 * Verify a signature made using the private key of an certificate.
2378 * @param context A hx509 context.
2379 * @param signer the certificate that made the signature.
2380 * @param alg algorthm that was used to sign the data.
2381 * @param data the data that was signed.
2382 * @param sig the sigature to verify.
2384 * @return An hx509 error code, see hx509_get_error_string().
2386 * @ingroup hx509_crypto
2390 hx509_verify_signature(hx509_context context
,
2391 const hx509_cert signer
,
2392 const AlgorithmIdentifier
*alg
,
2393 const heim_octet_string
*data
,
2394 const heim_octet_string
*sig
)
2396 return _hx509_verify_signature(context
, signer
, alg
, data
, sig
);
2400 _hx509_verify_signature_bitstring(hx509_context context
,
2401 const hx509_cert signer
,
2402 const AlgorithmIdentifier
*alg
,
2403 const heim_octet_string
*data
,
2404 const heim_bit_string
*sig
)
2406 heim_octet_string os
;
2408 if (sig
->length
& 7) {
2409 hx509_set_error_string(context
, 0, HX509_CRYPTO_SIG_INVALID_FORMAT
,
2410 "signature not multiple of 8 bits");
2411 return HX509_CRYPTO_SIG_INVALID_FORMAT
;
2414 os
.data
= sig
->data
;
2415 os
.length
= sig
->length
/ 8;
2417 return _hx509_verify_signature(context
, signer
, alg
, data
, &os
);
2423 * Verify that the certificate is allowed to be used for the hostname
2426 * @param context A hx509 context.
2427 * @param cert the certificate to match with
2428 * @param flags Flags to modify the behavior:
2429 * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok
2430 * @param type type of hostname:
2431 * - HX509_HN_HOSTNAME for plain hostname.
2432 * - HX509_HN_DNSSRV for DNS SRV names.
2433 * @param hostname the hostname to check
2434 * @param sa address of the host
2435 * @param sa_size length of address
2437 * @return An hx509 error code, see hx509_get_error_string().
2439 * @ingroup hx509_cert
2443 hx509_verify_hostname(hx509_context context
,
2444 const hx509_cert cert
,
2446 hx509_hostname_type type
,
2447 const char *hostname
,
2448 const struct sockaddr
*sa
,
2449 /* XXX krb5_socklen_t */ int sa_size
)
2455 if (sa
&& sa_size
<= 0)
2458 memset(&san
, 0, sizeof(san
));
2462 ret
= find_extension_subject_alt_name(cert
->data
, &i
, &san
);
2463 if (ret
== HX509_EXTENSION_NOT_FOUND
)
2466 return HX509_PARSING_NAME_FAILED
;
2468 for (j
= 0; j
< san
.len
; j
++) {
2469 switch (san
.val
[j
].element
) {
2470 case choice_GeneralName_dNSName
: {
2471 heim_printable_string hn
;
2472 hn
.data
= rk_UNCONST(hostname
);
2473 hn
.length
= strlen(hostname
);
2475 if (der_printable_string_cmp(&san
.val
[j
].u
.dNSName
, &hn
) == 0) {
2476 free_GeneralNames(&san
);
2485 free_GeneralNames(&san
);
2488 name
= &cert
->data
->tbsCertificate
.subject
;
2490 /* Find first CN= in the name, and try to match the hostname on that */
2491 for (ret
= 0, i
= name
->u
.rdnSequence
.len
- 1; ret
== 0 && i
>= 0; i
--) {
2492 for (j
= 0; ret
== 0 && j
< name
->u
.rdnSequence
.val
[i
].len
; j
++) {
2493 AttributeTypeAndValue
*n
= &name
->u
.rdnSequence
.val
[i
].val
[j
];
2495 if (der_heim_oid_cmp(&n
->type
, &asn1_oid_id_at_commonName
) == 0) {
2496 DirectoryString
*ds
= &n
->value
;
2497 switch (ds
->element
) {
2498 case choice_DirectoryString_printableString
: {
2499 heim_printable_string hn
;
2500 hn
.data
= rk_UNCONST(hostname
);
2501 hn
.length
= strlen(hostname
);
2503 if (der_printable_string_cmp(&ds
->u
.printableString
, &hn
) == 0)
2507 case choice_DirectoryString_ia5String
: {
2509 hn
.data
= rk_UNCONST(hostname
);
2510 hn
.length
= strlen(hostname
);
2512 if (der_ia5_string_cmp(&ds
->u
.ia5String
, &hn
) == 0)
2516 case choice_DirectoryString_utf8String
:
2517 if (strcasecmp(ds
->u
.utf8String
, hostname
) == 0)
2522 ret
= HX509_NAME_CONSTRAINT_ERROR
;
2527 if ((flags
& HX509_VHN_F_ALLOW_NO_MATCH
) == 0)
2528 ret
= HX509_NAME_CONSTRAINT_ERROR
;
2534 _hx509_set_cert_attribute(hx509_context context
,
2536 const heim_oid
*oid
,
2537 const heim_octet_string
*attr
)
2539 hx509_cert_attribute a
;
2542 if (hx509_cert_get_attribute(cert
, oid
) != NULL
)
2545 d
= realloc(cert
->attrs
.val
,
2546 sizeof(cert
->attrs
.val
[0]) * (cert
->attrs
.len
+ 1));
2548 hx509_clear_error_string(context
);
2551 cert
->attrs
.val
= d
;
2553 a
= malloc(sizeof(*a
));
2557 der_copy_octet_string(attr
, &a
->data
);
2558 der_copy_oid(oid
, &a
->oid
);
2560 cert
->attrs
.val
[cert
->attrs
.len
] = a
;
2567 * Get an external attribute for the certificate, examples are
2568 * friendly name and id.
2570 * @param cert hx509 certificate object to search
2571 * @param oid an oid to search for.
2573 * @return an hx509_cert_attribute, only valid as long as the
2574 * certificate is referenced.
2576 * @ingroup hx509_cert
2579 hx509_cert_attribute
2580 hx509_cert_get_attribute(hx509_cert cert
, const heim_oid
*oid
)
2583 for (i
= 0; i
< cert
->attrs
.len
; i
++)
2584 if (der_heim_oid_cmp(oid
, &cert
->attrs
.val
[i
]->oid
) == 0)
2585 return cert
->attrs
.val
[i
];
2590 * Set the friendly name on the certificate.
2592 * @param cert The certificate to set the friendly name on
2593 * @param name Friendly name.
2595 * @return An hx509 error code, see hx509_get_error_string().
2597 * @ingroup hx509_cert
2601 hx509_cert_set_friendly_name(hx509_cert cert
, const char *name
)
2603 if (cert
->friendlyname
)
2604 free(cert
->friendlyname
);
2605 cert
->friendlyname
= strdup(name
);
2606 if (cert
->friendlyname
== NULL
)
2612 * Get friendly name of the certificate.
2614 * @param cert cert to get the friendly name from.
2616 * @return an friendly name or NULL if there is. The friendly name is
2617 * only valid as long as the certificate is referenced.
2619 * @ingroup hx509_cert
2623 hx509_cert_get_friendly_name(hx509_cert cert
)
2625 hx509_cert_attribute a
;
2626 PKCS9_friendlyName n
;
2630 if (cert
->friendlyname
)
2631 return cert
->friendlyname
;
2633 a
= hx509_cert_get_attribute(cert
, &asn1_oid_id_pkcs_9_at_friendlyName
);
2637 ret
= hx509_cert_get_subject(cert
, &name
);
2640 ret
= hx509_name_to_string(name
, &cert
->friendlyname
);
2641 hx509_name_free(&name
);
2644 return cert
->friendlyname
;
2647 ret
= decode_PKCS9_friendlyName(a
->data
.data
, a
->data
.length
, &n
, &sz
);
2652 free_PKCS9_friendlyName(&n
);
2656 cert
->friendlyname
= malloc(n
.val
[0].length
+ 1);
2657 if (cert
->friendlyname
== NULL
) {
2658 free_PKCS9_friendlyName(&n
);
2662 for (i
= 0; i
< n
.val
[0].length
; i
++) {
2663 if (n
.val
[0].data
[i
] <= 0xff)
2664 cert
->friendlyname
[i
] = n
.val
[0].data
[i
] & 0xff;
2666 cert
->friendlyname
[i
] = 'X';
2668 cert
->friendlyname
[i
] = '\0';
2669 free_PKCS9_friendlyName(&n
);
2671 return cert
->friendlyname
;
2675 _hx509_query_clear(hx509_query
*q
)
2677 memset(q
, 0, sizeof(*q
));
2681 * Allocate an query controller. Free using hx509_query_free().
2683 * @param context A hx509 context.
2684 * @param q return pointer to a hx509_query.
2686 * @return An hx509 error code, see hx509_get_error_string().
2688 * @ingroup hx509_cert
2692 hx509_query_alloc(hx509_context context
, hx509_query
**q
)
2694 *q
= calloc(1, sizeof(**q
));
2702 * Set match options for the hx509 query controller.
2704 * @param q query controller.
2705 * @param option options to control the query controller.
2707 * @return An hx509 error code, see hx509_get_error_string().
2709 * @ingroup hx509_cert
2713 hx509_query_match_option(hx509_query
*q
, hx509_query_option option
)
2716 case HX509_QUERY_OPTION_PRIVATE_KEY
:
2717 q
->match
|= HX509_QUERY_PRIVATE_KEY
;
2719 case HX509_QUERY_OPTION_KU_ENCIPHERMENT
:
2720 q
->match
|= HX509_QUERY_KU_ENCIPHERMENT
;
2722 case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE
:
2723 q
->match
|= HX509_QUERY_KU_DIGITALSIGNATURE
;
2725 case HX509_QUERY_OPTION_KU_KEYCERTSIGN
:
2726 q
->match
|= HX509_QUERY_KU_KEYCERTSIGN
;
2728 case HX509_QUERY_OPTION_END
:
2735 * Set the issuer and serial number of match in the query
2736 * controller. The function make copies of the isser and serial number.
2738 * @param q a hx509 query controller
2739 * @param issuer issuer to search for
2740 * @param serialNumber the serialNumber of the issuer.
2742 * @return An hx509 error code, see hx509_get_error_string().
2744 * @ingroup hx509_cert
2748 hx509_query_match_issuer_serial(hx509_query
*q
,
2750 const heim_integer
*serialNumber
)
2754 der_free_heim_integer(q
->serial
);
2757 q
->serial
= malloc(sizeof(*q
->serial
));
2758 if (q
->serial
== NULL
)
2760 ret
= der_copy_heim_integer(serialNumber
, q
->serial
);
2766 if (q
->issuer_name
) {
2767 free_Name(q
->issuer_name
);
2768 free(q
->issuer_name
);
2770 q
->issuer_name
= malloc(sizeof(*q
->issuer_name
));
2771 if (q
->issuer_name
== NULL
)
2773 ret
= copy_Name(issuer
, q
->issuer_name
);
2775 free(q
->issuer_name
);
2776 q
->issuer_name
= NULL
;
2779 q
->match
|= HX509_QUERY_MATCH_SERIALNUMBER
|HX509_QUERY_MATCH_ISSUER_NAME
;
2784 * Set the query controller to match on a friendly name
2786 * @param q a hx509 query controller.
2787 * @param name a friendly name to match on
2789 * @return An hx509 error code, see hx509_get_error_string().
2791 * @ingroup hx509_cert
2795 hx509_query_match_friendly_name(hx509_query
*q
, const char *name
)
2797 if (q
->friendlyname
)
2798 free(q
->friendlyname
);
2799 q
->friendlyname
= strdup(name
);
2800 if (q
->friendlyname
== NULL
)
2802 q
->match
|= HX509_QUERY_MATCH_FRIENDLY_NAME
;
2807 * Set the query controller to require an one specific EKU (extended
2808 * key usage). Any previous EKU matching is overwitten. If NULL is
2809 * passed in as the eku, the EKU requirement is reset.
2811 * @param q a hx509 query controller.
2812 * @param eku an EKU to match on.
2814 * @return An hx509 error code, see hx509_get_error_string().
2816 * @ingroup hx509_cert
2820 hx509_query_match_eku(hx509_query
*q
, const heim_oid
*eku
)
2826 der_free_oid(q
->eku
);
2830 q
->match
&= ~HX509_QUERY_MATCH_EKU
;
2833 der_free_oid(q
->eku
);
2835 q
->eku
= calloc(1, sizeof(*q
->eku
));
2839 ret
= der_copy_oid(eku
, q
->eku
);
2845 q
->match
|= HX509_QUERY_MATCH_EKU
;
2851 hx509_query_match_expr(hx509_context context
, hx509_query
*q
, const char *expr
)
2854 _hx509_expr_free(q
->expr
);
2859 q
->match
&= ~HX509_QUERY_MATCH_EXPR
;
2861 q
->expr
= _hx509_expr_parse(expr
);
2863 q
->match
|= HX509_QUERY_MATCH_EXPR
;
2870 * Set the query controller to match using a specific match function.
2872 * @param q a hx509 query controller.
2873 * @param func function to use for matching, if the argument is NULL,
2874 * the match function is removed.
2875 * @param ctx context passed to the function.
2877 * @return An hx509 error code, see hx509_get_error_string().
2879 * @ingroup hx509_cert
2883 hx509_query_match_cmp_func(hx509_query
*q
,
2884 int (*func
)(hx509_context
, hx509_cert
, void *),
2888 q
->match
|= HX509_QUERY_MATCH_FUNCTION
;
2890 q
->match
&= ~HX509_QUERY_MATCH_FUNCTION
;
2892 q
->cmp_func_ctx
= ctx
;
2897 * Free the query controller.
2899 * @param context A hx509 context.
2900 * @param q a pointer to the query controller.
2902 * @ingroup hx509_cert
2906 hx509_query_free(hx509_context context
, hx509_query
*q
)
2912 der_free_heim_integer(q
->serial
);
2915 if (q
->issuer_name
) {
2916 free_Name(q
->issuer_name
);
2917 free(q
->issuer_name
);
2920 der_free_oid(q
->eku
);
2923 if (q
->friendlyname
)
2924 free(q
->friendlyname
);
2926 _hx509_expr_free(q
->expr
);
2928 memset(q
, 0, sizeof(*q
));
2933 _hx509_query_match_cert(hx509_context context
, const hx509_query
*q
, hx509_cert cert
)
2935 Certificate
*c
= _hx509_get_cert(cert
);
2938 _hx509_query_statistic(context
, 1, q
);
2940 if ((q
->match
& HX509_QUERY_FIND_ISSUER_CERT
) &&
2941 _hx509_cert_is_parent_cmp(q
->subject
, c
, 0) != 0)
2944 if ((q
->match
& HX509_QUERY_MATCH_CERTIFICATE
) &&
2945 _hx509_Certificate_cmp(q
->certificate
, c
) != 0)
2948 if ((q
->match
& HX509_QUERY_MATCH_SERIALNUMBER
)
2949 && der_heim_integer_cmp(&c
->tbsCertificate
.serialNumber
, q
->serial
) != 0)
2952 if (q
->match
& HX509_QUERY_MATCH_ISSUER_NAME
) {
2953 ret
= _hx509_name_cmp(&c
->tbsCertificate
.issuer
, q
->issuer_name
, &diff
);
2958 if (q
->match
& HX509_QUERY_MATCH_SUBJECT_NAME
) {
2959 ret
= _hx509_name_cmp(&c
->tbsCertificate
.subject
, q
->subject_name
, &diff
);
2964 if (q
->match
& HX509_QUERY_MATCH_SUBJECT_KEY_ID
) {
2965 SubjectKeyIdentifier si
;
2967 ret
= _hx509_find_extension_subject_key_id(c
, &si
);
2969 if (der_heim_octet_string_cmp(&si
, q
->subject_id
) != 0)
2971 free_SubjectKeyIdentifier(&si
);
2976 if ((q
->match
& HX509_QUERY_MATCH_ISSUER_ID
))
2978 if ((q
->match
& HX509_QUERY_PRIVATE_KEY
) &&
2979 _hx509_cert_private_key(cert
) == NULL
)
2984 if (q
->match
& HX509_QUERY_KU_DIGITALSIGNATURE
)
2986 if (q
->match
& HX509_QUERY_KU_NONREPUDIATION
)
2988 if (q
->match
& HX509_QUERY_KU_ENCIPHERMENT
)
2990 if (q
->match
& HX509_QUERY_KU_DATAENCIPHERMENT
)
2992 if (q
->match
& HX509_QUERY_KU_KEYAGREEMENT
)
2994 if (q
->match
& HX509_QUERY_KU_KEYCERTSIGN
)
2996 if (q
->match
& HX509_QUERY_KU_CRLSIGN
)
2998 if (ku
&& check_key_usage(context
, c
, ku
, TRUE
))
3001 if ((q
->match
& HX509_QUERY_ANCHOR
))
3004 if (q
->match
& HX509_QUERY_MATCH_LOCAL_KEY_ID
) {
3005 hx509_cert_attribute a
;
3007 a
= hx509_cert_get_attribute(cert
, &asn1_oid_id_pkcs_9_at_localKeyId
);
3010 if (der_heim_octet_string_cmp(&a
->data
, q
->local_key_id
) != 0)
3014 if (q
->match
& HX509_QUERY_NO_MATCH_PATH
) {
3017 for (i
= 0; i
< q
->path
->len
; i
++)
3018 if (hx509_cert_cmp(q
->path
->val
[i
], cert
) == 0)
3021 if (q
->match
& HX509_QUERY_MATCH_FRIENDLY_NAME
) {
3022 const char *name
= hx509_cert_get_friendly_name(cert
);
3025 if (strcasecmp(q
->friendlyname
, name
) != 0)
3028 if (q
->match
& HX509_QUERY_MATCH_FUNCTION
) {
3029 ret
= (*q
->cmp_func
)(context
, cert
, q
->cmp_func_ctx
);
3034 if (q
->match
& HX509_QUERY_MATCH_KEY_HASH_SHA1
) {
3035 heim_octet_string os
;
3037 os
.data
= c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.data
;
3039 c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.length
/ 8;
3041 ret
= _hx509_verify_signature(context
,
3043 hx509_signature_sha1(),
3050 if (q
->match
& HX509_QUERY_MATCH_TIME
) {
3052 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
3055 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notAfter
);
3060 /* If an EKU is required, check the cert for it. */
3061 if ((q
->match
& HX509_QUERY_MATCH_EKU
) &&
3062 hx509_cert_check_eku(context
, cert
, q
->eku
, 0))
3065 if ((q
->match
& HX509_QUERY_MATCH_EXPR
)) {
3066 hx509_env env
= NULL
;
3068 ret
= _hx509_cert_to_env(context
, cert
, &env
);
3072 ret
= _hx509_expr_eval(context
, env
, q
->expr
);
3073 hx509_env_free(&env
);
3078 if (q
->match
& ~HX509_QUERY_MASK
)
3085 * Set a statistic file for the query statistics.
3087 * @param context A hx509 context.
3088 * @param fn statistics file name
3090 * @ingroup hx509_cert
3094 hx509_query_statistic_file(hx509_context context
, const char *fn
)
3096 if (context
->querystat
)
3097 free(context
->querystat
);
3098 context
->querystat
= strdup(fn
);
3102 _hx509_query_statistic(hx509_context context
, int type
, const hx509_query
*q
)
3105 if (context
->querystat
== NULL
)
3107 f
= fopen(context
->querystat
, "a");
3111 fprintf(f
, "%d %d\n", type
, q
->match
);
3115 static const char *statname
[] = {
3117 "match serialnumber",
3118 "match issuer name",
3119 "match subject name",
3120 "match subject key id",
3124 "ku digitalsignature",
3127 "ku nonrepudiation",
3129 "ku dataencipherment",
3131 "match certificate",
3132 "match local key id",
3134 "match friendly name",
3136 "match key hash sha1",
3141 unsigned long stats
;
3147 stat_sort(const void *a
, const void *b
)
3149 const struct stat_el
*ae
= a
;
3150 const struct stat_el
*be
= b
;
3151 return be
->stats
- ae
->stats
;
3155 * Unparse the statistics file and print the result on a FILE descriptor.
3157 * @param context A hx509 context.
3158 * @param printtype tyep to print
3159 * @param out the FILE to write the data on.
3161 * @ingroup hx509_cert
3165 hx509_query_unparse_stats(hx509_context context
, int printtype
, FILE *out
)
3169 int type
, mask
, i
, num
;
3170 unsigned long multiqueries
= 0, totalqueries
= 0;
3171 struct stat_el stats
[32];
3173 if (context
->querystat
== NULL
)
3175 f
= fopen(context
->querystat
, "r");
3177 fprintf(out
, "No statistic file %s: %s.\n",
3178 context
->querystat
, strerror(errno
));
3183 for (i
= 0; i
< sizeof(stats
)/sizeof(stats
[0]); i
++) {
3188 while (fscanf(f
, "%d %d\n", &type
, &mask
) == 2) {
3189 if (type
!= printtype
)
3192 while (mask
&& i
< sizeof(stats
)/sizeof(stats
[0])) {
3206 qsort(stats
, sizeof(stats
)/sizeof(stats
[0]), sizeof(stats
[0]), stat_sort
);
3210 errx(1, "out of memory");
3212 rtbl_set_separator (t
, " ");
3214 rtbl_add_column_by_id (t
, 0, "Name", 0);
3215 rtbl_add_column_by_id (t
, 1, "Counter", 0);
3218 for (i
= 0; i
< sizeof(stats
)/sizeof(stats
[0]); i
++) {
3221 if (stats
[i
].index
< sizeof(statname
)/sizeof(statname
[0]))
3222 rtbl_add_column_entry_by_id (t
, 0, statname
[stats
[i
].index
]);
3224 snprintf(str
, sizeof(str
), "%d", stats
[i
].index
);
3225 rtbl_add_column_entry_by_id (t
, 0, str
);
3227 snprintf(str
, sizeof(str
), "%lu", stats
[i
].stats
);
3228 rtbl_add_column_entry_by_id (t
, 1, str
);
3231 rtbl_format(t
, out
);
3234 fprintf(out
, "\nQueries: multi %lu total %lu\n",
3235 multiqueries
, totalqueries
);
3239 * Check the extended key usage on the hx509 certificate.
3241 * @param context A hx509 context.
3242 * @param cert A hx509 context.
3243 * @param eku the EKU to check for
3244 * @param allow_any_eku if the any EKU is set, allow that to be a
3247 * @return An hx509 error code, see hx509_get_error_string().
3249 * @ingroup hx509_cert
3253 hx509_cert_check_eku(hx509_context context
, hx509_cert cert
,
3254 const heim_oid
*eku
, int allow_any_eku
)
3259 ret
= find_extension_eku(_hx509_get_cert(cert
), &e
);
3261 hx509_clear_error_string(context
);
3265 for (i
= 0; i
< e
.len
; i
++) {
3266 if (der_heim_oid_cmp(eku
, &e
.val
[i
]) == 0) {
3267 free_ExtKeyUsage(&e
);
3270 if (allow_any_eku
) {
3272 if (der_heim_oid_cmp(id_any_eku
, &e
.val
[i
]) == 0) {
3273 free_ExtKeyUsage(&e
);
3279 free_ExtKeyUsage(&e
);
3280 hx509_clear_error_string(context
);
3281 return HX509_CERTIFICATE_MISSING_EKU
;
3285 _hx509_cert_get_keyusage(hx509_context context
,
3294 memset(ku
, 0, sizeof(*ku
));
3296 cert
= _hx509_get_cert(c
);
3298 if (_hx509_cert_get_version(cert
) < 3)
3301 e
= find_extension(cert
, &asn1_oid_id_x509_ce_keyUsage
, &i
);
3303 return HX509_KU_CERT_MISSING
;
3305 ret
= decode_KeyUsage(e
->extnValue
.data
, e
->extnValue
.length
, ku
, &size
);
3312 _hx509_cert_get_eku(hx509_context context
,
3318 memset(e
, 0, sizeof(*e
));
3320 ret
= find_extension_eku(_hx509_get_cert(cert
), e
);
3321 if (ret
&& ret
!= HX509_EXTENSION_NOT_FOUND
) {
3322 hx509_clear_error_string(context
);
3329 * Encodes the hx509 certificate as a DER encode binary.
3331 * @param context A hx509 context.
3332 * @param c the certificate to encode.
3333 * @param os the encode certificate, set to NULL, 0 on case of
3334 * error. Free the os->data with hx509_xfree().
3336 * @return An hx509 error code, see hx509_get_error_string().
3338 * @ingroup hx509_cert
3342 hx509_cert_binary(hx509_context context
, hx509_cert c
, heim_octet_string
*os
)
3350 ASN1_MALLOC_ENCODE(Certificate
, os
->data
, os
->length
,
3351 _hx509_get_cert(c
), &size
, ret
);
3357 if (os
->length
!= size
)
3358 _hx509_abort("internal ASN.1 encoder error");
3364 * Last to avoid lost __attribute__s due to #undef.
3367 #undef __attribute__
3368 #define __attribute__(X)
3371 _hx509_abort(const char *fmt
, ...)
3372 __attribute__ ((noreturn
, format (printf
, 1, 2)))
3384 * Free a data element allocated in the library.
3386 * @param ptr data to be freed.
3388 * @ingroup hx509_misc
3392 hx509_xfree(void *ptr
)
3402 _hx509_cert_to_env(hx509_context context
, hx509_cert cert
, hx509_env
*env
)
3408 hx509_env envcert
= NULL
;
3413 asprintf(&buf
, "%d", _hx509_cert_get_version(_hx509_get_cert(cert
)));
3414 ret
= hx509_env_add(context
, &envcert
, "version", buf
);
3420 ret
= hx509_cert_get_subject(cert
, &name
);
3424 ret
= hx509_name_to_string(name
, &buf
);
3426 hx509_name_free(&name
);
3430 ret
= hx509_env_add(context
, &envcert
, "subject", buf
);
3431 hx509_name_free(&name
);
3436 ret
= hx509_cert_get_issuer(cert
, &name
);
3440 ret
= hx509_name_to_string(name
, &buf
);
3441 hx509_name_free(&name
);
3445 ret
= hx509_env_add(context
, &envcert
, "issuer", buf
);
3452 ret
= _hx509_cert_get_eku(context
, cert
, &eku
);
3453 if (ret
== HX509_EXTENSION_NOT_FOUND
)
3459 hx509_env enveku
= NULL
;
3461 for (i
= 0; i
< eku
.len
; i
++) {
3463 ret
= der_print_heim_oid(&eku
.val
[i
], '.', &buf
);
3465 free_ExtKeyUsage(&eku
);
3466 hx509_env_free(&enveku
);
3469 ret
= hx509_env_add(context
, &enveku
, buf
, "oid-name-here");
3472 free_ExtKeyUsage(&eku
);
3473 hx509_env_free(&enveku
);
3477 free_ExtKeyUsage(&eku
);
3479 ret
= hx509_env_add_binding(context
, &envcert
, "eku", enveku
);
3481 hx509_env_free(&enveku
);
3487 Certificate
*c
= _hx509_get_cert(cert
);
3488 heim_octet_string os
, sig
;
3489 hx509_env envhash
= NULL
;
3491 os
.data
= c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.data
;
3493 c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.length
/ 8;
3495 ret
= _hx509_create_signature(context
,
3497 hx509_signature_sha1(),
3504 ret
= hex_encode(sig
.data
, sig
.length
, &buf
);
3505 der_free_octet_string(&sig
);
3508 hx509_set_error_string(context
, 0, ret
,
3513 ret
= hx509_env_add(context
, &envhash
, "sha1", buf
);
3518 ret
= hx509_env_add_binding(context
, &envcert
, "hash", envhash
);
3520 hx509_env_free(&envhash
);
3525 ret
= hx509_env_add_binding(context
, env
, "certificate", envcert
);
3532 hx509_env_free(&envcert
);
3537 * Print a simple representation of a certificate
3539 * @param context A hx509 context, can be NULL
3540 * @param cert certificate to print
3541 * @param out the stdio output stream, if NULL, stdout is used
3543 * @return An hx509 error code
3545 * @ingroup hx509_cert
3549 hx509_print_cert(hx509_context context
, hx509_cert cert
, FILE *out
)
3558 ret
= hx509_cert_get_issuer(cert
, &name
);
3561 hx509_name_to_string(name
, &str
);
3562 hx509_name_free(&name
);
3563 fprintf(out
, " issuer: \"%s\"\n", str
);
3566 ret
= hx509_cert_get_subject(cert
, &name
);
3569 hx509_name_to_string(name
, &str
);
3570 hx509_name_free(&name
);
3571 fprintf(out
, " subject: \"%s\"\n", str
);
3575 heim_integer serialNumber
;
3577 ret
= hx509_cert_get_serialnumber(cert
, &serialNumber
);
3580 ret
= der_print_hex_heim_integer(&serialNumber
, &str
);
3583 der_free_heim_integer(&serialNumber
);
3584 fprintf(out
, " serial: %s\n", str
);
3588 printf(" keyusage: ");
3589 ret
= hx509_cert_keyusage_print(context
, cert
, &str
);
3591 fprintf(out
, "%s\n", str
);