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");
1033 * The subjectName is "null" when it's empty set of relative DBs.
1037 subject_null_p(const Certificate
*c
)
1039 return c
->tbsCertificate
.subject
.u
.rdnSequence
.len
== 0;
1044 find_parent(hx509_context context
,
1046 hx509_certs trust_anchors
,
1052 AuthorityKeyIdentifier ai
;
1057 memset(&ai
, 0, sizeof(ai
));
1059 _hx509_query_clear(&q
);
1061 if (!subject_null_p(current
->data
)) {
1062 q
.match
|= HX509_QUERY_FIND_ISSUER_CERT
;
1063 q
.subject
= _hx509_get_cert(current
);
1065 ret
= find_extension_auth_key_id(current
->data
, &ai
);
1067 hx509_set_error_string(context
, 0, HX509_CERTIFICATE_MALFORMED
,
1068 "Subjectless certificate missing AuthKeyID");
1069 return HX509_CERTIFICATE_MALFORMED
;
1072 if (ai
.keyIdentifier
== NULL
) {
1073 free_AuthorityKeyIdentifier(&ai
);
1074 hx509_set_error_string(context
, 0, HX509_CERTIFICATE_MALFORMED
,
1075 "Subjectless certificate missing keyIdentifier "
1076 "inside AuthKeyID");
1077 return HX509_CERTIFICATE_MALFORMED
;
1080 q
.subject_id
= ai
.keyIdentifier
;
1081 q
.match
= HX509_QUERY_MATCH_SUBJECT_KEY_ID
;
1085 q
.match
|= HX509_QUERY_NO_MATCH_PATH
;
1088 q
.timenow
= time_now
;
1089 q
.match
|= HX509_QUERY_MATCH_TIME
;
1091 ret
= hx509_certs_find(context
, pool
, &q
, parent
);
1093 free_AuthorityKeyIdentifier(&ai
);
1096 q
.match
&= ~HX509_QUERY_MATCH_TIME
;
1099 if (trust_anchors
) {
1100 ret
= hx509_certs_find(context
, trust_anchors
, &q
, parent
);
1102 free_AuthorityKeyIdentifier(&ai
);
1106 free_AuthorityKeyIdentifier(&ai
);
1112 ret
= hx509_cert_get_subject(current
, &name
);
1114 hx509_clear_error_string(context
);
1115 return HX509_ISSUER_NOT_FOUND
;
1117 ret
= hx509_name_to_string(name
, &str
);
1118 hx509_name_free(&name
);
1120 hx509_clear_error_string(context
);
1121 return HX509_ISSUER_NOT_FOUND
;
1124 hx509_set_error_string(context
, 0, HX509_ISSUER_NOT_FOUND
,
1125 "Failed to find issuer for "
1126 "certificate with subject: '%s'", str
);
1129 return HX509_ISSUER_NOT_FOUND
;
1137 is_proxy_cert(hx509_context context
,
1138 const Certificate
*cert
,
1139 ProxyCertInfo
*rinfo
)
1147 memset(rinfo
, 0, sizeof(*rinfo
));
1149 e
= find_extension(cert
, &asn1_oid_id_pkix_pe_proxyCertInfo
, &i
);
1151 hx509_clear_error_string(context
);
1152 return HX509_EXTENSION_NOT_FOUND
;
1155 ret
= decode_ProxyCertInfo(e
->extnValue
.data
,
1156 e
->extnValue
.length
,
1160 hx509_clear_error_string(context
);
1163 if (size
!= e
->extnValue
.length
) {
1164 free_ProxyCertInfo(&info
);
1165 hx509_clear_error_string(context
);
1166 return HX509_EXTRA_DATA_AFTER_STRUCTURE
;
1169 free_ProxyCertInfo(&info
);
1177 * Path operations are like MEMORY based keyset, but with exposed
1178 * internal so we can do easy searches.
1182 _hx509_path_append(hx509_context context
, hx509_path
*path
, hx509_cert cert
)
1185 val
= realloc(path
->val
, (path
->len
+ 1) * sizeof(path
->val
[0]));
1187 hx509_set_error_string(context
, 0, ENOMEM
, "out of memory");
1192 path
->val
[path
->len
] = hx509_cert_ref(cert
);
1199 _hx509_path_free(hx509_path
*path
)
1203 for (i
= 0; i
< path
->len
; i
++)
1204 hx509_cert_free(path
->val
[i
]);
1211 * Find path by looking up issuer for the top certificate and continue
1212 * until an anchor certificate is found or max limit is found. A
1213 * certificate never included twice in the path.
1215 * If the trust anchors are not given, calculate optimistic path, just
1216 * follow the chain upward until we no longer find a parent or we hit
1217 * the max path limit. In this case, a failure will always be returned
1218 * depending on what error condition is hit first.
1220 * The path includes a path from the top certificate to the anchor
1223 * The caller needs to free `path´ both on successful built path and
1228 _hx509_calculate_path(hx509_context context
,
1231 hx509_certs anchors
,
1232 unsigned int max_depth
,
1237 hx509_cert parent
, current
;
1241 max_depth
= HX509_VERIFY_MAX_DEPTH
;
1243 ret
= _hx509_path_append(context
, path
, cert
);
1247 current
= hx509_cert_ref(cert
);
1249 while (!certificate_is_anchor(context
, anchors
, current
)) {
1251 ret
= find_parent(context
, time_now
, anchors
, path
,
1252 pool
, current
, &parent
);
1253 hx509_cert_free(current
);
1257 ret
= _hx509_path_append(context
, path
, parent
);
1262 if (path
->len
> max_depth
) {
1263 hx509_cert_free(current
);
1264 hx509_set_error_string(context
, 0, HX509_PATH_TOO_LONG
,
1265 "Path too long while bulding "
1266 "certificate chain");
1267 return HX509_PATH_TOO_LONG
;
1271 if ((flags
& HX509_CALCULATE_PATH_NO_ANCHOR
) &&
1273 certificate_is_anchor(context
, anchors
, path
->val
[path
->len
- 1]))
1275 hx509_cert_free(path
->val
[path
->len
- 1]);
1279 hx509_cert_free(current
);
1284 _hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier
*p
,
1285 const AlgorithmIdentifier
*q
)
1288 diff
= der_heim_oid_cmp(&p
->algorithm
, &q
->algorithm
);
1291 if (p
->parameters
) {
1293 return heim_any_cmp(p
->parameters
,
1306 _hx509_Certificate_cmp(const Certificate
*p
, const Certificate
*q
)
1309 diff
= der_heim_bit_string_cmp(&p
->signatureValue
, &q
->signatureValue
);
1312 diff
= _hx509_AlgorithmIdentifier_cmp(&p
->signatureAlgorithm
,
1313 &q
->signatureAlgorithm
);
1316 diff
= der_heim_octet_string_cmp(&p
->tbsCertificate
._save
,
1317 &q
->tbsCertificate
._save
);
1322 * Compare to hx509 certificate object, useful for sorting.
1324 * @param p a hx509 certificate object.
1325 * @param q a hx509 certificate object.
1327 * @return 0 the objects are the same, returns > 0 is p is "larger"
1328 * then q, < 0 if p is "smaller" then q.
1330 * @ingroup hx509_cert
1334 hx509_cert_cmp(hx509_cert p
, hx509_cert q
)
1336 return _hx509_Certificate_cmp(p
->data
, q
->data
);
1340 * Return the name of the issuer of the hx509 certificate.
1342 * @param p a hx509 certificate object.
1343 * @param name a pointer to a hx509 name, should be freed by
1344 * hx509_name_free().
1346 * @return An hx509 error code, see hx509_get_error_string().
1348 * @ingroup hx509_cert
1352 hx509_cert_get_issuer(hx509_cert p
, hx509_name
*name
)
1354 return _hx509_name_from_Name(&p
->data
->tbsCertificate
.issuer
, name
);
1358 * Return the name of the subject of the hx509 certificate.
1360 * @param p a hx509 certificate object.
1361 * @param name a pointer to a hx509 name, should be freed by
1362 * hx509_name_free(). See also hx509_cert_get_base_subject().
1364 * @return An hx509 error code, see hx509_get_error_string().
1366 * @ingroup hx509_cert
1370 hx509_cert_get_subject(hx509_cert p
, hx509_name
*name
)
1372 return _hx509_name_from_Name(&p
->data
->tbsCertificate
.subject
, name
);
1376 * Return the name of the base subject of the hx509 certificate. If
1377 * the certiicate is a verified proxy certificate, the this function
1378 * return the base certificate (root of the proxy chain). If the proxy
1379 * certificate is not verified with the base certificate
1380 * HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned.
1382 * @param context a hx509 context.
1383 * @param c a hx509 certificate object.
1384 * @param name a pointer to a hx509 name, should be freed by
1385 * hx509_name_free(). See also hx509_cert_get_subject().
1387 * @return An hx509 error code, see hx509_get_error_string().
1389 * @ingroup hx509_cert
1393 hx509_cert_get_base_subject(hx509_context context
, hx509_cert c
,
1397 return hx509_name_copy(context
, c
->basename
, name
);
1398 if (is_proxy_cert(context
, c
->data
, NULL
) == 0) {
1399 int ret
= HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED
;
1400 hx509_set_error_string(context
, 0, ret
,
1401 "Proxy certificate have not been "
1402 "canonicalize yet, no base name");
1405 return _hx509_name_from_Name(&c
->data
->tbsCertificate
.subject
, name
);
1409 * Get serial number of the certificate.
1411 * @param p a hx509 certificate object.
1412 * @param i serial number, should be freed ith der_free_heim_integer().
1414 * @return An hx509 error code, see hx509_get_error_string().
1416 * @ingroup hx509_cert
1420 hx509_cert_get_serialnumber(hx509_cert p
, heim_integer
*i
)
1422 return der_copy_heim_integer(&p
->data
->tbsCertificate
.serialNumber
, i
);
1426 * Get notBefore time of the certificate.
1428 * @param p a hx509 certificate object.
1430 * @return return not before time
1432 * @ingroup hx509_cert
1436 hx509_cert_get_notBefore(hx509_cert p
)
1438 return _hx509_Time2time_t(&p
->data
->tbsCertificate
.validity
.notBefore
);
1442 * Get notAfter time of the certificate.
1444 * @param p a hx509 certificate object.
1446 * @return return not after time.
1448 * @ingroup hx509_cert
1452 hx509_cert_get_notAfter(hx509_cert p
)
1454 return _hx509_Time2time_t(&p
->data
->tbsCertificate
.validity
.notAfter
);
1458 * Get the SubjectPublicKeyInfo structure from the hx509 certificate.
1460 * @param context a hx509 context.
1461 * @param p a hx509 certificate object.
1462 * @param spki SubjectPublicKeyInfo, should be freed with
1463 * free_SubjectPublicKeyInfo().
1465 * @return An hx509 error code, see hx509_get_error_string().
1467 * @ingroup hx509_cert
1471 hx509_cert_get_SPKI(hx509_context context
, hx509_cert p
, SubjectPublicKeyInfo
*spki
)
1475 ret
= copy_SubjectPublicKeyInfo(&p
->data
->tbsCertificate
.subjectPublicKeyInfo
, spki
);
1477 hx509_set_error_string(context
, 0, ret
, "Failed to copy SPKI");
1482 * Get the AlgorithmIdentifier from the hx509 certificate.
1484 * @param context a hx509 context.
1485 * @param p a hx509 certificate object.
1486 * @param alg AlgorithmIdentifier, should be freed with
1487 * free_AlgorithmIdentifier(). The algorithmidentifier is
1488 * typicly rsaEncryption, or id-ecPublicKey, or some other
1489 * public key mechanism.
1491 * @return An hx509 error code, see hx509_get_error_string().
1493 * @ingroup hx509_cert
1497 hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context
,
1499 AlgorithmIdentifier
*alg
)
1503 ret
= copy_AlgorithmIdentifier(&p
->data
->tbsCertificate
.subjectPublicKeyInfo
.algorithm
, alg
);
1505 hx509_set_error_string(context
, 0, ret
,
1506 "Failed to copy SPKI AlgorithmIdentifier");
1512 _hx509_cert_private_key(hx509_cert p
)
1514 return p
->private_key
;
1518 hx509_cert_have_private_key(hx509_cert p
)
1520 return p
->private_key
? 1 : 0;
1525 _hx509_cert_private_key_exportable(hx509_cert p
)
1527 if (p
->private_key
== NULL
)
1529 return _hx509_private_key_exportable(p
->private_key
);
1533 _hx509_cert_private_decrypt(hx509_context context
,
1534 const heim_octet_string
*ciphertext
,
1535 const heim_oid
*encryption_oid
,
1537 heim_octet_string
*cleartext
)
1539 cleartext
->data
= NULL
;
1540 cleartext
->length
= 0;
1542 if (p
->private_key
== NULL
) {
1543 hx509_set_error_string(context
, 0, HX509_PRIVATE_KEY_MISSING
,
1544 "Private key missing");
1545 return HX509_PRIVATE_KEY_MISSING
;
1548 return _hx509_private_key_private_decrypt(context
,
1556 _hx509_cert_public_encrypt(hx509_context context
,
1557 const heim_octet_string
*cleartext
,
1559 heim_oid
*encryption_oid
,
1560 heim_octet_string
*ciphertext
)
1562 return _hx509_public_encrypt(context
,
1564 encryption_oid
, ciphertext
);
1572 _hx509_Time2time_t(const Time
*t
)
1574 switch(t
->element
) {
1575 case choice_Time_utcTime
:
1576 return t
->u
.utcTime
;
1577 case choice_Time_generalTime
:
1578 return t
->u
.generalTime
;
1588 init_name_constraints(hx509_name_constraints
*nc
)
1590 memset(nc
, 0, sizeof(*nc
));
1595 add_name_constraints(hx509_context context
, const Certificate
*c
, int not_ca
,
1596 hx509_name_constraints
*nc
)
1598 NameConstraints tnc
;
1601 ret
= find_extension_name_constraints(c
, &tnc
);
1602 if (ret
== HX509_EXTENSION_NOT_FOUND
)
1605 hx509_set_error_string(context
, 0, ret
, "Failed getting NameConstraints");
1607 } else if (not_ca
) {
1608 ret
= HX509_VERIFY_CONSTRAINTS
;
1609 hx509_set_error_string(context
, 0, ret
, "Not a CA and "
1610 "have NameConstraints");
1612 NameConstraints
*val
;
1613 val
= realloc(nc
->val
, sizeof(nc
->val
[0]) * (nc
->len
+ 1));
1615 hx509_clear_error_string(context
);
1620 ret
= copy_NameConstraints(&tnc
, &nc
->val
[nc
->len
]);
1622 hx509_clear_error_string(context
);
1628 free_NameConstraints(&tnc
);
1633 match_RDN(const RelativeDistinguishedName
*c
,
1634 const RelativeDistinguishedName
*n
)
1638 if (c
->len
!= n
->len
)
1639 return HX509_NAME_CONSTRAINT_ERROR
;
1641 for (i
= 0; i
< n
->len
; i
++) {
1644 if (der_heim_oid_cmp(&c
->val
[i
].type
, &n
->val
[i
].type
) != 0)
1645 return HX509_NAME_CONSTRAINT_ERROR
;
1646 ret
= _hx509_name_ds_cmp(&c
->val
[i
].value
, &n
->val
[i
].value
, &diff
);
1650 return HX509_NAME_CONSTRAINT_ERROR
;
1656 match_X501Name(const Name
*c
, const Name
*n
)
1660 if (c
->element
!= choice_Name_rdnSequence
1661 || n
->element
!= choice_Name_rdnSequence
)
1663 if (c
->u
.rdnSequence
.len
> n
->u
.rdnSequence
.len
)
1664 return HX509_NAME_CONSTRAINT_ERROR
;
1665 for (i
= 0; i
< c
->u
.rdnSequence
.len
; i
++) {
1666 ret
= match_RDN(&c
->u
.rdnSequence
.val
[i
], &n
->u
.rdnSequence
.val
[i
]);
1675 match_general_name(const GeneralName
*c
, const GeneralName
*n
, int *match
)
1678 * Name constraints only apply to the same name type, see RFC3280,
1681 assert(c
->element
== n
->element
);
1683 switch(c
->element
) {
1684 case choice_GeneralName_otherName
:
1685 if (der_heim_oid_cmp(&c
->u
.otherName
.type_id
,
1686 &n
->u
.otherName
.type_id
) != 0)
1687 return HX509_NAME_CONSTRAINT_ERROR
;
1688 if (heim_any_cmp(&c
->u
.otherName
.value
,
1689 &n
->u
.otherName
.value
) != 0)
1690 return HX509_NAME_CONSTRAINT_ERROR
;
1693 case choice_GeneralName_rfc822Name
: {
1696 s
= strchr(c
->u
.rfc822Name
, '@');
1698 if (strcasecmp(c
->u
.rfc822Name
, n
->u
.rfc822Name
) != 0)
1699 return HX509_NAME_CONSTRAINT_ERROR
;
1701 s
= strchr(n
->u
.rfc822Name
, '@');
1703 return HX509_NAME_CONSTRAINT_ERROR
;
1704 len1
= strlen(c
->u
.rfc822Name
);
1705 len2
= strlen(s
+ 1);
1707 return HX509_NAME_CONSTRAINT_ERROR
;
1708 if (strcasecmp(s
+ 1 + len2
- len1
, c
->u
.rfc822Name
) != 0)
1709 return HX509_NAME_CONSTRAINT_ERROR
;
1710 if (len1
< len2
&& s
[len2
- len1
+ 1] != '.')
1711 return HX509_NAME_CONSTRAINT_ERROR
;
1716 case choice_GeneralName_dNSName
: {
1719 lenc
= strlen(c
->u
.dNSName
);
1720 lenn
= strlen(n
->u
.dNSName
);
1722 return HX509_NAME_CONSTRAINT_ERROR
;
1723 if (strcasecmp(&n
->u
.dNSName
[lenn
- lenc
], c
->u
.dNSName
) != 0)
1724 return HX509_NAME_CONSTRAINT_ERROR
;
1725 if (lenc
!= lenn
&& n
->u
.dNSName
[lenn
- lenc
- 1] != '.')
1726 return HX509_NAME_CONSTRAINT_ERROR
;
1730 case choice_GeneralName_directoryName
: {
1731 Name c_name
, n_name
;
1734 c_name
._save
.data
= NULL
;
1735 c_name
._save
.length
= 0;
1736 c_name
.element
= c
->u
.directoryName
.element
;
1737 c_name
.u
.rdnSequence
= c
->u
.directoryName
.u
.rdnSequence
;
1739 n_name
._save
.data
= NULL
;
1740 n_name
._save
.length
= 0;
1741 n_name
.element
= n
->u
.directoryName
.element
;
1742 n_name
.u
.rdnSequence
= n
->u
.directoryName
.u
.rdnSequence
;
1744 ret
= match_X501Name(&c_name
, &n_name
);
1749 case choice_GeneralName_uniformResourceIdentifier
:
1750 case choice_GeneralName_iPAddress
:
1751 case choice_GeneralName_registeredID
:
1753 return HX509_NAME_CONSTRAINT_ERROR
;
1758 match_alt_name(const GeneralName
*n
, const Certificate
*c
,
1759 int *same
, int *match
)
1766 ret
= find_extension_subject_alt_name(c
, &i
, &sa
);
1767 if (ret
== HX509_EXTENSION_NOT_FOUND
) {
1770 } else if (ret
!= 0)
1773 for (j
= 0; j
< sa
.len
; j
++) {
1774 if (n
->element
== sa
.val
[j
].element
) {
1776 ret
= match_general_name(n
, &sa
.val
[j
], match
);
1779 free_GeneralNames(&sa
);
1786 match_tree(const GeneralSubtrees
*t
, const Certificate
*c
, int *match
)
1788 int name
, alt_name
, same
;
1792 name
= alt_name
= same
= *match
= 0;
1793 for (i
= 0; i
< t
->len
; i
++) {
1794 if (t
->val
[i
].minimum
&& t
->val
[i
].maximum
)
1798 * If the constraint apply to directoryNames, test is with
1799 * subjectName of the certificate if the certificate have a
1800 * non-null (empty) subjectName.
1803 if (t
->val
[i
].base
.element
== choice_GeneralName_directoryName
1804 && !subject_null_p(c
))
1806 GeneralName certname
;
1808 memset(&certname
, 0, sizeof(certname
));
1809 certname
.element
= choice_GeneralName_directoryName
;
1810 certname
.u
.directoryName
.element
=
1811 c
->tbsCertificate
.subject
.element
;
1812 certname
.u
.directoryName
.u
.rdnSequence
=
1813 c
->tbsCertificate
.subject
.u
.rdnSequence
;
1815 ret
= match_general_name(&t
->val
[i
].base
, &certname
, &name
);
1818 /* Handle subjectAltNames, this is icky since they
1819 * restrictions only apply if the subjectAltName is of the
1820 * same type. So if there have been a match of type, require
1821 * altname to be set.
1823 ret
= match_alt_name(&t
->val
[i
].base
, c
, &same
, &alt_name
);
1825 if (name
&& (!same
|| alt_name
))
1831 check_name_constraints(hx509_context context
,
1832 const hx509_name_constraints
*nc
,
1833 const Certificate
*c
)
1838 for (i
= 0 ; i
< nc
->len
; i
++) {
1841 if (nc
->val
[i
].permittedSubtrees
) {
1842 GeneralSubtrees_SET(&gs
, nc
->val
[i
].permittedSubtrees
);
1843 ret
= match_tree(&gs
, c
, &match
);
1845 hx509_clear_error_string(context
);
1848 /* allow null subjectNames, they wont matches anything */
1849 if (match
== 0 && !subject_null_p(c
)) {
1850 hx509_set_error_string(context
, 0, HX509_VERIFY_CONSTRAINTS
,
1851 "Error verify constraints, "
1852 "certificate didn't match any "
1853 "permitted subtree");
1854 return HX509_VERIFY_CONSTRAINTS
;
1857 if (nc
->val
[i
].excludedSubtrees
) {
1858 GeneralSubtrees_SET(&gs
, nc
->val
[i
].excludedSubtrees
);
1859 ret
= match_tree(&gs
, c
, &match
);
1861 hx509_clear_error_string(context
);
1865 hx509_set_error_string(context
, 0, HX509_VERIFY_CONSTRAINTS
,
1866 "Error verify constraints, "
1867 "certificate included in excluded "
1869 return HX509_VERIFY_CONSTRAINTS
;
1877 free_name_constraints(hx509_name_constraints
*nc
)
1881 for (i
= 0 ; i
< nc
->len
; i
++)
1882 free_NameConstraints(&nc
->val
[i
]);
1887 * Build and verify the path for the certificate to the trust anchor
1888 * specified in the verify context. The path is constructed from the
1889 * certificate, the pool and the trust anchors.
1891 * @param context A hx509 context.
1892 * @param ctx A hx509 verification context.
1893 * @param cert the certificate to build the path from.
1894 * @param pool A keyset of certificates to build the chain from.
1896 * @return An hx509 error code, see hx509_get_error_string().
1898 * @ingroup hx509_verify
1902 hx509_verify_path(hx509_context context
,
1903 hx509_verify_ctx ctx
,
1907 hx509_name_constraints nc
;
1909 int ret
, i
, proxy_cert_depth
, selfsigned_depth
, diff
;
1912 hx509_certs anchors
= NULL
;
1914 memset(&proxy_issuer
, 0, sizeof(proxy_issuer
));
1916 ret
= init_name_constraints(&nc
);
1923 if ((ctx
->flags
& HX509_VERIFY_CTX_F_TIME_SET
) == 0)
1924 ctx
->time_now
= time(NULL
);
1929 if (ctx
->trust_anchors
)
1930 anchors
= hx509_certs_ref(ctx
->trust_anchors
);
1931 else if (context
->default_trust_anchors
&& ALLOW_DEF_TA(ctx
))
1932 anchors
= hx509_certs_ref(context
->default_trust_anchors
);
1934 ret
= hx509_certs_init(context
, "MEMORY:no-TA", 0, NULL
, &anchors
);
1940 * Calculate the path from the certificate user presented to the
1943 ret
= _hx509_calculate_path(context
, 0, ctx
->time_now
,
1944 anchors
, ctx
->max_depth
,
1950 * Check CA and proxy certificate chain from the top of the
1951 * certificate chain. Also check certificate is valid with respect
1952 * to the current time.
1956 proxy_cert_depth
= 0;
1957 selfsigned_depth
= 0;
1959 if (ctx
->flags
& HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
)
1964 for (i
= 0; i
< path
.len
; i
++) {
1968 c
= _hx509_get_cert(path
.val
[i
]);
1971 * Lets do some basic check on issuer like
1972 * keyUsage.keyCertSign and basicConstraints.cA bit depending
1973 * on what type of certificate this is.
1979 /* XXX make constants for keyusage */
1980 ret
= check_key_usage(context
, c
, 1 << 5,
1981 REQUIRE_RFC3280(ctx
) ? TRUE
: FALSE
);
1983 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
1984 "Key usage missing from CA certificate");
1988 /* self signed cert doesn't add to path length */
1989 if (i
+ 1 != path
.len
) {
1992 ret
= certificate_is_self_signed(context
, c
, &selfsigned
);
2003 if (is_proxy_cert(context
, c
, &info
) == 0) {
2006 if (info
.pCPathLenConstraint
!= NULL
&&
2007 *info
.pCPathLenConstraint
< i
)
2009 free_ProxyCertInfo(&info
);
2010 ret
= HX509_PATH_TOO_LONG
;
2011 hx509_set_error_string(context
, 0, ret
,
2012 "Proxy certificate chain "
2013 "longer then allowed");
2016 /* XXX MUST check info.proxyPolicy */
2017 free_ProxyCertInfo(&info
);
2020 if (find_extension(c
, &asn1_oid_id_x509_ce_subjectAltName
, &j
)) {
2021 ret
= HX509_PROXY_CERT_INVALID
;
2022 hx509_set_error_string(context
, 0, ret
,
2023 "Proxy certificate have explicity "
2024 "forbidden subjectAltName");
2029 if (find_extension(c
, &asn1_oid_id_x509_ce_issuerAltName
, &j
)) {
2030 ret
= HX509_PROXY_CERT_INVALID
;
2031 hx509_set_error_string(context
, 0, ret
,
2032 "Proxy certificate have explicity "
2033 "forbidden issuerAltName");
2038 * The subject name of the proxy certificate should be
2039 * CN=XXX,<proxy issuer>, prune of CN and check if its
2040 * the same over the whole chain of proxy certs and
2041 * then check with the EE cert when we get to it.
2044 if (proxy_cert_depth
) {
2045 ret
= _hx509_name_cmp(&proxy_issuer
, &c
->tbsCertificate
.subject
, &diff
);
2047 hx509_set_error_string(context
, 0, ret
, "Out of memory");
2051 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2052 hx509_set_error_string(context
, 0, ret
,
2053 "Base proxy name not right");
2058 free_Name(&proxy_issuer
);
2060 ret
= copy_Name(&c
->tbsCertificate
.subject
, &proxy_issuer
);
2062 hx509_clear_error_string(context
);
2066 j
= proxy_issuer
.u
.rdnSequence
.len
;
2067 if (proxy_issuer
.u
.rdnSequence
.len
< 2
2068 || proxy_issuer
.u
.rdnSequence
.val
[j
- 1].len
> 1
2069 || der_heim_oid_cmp(&proxy_issuer
.u
.rdnSequence
.val
[j
- 1].val
[0].type
,
2070 &asn1_oid_id_at_commonName
))
2072 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2073 hx509_set_error_string(context
, 0, ret
,
2074 "Proxy name too short or "
2075 "does not have Common name "
2080 free_RelativeDistinguishedName(&proxy_issuer
.u
.rdnSequence
.val
[j
- 1]);
2081 proxy_issuer
.u
.rdnSequence
.len
-= 1;
2083 ret
= _hx509_name_cmp(&proxy_issuer
, &c
->tbsCertificate
.issuer
, &diff
);
2085 hx509_set_error_string(context
, 0, ret
, "Out of memory");
2089 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2090 hx509_set_error_string(context
, 0, ret
,
2091 "Proxy issuer name not as expected");
2098 * Now we are done with the proxy certificates, this
2099 * cert was an EE cert and we we will fall though to
2100 * EE checking below.
2108 * If there where any proxy certificates in the chain
2109 * (proxy_cert_depth > 0), check that the proxy issuer
2110 * matched proxy certificates "base" subject.
2112 if (proxy_cert_depth
) {
2114 ret
= _hx509_name_cmp(&proxy_issuer
,
2115 &c
->tbsCertificate
.subject
, &diff
);
2117 hx509_set_error_string(context
, 0, ret
, "out of memory");
2121 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2122 hx509_clear_error_string(context
);
2126 hx509_name_free(&cert
->basename
);
2128 ret
= _hx509_name_from_Name(&proxy_issuer
, &cert
->basename
);
2130 hx509_clear_error_string(context
);
2138 ret
= check_basic_constraints(context
, c
, type
,
2139 i
- proxy_cert_depth
- selfsigned_depth
);
2144 * Don't check the trust anchors expiration time since they
2145 * are transported out of band, from RFC3820.
2147 if (i
+ 1 != path
.len
|| CHECK_TA(ctx
)) {
2149 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
2150 if (t
> ctx
->time_now
) {
2151 ret
= HX509_CERT_USED_BEFORE_TIME
;
2152 hx509_clear_error_string(context
);
2155 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notAfter
);
2156 if (t
< ctx
->time_now
) {
2157 ret
= HX509_CERT_USED_AFTER_TIME
;
2158 hx509_clear_error_string(context
);
2163 if (type
== EE_CERT
)
2165 else if (type
== PROXY_CERT
)
2170 * Verify constraints, do this backward so path constraints are
2171 * checked in the right order.
2174 for (ret
= 0, i
= path
.len
- 1; i
>= 0; i
--) {
2178 c
= _hx509_get_cert(path
.val
[i
]);
2180 ret
= certificate_is_self_signed(context
, c
, &selfsigned
);
2184 /* verify name constraints, not for selfsigned and anchor */
2185 if (!selfsigned
|| i
+ 1 != path
.len
) {
2186 ret
= check_name_constraints(context
, &nc
, c
);
2191 ret
= add_name_constraints(context
, c
, i
== 0, &nc
);
2195 /* XXX verify all other silly constraints */
2200 * Verify that no certificates has been revoked.
2203 if (ctx
->revoke_ctx
) {
2206 ret
= hx509_certs_init(context
, "MEMORY:revoke-certs", 0,
2211 for (i
= 0; i
< path
.len
; i
++) {
2212 ret
= hx509_certs_add(context
, certs
, path
.val
[i
]);
2214 hx509_certs_free(&certs
);
2218 ret
= hx509_certs_merge(context
, certs
, pool
);
2220 hx509_certs_free(&certs
);
2224 for (i
= 0; i
< path
.len
- 1; i
++) {
2225 int parent
= (i
< path
.len
- 1) ? i
+ 1 : i
;
2227 ret
= hx509_revoke_verify(context
,
2234 hx509_certs_free(&certs
);
2238 hx509_certs_free(&certs
);
2242 * Verify signatures, do this backward so public key working
2243 * parameter is passed up from the anchor up though the chain.
2246 for (i
= path
.len
- 1; i
>= 0; i
--) {
2250 c
= _hx509_get_cert(path
.val
[i
]);
2252 /* is last in chain (trust anchor) */
2253 if (i
+ 1 == path
.len
) {
2256 signer
= path
.val
[i
];
2258 ret
= certificate_is_self_signed(context
, signer
->data
, &selfsigned
);
2262 /* if trust anchor is not self signed, don't check sig */
2266 /* take next certificate in chain */
2267 signer
= path
.val
[i
+ 1];
2270 /* verify signatureValue */
2271 ret
= _hx509_verify_signature_bitstring(context
,
2273 &c
->signatureAlgorithm
,
2274 &c
->tbsCertificate
._save
,
2275 &c
->signatureValue
);
2277 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
2278 "Failed to verify signature of certificate");
2282 * Verify that the sigature algorithm "best-before" date is
2283 * before the creation date of the certificate, do this for
2284 * trust anchors too, since any trust anchor that is created
2285 * after a algorithm is known to be bad deserved to be invalid.
2287 * Skip the leaf certificate for now...
2290 if (i
!= 0 && (ctx
->flags
& HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK
) == 0) {
2292 _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
2293 ret
= _hx509_signature_best_before(context
,
2294 &c
->signatureAlgorithm
,
2302 hx509_certs_free(&anchors
);
2303 free_Name(&proxy_issuer
);
2304 free_name_constraints(&nc
);
2305 _hx509_path_free(&path
);
2311 * Verify a signature made using the private key of an certificate.
2313 * @param context A hx509 context.
2314 * @param signer the certificate that made the signature.
2315 * @param alg algorthm that was used to sign the data.
2316 * @param data the data that was signed.
2317 * @param sig the sigature to verify.
2319 * @return An hx509 error code, see hx509_get_error_string().
2321 * @ingroup hx509_crypto
2325 hx509_verify_signature(hx509_context context
,
2326 const hx509_cert signer
,
2327 const AlgorithmIdentifier
*alg
,
2328 const heim_octet_string
*data
,
2329 const heim_octet_string
*sig
)
2331 return _hx509_verify_signature(context
, signer
, alg
, data
, sig
);
2335 _hx509_verify_signature_bitstring(hx509_context context
,
2336 const hx509_cert signer
,
2337 const AlgorithmIdentifier
*alg
,
2338 const heim_octet_string
*data
,
2339 const heim_bit_string
*sig
)
2341 heim_octet_string os
;
2343 if (sig
->length
& 7) {
2344 hx509_set_error_string(context
, 0, HX509_CRYPTO_SIG_INVALID_FORMAT
,
2345 "signature not multiple of 8 bits");
2346 return HX509_CRYPTO_SIG_INVALID_FORMAT
;
2349 os
.data
= sig
->data
;
2350 os
.length
= sig
->length
/ 8;
2352 return _hx509_verify_signature(context
, signer
, alg
, data
, &os
);
2358 * Verify that the certificate is allowed to be used for the hostname
2361 * @param context A hx509 context.
2362 * @param cert the certificate to match with
2363 * @param flags Flags to modify the behavior:
2364 * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok
2365 * @param type type of hostname:
2366 * - HX509_HN_HOSTNAME for plain hostname.
2367 * - HX509_HN_DNSSRV for DNS SRV names.
2368 * @param hostname the hostname to check
2369 * @param sa address of the host
2370 * @param sa_size length of address
2372 * @return An hx509 error code, see hx509_get_error_string().
2374 * @ingroup hx509_cert
2378 hx509_verify_hostname(hx509_context context
,
2379 const hx509_cert cert
,
2381 hx509_hostname_type type
,
2382 const char *hostname
,
2383 const struct sockaddr
*sa
,
2384 /* XXX krb5_socklen_t */ int sa_size
)
2390 if (sa
&& sa_size
<= 0)
2393 memset(&san
, 0, sizeof(san
));
2397 ret
= find_extension_subject_alt_name(cert
->data
, &i
, &san
);
2398 if (ret
== HX509_EXTENSION_NOT_FOUND
)
2401 return HX509_PARSING_NAME_FAILED
;
2403 for (j
= 0; j
< san
.len
; j
++) {
2404 switch (san
.val
[j
].element
) {
2405 case choice_GeneralName_dNSName
:
2406 if (strcasecmp(san
.val
[j
].u
.dNSName
, hostname
) == 0) {
2407 free_GeneralNames(&san
);
2415 free_GeneralNames(&san
);
2418 name
= &cert
->data
->tbsCertificate
.subject
;
2420 /* Find first CN= in the name, and try to match the hostname on that */
2421 for (ret
= 0, i
= name
->u
.rdnSequence
.len
- 1; ret
== 0 && i
>= 0; i
--) {
2422 for (j
= 0; ret
== 0 && j
< name
->u
.rdnSequence
.val
[i
].len
; j
++) {
2423 AttributeTypeAndValue
*n
= &name
->u
.rdnSequence
.val
[i
].val
[j
];
2425 if (der_heim_oid_cmp(&n
->type
, &asn1_oid_id_at_commonName
) == 0) {
2426 DirectoryString
*ds
= &n
->value
;
2427 switch (ds
->element
) {
2428 case choice_DirectoryString_printableString
:
2429 if (strcasecmp(ds
->u
.printableString
, hostname
) == 0)
2432 case choice_DirectoryString_ia5String
:
2433 if (strcasecmp(ds
->u
.ia5String
, hostname
) == 0)
2436 case choice_DirectoryString_utf8String
:
2437 if (strcasecmp(ds
->u
.utf8String
, hostname
) == 0)
2442 ret
= HX509_NAME_CONSTRAINT_ERROR
;
2447 if ((flags
& HX509_VHN_F_ALLOW_NO_MATCH
) == 0)
2448 ret
= HX509_NAME_CONSTRAINT_ERROR
;
2454 _hx509_set_cert_attribute(hx509_context context
,
2456 const heim_oid
*oid
,
2457 const heim_octet_string
*attr
)
2459 hx509_cert_attribute a
;
2462 if (hx509_cert_get_attribute(cert
, oid
) != NULL
)
2465 d
= realloc(cert
->attrs
.val
,
2466 sizeof(cert
->attrs
.val
[0]) * (cert
->attrs
.len
+ 1));
2468 hx509_clear_error_string(context
);
2471 cert
->attrs
.val
= d
;
2473 a
= malloc(sizeof(*a
));
2477 der_copy_octet_string(attr
, &a
->data
);
2478 der_copy_oid(oid
, &a
->oid
);
2480 cert
->attrs
.val
[cert
->attrs
.len
] = a
;
2487 * Get an external attribute for the certificate, examples are
2488 * friendly name and id.
2490 * @param cert hx509 certificate object to search
2491 * @param oid an oid to search for.
2493 * @return an hx509_cert_attribute, only valid as long as the
2494 * certificate is referenced.
2496 * @ingroup hx509_cert
2499 hx509_cert_attribute
2500 hx509_cert_get_attribute(hx509_cert cert
, const heim_oid
*oid
)
2503 for (i
= 0; i
< cert
->attrs
.len
; i
++)
2504 if (der_heim_oid_cmp(oid
, &cert
->attrs
.val
[i
]->oid
) == 0)
2505 return cert
->attrs
.val
[i
];
2510 * Set the friendly name on the certificate.
2512 * @param cert The certificate to set the friendly name on
2513 * @param name Friendly name.
2515 * @return An hx509 error code, see hx509_get_error_string().
2517 * @ingroup hx509_cert
2521 hx509_cert_set_friendly_name(hx509_cert cert
, const char *name
)
2523 if (cert
->friendlyname
)
2524 free(cert
->friendlyname
);
2525 cert
->friendlyname
= strdup(name
);
2526 if (cert
->friendlyname
== NULL
)
2532 * Get friendly name of the certificate.
2534 * @param cert cert to get the friendly name from.
2536 * @return an friendly name or NULL if there is. The friendly name is
2537 * only valid as long as the certificate is referenced.
2539 * @ingroup hx509_cert
2543 hx509_cert_get_friendly_name(hx509_cert cert
)
2545 hx509_cert_attribute a
;
2546 PKCS9_friendlyName n
;
2550 if (cert
->friendlyname
)
2551 return cert
->friendlyname
;
2553 a
= hx509_cert_get_attribute(cert
, &asn1_oid_id_pkcs_9_at_friendlyName
);
2557 ret
= hx509_cert_get_subject(cert
, &name
);
2560 ret
= hx509_name_to_string(name
, &cert
->friendlyname
);
2561 hx509_name_free(&name
);
2564 return cert
->friendlyname
;
2567 ret
= decode_PKCS9_friendlyName(a
->data
.data
, a
->data
.length
, &n
, &sz
);
2572 free_PKCS9_friendlyName(&n
);
2576 cert
->friendlyname
= malloc(n
.val
[0].length
+ 1);
2577 if (cert
->friendlyname
== NULL
) {
2578 free_PKCS9_friendlyName(&n
);
2582 for (i
= 0; i
< n
.val
[0].length
; i
++) {
2583 if (n
.val
[0].data
[i
] <= 0xff)
2584 cert
->friendlyname
[i
] = n
.val
[0].data
[i
] & 0xff;
2586 cert
->friendlyname
[i
] = 'X';
2588 cert
->friendlyname
[i
] = '\0';
2589 free_PKCS9_friendlyName(&n
);
2591 return cert
->friendlyname
;
2595 _hx509_query_clear(hx509_query
*q
)
2597 memset(q
, 0, sizeof(*q
));
2601 * Allocate an query controller. Free using hx509_query_free().
2603 * @param context A hx509 context.
2604 * @param q return pointer to a hx509_query.
2606 * @return An hx509 error code, see hx509_get_error_string().
2608 * @ingroup hx509_cert
2612 hx509_query_alloc(hx509_context context
, hx509_query
**q
)
2614 *q
= calloc(1, sizeof(**q
));
2622 * Set match options for the hx509 query controller.
2624 * @param q query controller.
2625 * @param option options to control the query controller.
2627 * @return An hx509 error code, see hx509_get_error_string().
2629 * @ingroup hx509_cert
2633 hx509_query_match_option(hx509_query
*q
, hx509_query_option option
)
2636 case HX509_QUERY_OPTION_PRIVATE_KEY
:
2637 q
->match
|= HX509_QUERY_PRIVATE_KEY
;
2639 case HX509_QUERY_OPTION_KU_ENCIPHERMENT
:
2640 q
->match
|= HX509_QUERY_KU_ENCIPHERMENT
;
2642 case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE
:
2643 q
->match
|= HX509_QUERY_KU_DIGITALSIGNATURE
;
2645 case HX509_QUERY_OPTION_KU_KEYCERTSIGN
:
2646 q
->match
|= HX509_QUERY_KU_KEYCERTSIGN
;
2648 case HX509_QUERY_OPTION_END
:
2655 * Set the issuer and serial number of match in the query
2656 * controller. The function make copies of the isser and serial number.
2658 * @param q a hx509 query controller
2659 * @param issuer issuer to search for
2660 * @param serialNumber the serialNumber of the issuer.
2662 * @return An hx509 error code, see hx509_get_error_string().
2664 * @ingroup hx509_cert
2668 hx509_query_match_issuer_serial(hx509_query
*q
,
2670 const heim_integer
*serialNumber
)
2674 der_free_heim_integer(q
->serial
);
2677 q
->serial
= malloc(sizeof(*q
->serial
));
2678 if (q
->serial
== NULL
)
2680 ret
= der_copy_heim_integer(serialNumber
, q
->serial
);
2686 if (q
->issuer_name
) {
2687 free_Name(q
->issuer_name
);
2688 free(q
->issuer_name
);
2690 q
->issuer_name
= malloc(sizeof(*q
->issuer_name
));
2691 if (q
->issuer_name
== NULL
)
2693 ret
= copy_Name(issuer
, q
->issuer_name
);
2695 free(q
->issuer_name
);
2696 q
->issuer_name
= NULL
;
2699 q
->match
|= HX509_QUERY_MATCH_SERIALNUMBER
|HX509_QUERY_MATCH_ISSUER_NAME
;
2704 * Set the query controller to match on a friendly name
2706 * @param q a hx509 query controller.
2707 * @param name a friendly name to match on
2709 * @return An hx509 error code, see hx509_get_error_string().
2711 * @ingroup hx509_cert
2715 hx509_query_match_friendly_name(hx509_query
*q
, const char *name
)
2717 if (q
->friendlyname
)
2718 free(q
->friendlyname
);
2719 q
->friendlyname
= strdup(name
);
2720 if (q
->friendlyname
== NULL
)
2722 q
->match
|= HX509_QUERY_MATCH_FRIENDLY_NAME
;
2727 * Set the query controller to require an one specific EKU (extended
2728 * key usage). Any previous EKU matching is overwitten. If NULL is
2729 * passed in as the eku, the EKU requirement is reset.
2731 * @param q a hx509 query controller.
2732 * @param eku an EKU to match on.
2734 * @return An hx509 error code, see hx509_get_error_string().
2736 * @ingroup hx509_cert
2740 hx509_query_match_eku(hx509_query
*q
, const heim_oid
*eku
)
2746 der_free_oid(q
->eku
);
2750 q
->match
&= ~HX509_QUERY_MATCH_EKU
;
2753 der_free_oid(q
->eku
);
2755 q
->eku
= calloc(1, sizeof(*q
->eku
));
2759 ret
= der_copy_oid(eku
, q
->eku
);
2765 q
->match
|= HX509_QUERY_MATCH_EKU
;
2771 hx509_query_match_expr(hx509_context context
, hx509_query
*q
, const char *expr
)
2774 _hx509_expr_free(q
->expr
);
2779 q
->match
&= ~HX509_QUERY_MATCH_EXPR
;
2781 q
->expr
= _hx509_expr_parse(expr
);
2783 q
->match
|= HX509_QUERY_MATCH_EXPR
;
2790 * Set the query controller to match using a specific match function.
2792 * @param q a hx509 query controller.
2793 * @param func function to use for matching, if the argument is NULL,
2794 * the match function is removed.
2795 * @param ctx context passed to the function.
2797 * @return An hx509 error code, see hx509_get_error_string().
2799 * @ingroup hx509_cert
2803 hx509_query_match_cmp_func(hx509_query
*q
,
2804 int (*func
)(hx509_context
, hx509_cert
, void *),
2808 q
->match
|= HX509_QUERY_MATCH_FUNCTION
;
2810 q
->match
&= ~HX509_QUERY_MATCH_FUNCTION
;
2812 q
->cmp_func_ctx
= ctx
;
2817 * Free the query controller.
2819 * @param context A hx509 context.
2820 * @param q a pointer to the query controller.
2822 * @ingroup hx509_cert
2826 hx509_query_free(hx509_context context
, hx509_query
*q
)
2832 der_free_heim_integer(q
->serial
);
2835 if (q
->issuer_name
) {
2836 free_Name(q
->issuer_name
);
2837 free(q
->issuer_name
);
2840 der_free_oid(q
->eku
);
2843 if (q
->friendlyname
)
2844 free(q
->friendlyname
);
2846 _hx509_expr_free(q
->expr
);
2848 memset(q
, 0, sizeof(*q
));
2853 _hx509_query_match_cert(hx509_context context
, const hx509_query
*q
, hx509_cert cert
)
2855 Certificate
*c
= _hx509_get_cert(cert
);
2858 _hx509_query_statistic(context
, 1, q
);
2860 if ((q
->match
& HX509_QUERY_FIND_ISSUER_CERT
) &&
2861 _hx509_cert_is_parent_cmp(q
->subject
, c
, 0) != 0)
2864 if ((q
->match
& HX509_QUERY_MATCH_CERTIFICATE
) &&
2865 _hx509_Certificate_cmp(q
->certificate
, c
) != 0)
2868 if ((q
->match
& HX509_QUERY_MATCH_SERIALNUMBER
)
2869 && der_heim_integer_cmp(&c
->tbsCertificate
.serialNumber
, q
->serial
) != 0)
2872 if (q
->match
& HX509_QUERY_MATCH_ISSUER_NAME
) {
2873 ret
= _hx509_name_cmp(&c
->tbsCertificate
.issuer
, q
->issuer_name
, &diff
);
2878 if (q
->match
& HX509_QUERY_MATCH_SUBJECT_NAME
) {
2879 ret
= _hx509_name_cmp(&c
->tbsCertificate
.subject
, q
->subject_name
, &diff
);
2884 if (q
->match
& HX509_QUERY_MATCH_SUBJECT_KEY_ID
) {
2885 SubjectKeyIdentifier si
;
2887 ret
= _hx509_find_extension_subject_key_id(c
, &si
);
2889 if (der_heim_octet_string_cmp(&si
, q
->subject_id
) != 0)
2891 free_SubjectKeyIdentifier(&si
);
2896 if ((q
->match
& HX509_QUERY_MATCH_ISSUER_ID
))
2898 if ((q
->match
& HX509_QUERY_PRIVATE_KEY
) &&
2899 _hx509_cert_private_key(cert
) == NULL
)
2904 if (q
->match
& HX509_QUERY_KU_DIGITALSIGNATURE
)
2906 if (q
->match
& HX509_QUERY_KU_NONREPUDIATION
)
2908 if (q
->match
& HX509_QUERY_KU_ENCIPHERMENT
)
2910 if (q
->match
& HX509_QUERY_KU_DATAENCIPHERMENT
)
2912 if (q
->match
& HX509_QUERY_KU_KEYAGREEMENT
)
2914 if (q
->match
& HX509_QUERY_KU_KEYCERTSIGN
)
2916 if (q
->match
& HX509_QUERY_KU_CRLSIGN
)
2918 if (ku
&& check_key_usage(context
, c
, ku
, TRUE
))
2921 if ((q
->match
& HX509_QUERY_ANCHOR
))
2924 if (q
->match
& HX509_QUERY_MATCH_LOCAL_KEY_ID
) {
2925 hx509_cert_attribute a
;
2927 a
= hx509_cert_get_attribute(cert
, &asn1_oid_id_pkcs_9_at_localKeyId
);
2930 if (der_heim_octet_string_cmp(&a
->data
, q
->local_key_id
) != 0)
2934 if (q
->match
& HX509_QUERY_NO_MATCH_PATH
) {
2937 for (i
= 0; i
< q
->path
->len
; i
++)
2938 if (hx509_cert_cmp(q
->path
->val
[i
], cert
) == 0)
2941 if (q
->match
& HX509_QUERY_MATCH_FRIENDLY_NAME
) {
2942 const char *name
= hx509_cert_get_friendly_name(cert
);
2945 if (strcasecmp(q
->friendlyname
, name
) != 0)
2948 if (q
->match
& HX509_QUERY_MATCH_FUNCTION
) {
2949 ret
= (*q
->cmp_func
)(context
, cert
, q
->cmp_func_ctx
);
2954 if (q
->match
& HX509_QUERY_MATCH_KEY_HASH_SHA1
) {
2955 heim_octet_string os
;
2957 os
.data
= c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.data
;
2959 c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.length
/ 8;
2961 ret
= _hx509_verify_signature(context
,
2963 hx509_signature_sha1(),
2970 if (q
->match
& HX509_QUERY_MATCH_TIME
) {
2972 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
2975 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notAfter
);
2980 /* If an EKU is required, check the cert for it. */
2981 if ((q
->match
& HX509_QUERY_MATCH_EKU
) &&
2982 hx509_cert_check_eku(context
, cert
, q
->eku
, 0))
2985 if ((q
->match
& HX509_QUERY_MATCH_EXPR
)) {
2986 hx509_env env
= NULL
;
2988 ret
= _hx509_cert_to_env(context
, cert
, &env
);
2992 ret
= _hx509_expr_eval(context
, env
, q
->expr
);
2993 hx509_env_free(&env
);
2998 if (q
->match
& ~HX509_QUERY_MASK
)
3005 * Set a statistic file for the query statistics.
3007 * @param context A hx509 context.
3008 * @param fn statistics file name
3010 * @ingroup hx509_cert
3014 hx509_query_statistic_file(hx509_context context
, const char *fn
)
3016 if (context
->querystat
)
3017 free(context
->querystat
);
3018 context
->querystat
= strdup(fn
);
3022 _hx509_query_statistic(hx509_context context
, int type
, const hx509_query
*q
)
3025 if (context
->querystat
== NULL
)
3027 f
= fopen(context
->querystat
, "a");
3031 fprintf(f
, "%d %d\n", type
, q
->match
);
3035 static const char *statname
[] = {
3037 "match serialnumber",
3038 "match issuer name",
3039 "match subject name",
3040 "match subject key id",
3044 "ku digitalsignature",
3047 "ku nonrepudiation",
3049 "ku dataencipherment",
3051 "match certificate",
3052 "match local key id",
3054 "match friendly name",
3056 "match key hash sha1",
3061 unsigned long stats
;
3067 stat_sort(const void *a
, const void *b
)
3069 const struct stat_el
*ae
= a
;
3070 const struct stat_el
*be
= b
;
3071 return be
->stats
- ae
->stats
;
3075 * Unparse the statistics file and print the result on a FILE descriptor.
3077 * @param context A hx509 context.
3078 * @param printtype tyep to print
3079 * @param out the FILE to write the data on.
3081 * @ingroup hx509_cert
3085 hx509_query_unparse_stats(hx509_context context
, int printtype
, FILE *out
)
3089 int type
, mask
, i
, num
;
3090 unsigned long multiqueries
= 0, totalqueries
= 0;
3091 struct stat_el stats
[32];
3093 if (context
->querystat
== NULL
)
3095 f
= fopen(context
->querystat
, "r");
3097 fprintf(out
, "No statistic file %s: %s.\n",
3098 context
->querystat
, strerror(errno
));
3103 for (i
= 0; i
< sizeof(stats
)/sizeof(stats
[0]); i
++) {
3108 while (fscanf(f
, "%d %d\n", &type
, &mask
) == 2) {
3109 if (type
!= printtype
)
3112 while (mask
&& i
< sizeof(stats
)/sizeof(stats
[0])) {
3126 qsort(stats
, sizeof(stats
)/sizeof(stats
[0]), sizeof(stats
[0]), stat_sort
);
3130 errx(1, "out of memory");
3132 rtbl_set_separator (t
, " ");
3134 rtbl_add_column_by_id (t
, 0, "Name", 0);
3135 rtbl_add_column_by_id (t
, 1, "Counter", 0);
3138 for (i
= 0; i
< sizeof(stats
)/sizeof(stats
[0]); i
++) {
3141 if (stats
[i
].index
< sizeof(statname
)/sizeof(statname
[0]))
3142 rtbl_add_column_entry_by_id (t
, 0, statname
[stats
[i
].index
]);
3144 snprintf(str
, sizeof(str
), "%d", stats
[i
].index
);
3145 rtbl_add_column_entry_by_id (t
, 0, str
);
3147 snprintf(str
, sizeof(str
), "%lu", stats
[i
].stats
);
3148 rtbl_add_column_entry_by_id (t
, 1, str
);
3151 rtbl_format(t
, out
);
3154 fprintf(out
, "\nQueries: multi %lu total %lu\n",
3155 multiqueries
, totalqueries
);
3159 * Check the extended key usage on the hx509 certificate.
3161 * @param context A hx509 context.
3162 * @param cert A hx509 context.
3163 * @param eku the EKU to check for
3164 * @param allow_any_eku if the any EKU is set, allow that to be a
3167 * @return An hx509 error code, see hx509_get_error_string().
3169 * @ingroup hx509_cert
3173 hx509_cert_check_eku(hx509_context context
, hx509_cert cert
,
3174 const heim_oid
*eku
, int allow_any_eku
)
3179 ret
= find_extension_eku(_hx509_get_cert(cert
), &e
);
3181 hx509_clear_error_string(context
);
3185 for (i
= 0; i
< e
.len
; i
++) {
3186 if (der_heim_oid_cmp(eku
, &e
.val
[i
]) == 0) {
3187 free_ExtKeyUsage(&e
);
3190 if (allow_any_eku
) {
3192 if (der_heim_oid_cmp(id_any_eku
, &e
.val
[i
]) == 0) {
3193 free_ExtKeyUsage(&e
);
3199 free_ExtKeyUsage(&e
);
3200 hx509_clear_error_string(context
);
3201 return HX509_CERTIFICATE_MISSING_EKU
;
3205 _hx509_cert_get_keyusage(hx509_context context
,
3214 memset(ku
, 0, sizeof(*ku
));
3216 cert
= _hx509_get_cert(c
);
3218 if (_hx509_cert_get_version(cert
) < 3)
3221 e
= find_extension(cert
, &asn1_oid_id_x509_ce_keyUsage
, &i
);
3223 return HX509_KU_CERT_MISSING
;
3225 ret
= decode_KeyUsage(e
->extnValue
.data
, e
->extnValue
.length
, ku
, &size
);
3232 _hx509_cert_get_eku(hx509_context context
,
3238 memset(e
, 0, sizeof(*e
));
3240 ret
= find_extension_eku(_hx509_get_cert(cert
), e
);
3241 if (ret
&& ret
!= HX509_EXTENSION_NOT_FOUND
) {
3242 hx509_clear_error_string(context
);
3249 * Encodes the hx509 certificate as a DER encode binary.
3251 * @param context A hx509 context.
3252 * @param c the certificate to encode.
3253 * @param os the encode certificate, set to NULL, 0 on case of
3254 * error. Free the returned structure with hx509_xfree().
3256 * @return An hx509 error code, see hx509_get_error_string().
3258 * @ingroup hx509_cert
3262 hx509_cert_binary(hx509_context context
, hx509_cert c
, heim_octet_string
*os
)
3270 ASN1_MALLOC_ENCODE(Certificate
, os
->data
, os
->length
,
3271 _hx509_get_cert(c
), &size
, ret
);
3277 if (os
->length
!= size
)
3278 _hx509_abort("internal ASN.1 encoder error");
3284 * Last to avoid lost __attribute__s due to #undef.
3287 #undef __attribute__
3288 #define __attribute__(X)
3291 _hx509_abort(const char *fmt
, ...)
3292 __attribute__ ((noreturn
, format (printf
, 1, 2)))
3304 * Free a data element allocated in the library.
3306 * @param ptr data to be freed.
3308 * @ingroup hx509_misc
3312 hx509_xfree(void *ptr
)
3322 _hx509_cert_to_env(hx509_context context
, hx509_cert cert
, hx509_env
*env
)
3328 hx509_env envcert
= NULL
;
3333 asprintf(&buf
, "%d", _hx509_cert_get_version(_hx509_get_cert(cert
)));
3334 ret
= hx509_env_add(context
, &envcert
, "version", buf
);
3340 ret
= hx509_cert_get_subject(cert
, &name
);
3344 ret
= hx509_name_to_string(name
, &buf
);
3346 hx509_name_free(&name
);
3350 ret
= hx509_env_add(context
, &envcert
, "subject", buf
);
3351 hx509_name_free(&name
);
3356 ret
= hx509_cert_get_issuer(cert
, &name
);
3360 ret
= hx509_name_to_string(name
, &buf
);
3361 hx509_name_free(&name
);
3365 ret
= hx509_env_add(context
, &envcert
, "issuer", buf
);
3372 ret
= _hx509_cert_get_eku(context
, cert
, &eku
);
3373 if (ret
== HX509_EXTENSION_NOT_FOUND
)
3379 hx509_env enveku
= NULL
;
3381 for (i
= 0; i
< eku
.len
; i
++) {
3383 ret
= der_print_heim_oid(&eku
.val
[i
], '.', &buf
);
3385 free_ExtKeyUsage(&eku
);
3386 hx509_env_free(&enveku
);
3389 ret
= hx509_env_add(context
, &enveku
, buf
, "oid-name-here");
3392 free_ExtKeyUsage(&eku
);
3393 hx509_env_free(&enveku
);
3397 free_ExtKeyUsage(&eku
);
3399 ret
= hx509_env_add_binding(context
, &envcert
, "eku", enveku
);
3401 hx509_env_free(&enveku
);
3407 Certificate
*c
= _hx509_get_cert(cert
);
3408 heim_octet_string os
, sig
;
3409 hx509_env envhash
= NULL
;
3411 os
.data
= c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.data
;
3413 c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.length
/ 8;
3415 ret
= _hx509_create_signature(context
,
3417 hx509_signature_sha1(),
3424 ret
= hex_encode(sig
.data
, sig
.length
, &buf
);
3425 der_free_octet_string(&sig
);
3428 hx509_set_error_string(context
, 0, ret
,
3433 ret
= hx509_env_add(context
, &envhash
, "sha1", buf
);
3438 ret
= hx509_env_add_binding(context
, &envcert
, "hash", envhash
);
3440 hx509_env_free(&envhash
);
3445 ret
= hx509_env_add_binding(context
, env
, "certificate", envcert
);
3452 hx509_env_free(&envcert
);
3457 * Print a simple representation of a certificate
3459 * @param context A hx509 context, can be NULL
3460 * @param cert certificate to print
3461 * @param out the stdio output stream, if NULL, stdout is used
3463 * @return An hx509 error code
3465 * @ingroup hx509_cert
3469 hx509_print_cert(hx509_context context
, hx509_cert cert
, FILE *out
)
3478 ret
= hx509_cert_get_issuer(cert
, &name
);
3481 hx509_name_to_string(name
, &str
);
3482 hx509_name_free(&name
);
3483 fprintf(out
, " issuer: \"%s\"\n", str
);
3486 ret
= hx509_cert_get_subject(cert
, &name
);
3489 hx509_name_to_string(name
, &str
);
3490 hx509_name_free(&name
);
3491 fprintf(out
, " subject: \"%s\"\n", str
);
3495 heim_integer serialNumber
;
3497 ret
= hx509_cert_get_serialnumber(cert
, &serialNumber
);
3500 ret
= der_print_hex_heim_integer(&serialNumber
, &str
);
3503 der_free_heim_integer(&serialNumber
);
3504 fprintf(out
, " serial: %s\n", str
);
3508 printf(" keyusage: ");
3509 ret
= hx509_cert_keyusage_print(context
, cert
, &str
);
3511 fprintf(out
, "%s\n", str
);