1 /* $NetBSD: cert.c,v 1.3 2014/04/24 13:45:34 pettai Exp $ */
4 * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #include "crypto-headers.h"
38 #include <krb5/rtbl.h>
41 * @page page_cert The basic certificate
43 * The basic hx509 cerificate object in hx509 is hx509_cert. The
44 * hx509_cert object is representing one X509/PKIX certificate and
45 * associated attributes; like private key, friendly name, etc.
47 * A hx509_cert object is usully found via the keyset interfaces (@ref
48 * page_keyset), but its also possible to create a certificate
49 * directly from a parsed object with hx509_cert_init() and
50 * hx509_cert_init_data().
52 * See the library functions here: @ref hx509_cert
55 struct hx509_verify_ctx_data
{
56 hx509_certs trust_anchors
;
58 #define HX509_VERIFY_CTX_F_TIME_SET 1
59 #define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE 2
60 #define HX509_VERIFY_CTX_F_REQUIRE_RFC3280 4
61 #define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS 8
62 #define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS 16
63 #define HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK 32
65 unsigned int max_depth
;
66 #define HX509_VERIFY_MAX_DEPTH 30
67 hx509_revoke_ctx revoke_ctx
;
70 #define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280)
71 #define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS)
72 #define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0)
74 struct _hx509_cert_attrs
{
76 hx509_cert_attribute
*val
;
79 struct hx509_cert_data
{
83 hx509_private_key private_key
;
84 struct _hx509_cert_attrs attrs
;
86 _hx509_cert_release_func release
;
90 typedef struct hx509_name_constraints
{
93 } hx509_name_constraints
;
95 #define GeneralSubtrees_SET(g,var) \
96 (g)->len = (var)->len, (g)->val = (var)->val;
99 * Creates a hx509 context that most functions in the library
100 * uses. The context is only allowed to be used by one thread at each
101 * moment. Free the context with hx509_context_free().
103 * @param context Returns a pointer to new hx509 context.
105 * @return Returns an hx509 error code.
111 hx509_context_init(hx509_context
*context
)
113 *context
= calloc(1, sizeof(**context
));
114 if (*context
== NULL
)
117 _hx509_ks_null_register(*context
);
118 _hx509_ks_mem_register(*context
);
119 _hx509_ks_file_register(*context
);
120 _hx509_ks_pkcs12_register(*context
);
121 _hx509_ks_pkcs11_register(*context
);
122 _hx509_ks_dir_register(*context
);
123 _hx509_ks_keychain_register(*context
);
125 ENGINE_add_conf_module();
126 OpenSSL_add_all_algorithms();
128 (*context
)->ocsp_time_diff
= HX509_DEFAULT_OCSP_TIME_DIFF
;
130 initialize_hx_error_table_r(&(*context
)->et_list
);
131 initialize_asn1_error_table_r(&(*context
)->et_list
);
133 #ifdef HX509_DEFAULT_ANCHORS
134 (void)hx509_certs_init(*context
, HX509_DEFAULT_ANCHORS
, 0,
135 NULL
, &(*context
)->default_trust_anchors
);
142 * Selects if the hx509_revoke_verify() function is going to require
143 * the existans of a revokation method (OCSP, CRL) or not. Note that
144 * hx509_verify_path(), hx509_cms_verify_signed(), and other function
145 * call hx509_revoke_verify().
147 * @param context hx509 context to change the flag for.
148 * @param flag zero, revokation method required, non zero missing
149 * revokation method ok
151 * @ingroup hx509_verify
155 hx509_context_set_missing_revoke(hx509_context context
, int flag
)
158 context
->flags
|= HX509_CTX_VERIFY_MISSING_OK
;
160 context
->flags
&= ~HX509_CTX_VERIFY_MISSING_OK
;
164 * Free the context allocated by hx509_context_init().
166 * @param context context to be freed.
172 hx509_context_free(hx509_context
*context
)
174 hx509_clear_error_string(*context
);
175 if ((*context
)->ks_ops
) {
176 free((*context
)->ks_ops
);
177 (*context
)->ks_ops
= NULL
;
179 (*context
)->ks_num_ops
= 0;
180 free_error_table ((*context
)->et_list
);
181 if ((*context
)->querystat
)
182 free((*context
)->querystat
);
183 memset(*context
, 0, sizeof(**context
));
193 _hx509_get_cert(hx509_cert cert
)
203 _hx509_cert_get_version(const Certificate
*t
)
205 return t
->tbsCertificate
.version
? *t
->tbsCertificate
.version
+ 1 : 1;
209 * Allocate and init an hx509 certificate object from the decoded
212 * @param context A hx509 context.
216 * @return Returns an hx509 error code.
218 * @ingroup hx509_cert
222 hx509_cert_init(hx509_context context
, const Certificate
*c
, hx509_cert
*cert
)
226 *cert
= malloc(sizeof(**cert
));
230 (*cert
)->friendlyname
= NULL
;
231 (*cert
)->attrs
.len
= 0;
232 (*cert
)->attrs
.val
= NULL
;
233 (*cert
)->private_key
= NULL
;
234 (*cert
)->basename
= NULL
;
235 (*cert
)->release
= NULL
;
238 (*cert
)->data
= calloc(1, sizeof(*(*cert
)->data
));
239 if ((*cert
)->data
== NULL
) {
243 ret
= copy_Certificate(c
, (*cert
)->data
);
253 * Just like hx509_cert_init(), but instead of a decode certificate
254 * takes an pointer and length to a memory region that contains a
255 * DER/BER encoded certificate.
257 * If the memory region doesn't contain just the certificate and
258 * nothing more the function will fail with
259 * HX509_EXTRA_DATA_AFTER_STRUCTURE.
261 * @param context A hx509 context.
262 * @param ptr pointer to memory region containing encoded certificate.
263 * @param len length of memory region.
264 * @param cert a return pointer to a hx509 certificate object, will
265 * contain NULL on error.
267 * @return An hx509 error code, see hx509_get_error_string().
269 * @ingroup hx509_cert
273 hx509_cert_init_data(hx509_context context
,
282 ret
= decode_Certificate(ptr
, len
, &t
, &size
);
284 hx509_set_error_string(context
, 0, ret
, "Failed to decode certificate");
288 free_Certificate(&t
);
289 hx509_set_error_string(context
, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE
,
290 "Extra data after certificate");
291 return HX509_EXTRA_DATA_AFTER_STRUCTURE
;
294 ret
= hx509_cert_init(context
, &t
, cert
);
295 free_Certificate(&t
);
300 _hx509_cert_set_release(hx509_cert cert
,
301 _hx509_cert_release_func release
,
304 cert
->release
= release
;
309 /* Doesn't make a copy of `private_key'. */
312 _hx509_cert_assign_key(hx509_cert cert
, hx509_private_key private_key
)
314 if (cert
->private_key
)
315 hx509_private_key_free(&cert
->private_key
);
316 cert
->private_key
= _hx509_private_key_ref(private_key
);
321 * Free reference to the hx509 certificate object, if the refcounter
322 * reaches 0, the object if freed. Its allowed to pass in NULL.
324 * @param cert the cert to free.
326 * @ingroup hx509_cert
330 hx509_cert_free(hx509_cert cert
)
338 _hx509_abort("cert refcount <= 0 on free");
343 (cert
->release
)(cert
, cert
->ctx
);
345 if (cert
->private_key
)
346 hx509_private_key_free(&cert
->private_key
);
348 free_Certificate(cert
->data
);
351 for (i
= 0; i
< cert
->attrs
.len
; i
++) {
352 der_free_octet_string(&cert
->attrs
.val
[i
]->data
);
353 der_free_oid(&cert
->attrs
.val
[i
]->oid
);
354 free(cert
->attrs
.val
[i
]);
356 free(cert
->attrs
.val
);
357 free(cert
->friendlyname
);
359 hx509_name_free(&cert
->basename
);
360 memset(cert
, 0, sizeof(*cert
));
365 * Add a reference to a hx509 certificate object.
367 * @param cert a pointer to an hx509 certificate object.
369 * @return the same object as is passed in.
371 * @ingroup hx509_cert
375 hx509_cert_ref(hx509_cert cert
)
380 _hx509_abort("cert refcount <= 0");
383 _hx509_abort("cert refcount == 0");
388 * Allocate an verification context that is used fo control the
389 * verification process.
391 * @param context A hx509 context.
392 * @param ctx returns a pointer to a hx509_verify_ctx object.
394 * @return An hx509 error code, see hx509_get_error_string().
396 * @ingroup hx509_verify
400 hx509_verify_init_ctx(hx509_context context
, hx509_verify_ctx
*ctx
)
404 c
= calloc(1, sizeof(*c
));
408 c
->max_depth
= HX509_VERIFY_MAX_DEPTH
;
416 * Free an hx509 verification context.
418 * @param ctx the context to be freed.
420 * @ingroup hx509_verify
424 hx509_verify_destroy_ctx(hx509_verify_ctx ctx
)
427 hx509_certs_free(&ctx
->trust_anchors
);
428 hx509_revoke_free(&ctx
->revoke_ctx
);
429 memset(ctx
, 0, sizeof(*ctx
));
435 * Set the trust anchors in the verification context, makes an
436 * reference to the keyset, so the consumer can free the keyset
437 * independent of the destruction of the verification context (ctx).
438 * If there already is a keyset attached, it's released.
440 * @param ctx a verification context
441 * @param set a keyset containing the trust anchors.
443 * @ingroup hx509_verify
447 hx509_verify_attach_anchors(hx509_verify_ctx ctx
, hx509_certs set
)
449 if (ctx
->trust_anchors
)
450 hx509_certs_free(&ctx
->trust_anchors
);
451 ctx
->trust_anchors
= hx509_certs_ref(set
);
455 * Attach an revocation context to the verfication context, , makes an
456 * reference to the revoke context, so the consumer can free the
457 * revoke context independent of the destruction of the verification
458 * context. If there is no revoke context, the verification process is
459 * NOT going to check any verification status.
461 * @param ctx a verification context.
462 * @param revoke_ctx a revoke context.
464 * @ingroup hx509_verify
468 hx509_verify_attach_revoke(hx509_verify_ctx ctx
, hx509_revoke_ctx revoke_ctx
)
471 hx509_revoke_free(&ctx
->revoke_ctx
);
472 ctx
->revoke_ctx
= _hx509_revoke_ref(revoke_ctx
);
476 * Set the clock time the the verification process is going to
477 * use. Used to check certificate in the past and future time. If not
478 * set the current time will be used.
480 * @param ctx a verification context.
481 * @param t the time the verifiation is using.
484 * @ingroup hx509_verify
488 hx509_verify_set_time(hx509_verify_ctx ctx
, time_t t
)
490 ctx
->flags
|= HX509_VERIFY_CTX_F_TIME_SET
;
495 _hx509_verify_get_time(hx509_verify_ctx ctx
)
497 return ctx
->time_now
;
501 * Set the maximum depth of the certificate chain that the path
502 * builder is going to try.
504 * @param ctx a verification context
505 * @param max_depth maxium depth of the certificate chain, include
508 * @ingroup hx509_verify
512 hx509_verify_set_max_depth(hx509_verify_ctx ctx
, unsigned int max_depth
)
514 ctx
->max_depth
= max_depth
;
518 * Allow or deny the use of proxy certificates
520 * @param ctx a verification context
521 * @param boolean if non zero, allow proxy certificates.
523 * @ingroup hx509_verify
527 hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx
, int boolean
)
530 ctx
->flags
|= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
;
532 ctx
->flags
&= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
;
536 * Select strict RFC3280 verification of certificiates. This means
537 * checking key usage on CA certificates, this will make version 1
538 * certificiates unuseable.
540 * @param ctx a verification context
541 * @param boolean if non zero, use strict verification.
543 * @ingroup hx509_verify
547 hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx
, int boolean
)
550 ctx
->flags
|= HX509_VERIFY_CTX_F_REQUIRE_RFC3280
;
552 ctx
->flags
&= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280
;
556 * Allow using the operating system builtin trust anchors if no other
557 * trust anchors are configured.
559 * @param ctx a verification context
560 * @param boolean if non zero, useing the operating systems builtin
564 * @return An hx509 error code, see hx509_get_error_string().
566 * @ingroup hx509_cert
570 hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx
, int boolean
)
573 ctx
->flags
&= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS
;
575 ctx
->flags
|= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS
;
579 hx509_verify_ctx_f_allow_best_before_signature_algs(hx509_context ctx
,
583 ctx
->flags
&= ~HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK
;
585 ctx
->flags
|= HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK
;
588 static const Extension
*
589 find_extension(const Certificate
*cert
, const heim_oid
*oid
, size_t *idx
)
591 const TBSCertificate
*c
= &cert
->tbsCertificate
;
593 if (c
->version
== NULL
|| *c
->version
< 2 || c
->extensions
== NULL
)
596 for (;*idx
< c
->extensions
->len
; (*idx
)++) {
597 if (der_heim_oid_cmp(&c
->extensions
->val
[*idx
].extnID
, oid
) == 0)
598 return &c
->extensions
->val
[(*idx
)++];
604 find_extension_auth_key_id(const Certificate
*subject
,
605 AuthorityKeyIdentifier
*ai
)
611 memset(ai
, 0, sizeof(*ai
));
613 e
= find_extension(subject
, &asn1_oid_id_x509_ce_authorityKeyIdentifier
, &i
);
615 return HX509_EXTENSION_NOT_FOUND
;
617 return decode_AuthorityKeyIdentifier(e
->extnValue
.data
,
623 _hx509_find_extension_subject_key_id(const Certificate
*issuer
,
624 SubjectKeyIdentifier
*si
)
630 memset(si
, 0, sizeof(*si
));
632 e
= find_extension(issuer
, &asn1_oid_id_x509_ce_subjectKeyIdentifier
, &i
);
634 return HX509_EXTENSION_NOT_FOUND
;
636 return decode_SubjectKeyIdentifier(e
->extnValue
.data
,
642 find_extension_name_constraints(const Certificate
*subject
,
649 memset(nc
, 0, sizeof(*nc
));
651 e
= find_extension(subject
, &asn1_oid_id_x509_ce_nameConstraints
, &i
);
653 return HX509_EXTENSION_NOT_FOUND
;
655 return decode_NameConstraints(e
->extnValue
.data
,
661 find_extension_subject_alt_name(const Certificate
*cert
, size_t *i
,
667 memset(sa
, 0, sizeof(*sa
));
669 e
= find_extension(cert
, &asn1_oid_id_x509_ce_subjectAltName
, i
);
671 return HX509_EXTENSION_NOT_FOUND
;
673 return decode_GeneralNames(e
->extnValue
.data
,
679 find_extension_eku(const Certificate
*cert
, ExtKeyUsage
*eku
)
685 memset(eku
, 0, sizeof(*eku
));
687 e
= find_extension(cert
, &asn1_oid_id_x509_ce_extKeyUsage
, &i
);
689 return HX509_EXTENSION_NOT_FOUND
;
691 return decode_ExtKeyUsage(e
->extnValue
.data
,
697 add_to_list(hx509_octet_string_list
*list
, const heim_octet_string
*entry
)
702 p
= realloc(list
->val
, (list
->len
+ 1) * sizeof(list
->val
[0]));
706 ret
= der_copy_octet_string(entry
, &list
->val
[list
->len
]);
714 * Free a list of octet strings returned by another hx509 library
717 * @param list list to be freed.
719 * @ingroup hx509_misc
723 hx509_free_octet_string_list(hx509_octet_string_list
*list
)
726 for (i
= 0; i
< list
->len
; i
++)
727 der_free_octet_string(&list
->val
[i
]);
734 * Return a list of subjectAltNames specified by oid in the
735 * certificate. On error the
737 * The returned list of octet string should be freed with
738 * hx509_free_octet_string_list().
740 * @param context A hx509 context.
741 * @param cert a hx509 certificate object.
742 * @param oid an oid to for SubjectAltName.
743 * @param list list of matching SubjectAltName.
745 * @return An hx509 error code, see hx509_get_error_string().
747 * @ingroup hx509_cert
751 hx509_cert_find_subjectAltName_otherName(hx509_context context
,
754 hx509_octet_string_list
*list
)
765 ret
= find_extension_subject_alt_name(_hx509_get_cert(cert
), &i
, &sa
);
767 if (ret
== HX509_EXTENSION_NOT_FOUND
) {
769 } else if (ret
!= 0) {
770 hx509_set_error_string(context
, 0, ret
, "Error searching for SAN");
771 hx509_free_octet_string_list(list
);
775 for (j
= 0; j
< sa
.len
; j
++) {
776 if (sa
.val
[j
].element
== choice_GeneralName_otherName
&&
777 der_heim_oid_cmp(&sa
.val
[j
].u
.otherName
.type_id
, oid
) == 0)
779 ret
= add_to_list(list
, &sa
.val
[j
].u
.otherName
.value
);
781 hx509_set_error_string(context
, 0, ret
,
782 "Error adding an exra SAN to "
784 hx509_free_octet_string_list(list
);
785 free_GeneralNames(&sa
);
790 free_GeneralNames(&sa
);
796 check_key_usage(hx509_context context
, const Certificate
*cert
,
797 unsigned flags
, int req_present
)
806 if (_hx509_cert_get_version(cert
) < 3)
809 e
= find_extension(cert
, &asn1_oid_id_x509_ce_keyUsage
, &i
);
812 hx509_set_error_string(context
, 0, HX509_KU_CERT_MISSING
,
813 "Required extension key "
814 "usage missing from certifiate");
815 return HX509_KU_CERT_MISSING
;
820 ret
= decode_KeyUsage(e
->extnValue
.data
, e
->extnValue
.length
, &ku
, &size
);
823 ku_flags
= KeyUsage2int(ku
);
824 if ((ku_flags
& flags
) != flags
) {
825 unsigned missing
= (~ku_flags
) & flags
;
826 char buf
[256], *name
;
828 unparse_flags(missing
, asn1_KeyUsage_units(), buf
, sizeof(buf
));
829 _hx509_unparse_Name(&cert
->tbsCertificate
.subject
, &name
);
830 hx509_set_error_string(context
, 0, HX509_KU_CERT_MISSING
,
831 "Key usage %s required but missing "
832 "from certifiate %s", buf
, name
);
834 return HX509_KU_CERT_MISSING
;
840 * Return 0 on matching key usage 'flags' for 'cert', otherwise return
841 * an error code. If 'req_present' the existance is required of the
842 * KeyUsage extension.
846 _hx509_check_key_usage(hx509_context context
, hx509_cert cert
,
847 unsigned flags
, int req_present
)
849 return check_key_usage(context
, _hx509_get_cert(cert
), flags
, req_present
);
852 enum certtype
{ PROXY_CERT
, EE_CERT
, CA_CERT
};
855 check_basic_constraints(hx509_context context
, const Certificate
*cert
,
856 enum certtype type
, size_t depth
)
864 if (_hx509_cert_get_version(cert
) < 3)
867 e
= find_extension(cert
, &asn1_oid_id_x509_ce_basicConstraints
, &i
);
875 ret
= _hx509_unparse_Name(&cert
->tbsCertificate
.subject
, &name
);
877 hx509_set_error_string(context
, 0, HX509_EXTENSION_NOT_FOUND
,
878 "basicConstraints missing from "
879 "CA certifiacte %s", name
);
881 return HX509_EXTENSION_NOT_FOUND
;
886 ret
= decode_BasicConstraints(e
->extnValue
.data
,
887 e
->extnValue
.length
, &bc
,
893 if (bc
.cA
!= NULL
&& *bc
.cA
)
894 ret
= HX509_PARENT_IS_CA
;
900 if (bc
.cA
== NULL
|| !*bc
.cA
)
901 ret
= HX509_PARENT_NOT_CA
;
902 else if (bc
.pathLenConstraint
)
903 if (depth
- 1 > *bc
.pathLenConstraint
)
904 ret
= HX509_CA_PATH_TOO_DEEP
;
907 free_BasicConstraints(&bc
);
912 _hx509_cert_is_parent_cmp(const Certificate
*subject
,
913 const Certificate
*issuer
,
914 int allow_self_signed
)
917 AuthorityKeyIdentifier ai
;
918 SubjectKeyIdentifier si
;
919 int ret_ai
, ret_si
, ret
;
921 ret
= _hx509_name_cmp(&issuer
->tbsCertificate
.subject
,
922 &subject
->tbsCertificate
.issuer
,
929 memset(&ai
, 0, sizeof(ai
));
930 memset(&si
, 0, sizeof(si
));
933 * Try to find AuthorityKeyIdentifier, if it's not present in the
934 * subject certificate nor the parent.
937 ret_ai
= find_extension_auth_key_id(subject
, &ai
);
938 if (ret_ai
&& ret_ai
!= HX509_EXTENSION_NOT_FOUND
)
940 ret_si
= _hx509_find_extension_subject_key_id(issuer
, &si
);
941 if (ret_si
&& ret_si
!= HX509_EXTENSION_NOT_FOUND
)
944 if (ret_si
&& ret_ai
)
949 if (allow_self_signed
) {
952 } else if (ai
.keyIdentifier
) {
958 if (ai
.keyIdentifier
== NULL
) {
961 if (ai
.authorityCertIssuer
== NULL
)
963 if (ai
.authorityCertSerialNumber
== NULL
)
966 diff
= der_heim_integer_cmp(ai
.authorityCertSerialNumber
,
967 &issuer
->tbsCertificate
.serialNumber
);
970 if (ai
.authorityCertIssuer
->len
!= 1)
972 if (ai
.authorityCertIssuer
->val
[0].element
!= choice_GeneralName_directoryName
)
976 ai
.authorityCertIssuer
->val
[0].u
.directoryName
.element
;
978 ai
.authorityCertIssuer
->val
[0].u
.directoryName
.u
.rdnSequence
;
980 ret
= _hx509_name_cmp(&issuer
->tbsCertificate
.subject
,
989 diff
= der_heim_octet_string_cmp(ai
.keyIdentifier
, &si
);
994 free_AuthorityKeyIdentifier(&ai
);
995 free_SubjectKeyIdentifier(&si
);
1000 certificate_is_anchor(hx509_context context
,
1001 hx509_certs trust_anchors
,
1002 const hx509_cert cert
)
1008 if (trust_anchors
== NULL
)
1011 _hx509_query_clear(&q
);
1013 q
.match
= HX509_QUERY_MATCH_CERTIFICATE
;
1014 q
.certificate
= _hx509_get_cert(cert
);
1016 ret
= hx509_certs_find(context
, trust_anchors
, &q
, &c
);
1023 certificate_is_self_signed(hx509_context context
,
1024 const Certificate
*cert
,
1028 ret
= _hx509_name_cmp(&cert
->tbsCertificate
.subject
,
1029 &cert
->tbsCertificate
.issuer
, &diff
);
1030 *self_signed
= (diff
== 0);
1032 hx509_set_error_string(context
, 0, ret
,
1033 "Failed to check if self signed");
1035 ret
= _hx509_self_signed_valid(context
, &cert
->signatureAlgorithm
);
1041 * The subjectName is "null" when it's empty set of relative DBs.
1045 subject_null_p(const Certificate
*c
)
1047 return c
->tbsCertificate
.subject
.u
.rdnSequence
.len
== 0;
1052 find_parent(hx509_context context
,
1054 hx509_certs trust_anchors
,
1060 AuthorityKeyIdentifier ai
;
1065 memset(&ai
, 0, sizeof(ai
));
1067 _hx509_query_clear(&q
);
1069 if (!subject_null_p(current
->data
)) {
1070 q
.match
|= HX509_QUERY_FIND_ISSUER_CERT
;
1071 q
.subject
= _hx509_get_cert(current
);
1073 ret
= find_extension_auth_key_id(current
->data
, &ai
);
1075 hx509_set_error_string(context
, 0, HX509_CERTIFICATE_MALFORMED
,
1076 "Subjectless certificate missing AuthKeyID");
1077 return HX509_CERTIFICATE_MALFORMED
;
1080 if (ai
.keyIdentifier
== NULL
) {
1081 free_AuthorityKeyIdentifier(&ai
);
1082 hx509_set_error_string(context
, 0, HX509_CERTIFICATE_MALFORMED
,
1083 "Subjectless certificate missing keyIdentifier "
1084 "inside AuthKeyID");
1085 return HX509_CERTIFICATE_MALFORMED
;
1088 q
.subject_id
= ai
.keyIdentifier
;
1089 q
.match
= HX509_QUERY_MATCH_SUBJECT_KEY_ID
;
1093 q
.match
|= HX509_QUERY_NO_MATCH_PATH
;
1096 q
.timenow
= time_now
;
1097 q
.match
|= HX509_QUERY_MATCH_TIME
;
1099 ret
= hx509_certs_find(context
, pool
, &q
, parent
);
1101 free_AuthorityKeyIdentifier(&ai
);
1104 q
.match
&= ~HX509_QUERY_MATCH_TIME
;
1107 if (trust_anchors
) {
1108 ret
= hx509_certs_find(context
, trust_anchors
, &q
, parent
);
1110 free_AuthorityKeyIdentifier(&ai
);
1114 free_AuthorityKeyIdentifier(&ai
);
1120 ret
= hx509_cert_get_subject(current
, &name
);
1122 hx509_clear_error_string(context
);
1123 return HX509_ISSUER_NOT_FOUND
;
1125 ret
= hx509_name_to_string(name
, &str
);
1126 hx509_name_free(&name
);
1128 hx509_clear_error_string(context
);
1129 return HX509_ISSUER_NOT_FOUND
;
1132 hx509_set_error_string(context
, 0, HX509_ISSUER_NOT_FOUND
,
1133 "Failed to find issuer for "
1134 "certificate with subject: '%s'", str
);
1137 return HX509_ISSUER_NOT_FOUND
;
1145 is_proxy_cert(hx509_context context
,
1146 const Certificate
*cert
,
1147 ProxyCertInfo
*rinfo
)
1156 memset(rinfo
, 0, sizeof(*rinfo
));
1158 e
= find_extension(cert
, &asn1_oid_id_pkix_pe_proxyCertInfo
, &i
);
1160 hx509_clear_error_string(context
);
1161 return HX509_EXTENSION_NOT_FOUND
;
1164 ret
= decode_ProxyCertInfo(e
->extnValue
.data
,
1165 e
->extnValue
.length
,
1169 hx509_clear_error_string(context
);
1172 if (size
!= e
->extnValue
.length
) {
1173 free_ProxyCertInfo(&info
);
1174 hx509_clear_error_string(context
);
1175 return HX509_EXTRA_DATA_AFTER_STRUCTURE
;
1178 free_ProxyCertInfo(&info
);
1186 * Path operations are like MEMORY based keyset, but with exposed
1187 * internal so we can do easy searches.
1191 _hx509_path_append(hx509_context context
, hx509_path
*path
, hx509_cert cert
)
1194 val
= realloc(path
->val
, (path
->len
+ 1) * sizeof(path
->val
[0]));
1196 hx509_set_error_string(context
, 0, ENOMEM
, "out of memory");
1201 path
->val
[path
->len
] = hx509_cert_ref(cert
);
1208 _hx509_path_free(hx509_path
*path
)
1212 for (i
= 0; i
< path
->len
; i
++)
1213 hx509_cert_free(path
->val
[i
]);
1220 * Find path by looking up issuer for the top certificate and continue
1221 * until an anchor certificate is found or max limit is found. A
1222 * certificate never included twice in the path.
1224 * If the trust anchors are not given, calculate optimistic path, just
1225 * follow the chain upward until we no longer find a parent or we hit
1226 * the max path limit. In this case, a failure will always be returned
1227 * depending on what error condition is hit first.
1229 * The path includes a path from the top certificate to the anchor
1232 * The caller needs to free `path´ both on successful built path and
1237 _hx509_calculate_path(hx509_context context
,
1240 hx509_certs anchors
,
1241 unsigned int max_depth
,
1246 hx509_cert parent
, current
;
1250 max_depth
= HX509_VERIFY_MAX_DEPTH
;
1252 ret
= _hx509_path_append(context
, path
, cert
);
1256 current
= hx509_cert_ref(cert
);
1258 while (!certificate_is_anchor(context
, anchors
, current
)) {
1260 ret
= find_parent(context
, time_now
, anchors
, path
,
1261 pool
, current
, &parent
);
1262 hx509_cert_free(current
);
1266 ret
= _hx509_path_append(context
, path
, parent
);
1271 if (path
->len
> max_depth
) {
1272 hx509_cert_free(current
);
1273 hx509_set_error_string(context
, 0, HX509_PATH_TOO_LONG
,
1274 "Path too long while bulding "
1275 "certificate chain");
1276 return HX509_PATH_TOO_LONG
;
1280 if ((flags
& HX509_CALCULATE_PATH_NO_ANCHOR
) &&
1282 certificate_is_anchor(context
, anchors
, path
->val
[path
->len
- 1]))
1284 hx509_cert_free(path
->val
[path
->len
- 1]);
1288 hx509_cert_free(current
);
1293 _hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier
*p
,
1294 const AlgorithmIdentifier
*q
)
1297 diff
= der_heim_oid_cmp(&p
->algorithm
, &q
->algorithm
);
1300 if (p
->parameters
) {
1302 return heim_any_cmp(p
->parameters
,
1315 _hx509_Certificate_cmp(const Certificate
*p
, const Certificate
*q
)
1318 diff
= der_heim_bit_string_cmp(&p
->signatureValue
, &q
->signatureValue
);
1321 diff
= _hx509_AlgorithmIdentifier_cmp(&p
->signatureAlgorithm
,
1322 &q
->signatureAlgorithm
);
1325 diff
= der_heim_octet_string_cmp(&p
->tbsCertificate
._save
,
1326 &q
->tbsCertificate
._save
);
1331 * Compare to hx509 certificate object, useful for sorting.
1333 * @param p a hx509 certificate object.
1334 * @param q a hx509 certificate object.
1336 * @return 0 the objects are the same, returns > 0 is p is "larger"
1337 * then q, < 0 if p is "smaller" then q.
1339 * @ingroup hx509_cert
1343 hx509_cert_cmp(hx509_cert p
, hx509_cert q
)
1345 return _hx509_Certificate_cmp(p
->data
, q
->data
);
1349 * Return the name of the issuer of the hx509 certificate.
1351 * @param p a hx509 certificate object.
1352 * @param name a pointer to a hx509 name, should be freed by
1353 * hx509_name_free().
1355 * @return An hx509 error code, see hx509_get_error_string().
1357 * @ingroup hx509_cert
1361 hx509_cert_get_issuer(hx509_cert p
, hx509_name
*name
)
1363 return _hx509_name_from_Name(&p
->data
->tbsCertificate
.issuer
, name
);
1367 * Return the name of the subject of the hx509 certificate.
1369 * @param p a hx509 certificate object.
1370 * @param name a pointer to a hx509 name, should be freed by
1371 * hx509_name_free(). See also hx509_cert_get_base_subject().
1373 * @return An hx509 error code, see hx509_get_error_string().
1375 * @ingroup hx509_cert
1379 hx509_cert_get_subject(hx509_cert p
, hx509_name
*name
)
1381 return _hx509_name_from_Name(&p
->data
->tbsCertificate
.subject
, name
);
1385 * Return the name of the base subject of the hx509 certificate. If
1386 * the certiicate is a verified proxy certificate, the this function
1387 * return the base certificate (root of the proxy chain). If the proxy
1388 * certificate is not verified with the base certificate
1389 * HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned.
1391 * @param context a hx509 context.
1392 * @param c a hx509 certificate object.
1393 * @param name a pointer to a hx509 name, should be freed by
1394 * hx509_name_free(). See also hx509_cert_get_subject().
1396 * @return An hx509 error code, see hx509_get_error_string().
1398 * @ingroup hx509_cert
1402 hx509_cert_get_base_subject(hx509_context context
, hx509_cert c
,
1406 return hx509_name_copy(context
, c
->basename
, name
);
1407 if (is_proxy_cert(context
, c
->data
, NULL
) == 0) {
1408 int ret
= HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED
;
1409 hx509_set_error_string(context
, 0, ret
,
1410 "Proxy certificate have not been "
1411 "canonicalize yet, no base name");
1414 return _hx509_name_from_Name(&c
->data
->tbsCertificate
.subject
, name
);
1418 * Get serial number of the certificate.
1420 * @param p a hx509 certificate object.
1421 * @param i serial number, should be freed ith der_free_heim_integer().
1423 * @return An hx509 error code, see hx509_get_error_string().
1425 * @ingroup hx509_cert
1429 hx509_cert_get_serialnumber(hx509_cert p
, heim_integer
*i
)
1431 return der_copy_heim_integer(&p
->data
->tbsCertificate
.serialNumber
, i
);
1435 * Get notBefore time of the certificate.
1437 * @param p a hx509 certificate object.
1439 * @return return not before time
1441 * @ingroup hx509_cert
1445 hx509_cert_get_notBefore(hx509_cert p
)
1447 return _hx509_Time2time_t(&p
->data
->tbsCertificate
.validity
.notBefore
);
1451 * Get notAfter time of the certificate.
1453 * @param p a hx509 certificate object.
1455 * @return return not after time.
1457 * @ingroup hx509_cert
1461 hx509_cert_get_notAfter(hx509_cert p
)
1463 return _hx509_Time2time_t(&p
->data
->tbsCertificate
.validity
.notAfter
);
1467 * Get the SubjectPublicKeyInfo structure from the hx509 certificate.
1469 * @param context a hx509 context.
1470 * @param p a hx509 certificate object.
1471 * @param spki SubjectPublicKeyInfo, should be freed with
1472 * free_SubjectPublicKeyInfo().
1474 * @return An hx509 error code, see hx509_get_error_string().
1476 * @ingroup hx509_cert
1480 hx509_cert_get_SPKI(hx509_context context
, hx509_cert p
, SubjectPublicKeyInfo
*spki
)
1484 ret
= copy_SubjectPublicKeyInfo(&p
->data
->tbsCertificate
.subjectPublicKeyInfo
, spki
);
1486 hx509_set_error_string(context
, 0, ret
, "Failed to copy SPKI");
1491 * Get the AlgorithmIdentifier from the hx509 certificate.
1493 * @param context a hx509 context.
1494 * @param p a hx509 certificate object.
1495 * @param alg AlgorithmIdentifier, should be freed with
1496 * free_AlgorithmIdentifier(). The algorithmidentifier is
1497 * typicly rsaEncryption, or id-ecPublicKey, or some other
1498 * public key mechanism.
1500 * @return An hx509 error code, see hx509_get_error_string().
1502 * @ingroup hx509_cert
1506 hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context
,
1508 AlgorithmIdentifier
*alg
)
1512 ret
= copy_AlgorithmIdentifier(&p
->data
->tbsCertificate
.subjectPublicKeyInfo
.algorithm
, alg
);
1514 hx509_set_error_string(context
, 0, ret
,
1515 "Failed to copy SPKI AlgorithmIdentifier");
1520 get_x_unique_id(hx509_context context
, const char *name
,
1521 const heim_bit_string
*cert
, heim_bit_string
*subject
)
1526 ret
= HX509_EXTENSION_NOT_FOUND
;
1527 hx509_set_error_string(context
, 0, ret
, "%s unique id doesn't exists", name
);
1530 ret
= der_copy_bit_string(cert
, subject
);
1532 hx509_set_error_string(context
, 0, ret
, "malloc out of memory", name
);
1539 * Get a copy of the Issuer Unique ID
1541 * @param context a hx509_context
1542 * @param p a hx509 certificate
1543 * @param issuer the issuer id returned, free with der_free_bit_string()
1545 * @return An hx509 error code, see hx509_get_error_string(). The
1546 * error code HX509_EXTENSION_NOT_FOUND is returned if the certificate
1547 * doesn't have a issuerUniqueID
1549 * @ingroup hx509_cert
1553 hx509_cert_get_issuer_unique_id(hx509_context context
, hx509_cert p
, heim_bit_string
*issuer
)
1555 return get_x_unique_id(context
, "issuer", p
->data
->tbsCertificate
.issuerUniqueID
, issuer
);
1559 * Get a copy of the Subect Unique ID
1561 * @param context a hx509_context
1562 * @param p a hx509 certificate
1563 * @param subject the subject id returned, free with der_free_bit_string()
1565 * @return An hx509 error code, see hx509_get_error_string(). The
1566 * error code HX509_EXTENSION_NOT_FOUND is returned if the certificate
1567 * doesn't have a subjectUniqueID
1569 * @ingroup hx509_cert
1573 hx509_cert_get_subject_unique_id(hx509_context context
, hx509_cert p
, heim_bit_string
*subject
)
1575 return get_x_unique_id(context
, "subject", p
->data
->tbsCertificate
.subjectUniqueID
, subject
);
1580 _hx509_cert_private_key(hx509_cert p
)
1582 return p
->private_key
;
1586 hx509_cert_have_private_key(hx509_cert p
)
1588 return p
->private_key
? 1 : 0;
1593 _hx509_cert_private_key_exportable(hx509_cert p
)
1595 if (p
->private_key
== NULL
)
1597 return _hx509_private_key_exportable(p
->private_key
);
1601 _hx509_cert_private_decrypt(hx509_context context
,
1602 const heim_octet_string
*ciphertext
,
1603 const heim_oid
*encryption_oid
,
1605 heim_octet_string
*cleartext
)
1607 cleartext
->data
= NULL
;
1608 cleartext
->length
= 0;
1610 if (p
->private_key
== NULL
) {
1611 hx509_set_error_string(context
, 0, HX509_PRIVATE_KEY_MISSING
,
1612 "Private key missing");
1613 return HX509_PRIVATE_KEY_MISSING
;
1616 return hx509_private_key_private_decrypt(context
,
1624 hx509_cert_public_encrypt(hx509_context context
,
1625 const heim_octet_string
*cleartext
,
1627 heim_oid
*encryption_oid
,
1628 heim_octet_string
*ciphertext
)
1630 return _hx509_public_encrypt(context
,
1632 encryption_oid
, ciphertext
);
1640 _hx509_Time2time_t(const Time
*t
)
1642 switch(t
->element
) {
1643 case choice_Time_utcTime
:
1644 return t
->u
.utcTime
;
1645 case choice_Time_generalTime
:
1646 return t
->u
.generalTime
;
1656 init_name_constraints(hx509_name_constraints
*nc
)
1658 memset(nc
, 0, sizeof(*nc
));
1663 add_name_constraints(hx509_context context
, const Certificate
*c
, int not_ca
,
1664 hx509_name_constraints
*nc
)
1666 NameConstraints tnc
;
1669 ret
= find_extension_name_constraints(c
, &tnc
);
1670 if (ret
== HX509_EXTENSION_NOT_FOUND
)
1673 hx509_set_error_string(context
, 0, ret
, "Failed getting NameConstraints");
1675 } else if (not_ca
) {
1676 ret
= HX509_VERIFY_CONSTRAINTS
;
1677 hx509_set_error_string(context
, 0, ret
, "Not a CA and "
1678 "have NameConstraints");
1680 NameConstraints
*val
;
1681 val
= realloc(nc
->val
, sizeof(nc
->val
[0]) * (nc
->len
+ 1));
1683 hx509_clear_error_string(context
);
1688 ret
= copy_NameConstraints(&tnc
, &nc
->val
[nc
->len
]);
1690 hx509_clear_error_string(context
);
1696 free_NameConstraints(&tnc
);
1701 match_RDN(const RelativeDistinguishedName
*c
,
1702 const RelativeDistinguishedName
*n
)
1706 if (c
->len
!= n
->len
)
1707 return HX509_NAME_CONSTRAINT_ERROR
;
1709 for (i
= 0; i
< n
->len
; i
++) {
1712 if (der_heim_oid_cmp(&c
->val
[i
].type
, &n
->val
[i
].type
) != 0)
1713 return HX509_NAME_CONSTRAINT_ERROR
;
1714 ret
= _hx509_name_ds_cmp(&c
->val
[i
].value
, &n
->val
[i
].value
, &diff
);
1718 return HX509_NAME_CONSTRAINT_ERROR
;
1724 match_X501Name(const Name
*c
, const Name
*n
)
1729 if (c
->element
!= choice_Name_rdnSequence
1730 || n
->element
!= choice_Name_rdnSequence
)
1732 if (c
->u
.rdnSequence
.len
> n
->u
.rdnSequence
.len
)
1733 return HX509_NAME_CONSTRAINT_ERROR
;
1734 for (i
= 0; i
< c
->u
.rdnSequence
.len
; i
++) {
1735 ret
= match_RDN(&c
->u
.rdnSequence
.val
[i
], &n
->u
.rdnSequence
.val
[i
]);
1744 match_general_name(const GeneralName
*c
, const GeneralName
*n
, int *match
)
1747 * Name constraints only apply to the same name type, see RFC3280,
1750 assert(c
->element
== n
->element
);
1752 switch(c
->element
) {
1753 case choice_GeneralName_otherName
:
1754 if (der_heim_oid_cmp(&c
->u
.otherName
.type_id
,
1755 &n
->u
.otherName
.type_id
) != 0)
1756 return HX509_NAME_CONSTRAINT_ERROR
;
1757 if (heim_any_cmp(&c
->u
.otherName
.value
,
1758 &n
->u
.otherName
.value
) != 0)
1759 return HX509_NAME_CONSTRAINT_ERROR
;
1762 case choice_GeneralName_rfc822Name
: {
1765 s
= memchr(c
->u
.rfc822Name
.data
, '@', c
->u
.rfc822Name
.length
);
1767 if (der_printable_string_cmp(&c
->u
.rfc822Name
, &n
->u
.rfc822Name
) != 0)
1768 return HX509_NAME_CONSTRAINT_ERROR
;
1770 s
= memchr(n
->u
.rfc822Name
.data
, '@', n
->u
.rfc822Name
.length
);
1772 return HX509_NAME_CONSTRAINT_ERROR
;
1773 len1
= c
->u
.rfc822Name
.length
;
1774 len2
= n
->u
.rfc822Name
.length
-
1775 (s
- ((char *)n
->u
.rfc822Name
.data
));
1777 return HX509_NAME_CONSTRAINT_ERROR
;
1778 if (memcmp(s
+ 1 + len2
- len1
, c
->u
.rfc822Name
.data
, len1
) != 0)
1779 return HX509_NAME_CONSTRAINT_ERROR
;
1780 if (len1
< len2
&& s
[len2
- len1
+ 1] != '.')
1781 return HX509_NAME_CONSTRAINT_ERROR
;
1786 case choice_GeneralName_dNSName
: {
1790 lenc
= c
->u
.dNSName
.length
;
1791 lenn
= n
->u
.dNSName
.length
;
1793 return HX509_NAME_CONSTRAINT_ERROR
;
1794 ptr
= n
->u
.dNSName
.data
;
1795 if (memcmp(&ptr
[lenn
- lenc
], c
->u
.dNSName
.data
, lenc
) != 0)
1796 return HX509_NAME_CONSTRAINT_ERROR
;
1797 if (lenn
!= lenc
&& ptr
[lenn
- lenc
- 1] != '.')
1798 return HX509_NAME_CONSTRAINT_ERROR
;
1802 case choice_GeneralName_directoryName
: {
1803 Name c_name
, n_name
;
1806 c_name
._save
.data
= NULL
;
1807 c_name
._save
.length
= 0;
1808 c_name
.element
= c
->u
.directoryName
.element
;
1809 c_name
.u
.rdnSequence
= c
->u
.directoryName
.u
.rdnSequence
;
1811 n_name
._save
.data
= NULL
;
1812 n_name
._save
.length
= 0;
1813 n_name
.element
= n
->u
.directoryName
.element
;
1814 n_name
.u
.rdnSequence
= n
->u
.directoryName
.u
.rdnSequence
;
1816 ret
= match_X501Name(&c_name
, &n_name
);
1821 case choice_GeneralName_uniformResourceIdentifier
:
1822 case choice_GeneralName_iPAddress
:
1823 case choice_GeneralName_registeredID
:
1825 return HX509_NAME_CONSTRAINT_ERROR
;
1830 match_alt_name(const GeneralName
*n
, const Certificate
*c
,
1831 int *same
, int *match
)
1839 ret
= find_extension_subject_alt_name(c
, &i
, &sa
);
1840 if (ret
== HX509_EXTENSION_NOT_FOUND
) {
1843 } else if (ret
!= 0)
1846 for (j
= 0; j
< sa
.len
; j
++) {
1847 if (n
->element
== sa
.val
[j
].element
) {
1849 ret
= match_general_name(n
, &sa
.val
[j
], match
);
1852 free_GeneralNames(&sa
);
1859 match_tree(const GeneralSubtrees
*t
, const Certificate
*c
, int *match
)
1861 int name
, alt_name
, same
;
1865 name
= alt_name
= same
= *match
= 0;
1866 for (i
= 0; i
< t
->len
; i
++) {
1867 if (t
->val
[i
].minimum
&& t
->val
[i
].maximum
)
1871 * If the constraint apply to directoryNames, test is with
1872 * subjectName of the certificate if the certificate have a
1873 * non-null (empty) subjectName.
1876 if (t
->val
[i
].base
.element
== choice_GeneralName_directoryName
1877 && !subject_null_p(c
))
1879 GeneralName certname
;
1881 memset(&certname
, 0, sizeof(certname
));
1882 certname
.element
= choice_GeneralName_directoryName
;
1883 certname
.u
.directoryName
.element
=
1884 c
->tbsCertificate
.subject
.element
;
1885 certname
.u
.directoryName
.u
.rdnSequence
=
1886 c
->tbsCertificate
.subject
.u
.rdnSequence
;
1888 ret
= match_general_name(&t
->val
[i
].base
, &certname
, &name
);
1891 /* Handle subjectAltNames, this is icky since they
1892 * restrictions only apply if the subjectAltName is of the
1893 * same type. So if there have been a match of type, require
1894 * altname to be set.
1896 ret
= match_alt_name(&t
->val
[i
].base
, c
, &same
, &alt_name
);
1898 if (name
&& (!same
|| alt_name
))
1904 check_name_constraints(hx509_context context
,
1905 const hx509_name_constraints
*nc
,
1906 const Certificate
*c
)
1911 for (i
= 0 ; i
< nc
->len
; i
++) {
1914 if (nc
->val
[i
].permittedSubtrees
) {
1915 GeneralSubtrees_SET(&gs
, nc
->val
[i
].permittedSubtrees
);
1916 ret
= match_tree(&gs
, c
, &match
);
1918 hx509_clear_error_string(context
);
1921 /* allow null subjectNames, they wont matches anything */
1922 if (match
== 0 && !subject_null_p(c
)) {
1923 hx509_set_error_string(context
, 0, HX509_VERIFY_CONSTRAINTS
,
1924 "Error verify constraints, "
1925 "certificate didn't match any "
1926 "permitted subtree");
1927 return HX509_VERIFY_CONSTRAINTS
;
1930 if (nc
->val
[i
].excludedSubtrees
) {
1931 GeneralSubtrees_SET(&gs
, nc
->val
[i
].excludedSubtrees
);
1932 ret
= match_tree(&gs
, c
, &match
);
1934 hx509_clear_error_string(context
);
1938 hx509_set_error_string(context
, 0, HX509_VERIFY_CONSTRAINTS
,
1939 "Error verify constraints, "
1940 "certificate included in excluded "
1942 return HX509_VERIFY_CONSTRAINTS
;
1950 free_name_constraints(hx509_name_constraints
*nc
)
1954 for (i
= 0 ; i
< nc
->len
; i
++)
1955 free_NameConstraints(&nc
->val
[i
]);
1960 * Build and verify the path for the certificate to the trust anchor
1961 * specified in the verify context. The path is constructed from the
1962 * certificate, the pool and the trust anchors.
1964 * @param context A hx509 context.
1965 * @param ctx A hx509 verification context.
1966 * @param cert the certificate to build the path from.
1967 * @param pool A keyset of certificates to build the chain from.
1969 * @return An hx509 error code, see hx509_get_error_string().
1971 * @ingroup hx509_verify
1975 hx509_verify_path(hx509_context context
,
1976 hx509_verify_ctx ctx
,
1980 hx509_name_constraints nc
;
1982 int ret
, proxy_cert_depth
, selfsigned_depth
, diff
;
1986 hx509_certs anchors
= NULL
;
1988 memset(&proxy_issuer
, 0, sizeof(proxy_issuer
));
1990 ret
= init_name_constraints(&nc
);
1997 if ((ctx
->flags
& HX509_VERIFY_CTX_F_TIME_SET
) == 0)
1998 ctx
->time_now
= time(NULL
);
2003 if (ctx
->trust_anchors
)
2004 anchors
= hx509_certs_ref(ctx
->trust_anchors
);
2005 else if (context
->default_trust_anchors
&& ALLOW_DEF_TA(ctx
))
2006 anchors
= hx509_certs_ref(context
->default_trust_anchors
);
2008 ret
= hx509_certs_init(context
, "MEMORY:no-TA", 0, NULL
, &anchors
);
2014 * Calculate the path from the certificate user presented to the
2017 ret
= _hx509_calculate_path(context
, 0, ctx
->time_now
,
2018 anchors
, ctx
->max_depth
,
2024 * Check CA and proxy certificate chain from the top of the
2025 * certificate chain. Also check certificate is valid with respect
2026 * to the current time.
2030 proxy_cert_depth
= 0;
2031 selfsigned_depth
= 0;
2033 if (ctx
->flags
& HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE
)
2038 for (i
= 0; i
< path
.len
; i
++) {
2042 c
= _hx509_get_cert(path
.val
[i
]);
2045 * Lets do some basic check on issuer like
2046 * keyUsage.keyCertSign and basicConstraints.cA bit depending
2047 * on what type of certificate this is.
2053 /* XXX make constants for keyusage */
2054 ret
= check_key_usage(context
, c
, 1 << 5,
2055 REQUIRE_RFC3280(ctx
) ? TRUE
: FALSE
);
2057 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
2058 "Key usage missing from CA certificate");
2062 /* self signed cert doesn't add to path length */
2063 if (i
+ 1 != path
.len
) {
2066 ret
= certificate_is_self_signed(context
, c
, &selfsigned
);
2077 if (is_proxy_cert(context
, c
, &info
) == 0) {
2080 if (info
.pCPathLenConstraint
!= NULL
&&
2081 *info
.pCPathLenConstraint
< i
)
2083 free_ProxyCertInfo(&info
);
2084 ret
= HX509_PATH_TOO_LONG
;
2085 hx509_set_error_string(context
, 0, ret
,
2086 "Proxy certificate chain "
2087 "longer then allowed");
2090 /* XXX MUST check info.proxyPolicy */
2091 free_ProxyCertInfo(&info
);
2094 if (find_extension(c
, &asn1_oid_id_x509_ce_subjectAltName
, &j
)) {
2095 ret
= HX509_PROXY_CERT_INVALID
;
2096 hx509_set_error_string(context
, 0, ret
,
2097 "Proxy certificate have explicity "
2098 "forbidden subjectAltName");
2103 if (find_extension(c
, &asn1_oid_id_x509_ce_issuerAltName
, &j
)) {
2104 ret
= HX509_PROXY_CERT_INVALID
;
2105 hx509_set_error_string(context
, 0, ret
,
2106 "Proxy certificate have explicity "
2107 "forbidden issuerAltName");
2112 * The subject name of the proxy certificate should be
2113 * CN=XXX,<proxy issuer>, prune of CN and check if its
2114 * the same over the whole chain of proxy certs and
2115 * then check with the EE cert when we get to it.
2118 if (proxy_cert_depth
) {
2119 ret
= _hx509_name_cmp(&proxy_issuer
, &c
->tbsCertificate
.subject
, &diff
);
2121 hx509_set_error_string(context
, 0, ret
, "Out of memory");
2125 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2126 hx509_set_error_string(context
, 0, ret
,
2127 "Base proxy name not right");
2132 free_Name(&proxy_issuer
);
2134 ret
= copy_Name(&c
->tbsCertificate
.subject
, &proxy_issuer
);
2136 hx509_clear_error_string(context
);
2140 j
= proxy_issuer
.u
.rdnSequence
.len
;
2141 if (proxy_issuer
.u
.rdnSequence
.len
< 2
2142 || proxy_issuer
.u
.rdnSequence
.val
[j
- 1].len
> 1
2143 || der_heim_oid_cmp(&proxy_issuer
.u
.rdnSequence
.val
[j
- 1].val
[0].type
,
2144 &asn1_oid_id_at_commonName
))
2146 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2147 hx509_set_error_string(context
, 0, ret
,
2148 "Proxy name too short or "
2149 "does not have Common name "
2154 free_RelativeDistinguishedName(&proxy_issuer
.u
.rdnSequence
.val
[j
- 1]);
2155 proxy_issuer
.u
.rdnSequence
.len
-= 1;
2157 ret
= _hx509_name_cmp(&proxy_issuer
, &c
->tbsCertificate
.issuer
, &diff
);
2159 hx509_set_error_string(context
, 0, ret
, "Out of memory");
2163 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2164 hx509_set_error_string(context
, 0, ret
,
2165 "Proxy issuer name not as expected");
2172 * Now we are done with the proxy certificates, this
2173 * cert was an EE cert and we we will fall though to
2174 * EE checking below.
2182 * If there where any proxy certificates in the chain
2183 * (proxy_cert_depth > 0), check that the proxy issuer
2184 * matched proxy certificates "base" subject.
2186 if (proxy_cert_depth
) {
2188 ret
= _hx509_name_cmp(&proxy_issuer
,
2189 &c
->tbsCertificate
.subject
, &diff
);
2191 hx509_set_error_string(context
, 0, ret
, "out of memory");
2195 ret
= HX509_PROXY_CERT_NAME_WRONG
;
2196 hx509_clear_error_string(context
);
2200 hx509_name_free(&cert
->basename
);
2202 ret
= _hx509_name_from_Name(&proxy_issuer
, &cert
->basename
);
2204 hx509_clear_error_string(context
);
2212 ret
= check_basic_constraints(context
, c
, type
,
2213 i
- proxy_cert_depth
- selfsigned_depth
);
2218 * Don't check the trust anchors expiration time since they
2219 * are transported out of band, from RFC3820.
2221 if (i
+ 1 != path
.len
|| CHECK_TA(ctx
)) {
2223 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
2224 if (t
> ctx
->time_now
) {
2225 ret
= HX509_CERT_USED_BEFORE_TIME
;
2226 hx509_clear_error_string(context
);
2229 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notAfter
);
2230 if (t
< ctx
->time_now
) {
2231 ret
= HX509_CERT_USED_AFTER_TIME
;
2232 hx509_clear_error_string(context
);
2237 if (type
== EE_CERT
)
2239 else if (type
== PROXY_CERT
)
2244 * Verify constraints, do this backward so path constraints are
2245 * checked in the right order.
2248 for (ret
= 0, k
= path
.len
; k
> 0; k
--) {
2253 c
= _hx509_get_cert(path
.val
[i
]);
2255 ret
= certificate_is_self_signed(context
, c
, &selfsigned
);
2259 /* verify name constraints, not for selfsigned and anchor */
2260 if (!selfsigned
|| i
+ 1 != path
.len
) {
2261 ret
= check_name_constraints(context
, &nc
, c
);
2266 ret
= add_name_constraints(context
, c
, i
== 0, &nc
);
2270 /* XXX verify all other silly constraints */
2275 * Verify that no certificates has been revoked.
2278 if (ctx
->revoke_ctx
) {
2281 ret
= hx509_certs_init(context
, "MEMORY:revoke-certs", 0,
2286 for (i
= 0; i
< path
.len
; i
++) {
2287 ret
= hx509_certs_add(context
, certs
, path
.val
[i
]);
2289 hx509_certs_free(&certs
);
2293 ret
= hx509_certs_merge(context
, certs
, pool
);
2295 hx509_certs_free(&certs
);
2299 for (i
= 0; i
< path
.len
- 1; i
++) {
2300 size_t parent
= (i
< path
.len
- 1) ? i
+ 1 : i
;
2302 ret
= hx509_revoke_verify(context
,
2309 hx509_certs_free(&certs
);
2313 hx509_certs_free(&certs
);
2317 * Verify signatures, do this backward so public key working
2318 * parameter is passed up from the anchor up though the chain.
2321 for (k
= path
.len
; k
> 0; k
--) {
2326 c
= _hx509_get_cert(path
.val
[i
]);
2328 /* is last in chain (trust anchor) */
2329 if (i
+ 1 == path
.len
) {
2332 signer
= path
.val
[i
];
2334 ret
= certificate_is_self_signed(context
, signer
->data
, &selfsigned
);
2338 /* if trust anchor is not self signed, don't check sig */
2342 /* take next certificate in chain */
2343 signer
= path
.val
[i
+ 1];
2346 /* verify signatureValue */
2347 ret
= _hx509_verify_signature_bitstring(context
,
2349 &c
->signatureAlgorithm
,
2350 &c
->tbsCertificate
._save
,
2351 &c
->signatureValue
);
2353 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
2354 "Failed to verify signature of certificate");
2358 * Verify that the sigature algorithm "best-before" date is
2359 * before the creation date of the certificate, do this for
2360 * trust anchors too, since any trust anchor that is created
2361 * after a algorithm is known to be bad deserved to be invalid.
2363 * Skip the leaf certificate for now...
2366 if (i
!= 0 && (ctx
->flags
& HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK
) == 0) {
2368 _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
2369 ret
= _hx509_signature_best_before(context
,
2370 &c
->signatureAlgorithm
,
2378 hx509_certs_free(&anchors
);
2379 free_Name(&proxy_issuer
);
2380 free_name_constraints(&nc
);
2381 _hx509_path_free(&path
);
2387 * Verify a signature made using the private key of an certificate.
2389 * @param context A hx509 context.
2390 * @param signer the certificate that made the signature.
2391 * @param alg algorthm that was used to sign the data.
2392 * @param data the data that was signed.
2393 * @param sig the sigature to verify.
2395 * @return An hx509 error code, see hx509_get_error_string().
2397 * @ingroup hx509_crypto
2401 hx509_verify_signature(hx509_context context
,
2402 const hx509_cert signer
,
2403 const AlgorithmIdentifier
*alg
,
2404 const heim_octet_string
*data
,
2405 const heim_octet_string
*sig
)
2407 return _hx509_verify_signature(context
, signer
, alg
, data
, sig
);
2411 _hx509_verify_signature_bitstring(hx509_context context
,
2412 const hx509_cert signer
,
2413 const AlgorithmIdentifier
*alg
,
2414 const heim_octet_string
*data
,
2415 const heim_bit_string
*sig
)
2417 heim_octet_string os
;
2419 if (sig
->length
& 7) {
2420 hx509_set_error_string(context
, 0, HX509_CRYPTO_SIG_INVALID_FORMAT
,
2421 "signature not multiple of 8 bits");
2422 return HX509_CRYPTO_SIG_INVALID_FORMAT
;
2425 os
.data
= sig
->data
;
2426 os
.length
= sig
->length
/ 8;
2428 return _hx509_verify_signature(context
, signer
, alg
, data
, &os
);
2434 * Verify that the certificate is allowed to be used for the hostname
2437 * @param context A hx509 context.
2438 * @param cert the certificate to match with
2439 * @param flags Flags to modify the behavior:
2440 * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok
2441 * @param type type of hostname:
2442 * - HX509_HN_HOSTNAME for plain hostname.
2443 * - HX509_HN_DNSSRV for DNS SRV names.
2444 * @param hostname the hostname to check
2445 * @param sa address of the host
2446 * @param sa_size length of address
2448 * @return An hx509 error code, see hx509_get_error_string().
2450 * @ingroup hx509_cert
2454 hx509_verify_hostname(hx509_context context
,
2455 const hx509_cert cert
,
2457 hx509_hostname_type type
,
2458 const char *hostname
,
2459 const struct sockaddr
*sa
,
2460 /* XXX krb5_socklen_t */ int sa_size
)
2467 if (sa
&& sa_size
<= 0)
2470 memset(&san
, 0, sizeof(san
));
2474 ret
= find_extension_subject_alt_name(cert
->data
, &i
, &san
);
2475 if (ret
== HX509_EXTENSION_NOT_FOUND
)
2478 return HX509_PARSING_NAME_FAILED
;
2480 for (j
= 0; j
< san
.len
; j
++) {
2481 switch (san
.val
[j
].element
) {
2482 case choice_GeneralName_dNSName
: {
2483 heim_printable_string hn
;
2484 hn
.data
= rk_UNCONST(hostname
);
2485 hn
.length
= strlen(hostname
);
2487 if (der_printable_string_cmp(&san
.val
[j
].u
.dNSName
, &hn
) == 0) {
2488 free_GeneralNames(&san
);
2497 free_GeneralNames(&san
);
2500 name
= &cert
->data
->tbsCertificate
.subject
;
2502 /* Find first CN= in the name, and try to match the hostname on that */
2503 for (ret
= 0, k
= name
->u
.rdnSequence
.len
; ret
== 0 && k
> 0; k
--) {
2505 for (j
= 0; ret
== 0 && j
< name
->u
.rdnSequence
.val
[i
].len
; j
++) {
2506 AttributeTypeAndValue
*n
= &name
->u
.rdnSequence
.val
[i
].val
[j
];
2508 if (der_heim_oid_cmp(&n
->type
, &asn1_oid_id_at_commonName
) == 0) {
2509 DirectoryString
*ds
= &n
->value
;
2510 switch (ds
->element
) {
2511 case choice_DirectoryString_printableString
: {
2512 heim_printable_string hn
;
2513 hn
.data
= rk_UNCONST(hostname
);
2514 hn
.length
= strlen(hostname
);
2516 if (der_printable_string_cmp(&ds
->u
.printableString
, &hn
) == 0)
2520 case choice_DirectoryString_ia5String
: {
2522 hn
.data
= rk_UNCONST(hostname
);
2523 hn
.length
= strlen(hostname
);
2525 if (der_ia5_string_cmp(&ds
->u
.ia5String
, &hn
) == 0)
2529 case choice_DirectoryString_utf8String
:
2530 if (strcasecmp(ds
->u
.utf8String
, hostname
) == 0)
2535 ret
= HX509_NAME_CONSTRAINT_ERROR
;
2540 if ((flags
& HX509_VHN_F_ALLOW_NO_MATCH
) == 0)
2541 ret
= HX509_NAME_CONSTRAINT_ERROR
;
2547 _hx509_set_cert_attribute(hx509_context context
,
2549 const heim_oid
*oid
,
2550 const heim_octet_string
*attr
)
2552 hx509_cert_attribute a
;
2555 if (hx509_cert_get_attribute(cert
, oid
) != NULL
)
2558 d
= realloc(cert
->attrs
.val
,
2559 sizeof(cert
->attrs
.val
[0]) * (cert
->attrs
.len
+ 1));
2561 hx509_clear_error_string(context
);
2564 cert
->attrs
.val
= d
;
2566 a
= malloc(sizeof(*a
));
2570 der_copy_octet_string(attr
, &a
->data
);
2571 der_copy_oid(oid
, &a
->oid
);
2573 cert
->attrs
.val
[cert
->attrs
.len
] = a
;
2580 * Get an external attribute for the certificate, examples are
2581 * friendly name and id.
2583 * @param cert hx509 certificate object to search
2584 * @param oid an oid to search for.
2586 * @return an hx509_cert_attribute, only valid as long as the
2587 * certificate is referenced.
2589 * @ingroup hx509_cert
2592 hx509_cert_attribute
2593 hx509_cert_get_attribute(hx509_cert cert
, const heim_oid
*oid
)
2596 for (i
= 0; i
< cert
->attrs
.len
; i
++)
2597 if (der_heim_oid_cmp(oid
, &cert
->attrs
.val
[i
]->oid
) == 0)
2598 return cert
->attrs
.val
[i
];
2603 * Set the friendly name on the certificate.
2605 * @param cert The certificate to set the friendly name on
2606 * @param name Friendly name.
2608 * @return An hx509 error code, see hx509_get_error_string().
2610 * @ingroup hx509_cert
2614 hx509_cert_set_friendly_name(hx509_cert cert
, const char *name
)
2616 if (cert
->friendlyname
)
2617 free(cert
->friendlyname
);
2618 cert
->friendlyname
= strdup(name
);
2619 if (cert
->friendlyname
== NULL
)
2625 * Get friendly name of the certificate.
2627 * @param cert cert to get the friendly name from.
2629 * @return an friendly name or NULL if there is. The friendly name is
2630 * only valid as long as the certificate is referenced.
2632 * @ingroup hx509_cert
2636 hx509_cert_get_friendly_name(hx509_cert cert
)
2638 hx509_cert_attribute a
;
2639 PKCS9_friendlyName n
;
2644 if (cert
->friendlyname
)
2645 return cert
->friendlyname
;
2647 a
= hx509_cert_get_attribute(cert
, &asn1_oid_id_pkcs_9_at_friendlyName
);
2651 ret
= hx509_cert_get_subject(cert
, &name
);
2654 ret
= hx509_name_to_string(name
, &cert
->friendlyname
);
2655 hx509_name_free(&name
);
2658 return cert
->friendlyname
;
2661 ret
= decode_PKCS9_friendlyName(a
->data
.data
, a
->data
.length
, &n
, &sz
);
2666 free_PKCS9_friendlyName(&n
);
2670 cert
->friendlyname
= malloc(n
.val
[0].length
+ 1);
2671 if (cert
->friendlyname
== NULL
) {
2672 free_PKCS9_friendlyName(&n
);
2676 for (i
= 0; i
< n
.val
[0].length
; i
++) {
2677 if (n
.val
[0].data
[i
] <= 0xff)
2678 cert
->friendlyname
[i
] = n
.val
[0].data
[i
] & 0xff;
2680 cert
->friendlyname
[i
] = 'X';
2682 cert
->friendlyname
[i
] = '\0';
2683 free_PKCS9_friendlyName(&n
);
2685 return cert
->friendlyname
;
2689 _hx509_query_clear(hx509_query
*q
)
2691 memset(q
, 0, sizeof(*q
));
2695 * Allocate an query controller. Free using hx509_query_free().
2697 * @param context A hx509 context.
2698 * @param q return pointer to a hx509_query.
2700 * @return An hx509 error code, see hx509_get_error_string().
2702 * @ingroup hx509_cert
2706 hx509_query_alloc(hx509_context context
, hx509_query
**q
)
2708 *q
= calloc(1, sizeof(**q
));
2716 * Set match options for the hx509 query controller.
2718 * @param q query controller.
2719 * @param option options to control the query controller.
2721 * @return An hx509 error code, see hx509_get_error_string().
2723 * @ingroup hx509_cert
2727 hx509_query_match_option(hx509_query
*q
, hx509_query_option option
)
2730 case HX509_QUERY_OPTION_PRIVATE_KEY
:
2731 q
->match
|= HX509_QUERY_PRIVATE_KEY
;
2733 case HX509_QUERY_OPTION_KU_ENCIPHERMENT
:
2734 q
->match
|= HX509_QUERY_KU_ENCIPHERMENT
;
2736 case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE
:
2737 q
->match
|= HX509_QUERY_KU_DIGITALSIGNATURE
;
2739 case HX509_QUERY_OPTION_KU_KEYCERTSIGN
:
2740 q
->match
|= HX509_QUERY_KU_KEYCERTSIGN
;
2742 case HX509_QUERY_OPTION_END
:
2749 * Set the issuer and serial number of match in the query
2750 * controller. The function make copies of the isser and serial number.
2752 * @param q a hx509 query controller
2753 * @param issuer issuer to search for
2754 * @param serialNumber the serialNumber of the issuer.
2756 * @return An hx509 error code, see hx509_get_error_string().
2758 * @ingroup hx509_cert
2762 hx509_query_match_issuer_serial(hx509_query
*q
,
2764 const heim_integer
*serialNumber
)
2768 der_free_heim_integer(q
->serial
);
2771 q
->serial
= malloc(sizeof(*q
->serial
));
2772 if (q
->serial
== NULL
)
2774 ret
= der_copy_heim_integer(serialNumber
, q
->serial
);
2780 if (q
->issuer_name
) {
2781 free_Name(q
->issuer_name
);
2782 free(q
->issuer_name
);
2784 q
->issuer_name
= malloc(sizeof(*q
->issuer_name
));
2785 if (q
->issuer_name
== NULL
)
2787 ret
= copy_Name(issuer
, q
->issuer_name
);
2789 free(q
->issuer_name
);
2790 q
->issuer_name
= NULL
;
2793 q
->match
|= HX509_QUERY_MATCH_SERIALNUMBER
|HX509_QUERY_MATCH_ISSUER_NAME
;
2798 * Set the query controller to match on a friendly name
2800 * @param q a hx509 query controller.
2801 * @param name a friendly name to match on
2803 * @return An hx509 error code, see hx509_get_error_string().
2805 * @ingroup hx509_cert
2809 hx509_query_match_friendly_name(hx509_query
*q
, const char *name
)
2811 if (q
->friendlyname
)
2812 free(q
->friendlyname
);
2813 q
->friendlyname
= strdup(name
);
2814 if (q
->friendlyname
== NULL
)
2816 q
->match
|= HX509_QUERY_MATCH_FRIENDLY_NAME
;
2821 * Set the query controller to require an one specific EKU (extended
2822 * key usage). Any previous EKU matching is overwitten. If NULL is
2823 * passed in as the eku, the EKU requirement is reset.
2825 * @param q a hx509 query controller.
2826 * @param eku an EKU to match on.
2828 * @return An hx509 error code, see hx509_get_error_string().
2830 * @ingroup hx509_cert
2834 hx509_query_match_eku(hx509_query
*q
, const heim_oid
*eku
)
2840 der_free_oid(q
->eku
);
2844 q
->match
&= ~HX509_QUERY_MATCH_EKU
;
2847 der_free_oid(q
->eku
);
2849 q
->eku
= calloc(1, sizeof(*q
->eku
));
2853 ret
= der_copy_oid(eku
, q
->eku
);
2859 q
->match
|= HX509_QUERY_MATCH_EKU
;
2865 hx509_query_match_expr(hx509_context context
, hx509_query
*q
, const char *expr
)
2868 _hx509_expr_free(q
->expr
);
2873 q
->match
&= ~HX509_QUERY_MATCH_EXPR
;
2875 q
->expr
= _hx509_expr_parse(expr
);
2877 q
->match
|= HX509_QUERY_MATCH_EXPR
;
2884 * Set the query controller to match using a specific match function.
2886 * @param q a hx509 query controller.
2887 * @param func function to use for matching, if the argument is NULL,
2888 * the match function is removed.
2889 * @param ctx context passed to the function.
2891 * @return An hx509 error code, see hx509_get_error_string().
2893 * @ingroup hx509_cert
2897 hx509_query_match_cmp_func(hx509_query
*q
,
2898 int (*func
)(hx509_context
, hx509_cert
, void *),
2902 q
->match
|= HX509_QUERY_MATCH_FUNCTION
;
2904 q
->match
&= ~HX509_QUERY_MATCH_FUNCTION
;
2906 q
->cmp_func_ctx
= ctx
;
2911 * Free the query controller.
2913 * @param context A hx509 context.
2914 * @param q a pointer to the query controller.
2916 * @ingroup hx509_cert
2920 hx509_query_free(hx509_context context
, hx509_query
*q
)
2926 der_free_heim_integer(q
->serial
);
2929 if (q
->issuer_name
) {
2930 free_Name(q
->issuer_name
);
2931 free(q
->issuer_name
);
2934 der_free_oid(q
->eku
);
2937 if (q
->friendlyname
)
2938 free(q
->friendlyname
);
2940 _hx509_expr_free(q
->expr
);
2942 memset(q
, 0, sizeof(*q
));
2947 _hx509_query_match_cert(hx509_context context
, const hx509_query
*q
, hx509_cert cert
)
2949 Certificate
*c
= _hx509_get_cert(cert
);
2952 _hx509_query_statistic(context
, 1, q
);
2954 if ((q
->match
& HX509_QUERY_FIND_ISSUER_CERT
) &&
2955 _hx509_cert_is_parent_cmp(q
->subject
, c
, 0) != 0)
2958 if ((q
->match
& HX509_QUERY_MATCH_CERTIFICATE
) &&
2959 _hx509_Certificate_cmp(q
->certificate
, c
) != 0)
2962 if ((q
->match
& HX509_QUERY_MATCH_SERIALNUMBER
)
2963 && der_heim_integer_cmp(&c
->tbsCertificate
.serialNumber
, q
->serial
) != 0)
2966 if (q
->match
& HX509_QUERY_MATCH_ISSUER_NAME
) {
2967 ret
= _hx509_name_cmp(&c
->tbsCertificate
.issuer
, q
->issuer_name
, &diff
);
2972 if (q
->match
& HX509_QUERY_MATCH_SUBJECT_NAME
) {
2973 ret
= _hx509_name_cmp(&c
->tbsCertificate
.subject
, q
->subject_name
, &diff
);
2978 if (q
->match
& HX509_QUERY_MATCH_SUBJECT_KEY_ID
) {
2979 SubjectKeyIdentifier si
;
2981 ret
= _hx509_find_extension_subject_key_id(c
, &si
);
2983 if (der_heim_octet_string_cmp(&si
, q
->subject_id
) != 0)
2985 free_SubjectKeyIdentifier(&si
);
2990 if ((q
->match
& HX509_QUERY_MATCH_ISSUER_ID
))
2992 if ((q
->match
& HX509_QUERY_PRIVATE_KEY
) &&
2993 _hx509_cert_private_key(cert
) == NULL
)
2998 if (q
->match
& HX509_QUERY_KU_DIGITALSIGNATURE
)
3000 if (q
->match
& HX509_QUERY_KU_NONREPUDIATION
)
3002 if (q
->match
& HX509_QUERY_KU_ENCIPHERMENT
)
3004 if (q
->match
& HX509_QUERY_KU_DATAENCIPHERMENT
)
3006 if (q
->match
& HX509_QUERY_KU_KEYAGREEMENT
)
3008 if (q
->match
& HX509_QUERY_KU_KEYCERTSIGN
)
3010 if (q
->match
& HX509_QUERY_KU_CRLSIGN
)
3012 if (ku
&& check_key_usage(context
, c
, ku
, TRUE
))
3015 if ((q
->match
& HX509_QUERY_ANCHOR
))
3018 if (q
->match
& HX509_QUERY_MATCH_LOCAL_KEY_ID
) {
3019 hx509_cert_attribute a
;
3021 a
= hx509_cert_get_attribute(cert
, &asn1_oid_id_pkcs_9_at_localKeyId
);
3024 if (der_heim_octet_string_cmp(&a
->data
, q
->local_key_id
) != 0)
3028 if (q
->match
& HX509_QUERY_NO_MATCH_PATH
) {
3031 for (i
= 0; i
< q
->path
->len
; i
++)
3032 if (hx509_cert_cmp(q
->path
->val
[i
], cert
) == 0)
3035 if (q
->match
& HX509_QUERY_MATCH_FRIENDLY_NAME
) {
3036 const char *name
= hx509_cert_get_friendly_name(cert
);
3039 if (strcasecmp(q
->friendlyname
, name
) != 0)
3042 if (q
->match
& HX509_QUERY_MATCH_FUNCTION
) {
3043 ret
= (*q
->cmp_func
)(context
, cert
, q
->cmp_func_ctx
);
3048 if (q
->match
& HX509_QUERY_MATCH_KEY_HASH_SHA1
) {
3049 heim_octet_string os
;
3051 os
.data
= c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.data
;
3053 c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.length
/ 8;
3055 ret
= _hx509_verify_signature(context
,
3057 hx509_signature_sha1(),
3064 if (q
->match
& HX509_QUERY_MATCH_TIME
) {
3066 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notBefore
);
3069 t
= _hx509_Time2time_t(&c
->tbsCertificate
.validity
.notAfter
);
3074 /* If an EKU is required, check the cert for it. */
3075 if ((q
->match
& HX509_QUERY_MATCH_EKU
) &&
3076 hx509_cert_check_eku(context
, cert
, q
->eku
, 0))
3079 if ((q
->match
& HX509_QUERY_MATCH_EXPR
)) {
3080 hx509_env env
= NULL
;
3082 ret
= _hx509_cert_to_env(context
, cert
, &env
);
3086 ret
= _hx509_expr_eval(context
, env
, q
->expr
);
3087 hx509_env_free(&env
);
3092 if (q
->match
& ~HX509_QUERY_MASK
)
3099 * Set a statistic file for the query statistics.
3101 * @param context A hx509 context.
3102 * @param fn statistics file name
3104 * @ingroup hx509_cert
3108 hx509_query_statistic_file(hx509_context context
, const char *fn
)
3110 if (context
->querystat
)
3111 free(context
->querystat
);
3112 context
->querystat
= strdup(fn
);
3116 _hx509_query_statistic(hx509_context context
, int type
, const hx509_query
*q
)
3119 if (context
->querystat
== NULL
)
3121 f
= fopen(context
->querystat
, "a");
3125 fprintf(f
, "%d %d\n", type
, q
->match
);
3129 static const char *statname
[] = {
3131 "match serialnumber",
3132 "match issuer name",
3133 "match subject name",
3134 "match subject key id",
3138 "ku digitalsignature",
3141 "ku nonrepudiation",
3143 "ku dataencipherment",
3145 "match certificate",
3146 "match local key id",
3148 "match friendly name",
3150 "match key hash sha1",
3155 unsigned long stats
;
3161 stat_sort(const void *a
, const void *b
)
3163 const struct stat_el
*ae
= a
;
3164 const struct stat_el
*be
= b
;
3165 return be
->stats
- ae
->stats
;
3169 * Unparse the statistics file and print the result on a FILE descriptor.
3171 * @param context A hx509 context.
3172 * @param printtype tyep to print
3173 * @param out the FILE to write the data on.
3175 * @ingroup hx509_cert
3179 hx509_query_unparse_stats(hx509_context context
, int printtype
, FILE *out
)
3183 int type
, mask
, num
;
3185 unsigned long multiqueries
= 0, totalqueries
= 0;
3186 struct stat_el stats
[32];
3188 if (context
->querystat
== NULL
)
3190 f
= fopen(context
->querystat
, "r");
3192 fprintf(out
, "No statistic file %s: %s.\n",
3193 context
->querystat
, strerror(errno
));
3198 for (i
= 0; i
< sizeof(stats
)/sizeof(stats
[0]); i
++) {
3203 while (fscanf(f
, "%d %d\n", &type
, &mask
) == 2) {
3204 if (type
!= printtype
)
3207 while (mask
&& i
< sizeof(stats
)/sizeof(stats
[0])) {
3221 qsort(stats
, sizeof(stats
)/sizeof(stats
[0]), sizeof(stats
[0]), stat_sort
);
3225 errx(1, "out of memory");
3227 rtbl_set_separator (t
, " ");
3229 rtbl_add_column_by_id (t
, 0, "Name", 0);
3230 rtbl_add_column_by_id (t
, 1, "Counter", 0);
3233 for (i
= 0; i
< sizeof(stats
)/sizeof(stats
[0]); i
++) {
3236 if (stats
[i
].index
< sizeof(statname
)/sizeof(statname
[0]))
3237 rtbl_add_column_entry_by_id (t
, 0, statname
[stats
[i
].index
]);
3239 snprintf(str
, sizeof(str
), "%d", stats
[i
].index
);
3240 rtbl_add_column_entry_by_id (t
, 0, str
);
3242 snprintf(str
, sizeof(str
), "%lu", stats
[i
].stats
);
3243 rtbl_add_column_entry_by_id (t
, 1, str
);
3246 rtbl_format(t
, out
);
3249 fprintf(out
, "\nQueries: multi %lu total %lu\n",
3250 multiqueries
, totalqueries
);
3254 * Check the extended key usage on the hx509 certificate.
3256 * @param context A hx509 context.
3257 * @param cert A hx509 context.
3258 * @param eku the EKU to check for
3259 * @param allow_any_eku if the any EKU is set, allow that to be a
3262 * @return An hx509 error code, see hx509_get_error_string().
3264 * @ingroup hx509_cert
3268 hx509_cert_check_eku(hx509_context context
, hx509_cert cert
,
3269 const heim_oid
*eku
, int allow_any_eku
)
3275 ret
= find_extension_eku(_hx509_get_cert(cert
), &e
);
3277 hx509_clear_error_string(context
);
3281 for (i
= 0; i
< e
.len
; i
++) {
3282 if (der_heim_oid_cmp(eku
, &e
.val
[i
]) == 0) {
3283 free_ExtKeyUsage(&e
);
3286 if (allow_any_eku
) {
3288 if (der_heim_oid_cmp(id_any_eku
, &e
.val
[i
]) == 0) {
3289 free_ExtKeyUsage(&e
);
3295 free_ExtKeyUsage(&e
);
3296 hx509_clear_error_string(context
);
3297 return HX509_CERTIFICATE_MISSING_EKU
;
3301 _hx509_cert_get_keyusage(hx509_context context
,
3311 memset(ku
, 0, sizeof(*ku
));
3313 cert
= _hx509_get_cert(c
);
3315 if (_hx509_cert_get_version(cert
) < 3)
3318 e
= find_extension(cert
, &asn1_oid_id_x509_ce_keyUsage
, &i
);
3320 return HX509_KU_CERT_MISSING
;
3322 ret
= decode_KeyUsage(e
->extnValue
.data
, e
->extnValue
.length
, ku
, &size
);
3329 _hx509_cert_get_eku(hx509_context context
,
3335 memset(e
, 0, sizeof(*e
));
3337 ret
= find_extension_eku(_hx509_get_cert(cert
), e
);
3338 if (ret
&& ret
!= HX509_EXTENSION_NOT_FOUND
) {
3339 hx509_clear_error_string(context
);
3346 * Encodes the hx509 certificate as a DER encode binary.
3348 * @param context A hx509 context.
3349 * @param c the certificate to encode.
3350 * @param os the encode certificate, set to NULL, 0 on case of
3351 * error. Free the os->data with hx509_xfree().
3353 * @return An hx509 error code, see hx509_get_error_string().
3355 * @ingroup hx509_cert
3359 hx509_cert_binary(hx509_context context
, hx509_cert c
, heim_octet_string
*os
)
3367 ASN1_MALLOC_ENCODE(Certificate
, os
->data
, os
->length
,
3368 _hx509_get_cert(c
), &size
, ret
);
3374 if (os
->length
!= size
)
3375 _hx509_abort("internal ASN.1 encoder error");
3381 * Last to avoid lost __attribute__s due to #undef.
3384 #undef __attribute__
3385 #define __attribute__(X)
3388 _hx509_abort(const char *fmt
, ...)
3389 __attribute__ ((noreturn
, format (printf
, 1, 2)))
3401 * Free a data element allocated in the library.
3403 * @param ptr data to be freed.
3405 * @ingroup hx509_misc
3409 hx509_xfree(void *ptr
)
3419 _hx509_cert_to_env(hx509_context context
, hx509_cert cert
, hx509_env
*env
)
3425 hx509_env envcert
= NULL
;
3430 asprintf(&buf
, "%d", _hx509_cert_get_version(_hx509_get_cert(cert
)));
3431 ret
= hx509_env_add(context
, &envcert
, "version", buf
);
3437 ret
= hx509_cert_get_subject(cert
, &name
);
3441 ret
= hx509_name_to_string(name
, &buf
);
3443 hx509_name_free(&name
);
3447 ret
= hx509_env_add(context
, &envcert
, "subject", buf
);
3448 hx509_name_free(&name
);
3453 ret
= hx509_cert_get_issuer(cert
, &name
);
3457 ret
= hx509_name_to_string(name
, &buf
);
3458 hx509_name_free(&name
);
3462 ret
= hx509_env_add(context
, &envcert
, "issuer", buf
);
3469 ret
= _hx509_cert_get_eku(context
, cert
, &eku
);
3470 if (ret
== HX509_EXTENSION_NOT_FOUND
)
3476 hx509_env enveku
= NULL
;
3478 for (i
= 0; i
< eku
.len
; i
++) {
3480 ret
= der_print_heim_oid(&eku
.val
[i
], '.', &buf
);
3482 free_ExtKeyUsage(&eku
);
3483 hx509_env_free(&enveku
);
3486 ret
= hx509_env_add(context
, &enveku
, buf
, "oid-name-here");
3489 free_ExtKeyUsage(&eku
);
3490 hx509_env_free(&enveku
);
3494 free_ExtKeyUsage(&eku
);
3496 ret
= hx509_env_add_binding(context
, &envcert
, "eku", enveku
);
3498 hx509_env_free(&enveku
);
3504 Certificate
*c
= _hx509_get_cert(cert
);
3505 heim_octet_string os
, sig
;
3506 hx509_env envhash
= NULL
;
3508 os
.data
= c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.data
;
3510 c
->tbsCertificate
.subjectPublicKeyInfo
.subjectPublicKey
.length
/ 8;
3512 ret
= _hx509_create_signature(context
,
3514 hx509_signature_sha1(),
3521 ret
= hex_encode(sig
.data
, sig
.length
, &buf
);
3522 der_free_octet_string(&sig
);
3525 hx509_set_error_string(context
, 0, ret
,
3530 ret
= hx509_env_add(context
, &envhash
, "sha1", buf
);
3535 ret
= hx509_env_add_binding(context
, &envcert
, "hash", envhash
);
3537 hx509_env_free(&envhash
);
3542 ret
= hx509_env_add_binding(context
, env
, "certificate", envcert
);
3549 hx509_env_free(&envcert
);
3554 * Print a simple representation of a certificate
3556 * @param context A hx509 context, can be NULL
3557 * @param cert certificate to print
3558 * @param out the stdio output stream, if NULL, stdout is used
3560 * @return An hx509 error code
3562 * @ingroup hx509_cert
3566 hx509_print_cert(hx509_context context
, hx509_cert cert
, FILE *out
)
3575 ret
= hx509_cert_get_issuer(cert
, &name
);
3578 hx509_name_to_string(name
, &str
);
3579 hx509_name_free(&name
);
3580 fprintf(out
, " issuer: \"%s\"\n", str
);
3583 ret
= hx509_cert_get_subject(cert
, &name
);
3586 hx509_name_to_string(name
, &str
);
3587 hx509_name_free(&name
);
3588 fprintf(out
, " subject: \"%s\"\n", str
);
3592 heim_integer serialNumber
;
3594 ret
= hx509_cert_get_serialnumber(cert
, &serialNumber
);
3597 ret
= der_print_hex_heim_integer(&serialNumber
, &str
);
3600 der_free_heim_integer(&serialNumber
);
3601 fprintf(out
, " serial: %s\n", str
);
3605 printf(" keyusage: ");
3606 ret
= hx509_cert_keyusage_print(context
, cert
, &str
);
3608 fprintf(out
, "%s\n", str
);