Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/hx509/cert.c
34879 views
1
/*
2
* Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
3
* (Royal Institute of Technology, Stockholm, Sweden).
4
* All rights reserved.
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
*
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
*
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.
16
*
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.
20
*
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
31
* SUCH DAMAGE.
32
*/
33
34
#include "hx_locl.h"
35
#include "crypto-headers.h"
36
#include <rtbl.h>
37
38
/**
39
* @page page_cert The basic certificate
40
*
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.
44
*
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().
49
*
50
* See the library functions here: @ref hx509_cert
51
*/
52
53
struct hx509_verify_ctx_data {
54
hx509_certs trust_anchors;
55
int flags;
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
62
time_t time_now;
63
unsigned int max_depth;
64
#define HX509_VERIFY_MAX_DEPTH 30
65
hx509_revoke_ctx revoke_ctx;
66
};
67
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)
71
72
struct _hx509_cert_attrs {
73
size_t len;
74
hx509_cert_attribute *val;
75
};
76
77
struct hx509_cert_data {
78
unsigned int ref;
79
char *friendlyname;
80
Certificate *data;
81
hx509_private_key private_key;
82
struct _hx509_cert_attrs attrs;
83
hx509_name basename;
84
_hx509_cert_release_func release;
85
void *ctx;
86
};
87
88
typedef struct hx509_name_constraints {
89
NameConstraints *val;
90
size_t len;
91
} hx509_name_constraints;
92
93
#define GeneralSubtrees_SET(g,var) \
94
(g)->len = (var)->len, (g)->val = (var)->val;
95
96
/**
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().
100
*
101
* @param context Returns a pointer to new hx509 context.
102
*
103
* @return Returns an hx509 error code.
104
*
105
* @ingroup hx509
106
*/
107
108
int
109
hx509_context_init(hx509_context *context)
110
{
111
*context = calloc(1, sizeof(**context));
112
if (*context == NULL)
113
return ENOMEM;
114
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);
122
123
ENGINE_add_conf_module();
124
OpenSSL_add_all_algorithms();
125
126
(*context)->ocsp_time_diff = HX509_DEFAULT_OCSP_TIME_DIFF;
127
128
initialize_hx_error_table_r(&(*context)->et_list);
129
initialize_asn1_error_table_r(&(*context)->et_list);
130
131
#ifdef HX509_DEFAULT_ANCHORS
132
(void)hx509_certs_init(*context, HX509_DEFAULT_ANCHORS, 0,
133
NULL, &(*context)->default_trust_anchors);
134
#endif
135
136
return 0;
137
}
138
139
/**
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().
144
*
145
* @param context hx509 context to change the flag for.
146
* @param flag zero, revokation method required, non zero missing
147
* revokation method ok
148
*
149
* @ingroup hx509_verify
150
*/
151
152
void
153
hx509_context_set_missing_revoke(hx509_context context, int flag)
154
{
155
if (flag)
156
context->flags |= HX509_CTX_VERIFY_MISSING_OK;
157
else
158
context->flags &= ~HX509_CTX_VERIFY_MISSING_OK;
159
}
160
161
/**
162
* Free the context allocated by hx509_context_init().
163
*
164
* @param context context to be freed.
165
*
166
* @ingroup hx509
167
*/
168
169
void
170
hx509_context_free(hx509_context *context)
171
{
172
hx509_clear_error_string(*context);
173
if ((*context)->ks_ops) {
174
free((*context)->ks_ops);
175
(*context)->ks_ops = NULL;
176
}
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));
182
free(*context);
183
*context = NULL;
184
}
185
186
/*
187
*
188
*/
189
190
Certificate *
191
_hx509_get_cert(hx509_cert cert)
192
{
193
return cert->data;
194
}
195
196
/*
197
*
198
*/
199
200
int
201
_hx509_cert_get_version(const Certificate *t)
202
{
203
return t->tbsCertificate.version ? *t->tbsCertificate.version + 1 : 1;
204
}
205
206
/**
207
* Allocate and init an hx509 certificate object from the decoded
208
* certificate `c´.
209
*
210
* @param context A hx509 context.
211
* @param c
212
* @param cert
213
*
214
* @return Returns an hx509 error code.
215
*
216
* @ingroup hx509_cert
217
*/
218
219
int
220
hx509_cert_init(hx509_context context, const Certificate *c, hx509_cert *cert)
221
{
222
int ret;
223
224
*cert = malloc(sizeof(**cert));
225
if (*cert == NULL)
226
return ENOMEM;
227
(*cert)->ref = 1;
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;
234
(*cert)->ctx = NULL;
235
236
(*cert)->data = calloc(1, sizeof(*(*cert)->data));
237
if ((*cert)->data == NULL) {
238
free(*cert);
239
return ENOMEM;
240
}
241
ret = copy_Certificate(c, (*cert)->data);
242
if (ret) {
243
free((*cert)->data);
244
free(*cert);
245
*cert = NULL;
246
}
247
return ret;
248
}
249
250
/**
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.
254
*
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.
258
*
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.
264
*
265
* @return An hx509 error code, see hx509_get_error_string().
266
*
267
* @ingroup hx509_cert
268
*/
269
270
int
271
hx509_cert_init_data(hx509_context context,
272
const void *ptr,
273
size_t len,
274
hx509_cert *cert)
275
{
276
Certificate t;
277
size_t size;
278
int ret;
279
280
ret = decode_Certificate(ptr, len, &t, &size);
281
if (ret) {
282
hx509_set_error_string(context, 0, ret, "Failed to decode certificate");
283
return ret;
284
}
285
if (size != len) {
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;
290
}
291
292
ret = hx509_cert_init(context, &t, cert);
293
free_Certificate(&t);
294
return ret;
295
}
296
297
void
298
_hx509_cert_set_release(hx509_cert cert,
299
_hx509_cert_release_func release,
300
void *ctx)
301
{
302
cert->release = release;
303
cert->ctx = ctx;
304
}
305
306
307
/* Doesn't make a copy of `private_key'. */
308
309
int
310
_hx509_cert_assign_key(hx509_cert cert, hx509_private_key private_key)
311
{
312
if (cert->private_key)
313
hx509_private_key_free(&cert->private_key);
314
cert->private_key = _hx509_private_key_ref(private_key);
315
return 0;
316
}
317
318
/**
319
* Free reference to the hx509 certificate object, if the refcounter
320
* reaches 0, the object if freed. Its allowed to pass in NULL.
321
*
322
* @param cert the cert to free.
323
*
324
* @ingroup hx509_cert
325
*/
326
327
void
328
hx509_cert_free(hx509_cert cert)
329
{
330
size_t i;
331
332
if (cert == NULL)
333
return;
334
335
if (cert->ref <= 0)
336
_hx509_abort("cert refcount <= 0 on free");
337
if (--cert->ref > 0)
338
return;
339
340
if (cert->release)
341
(cert->release)(cert, cert->ctx);
342
343
if (cert->private_key)
344
hx509_private_key_free(&cert->private_key);
345
346
free_Certificate(cert->data);
347
free(cert->data);
348
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]);
353
}
354
free(cert->attrs.val);
355
free(cert->friendlyname);
356
if (cert->basename)
357
hx509_name_free(&cert->basename);
358
memset(cert, 0, sizeof(*cert));
359
free(cert);
360
}
361
362
/**
363
* Add a reference to a hx509 certificate object.
364
*
365
* @param cert a pointer to an hx509 certificate object.
366
*
367
* @return the same object as is passed in.
368
*
369
* @ingroup hx509_cert
370
*/
371
372
hx509_cert
373
hx509_cert_ref(hx509_cert cert)
374
{
375
if (cert == NULL)
376
return NULL;
377
if (cert->ref <= 0)
378
_hx509_abort("cert refcount <= 0");
379
cert->ref++;
380
if (cert->ref == 0)
381
_hx509_abort("cert refcount == 0");
382
return cert;
383
}
384
385
/**
386
* Allocate an verification context that is used fo control the
387
* verification process.
388
*
389
* @param context A hx509 context.
390
* @param ctx returns a pointer to a hx509_verify_ctx object.
391
*
392
* @return An hx509 error code, see hx509_get_error_string().
393
*
394
* @ingroup hx509_verify
395
*/
396
397
int
398
hx509_verify_init_ctx(hx509_context context, hx509_verify_ctx *ctx)
399
{
400
hx509_verify_ctx c;
401
402
c = calloc(1, sizeof(*c));
403
if (c == NULL)
404
return ENOMEM;
405
406
c->max_depth = HX509_VERIFY_MAX_DEPTH;
407
408
*ctx = c;
409
410
return 0;
411
}
412
413
/**
414
* Free an hx509 verification context.
415
*
416
* @param ctx the context to be freed.
417
*
418
* @ingroup hx509_verify
419
*/
420
421
void
422
hx509_verify_destroy_ctx(hx509_verify_ctx ctx)
423
{
424
if (ctx) {
425
hx509_certs_free(&ctx->trust_anchors);
426
hx509_revoke_free(&ctx->revoke_ctx);
427
memset(ctx, 0, sizeof(*ctx));
428
}
429
free(ctx);
430
}
431
432
/**
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.
437
*
438
* @param ctx a verification context
439
* @param set a keyset containing the trust anchors.
440
*
441
* @ingroup hx509_verify
442
*/
443
444
void
445
hx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set)
446
{
447
if (ctx->trust_anchors)
448
hx509_certs_free(&ctx->trust_anchors);
449
ctx->trust_anchors = hx509_certs_ref(set);
450
}
451
452
/**
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.
458
*
459
* @param ctx a verification context.
460
* @param revoke_ctx a revoke context.
461
*
462
* @ingroup hx509_verify
463
*/
464
465
void
466
hx509_verify_attach_revoke(hx509_verify_ctx ctx, hx509_revoke_ctx revoke_ctx)
467
{
468
if (ctx->revoke_ctx)
469
hx509_revoke_free(&ctx->revoke_ctx);
470
ctx->revoke_ctx = _hx509_revoke_ref(revoke_ctx);
471
}
472
473
/**
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.
477
*
478
* @param ctx a verification context.
479
* @param t the time the verifiation is using.
480
*
481
*
482
* @ingroup hx509_verify
483
*/
484
485
void
486
hx509_verify_set_time(hx509_verify_ctx ctx, time_t t)
487
{
488
ctx->flags |= HX509_VERIFY_CTX_F_TIME_SET;
489
ctx->time_now = t;
490
}
491
492
time_t
493
_hx509_verify_get_time(hx509_verify_ctx ctx)
494
{
495
return ctx->time_now;
496
}
497
498
/**
499
* Set the maximum depth of the certificate chain that the path
500
* builder is going to try.
501
*
502
* @param ctx a verification context
503
* @param max_depth maxium depth of the certificate chain, include
504
* trust anchor.
505
*
506
* @ingroup hx509_verify
507
*/
508
509
void
510
hx509_verify_set_max_depth(hx509_verify_ctx ctx, unsigned int max_depth)
511
{
512
ctx->max_depth = max_depth;
513
}
514
515
/**
516
* Allow or deny the use of proxy certificates
517
*
518
* @param ctx a verification context
519
* @param boolean if non zero, allow proxy certificates.
520
*
521
* @ingroup hx509_verify
522
*/
523
524
void
525
hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean)
526
{
527
if (boolean)
528
ctx->flags |= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
529
else
530
ctx->flags &= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
531
}
532
533
/**
534
* Select strict RFC3280 verification of certificiates. This means
535
* checking key usage on CA certificates, this will make version 1
536
* certificiates unuseable.
537
*
538
* @param ctx a verification context
539
* @param boolean if non zero, use strict verification.
540
*
541
* @ingroup hx509_verify
542
*/
543
544
void
545
hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean)
546
{
547
if (boolean)
548
ctx->flags |= HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
549
else
550
ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
551
}
552
553
/**
554
* Allow using the operating system builtin trust anchors if no other
555
* trust anchors are configured.
556
*
557
* @param ctx a verification context
558
* @param boolean if non zero, useing the operating systems builtin
559
* trust anchors.
560
*
561
*
562
* @return An hx509 error code, see hx509_get_error_string().
563
*
564
* @ingroup hx509_cert
565
*/
566
567
void
568
hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean)
569
{
570
if (boolean)
571
ctx->flags &= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
572
else
573
ctx->flags |= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
574
}
575
576
void
577
hx509_verify_ctx_f_allow_best_before_signature_algs(hx509_context ctx,
578
int boolean)
579
{
580
if (boolean)
581
ctx->flags &= ~HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
582
else
583
ctx->flags |= HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
584
}
585
586
static const Extension *
587
find_extension(const Certificate *cert, const heim_oid *oid, size_t *idx)
588
{
589
const TBSCertificate *c = &cert->tbsCertificate;
590
591
if (c->version == NULL || *c->version < 2 || c->extensions == NULL)
592
return NULL;
593
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)++];
597
}
598
return NULL;
599
}
600
601
static int
602
find_extension_auth_key_id(const Certificate *subject,
603
AuthorityKeyIdentifier *ai)
604
{
605
const Extension *e;
606
size_t size;
607
size_t i = 0;
608
609
memset(ai, 0, sizeof(*ai));
610
611
e = find_extension(subject, &asn1_oid_id_x509_ce_authorityKeyIdentifier, &i);
612
if (e == NULL)
613
return HX509_EXTENSION_NOT_FOUND;
614
615
return decode_AuthorityKeyIdentifier(e->extnValue.data,
616
e->extnValue.length,
617
ai, &size);
618
}
619
620
int
621
_hx509_find_extension_subject_key_id(const Certificate *issuer,
622
SubjectKeyIdentifier *si)
623
{
624
const Extension *e;
625
size_t size;
626
size_t i = 0;
627
628
memset(si, 0, sizeof(*si));
629
630
e = find_extension(issuer, &asn1_oid_id_x509_ce_subjectKeyIdentifier, &i);
631
if (e == NULL)
632
return HX509_EXTENSION_NOT_FOUND;
633
634
return decode_SubjectKeyIdentifier(e->extnValue.data,
635
e->extnValue.length,
636
si, &size);
637
}
638
639
static int
640
find_extension_name_constraints(const Certificate *subject,
641
NameConstraints *nc)
642
{
643
const Extension *e;
644
size_t size;
645
size_t i = 0;
646
647
memset(nc, 0, sizeof(*nc));
648
649
e = find_extension(subject, &asn1_oid_id_x509_ce_nameConstraints, &i);
650
if (e == NULL)
651
return HX509_EXTENSION_NOT_FOUND;
652
653
return decode_NameConstraints(e->extnValue.data,
654
e->extnValue.length,
655
nc, &size);
656
}
657
658
static int
659
find_extension_subject_alt_name(const Certificate *cert, size_t *i,
660
GeneralNames *sa)
661
{
662
const Extension *e;
663
size_t size;
664
665
memset(sa, 0, sizeof(*sa));
666
667
e = find_extension(cert, &asn1_oid_id_x509_ce_subjectAltName, i);
668
if (e == NULL)
669
return HX509_EXTENSION_NOT_FOUND;
670
671
return decode_GeneralNames(e->extnValue.data,
672
e->extnValue.length,
673
sa, &size);
674
}
675
676
static int
677
find_extension_eku(const Certificate *cert, ExtKeyUsage *eku)
678
{
679
const Extension *e;
680
size_t size;
681
size_t i = 0;
682
683
memset(eku, 0, sizeof(*eku));
684
685
e = find_extension(cert, &asn1_oid_id_x509_ce_extKeyUsage, &i);
686
if (e == NULL)
687
return HX509_EXTENSION_NOT_FOUND;
688
689
return decode_ExtKeyUsage(e->extnValue.data,
690
e->extnValue.length,
691
eku, &size);
692
}
693
694
static int
695
add_to_list(hx509_octet_string_list *list, const heim_octet_string *entry)
696
{
697
void *p;
698
int ret;
699
700
p = realloc(list->val, (list->len + 1) * sizeof(list->val[0]));
701
if (p == NULL)
702
return ENOMEM;
703
list->val = p;
704
ret = der_copy_octet_string(entry, &list->val[list->len]);
705
if (ret)
706
return ret;
707
list->len++;
708
return 0;
709
}
710
711
/**
712
* Free a list of octet strings returned by another hx509 library
713
* function.
714
*
715
* @param list list to be freed.
716
*
717
* @ingroup hx509_misc
718
*/
719
720
void
721
hx509_free_octet_string_list(hx509_octet_string_list *list)
722
{
723
size_t i;
724
for (i = 0; i < list->len; i++)
725
der_free_octet_string(&list->val[i]);
726
free(list->val);
727
list->val = NULL;
728
list->len = 0;
729
}
730
731
/**
732
* Return a list of subjectAltNames specified by oid in the
733
* certificate. On error the
734
*
735
* The returned list of octet string should be freed with
736
* hx509_free_octet_string_list().
737
*
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.
742
*
743
* @return An hx509 error code, see hx509_get_error_string().
744
*
745
* @ingroup hx509_cert
746
*/
747
748
int
749
hx509_cert_find_subjectAltName_otherName(hx509_context context,
750
hx509_cert cert,
751
const heim_oid *oid,
752
hx509_octet_string_list *list)
753
{
754
GeneralNames sa;
755
int ret;
756
size_t i, j;
757
758
list->val = NULL;
759
list->len = 0;
760
761
i = 0;
762
while (1) {
763
ret = find_extension_subject_alt_name(_hx509_get_cert(cert), &i, &sa);
764
i++;
765
if (ret == HX509_EXTENSION_NOT_FOUND) {
766
return 0;
767
} else if (ret != 0) {
768
hx509_set_error_string(context, 0, ret, "Error searching for SAN");
769
hx509_free_octet_string_list(list);
770
return ret;
771
}
772
773
for (j = 0; j < sa.len; j++) {
774
if (sa.val[j].element == choice_GeneralName_otherName &&
775
der_heim_oid_cmp(&sa.val[j].u.otherName.type_id, oid) == 0)
776
{
777
ret = add_to_list(list, &sa.val[j].u.otherName.value);
778
if (ret) {
779
hx509_set_error_string(context, 0, ret,
780
"Error adding an exra SAN to "
781
"return list");
782
hx509_free_octet_string_list(list);
783
free_GeneralNames(&sa);
784
return ret;
785
}
786
}
787
}
788
free_GeneralNames(&sa);
789
}
790
}
791
792
793
static int
794
check_key_usage(hx509_context context, const Certificate *cert,
795
unsigned flags, int req_present)
796
{
797
const Extension *e;
798
KeyUsage ku;
799
size_t size;
800
int ret;
801
size_t i = 0;
802
unsigned ku_flags;
803
804
if (_hx509_cert_get_version(cert) < 3)
805
return 0;
806
807
e = find_extension(cert, &asn1_oid_id_x509_ce_keyUsage, &i);
808
if (e == NULL) {
809
if (req_present) {
810
hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
811
"Required extension key "
812
"usage missing from certifiate");
813
return HX509_KU_CERT_MISSING;
814
}
815
return 0;
816
}
817
818
ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &size);
819
if (ret)
820
return ret;
821
ku_flags = KeyUsage2int(ku);
822
if ((ku_flags & flags) != flags) {
823
unsigned missing = (~ku_flags) & flags;
824
char buf[256], *name;
825
826
unparse_flags(missing, asn1_KeyUsage_units(), buf, sizeof(buf));
827
_hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
828
hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
829
"Key usage %s required but missing "
830
"from certifiate %s", buf, name);
831
free(name);
832
return HX509_KU_CERT_MISSING;
833
}
834
return 0;
835
}
836
837
/*
838
* Return 0 on matching key usage 'flags' for 'cert', otherwise return
839
* an error code. If 'req_present' the existance is required of the
840
* KeyUsage extension.
841
*/
842
843
int
844
_hx509_check_key_usage(hx509_context context, hx509_cert cert,
845
unsigned flags, int req_present)
846
{
847
return check_key_usage(context, _hx509_get_cert(cert), flags, req_present);
848
}
849
850
enum certtype { PROXY_CERT, EE_CERT, CA_CERT };
851
852
static int
853
check_basic_constraints(hx509_context context, const Certificate *cert,
854
enum certtype type, size_t depth)
855
{
856
BasicConstraints bc;
857
const Extension *e;
858
size_t size;
859
int ret;
860
size_t i = 0;
861
862
if (_hx509_cert_get_version(cert) < 3)
863
return 0;
864
865
e = find_extension(cert, &asn1_oid_id_x509_ce_basicConstraints, &i);
866
if (e == NULL) {
867
switch(type) {
868
case PROXY_CERT:
869
case EE_CERT:
870
return 0;
871
case CA_CERT: {
872
char *name;
873
ret = _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
874
assert(ret == 0);
875
hx509_set_error_string(context, 0, HX509_EXTENSION_NOT_FOUND,
876
"basicConstraints missing from "
877
"CA certifiacte %s", name);
878
free(name);
879
return HX509_EXTENSION_NOT_FOUND;
880
}
881
}
882
}
883
884
ret = decode_BasicConstraints(e->extnValue.data,
885
e->extnValue.length, &bc,
886
&size);
887
if (ret)
888
return ret;
889
switch(type) {
890
case PROXY_CERT:
891
if (bc.cA != NULL && *bc.cA)
892
ret = HX509_PARENT_IS_CA;
893
break;
894
case EE_CERT:
895
ret = 0;
896
break;
897
case CA_CERT:
898
if (bc.cA == NULL || !*bc.cA)
899
ret = HX509_PARENT_NOT_CA;
900
else if (bc.pathLenConstraint)
901
if (depth - 1 > *bc.pathLenConstraint)
902
ret = HX509_CA_PATH_TOO_DEEP;
903
break;
904
}
905
free_BasicConstraints(&bc);
906
return ret;
907
}
908
909
int
910
_hx509_cert_is_parent_cmp(const Certificate *subject,
911
const Certificate *issuer,
912
int allow_self_signed)
913
{
914
int diff;
915
AuthorityKeyIdentifier ai;
916
SubjectKeyIdentifier si;
917
int ret_ai, ret_si, ret;
918
919
ret = _hx509_name_cmp(&issuer->tbsCertificate.subject,
920
&subject->tbsCertificate.issuer,
921
&diff);
922
if (ret)
923
return ret;
924
if (diff)
925
return diff;
926
927
memset(&ai, 0, sizeof(ai));
928
memset(&si, 0, sizeof(si));
929
930
/*
931
* Try to find AuthorityKeyIdentifier, if it's not present in the
932
* subject certificate nor the parent.
933
*/
934
935
ret_ai = find_extension_auth_key_id(subject, &ai);
936
if (ret_ai && ret_ai != HX509_EXTENSION_NOT_FOUND)
937
return 1;
938
ret_si = _hx509_find_extension_subject_key_id(issuer, &si);
939
if (ret_si && ret_si != HX509_EXTENSION_NOT_FOUND)
940
return -1;
941
942
if (ret_si && ret_ai)
943
goto out;
944
if (ret_ai)
945
goto out;
946
if (ret_si) {
947
if (allow_self_signed) {
948
diff = 0;
949
goto out;
950
} else if (ai.keyIdentifier) {
951
diff = -1;
952
goto out;
953
}
954
}
955
956
if (ai.keyIdentifier == NULL) {
957
Name name;
958
959
if (ai.authorityCertIssuer == NULL)
960
return -1;
961
if (ai.authorityCertSerialNumber == NULL)
962
return -1;
963
964
diff = der_heim_integer_cmp(ai.authorityCertSerialNumber,
965
&issuer->tbsCertificate.serialNumber);
966
if (diff)
967
return diff;
968
if (ai.authorityCertIssuer->len != 1)
969
return -1;
970
if (ai.authorityCertIssuer->val[0].element != choice_GeneralName_directoryName)
971
return -1;
972
973
name.element =
974
ai.authorityCertIssuer->val[0].u.directoryName.element;
975
name.u.rdnSequence =
976
ai.authorityCertIssuer->val[0].u.directoryName.u.rdnSequence;
977
978
ret = _hx509_name_cmp(&issuer->tbsCertificate.subject,
979
&name,
980
&diff);
981
if (ret)
982
return ret;
983
if (diff)
984
return diff;
985
diff = 0;
986
} else
987
diff = der_heim_octet_string_cmp(ai.keyIdentifier, &si);
988
if (diff)
989
goto out;
990
991
out:
992
free_AuthorityKeyIdentifier(&ai);
993
free_SubjectKeyIdentifier(&si);
994
return diff;
995
}
996
997
static int
998
certificate_is_anchor(hx509_context context,
999
hx509_certs trust_anchors,
1000
const hx509_cert cert)
1001
{
1002
hx509_query q;
1003
hx509_cert c;
1004
int ret;
1005
1006
if (trust_anchors == NULL)
1007
return 0;
1008
1009
_hx509_query_clear(&q);
1010
1011
q.match = HX509_QUERY_MATCH_CERTIFICATE;
1012
q.certificate = _hx509_get_cert(cert);
1013
1014
ret = hx509_certs_find(context, trust_anchors, &q, &c);
1015
if (ret == 0)
1016
hx509_cert_free(c);
1017
return ret == 0;
1018
}
1019
1020
static int
1021
certificate_is_self_signed(hx509_context context,
1022
const Certificate *cert,
1023
int *self_signed)
1024
{
1025
int ret, diff;
1026
ret = _hx509_name_cmp(&cert->tbsCertificate.subject,
1027
&cert->tbsCertificate.issuer, &diff);
1028
*self_signed = (diff == 0);
1029
if (ret) {
1030
hx509_set_error_string(context, 0, ret,
1031
"Failed to check if self signed");
1032
} else
1033
ret = _hx509_self_signed_valid(context, &cert->signatureAlgorithm);
1034
1035
return ret;
1036
}
1037
1038
/*
1039
* The subjectName is "null" when it's empty set of relative DBs.
1040
*/
1041
1042
static int
1043
subject_null_p(const Certificate *c)
1044
{
1045
return c->tbsCertificate.subject.u.rdnSequence.len == 0;
1046
}
1047
1048
1049
static int
1050
find_parent(hx509_context context,
1051
time_t time_now,
1052
hx509_certs trust_anchors,
1053
hx509_path *path,
1054
hx509_certs pool,
1055
hx509_cert current,
1056
hx509_cert *parent)
1057
{
1058
AuthorityKeyIdentifier ai;
1059
hx509_query q;
1060
int ret;
1061
1062
*parent = NULL;
1063
memset(&ai, 0, sizeof(ai));
1064
1065
_hx509_query_clear(&q);
1066
1067
if (!subject_null_p(current->data)) {
1068
q.match |= HX509_QUERY_FIND_ISSUER_CERT;
1069
q.subject = _hx509_get_cert(current);
1070
} else {
1071
ret = find_extension_auth_key_id(current->data, &ai);
1072
if (ret) {
1073
hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
1074
"Subjectless certificate missing AuthKeyID");
1075
return HX509_CERTIFICATE_MALFORMED;
1076
}
1077
1078
if (ai.keyIdentifier == NULL) {
1079
free_AuthorityKeyIdentifier(&ai);
1080
hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
1081
"Subjectless certificate missing keyIdentifier "
1082
"inside AuthKeyID");
1083
return HX509_CERTIFICATE_MALFORMED;
1084
}
1085
1086
q.subject_id = ai.keyIdentifier;
1087
q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID;
1088
}
1089
1090
q.path = path;
1091
q.match |= HX509_QUERY_NO_MATCH_PATH;
1092
1093
if (pool) {
1094
q.timenow = time_now;
1095
q.match |= HX509_QUERY_MATCH_TIME;
1096
1097
ret = hx509_certs_find(context, pool, &q, parent);
1098
if (ret == 0) {
1099
free_AuthorityKeyIdentifier(&ai);
1100
return 0;
1101
}
1102
q.match &= ~HX509_QUERY_MATCH_TIME;
1103
}
1104
1105
if (trust_anchors) {
1106
ret = hx509_certs_find(context, trust_anchors, &q, parent);
1107
if (ret == 0) {
1108
free_AuthorityKeyIdentifier(&ai);
1109
return ret;
1110
}
1111
}
1112
free_AuthorityKeyIdentifier(&ai);
1113
1114
{
1115
hx509_name name;
1116
char *str;
1117
1118
ret = hx509_cert_get_subject(current, &name);
1119
if (ret) {
1120
hx509_clear_error_string(context);
1121
return HX509_ISSUER_NOT_FOUND;
1122
}
1123
ret = hx509_name_to_string(name, &str);
1124
hx509_name_free(&name);
1125
if (ret) {
1126
hx509_clear_error_string(context);
1127
return HX509_ISSUER_NOT_FOUND;
1128
}
1129
1130
hx509_set_error_string(context, 0, HX509_ISSUER_NOT_FOUND,
1131
"Failed to find issuer for "
1132
"certificate with subject: '%s'", str);
1133
free(str);
1134
}
1135
return HX509_ISSUER_NOT_FOUND;
1136
}
1137
1138
/*
1139
*
1140
*/
1141
1142
static int
1143
is_proxy_cert(hx509_context context,
1144
const Certificate *cert,
1145
ProxyCertInfo *rinfo)
1146
{
1147
ProxyCertInfo info;
1148
const Extension *e;
1149
size_t size;
1150
int ret;
1151
size_t i = 0;
1152
1153
if (rinfo)
1154
memset(rinfo, 0, sizeof(*rinfo));
1155
1156
e = find_extension(cert, &asn1_oid_id_pkix_pe_proxyCertInfo, &i);
1157
if (e == NULL) {
1158
hx509_clear_error_string(context);
1159
return HX509_EXTENSION_NOT_FOUND;
1160
}
1161
1162
ret = decode_ProxyCertInfo(e->extnValue.data,
1163
e->extnValue.length,
1164
&info,
1165
&size);
1166
if (ret) {
1167
hx509_clear_error_string(context);
1168
return ret;
1169
}
1170
if (size != e->extnValue.length) {
1171
free_ProxyCertInfo(&info);
1172
hx509_clear_error_string(context);
1173
return HX509_EXTRA_DATA_AFTER_STRUCTURE;
1174
}
1175
if (rinfo == NULL)
1176
free_ProxyCertInfo(&info);
1177
else
1178
*rinfo = info;
1179
1180
return 0;
1181
}
1182
1183
/*
1184
* Path operations are like MEMORY based keyset, but with exposed
1185
* internal so we can do easy searches.
1186
*/
1187
1188
int
1189
_hx509_path_append(hx509_context context, hx509_path *path, hx509_cert cert)
1190
{
1191
hx509_cert *val;
1192
val = realloc(path->val, (path->len + 1) * sizeof(path->val[0]));
1193
if (val == NULL) {
1194
hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1195
return ENOMEM;
1196
}
1197
1198
path->val = val;
1199
path->val[path->len] = hx509_cert_ref(cert);
1200
path->len++;
1201
1202
return 0;
1203
}
1204
1205
void
1206
_hx509_path_free(hx509_path *path)
1207
{
1208
unsigned i;
1209
1210
for (i = 0; i < path->len; i++)
1211
hx509_cert_free(path->val[i]);
1212
free(path->val);
1213
path->val = NULL;
1214
path->len = 0;
1215
}
1216
1217
/*
1218
* Find path by looking up issuer for the top certificate and continue
1219
* until an anchor certificate is found or max limit is found. A
1220
* certificate never included twice in the path.
1221
*
1222
* If the trust anchors are not given, calculate optimistic path, just
1223
* follow the chain upward until we no longer find a parent or we hit
1224
* the max path limit. In this case, a failure will always be returned
1225
* depending on what error condition is hit first.
1226
*
1227
* The path includes a path from the top certificate to the anchor
1228
* certificate.
1229
*
1230
* The caller needs to free `path´ both on successful built path and
1231
* failure.
1232
*/
1233
1234
int
1235
_hx509_calculate_path(hx509_context context,
1236
int flags,
1237
time_t time_now,
1238
hx509_certs anchors,
1239
unsigned int max_depth,
1240
hx509_cert cert,
1241
hx509_certs pool,
1242
hx509_path *path)
1243
{
1244
hx509_cert parent, current;
1245
int ret;
1246
1247
if (max_depth == 0)
1248
max_depth = HX509_VERIFY_MAX_DEPTH;
1249
1250
ret = _hx509_path_append(context, path, cert);
1251
if (ret)
1252
return ret;
1253
1254
current = hx509_cert_ref(cert);
1255
1256
while (!certificate_is_anchor(context, anchors, current)) {
1257
1258
ret = find_parent(context, time_now, anchors, path,
1259
pool, current, &parent);
1260
hx509_cert_free(current);
1261
if (ret)
1262
return ret;
1263
1264
ret = _hx509_path_append(context, path, parent);
1265
if (ret)
1266
return ret;
1267
current = parent;
1268
1269
if (path->len > max_depth) {
1270
hx509_cert_free(current);
1271
hx509_set_error_string(context, 0, HX509_PATH_TOO_LONG,
1272
"Path too long while bulding "
1273
"certificate chain");
1274
return HX509_PATH_TOO_LONG;
1275
}
1276
}
1277
1278
if ((flags & HX509_CALCULATE_PATH_NO_ANCHOR) &&
1279
path->len > 0 &&
1280
certificate_is_anchor(context, anchors, path->val[path->len - 1]))
1281
{
1282
hx509_cert_free(path->val[path->len - 1]);
1283
path->len--;
1284
}
1285
1286
hx509_cert_free(current);
1287
return 0;
1288
}
1289
1290
int
1291
_hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier *p,
1292
const AlgorithmIdentifier *q)
1293
{
1294
int diff;
1295
diff = der_heim_oid_cmp(&p->algorithm, &q->algorithm);
1296
if (diff)
1297
return diff;
1298
if (p->parameters) {
1299
if (q->parameters)
1300
return heim_any_cmp(p->parameters,
1301
q->parameters);
1302
else
1303
return 1;
1304
} else {
1305
if (q->parameters)
1306
return -1;
1307
else
1308
return 0;
1309
}
1310
}
1311
1312
int
1313
_hx509_Certificate_cmp(const Certificate *p, const Certificate *q)
1314
{
1315
int diff;
1316
diff = der_heim_bit_string_cmp(&p->signatureValue, &q->signatureValue);
1317
if (diff)
1318
return diff;
1319
diff = _hx509_AlgorithmIdentifier_cmp(&p->signatureAlgorithm,
1320
&q->signatureAlgorithm);
1321
if (diff)
1322
return diff;
1323
diff = der_heim_octet_string_cmp(&p->tbsCertificate._save,
1324
&q->tbsCertificate._save);
1325
return diff;
1326
}
1327
1328
/**
1329
* Compare to hx509 certificate object, useful for sorting.
1330
*
1331
* @param p a hx509 certificate object.
1332
* @param q a hx509 certificate object.
1333
*
1334
* @return 0 the objects are the same, returns > 0 is p is "larger"
1335
* then q, < 0 if p is "smaller" then q.
1336
*
1337
* @ingroup hx509_cert
1338
*/
1339
1340
int
1341
hx509_cert_cmp(hx509_cert p, hx509_cert q)
1342
{
1343
return _hx509_Certificate_cmp(p->data, q->data);
1344
}
1345
1346
/**
1347
* Return the name of the issuer of the hx509 certificate.
1348
*
1349
* @param p a hx509 certificate object.
1350
* @param name a pointer to a hx509 name, should be freed by
1351
* hx509_name_free().
1352
*
1353
* @return An hx509 error code, see hx509_get_error_string().
1354
*
1355
* @ingroup hx509_cert
1356
*/
1357
1358
int
1359
hx509_cert_get_issuer(hx509_cert p, hx509_name *name)
1360
{
1361
return _hx509_name_from_Name(&p->data->tbsCertificate.issuer, name);
1362
}
1363
1364
/**
1365
* Return the name of the subject of the hx509 certificate.
1366
*
1367
* @param p a hx509 certificate object.
1368
* @param name a pointer to a hx509 name, should be freed by
1369
* hx509_name_free(). See also hx509_cert_get_base_subject().
1370
*
1371
* @return An hx509 error code, see hx509_get_error_string().
1372
*
1373
* @ingroup hx509_cert
1374
*/
1375
1376
int
1377
hx509_cert_get_subject(hx509_cert p, hx509_name *name)
1378
{
1379
return _hx509_name_from_Name(&p->data->tbsCertificate.subject, name);
1380
}
1381
1382
/**
1383
* Return the name of the base subject of the hx509 certificate. If
1384
* the certiicate is a verified proxy certificate, the this function
1385
* return the base certificate (root of the proxy chain). If the proxy
1386
* certificate is not verified with the base certificate
1387
* HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned.
1388
*
1389
* @param context a hx509 context.
1390
* @param c a hx509 certificate object.
1391
* @param name a pointer to a hx509 name, should be freed by
1392
* hx509_name_free(). See also hx509_cert_get_subject().
1393
*
1394
* @return An hx509 error code, see hx509_get_error_string().
1395
*
1396
* @ingroup hx509_cert
1397
*/
1398
1399
int
1400
hx509_cert_get_base_subject(hx509_context context, hx509_cert c,
1401
hx509_name *name)
1402
{
1403
if (c->basename)
1404
return hx509_name_copy(context, c->basename, name);
1405
if (is_proxy_cert(context, c->data, NULL) == 0) {
1406
int ret = HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED;
1407
hx509_set_error_string(context, 0, ret,
1408
"Proxy certificate have not been "
1409
"canonicalize yet, no base name");
1410
return ret;
1411
}
1412
return _hx509_name_from_Name(&c->data->tbsCertificate.subject, name);
1413
}
1414
1415
/**
1416
* Get serial number of the certificate.
1417
*
1418
* @param p a hx509 certificate object.
1419
* @param i serial number, should be freed ith der_free_heim_integer().
1420
*
1421
* @return An hx509 error code, see hx509_get_error_string().
1422
*
1423
* @ingroup hx509_cert
1424
*/
1425
1426
int
1427
hx509_cert_get_serialnumber(hx509_cert p, heim_integer *i)
1428
{
1429
return der_copy_heim_integer(&p->data->tbsCertificate.serialNumber, i);
1430
}
1431
1432
/**
1433
* Get notBefore time of the certificate.
1434
*
1435
* @param p a hx509 certificate object.
1436
*
1437
* @return return not before time
1438
*
1439
* @ingroup hx509_cert
1440
*/
1441
1442
time_t
1443
hx509_cert_get_notBefore(hx509_cert p)
1444
{
1445
return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notBefore);
1446
}
1447
1448
/**
1449
* Get notAfter time of the certificate.
1450
*
1451
* @param p a hx509 certificate object.
1452
*
1453
* @return return not after time.
1454
*
1455
* @ingroup hx509_cert
1456
*/
1457
1458
time_t
1459
hx509_cert_get_notAfter(hx509_cert p)
1460
{
1461
return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notAfter);
1462
}
1463
1464
/**
1465
* Get the SubjectPublicKeyInfo structure from the hx509 certificate.
1466
*
1467
* @param context a hx509 context.
1468
* @param p a hx509 certificate object.
1469
* @param spki SubjectPublicKeyInfo, should be freed with
1470
* free_SubjectPublicKeyInfo().
1471
*
1472
* @return An hx509 error code, see hx509_get_error_string().
1473
*
1474
* @ingroup hx509_cert
1475
*/
1476
1477
int
1478
hx509_cert_get_SPKI(hx509_context context, hx509_cert p, SubjectPublicKeyInfo *spki)
1479
{
1480
int ret;
1481
1482
ret = copy_SubjectPublicKeyInfo(&p->data->tbsCertificate.subjectPublicKeyInfo, spki);
1483
if (ret)
1484
hx509_set_error_string(context, 0, ret, "Failed to copy SPKI");
1485
return ret;
1486
}
1487
1488
/**
1489
* Get the AlgorithmIdentifier from the hx509 certificate.
1490
*
1491
* @param context a hx509 context.
1492
* @param p a hx509 certificate object.
1493
* @param alg AlgorithmIdentifier, should be freed with
1494
* free_AlgorithmIdentifier(). The algorithmidentifier is
1495
* typicly rsaEncryption, or id-ecPublicKey, or some other
1496
* public key mechanism.
1497
*
1498
* @return An hx509 error code, see hx509_get_error_string().
1499
*
1500
* @ingroup hx509_cert
1501
*/
1502
1503
int
1504
hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context,
1505
hx509_cert p,
1506
AlgorithmIdentifier *alg)
1507
{
1508
int ret;
1509
1510
ret = copy_AlgorithmIdentifier(&p->data->tbsCertificate.subjectPublicKeyInfo.algorithm, alg);
1511
if (ret)
1512
hx509_set_error_string(context, 0, ret,
1513
"Failed to copy SPKI AlgorithmIdentifier");
1514
return ret;
1515
}
1516
1517
static int
1518
get_x_unique_id(hx509_context context, const char *name,
1519
const heim_bit_string *cert, heim_bit_string *subject)
1520
{
1521
int ret;
1522
1523
if (cert == NULL) {
1524
ret = HX509_EXTENSION_NOT_FOUND;
1525
hx509_set_error_string(context, 0, ret, "%s unique id doesn't exists", name);
1526
return ret;
1527
}
1528
ret = der_copy_bit_string(cert, subject);
1529
if (ret) {
1530
hx509_set_error_string(context, 0, ret, "malloc out of memory", name);
1531
return ret;
1532
}
1533
return 0;
1534
}
1535
1536
/**
1537
* Get a copy of the Issuer Unique ID
1538
*
1539
* @param context a hx509_context
1540
* @param p a hx509 certificate
1541
* @param issuer the issuer id returned, free with der_free_bit_string()
1542
*
1543
* @return An hx509 error code, see hx509_get_error_string(). The
1544
* error code HX509_EXTENSION_NOT_FOUND is returned if the certificate
1545
* doesn't have a issuerUniqueID
1546
*
1547
* @ingroup hx509_cert
1548
*/
1549
1550
int
1551
hx509_cert_get_issuer_unique_id(hx509_context context, hx509_cert p, heim_bit_string *issuer)
1552
{
1553
return get_x_unique_id(context, "issuer", p->data->tbsCertificate.issuerUniqueID, issuer);
1554
}
1555
1556
/**
1557
* Get a copy of the Subect Unique ID
1558
*
1559
* @param context a hx509_context
1560
* @param p a hx509 certificate
1561
* @param subject the subject id returned, free with der_free_bit_string()
1562
*
1563
* @return An hx509 error code, see hx509_get_error_string(). The
1564
* error code HX509_EXTENSION_NOT_FOUND is returned if the certificate
1565
* doesn't have a subjectUniqueID
1566
*
1567
* @ingroup hx509_cert
1568
*/
1569
1570
int
1571
hx509_cert_get_subject_unique_id(hx509_context context, hx509_cert p, heim_bit_string *subject)
1572
{
1573
return get_x_unique_id(context, "subject", p->data->tbsCertificate.subjectUniqueID, subject);
1574
}
1575
1576
1577
hx509_private_key
1578
_hx509_cert_private_key(hx509_cert p)
1579
{
1580
return p->private_key;
1581
}
1582
1583
int
1584
hx509_cert_have_private_key(hx509_cert p)
1585
{
1586
return p->private_key ? 1 : 0;
1587
}
1588
1589
1590
int
1591
_hx509_cert_private_key_exportable(hx509_cert p)
1592
{
1593
if (p->private_key == NULL)
1594
return 0;
1595
return _hx509_private_key_exportable(p->private_key);
1596
}
1597
1598
int
1599
_hx509_cert_private_decrypt(hx509_context context,
1600
const heim_octet_string *ciphertext,
1601
const heim_oid *encryption_oid,
1602
hx509_cert p,
1603
heim_octet_string *cleartext)
1604
{
1605
cleartext->data = NULL;
1606
cleartext->length = 0;
1607
1608
if (p->private_key == NULL) {
1609
hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
1610
"Private key missing");
1611
return HX509_PRIVATE_KEY_MISSING;
1612
}
1613
1614
return hx509_private_key_private_decrypt(context,
1615
ciphertext,
1616
encryption_oid,
1617
p->private_key,
1618
cleartext);
1619
}
1620
1621
int
1622
hx509_cert_public_encrypt(hx509_context context,
1623
const heim_octet_string *cleartext,
1624
const hx509_cert p,
1625
heim_oid *encryption_oid,
1626
heim_octet_string *ciphertext)
1627
{
1628
return _hx509_public_encrypt(context,
1629
cleartext, p->data,
1630
encryption_oid, ciphertext);
1631
}
1632
1633
/*
1634
*
1635
*/
1636
1637
time_t
1638
_hx509_Time2time_t(const Time *t)
1639
{
1640
switch(t->element) {
1641
case choice_Time_utcTime:
1642
return t->u.utcTime;
1643
case choice_Time_generalTime:
1644
return t->u.generalTime;
1645
}
1646
return 0;
1647
}
1648
1649
/*
1650
*
1651
*/
1652
1653
static int
1654
init_name_constraints(hx509_name_constraints *nc)
1655
{
1656
memset(nc, 0, sizeof(*nc));
1657
return 0;
1658
}
1659
1660
static int
1661
add_name_constraints(hx509_context context, const Certificate *c, int not_ca,
1662
hx509_name_constraints *nc)
1663
{
1664
NameConstraints tnc;
1665
int ret;
1666
1667
ret = find_extension_name_constraints(c, &tnc);
1668
if (ret == HX509_EXTENSION_NOT_FOUND)
1669
return 0;
1670
else if (ret) {
1671
hx509_set_error_string(context, 0, ret, "Failed getting NameConstraints");
1672
return ret;
1673
} else if (not_ca) {
1674
ret = HX509_VERIFY_CONSTRAINTS;
1675
hx509_set_error_string(context, 0, ret, "Not a CA and "
1676
"have NameConstraints");
1677
} else {
1678
NameConstraints *val;
1679
val = realloc(nc->val, sizeof(nc->val[0]) * (nc->len + 1));
1680
if (val == NULL) {
1681
hx509_clear_error_string(context);
1682
ret = ENOMEM;
1683
goto out;
1684
}
1685
nc->val = val;
1686
ret = copy_NameConstraints(&tnc, &nc->val[nc->len]);
1687
if (ret) {
1688
hx509_clear_error_string(context);
1689
goto out;
1690
}
1691
nc->len += 1;
1692
}
1693
out:
1694
free_NameConstraints(&tnc);
1695
return ret;
1696
}
1697
1698
static int
1699
match_RDN(const RelativeDistinguishedName *c,
1700
const RelativeDistinguishedName *n)
1701
{
1702
size_t i;
1703
1704
if (c->len != n->len)
1705
return HX509_NAME_CONSTRAINT_ERROR;
1706
1707
for (i = 0; i < n->len; i++) {
1708
int diff, ret;
1709
1710
if (der_heim_oid_cmp(&c->val[i].type, &n->val[i].type) != 0)
1711
return HX509_NAME_CONSTRAINT_ERROR;
1712
ret = _hx509_name_ds_cmp(&c->val[i].value, &n->val[i].value, &diff);
1713
if (ret)
1714
return ret;
1715
if (diff != 0)
1716
return HX509_NAME_CONSTRAINT_ERROR;
1717
}
1718
return 0;
1719
}
1720
1721
static int
1722
match_X501Name(const Name *c, const Name *n)
1723
{
1724
size_t i;
1725
int ret;
1726
1727
if (c->element != choice_Name_rdnSequence
1728
|| n->element != choice_Name_rdnSequence)
1729
return 0;
1730
if (c->u.rdnSequence.len > n->u.rdnSequence.len)
1731
return HX509_NAME_CONSTRAINT_ERROR;
1732
for (i = 0; i < c->u.rdnSequence.len; i++) {
1733
ret = match_RDN(&c->u.rdnSequence.val[i], &n->u.rdnSequence.val[i]);
1734
if (ret)
1735
return ret;
1736
}
1737
return 0;
1738
}
1739
1740
1741
static int
1742
match_general_name(const GeneralName *c, const GeneralName *n, int *match)
1743
{
1744
/*
1745
* Name constraints only apply to the same name type, see RFC3280,
1746
* 4.2.1.11.
1747
*/
1748
assert(c->element == n->element);
1749
1750
switch(c->element) {
1751
case choice_GeneralName_otherName:
1752
if (der_heim_oid_cmp(&c->u.otherName.type_id,
1753
&n->u.otherName.type_id) != 0)
1754
return HX509_NAME_CONSTRAINT_ERROR;
1755
if (heim_any_cmp(&c->u.otherName.value,
1756
&n->u.otherName.value) != 0)
1757
return HX509_NAME_CONSTRAINT_ERROR;
1758
*match = 1;
1759
return 0;
1760
case choice_GeneralName_rfc822Name: {
1761
const char *s;
1762
size_t len1, len2;
1763
s = memchr(c->u.rfc822Name.data, '@', c->u.rfc822Name.length);
1764
if (s) {
1765
if (der_printable_string_cmp(&c->u.rfc822Name, &n->u.rfc822Name) != 0)
1766
return HX509_NAME_CONSTRAINT_ERROR;
1767
} else {
1768
s = memchr(n->u.rfc822Name.data, '@', n->u.rfc822Name.length);
1769
if (s == NULL)
1770
return HX509_NAME_CONSTRAINT_ERROR;
1771
len1 = c->u.rfc822Name.length;
1772
len2 = n->u.rfc822Name.length -
1773
(s - ((char *)n->u.rfc822Name.data));
1774
if (len1 > len2)
1775
return HX509_NAME_CONSTRAINT_ERROR;
1776
if (memcmp(s + 1 + len2 - len1, c->u.rfc822Name.data, len1) != 0)
1777
return HX509_NAME_CONSTRAINT_ERROR;
1778
if (len1 < len2 && s[len2 - len1 + 1] != '.')
1779
return HX509_NAME_CONSTRAINT_ERROR;
1780
}
1781
*match = 1;
1782
return 0;
1783
}
1784
case choice_GeneralName_dNSName: {
1785
size_t lenc, lenn;
1786
char *ptr;
1787
1788
lenc = c->u.dNSName.length;
1789
lenn = n->u.dNSName.length;
1790
if (lenc > lenn)
1791
return HX509_NAME_CONSTRAINT_ERROR;
1792
ptr = n->u.dNSName.data;
1793
if (memcmp(&ptr[lenn - lenc], c->u.dNSName.data, lenc) != 0)
1794
return HX509_NAME_CONSTRAINT_ERROR;
1795
if (lenn != lenc && ptr[lenn - lenc - 1] != '.')
1796
return HX509_NAME_CONSTRAINT_ERROR;
1797
*match = 1;
1798
return 0;
1799
}
1800
case choice_GeneralName_directoryName: {
1801
Name c_name, n_name;
1802
int ret;
1803
1804
c_name._save.data = NULL;
1805
c_name._save.length = 0;
1806
c_name.element = c->u.directoryName.element;
1807
c_name.u.rdnSequence = c->u.directoryName.u.rdnSequence;
1808
1809
n_name._save.data = NULL;
1810
n_name._save.length = 0;
1811
n_name.element = n->u.directoryName.element;
1812
n_name.u.rdnSequence = n->u.directoryName.u.rdnSequence;
1813
1814
ret = match_X501Name(&c_name, &n_name);
1815
if (ret == 0)
1816
*match = 1;
1817
return ret;
1818
}
1819
case choice_GeneralName_uniformResourceIdentifier:
1820
case choice_GeneralName_iPAddress:
1821
case choice_GeneralName_registeredID:
1822
default:
1823
return HX509_NAME_CONSTRAINT_ERROR;
1824
}
1825
}
1826
1827
static int
1828
match_alt_name(const GeneralName *n, const Certificate *c,
1829
int *same, int *match)
1830
{
1831
GeneralNames sa;
1832
int ret;
1833
size_t i, j;
1834
1835
i = 0;
1836
do {
1837
ret = find_extension_subject_alt_name(c, &i, &sa);
1838
if (ret == HX509_EXTENSION_NOT_FOUND) {
1839
ret = 0;
1840
break;
1841
} else if (ret != 0)
1842
break;
1843
1844
for (j = 0; j < sa.len; j++) {
1845
if (n->element == sa.val[j].element) {
1846
*same = 1;
1847
ret = match_general_name(n, &sa.val[j], match);
1848
}
1849
}
1850
free_GeneralNames(&sa);
1851
} while (1);
1852
return ret;
1853
}
1854
1855
1856
static int
1857
match_tree(const GeneralSubtrees *t, const Certificate *c, int *match)
1858
{
1859
int name, alt_name, same;
1860
unsigned int i;
1861
int ret = 0;
1862
1863
name = alt_name = same = *match = 0;
1864
for (i = 0; i < t->len; i++) {
1865
if (t->val[i].minimum && t->val[i].maximum)
1866
return HX509_RANGE;
1867
1868
/*
1869
* If the constraint apply to directoryNames, test is with
1870
* subjectName of the certificate if the certificate have a
1871
* non-null (empty) subjectName.
1872
*/
1873
1874
if (t->val[i].base.element == choice_GeneralName_directoryName
1875
&& !subject_null_p(c))
1876
{
1877
GeneralName certname;
1878
1879
memset(&certname, 0, sizeof(certname));
1880
certname.element = choice_GeneralName_directoryName;
1881
certname.u.directoryName.element =
1882
c->tbsCertificate.subject.element;
1883
certname.u.directoryName.u.rdnSequence =
1884
c->tbsCertificate.subject.u.rdnSequence;
1885
1886
ret = match_general_name(&t->val[i].base, &certname, &name);
1887
}
1888
1889
/* Handle subjectAltNames, this is icky since they
1890
* restrictions only apply if the subjectAltName is of the
1891
* same type. So if there have been a match of type, require
1892
* altname to be set.
1893
*/
1894
ret = match_alt_name(&t->val[i].base, c, &same, &alt_name);
1895
}
1896
if (name && (!same || alt_name))
1897
*match = 1;
1898
return ret;
1899
}
1900
1901
static int
1902
check_name_constraints(hx509_context context,
1903
const hx509_name_constraints *nc,
1904
const Certificate *c)
1905
{
1906
int match, ret;
1907
size_t i;
1908
1909
for (i = 0 ; i < nc->len; i++) {
1910
GeneralSubtrees gs;
1911
1912
if (nc->val[i].permittedSubtrees) {
1913
GeneralSubtrees_SET(&gs, nc->val[i].permittedSubtrees);
1914
ret = match_tree(&gs, c, &match);
1915
if (ret) {
1916
hx509_clear_error_string(context);
1917
return ret;
1918
}
1919
/* allow null subjectNames, they wont matches anything */
1920
if (match == 0 && !subject_null_p(c)) {
1921
hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS,
1922
"Error verify constraints, "
1923
"certificate didn't match any "
1924
"permitted subtree");
1925
return HX509_VERIFY_CONSTRAINTS;
1926
}
1927
}
1928
if (nc->val[i].excludedSubtrees) {
1929
GeneralSubtrees_SET(&gs, nc->val[i].excludedSubtrees);
1930
ret = match_tree(&gs, c, &match);
1931
if (ret) {
1932
hx509_clear_error_string(context);
1933
return ret;
1934
}
1935
if (match) {
1936
hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS,
1937
"Error verify constraints, "
1938
"certificate included in excluded "
1939
"subtree");
1940
return HX509_VERIFY_CONSTRAINTS;
1941
}
1942
}
1943
}
1944
return 0;
1945
}
1946
1947
static void
1948
free_name_constraints(hx509_name_constraints *nc)
1949
{
1950
size_t i;
1951
1952
for (i = 0 ; i < nc->len; i++)
1953
free_NameConstraints(&nc->val[i]);
1954
free(nc->val);
1955
}
1956
1957
/**
1958
* Build and verify the path for the certificate to the trust anchor
1959
* specified in the verify context. The path is constructed from the
1960
* certificate, the pool and the trust anchors.
1961
*
1962
* @param context A hx509 context.
1963
* @param ctx A hx509 verification context.
1964
* @param cert the certificate to build the path from.
1965
* @param pool A keyset of certificates to build the chain from.
1966
*
1967
* @return An hx509 error code, see hx509_get_error_string().
1968
*
1969
* @ingroup hx509_verify
1970
*/
1971
1972
int
1973
hx509_verify_path(hx509_context context,
1974
hx509_verify_ctx ctx,
1975
hx509_cert cert,
1976
hx509_certs pool)
1977
{
1978
hx509_name_constraints nc;
1979
hx509_path path;
1980
int ret, proxy_cert_depth, selfsigned_depth, diff;
1981
size_t i, k;
1982
enum certtype type;
1983
Name proxy_issuer;
1984
hx509_certs anchors = NULL;
1985
1986
memset(&proxy_issuer, 0, sizeof(proxy_issuer));
1987
1988
ret = init_name_constraints(&nc);
1989
if (ret)
1990
return ret;
1991
1992
path.val = NULL;
1993
path.len = 0;
1994
1995
if ((ctx->flags & HX509_VERIFY_CTX_F_TIME_SET) == 0)
1996
ctx->time_now = time(NULL);
1997
1998
/*
1999
*
2000
*/
2001
if (ctx->trust_anchors)
2002
anchors = hx509_certs_ref(ctx->trust_anchors);
2003
else if (context->default_trust_anchors && ALLOW_DEF_TA(ctx))
2004
anchors = hx509_certs_ref(context->default_trust_anchors);
2005
else {
2006
ret = hx509_certs_init(context, "MEMORY:no-TA", 0, NULL, &anchors);
2007
if (ret)
2008
goto out;
2009
}
2010
2011
/*
2012
* Calculate the path from the certificate user presented to the
2013
* to an anchor.
2014
*/
2015
ret = _hx509_calculate_path(context, 0, ctx->time_now,
2016
anchors, ctx->max_depth,
2017
cert, pool, &path);
2018
if (ret)
2019
goto out;
2020
2021
/*
2022
* Check CA and proxy certificate chain from the top of the
2023
* certificate chain. Also check certificate is valid with respect
2024
* to the current time.
2025
*
2026
*/
2027
2028
proxy_cert_depth = 0;
2029
selfsigned_depth = 0;
2030
2031
if (ctx->flags & HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE)
2032
type = PROXY_CERT;
2033
else
2034
type = EE_CERT;
2035
2036
for (i = 0; i < path.len; i++) {
2037
Certificate *c;
2038
time_t t;
2039
2040
c = _hx509_get_cert(path.val[i]);
2041
2042
/*
2043
* Lets do some basic check on issuer like
2044
* keyUsage.keyCertSign and basicConstraints.cA bit depending
2045
* on what type of certificate this is.
2046
*/
2047
2048
switch (type) {
2049
case CA_CERT:
2050
2051
/* XXX make constants for keyusage */
2052
ret = check_key_usage(context, c, 1 << 5,
2053
REQUIRE_RFC3280(ctx) ? TRUE : FALSE);
2054
if (ret) {
2055
hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
2056
"Key usage missing from CA certificate");
2057
goto out;
2058
}
2059
2060
/* self signed cert doesn't add to path length */
2061
if (i + 1 != path.len) {
2062
int selfsigned;
2063
2064
ret = certificate_is_self_signed(context, c, &selfsigned);
2065
if (ret)
2066
goto out;
2067
if (selfsigned)
2068
selfsigned_depth++;
2069
}
2070
2071
break;
2072
case PROXY_CERT: {
2073
ProxyCertInfo info;
2074
2075
if (is_proxy_cert(context, c, &info) == 0) {
2076
size_t j;
2077
2078
if (info.pCPathLenConstraint != NULL &&
2079
*info.pCPathLenConstraint < i)
2080
{
2081
free_ProxyCertInfo(&info);
2082
ret = HX509_PATH_TOO_LONG;
2083
hx509_set_error_string(context, 0, ret,
2084
"Proxy certificate chain "
2085
"longer then allowed");
2086
goto out;
2087
}
2088
/* XXX MUST check info.proxyPolicy */
2089
free_ProxyCertInfo(&info);
2090
2091
j = 0;
2092
if (find_extension(c, &asn1_oid_id_x509_ce_subjectAltName, &j)) {
2093
ret = HX509_PROXY_CERT_INVALID;
2094
hx509_set_error_string(context, 0, ret,
2095
"Proxy certificate have explicity "
2096
"forbidden subjectAltName");
2097
goto out;
2098
}
2099
2100
j = 0;
2101
if (find_extension(c, &asn1_oid_id_x509_ce_issuerAltName, &j)) {
2102
ret = HX509_PROXY_CERT_INVALID;
2103
hx509_set_error_string(context, 0, ret,
2104
"Proxy certificate have explicity "
2105
"forbidden issuerAltName");
2106
goto out;
2107
}
2108
2109
/*
2110
* The subject name of the proxy certificate should be
2111
* CN=XXX,<proxy issuer>, prune of CN and check if its
2112
* the same over the whole chain of proxy certs and
2113
* then check with the EE cert when we get to it.
2114
*/
2115
2116
if (proxy_cert_depth) {
2117
ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.subject, &diff);
2118
if (ret) {
2119
hx509_set_error_string(context, 0, ret, "Out of memory");
2120
goto out;
2121
}
2122
if (diff) {
2123
ret = HX509_PROXY_CERT_NAME_WRONG;
2124
hx509_set_error_string(context, 0, ret,
2125
"Base proxy name not right");
2126
goto out;
2127
}
2128
}
2129
2130
free_Name(&proxy_issuer);
2131
2132
ret = copy_Name(&c->tbsCertificate.subject, &proxy_issuer);
2133
if (ret) {
2134
hx509_clear_error_string(context);
2135
goto out;
2136
}
2137
2138
j = proxy_issuer.u.rdnSequence.len;
2139
if (proxy_issuer.u.rdnSequence.len < 2
2140
|| proxy_issuer.u.rdnSequence.val[j - 1].len > 1
2141
|| der_heim_oid_cmp(&proxy_issuer.u.rdnSequence.val[j - 1].val[0].type,
2142
&asn1_oid_id_at_commonName))
2143
{
2144
ret = HX509_PROXY_CERT_NAME_WRONG;
2145
hx509_set_error_string(context, 0, ret,
2146
"Proxy name too short or "
2147
"does not have Common name "
2148
"at the top");
2149
goto out;
2150
}
2151
2152
free_RelativeDistinguishedName(&proxy_issuer.u.rdnSequence.val[j - 1]);
2153
proxy_issuer.u.rdnSequence.len -= 1;
2154
2155
ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.issuer, &diff);
2156
if (ret) {
2157
hx509_set_error_string(context, 0, ret, "Out of memory");
2158
goto out;
2159
}
2160
if (diff != 0) {
2161
ret = HX509_PROXY_CERT_NAME_WRONG;
2162
hx509_set_error_string(context, 0, ret,
2163
"Proxy issuer name not as expected");
2164
goto out;
2165
}
2166
2167
break;
2168
} else {
2169
/*
2170
* Now we are done with the proxy certificates, this
2171
* cert was an EE cert and we we will fall though to
2172
* EE checking below.
2173
*/
2174
type = EE_CERT;
2175
/* FALLTHOUGH */
2176
}
2177
}
2178
case EE_CERT:
2179
/*
2180
* If there where any proxy certificates in the chain
2181
* (proxy_cert_depth > 0), check that the proxy issuer
2182
* matched proxy certificates "base" subject.
2183
*/
2184
if (proxy_cert_depth) {
2185
2186
ret = _hx509_name_cmp(&proxy_issuer,
2187
&c->tbsCertificate.subject, &diff);
2188
if (ret) {
2189
hx509_set_error_string(context, 0, ret, "out of memory");
2190
goto out;
2191
}
2192
if (diff) {
2193
ret = HX509_PROXY_CERT_NAME_WRONG;
2194
hx509_clear_error_string(context);
2195
goto out;
2196
}
2197
if (cert->basename)
2198
hx509_name_free(&cert->basename);
2199
2200
ret = _hx509_name_from_Name(&proxy_issuer, &cert->basename);
2201
if (ret) {
2202
hx509_clear_error_string(context);
2203
goto out;
2204
}
2205
}
2206
2207
break;
2208
}
2209
2210
ret = check_basic_constraints(context, c, type,
2211
i - proxy_cert_depth - selfsigned_depth);
2212
if (ret)
2213
goto out;
2214
2215
/*
2216
* Don't check the trust anchors expiration time since they
2217
* are transported out of band, from RFC3820.
2218
*/
2219
if (i + 1 != path.len || CHECK_TA(ctx)) {
2220
2221
t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2222
if (t > ctx->time_now) {
2223
ret = HX509_CERT_USED_BEFORE_TIME;
2224
hx509_clear_error_string(context);
2225
goto out;
2226
}
2227
t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
2228
if (t < ctx->time_now) {
2229
ret = HX509_CERT_USED_AFTER_TIME;
2230
hx509_clear_error_string(context);
2231
goto out;
2232
}
2233
}
2234
2235
if (type == EE_CERT)
2236
type = CA_CERT;
2237
else if (type == PROXY_CERT)
2238
proxy_cert_depth++;
2239
}
2240
2241
/*
2242
* Verify constraints, do this backward so path constraints are
2243
* checked in the right order.
2244
*/
2245
2246
for (ret = 0, k = path.len; k > 0; k--) {
2247
Certificate *c;
2248
int selfsigned;
2249
i = k - 1;
2250
2251
c = _hx509_get_cert(path.val[i]);
2252
2253
ret = certificate_is_self_signed(context, c, &selfsigned);
2254
if (ret)
2255
goto out;
2256
2257
/* verify name constraints, not for selfsigned and anchor */
2258
if (!selfsigned || i + 1 != path.len) {
2259
ret = check_name_constraints(context, &nc, c);
2260
if (ret) {
2261
goto out;
2262
}
2263
}
2264
ret = add_name_constraints(context, c, i == 0, &nc);
2265
if (ret)
2266
goto out;
2267
2268
/* XXX verify all other silly constraints */
2269
2270
}
2271
2272
/*
2273
* Verify that no certificates has been revoked.
2274
*/
2275
2276
if (ctx->revoke_ctx) {
2277
hx509_certs certs;
2278
2279
ret = hx509_certs_init(context, "MEMORY:revoke-certs", 0,
2280
NULL, &certs);
2281
if (ret)
2282
goto out;
2283
2284
for (i = 0; i < path.len; i++) {
2285
ret = hx509_certs_add(context, certs, path.val[i]);
2286
if (ret) {
2287
hx509_certs_free(&certs);
2288
goto out;
2289
}
2290
}
2291
ret = hx509_certs_merge(context, certs, pool);
2292
if (ret) {
2293
hx509_certs_free(&certs);
2294
goto out;
2295
}
2296
2297
for (i = 0; i < path.len - 1; i++) {
2298
size_t parent = (i < path.len - 1) ? i + 1 : i;
2299
2300
ret = hx509_revoke_verify(context,
2301
ctx->revoke_ctx,
2302
certs,
2303
ctx->time_now,
2304
path.val[i],
2305
path.val[parent]);
2306
if (ret) {
2307
hx509_certs_free(&certs);
2308
goto out;
2309
}
2310
}
2311
hx509_certs_free(&certs);
2312
}
2313
2314
/*
2315
* Verify signatures, do this backward so public key working
2316
* parameter is passed up from the anchor up though the chain.
2317
*/
2318
2319
for (k = path.len; k > 0; k--) {
2320
hx509_cert signer;
2321
Certificate *c;
2322
i = k - 1;
2323
2324
c = _hx509_get_cert(path.val[i]);
2325
2326
/* is last in chain (trust anchor) */
2327
if (i + 1 == path.len) {
2328
int selfsigned;
2329
2330
signer = path.val[i];
2331
2332
ret = certificate_is_self_signed(context, signer->data, &selfsigned);
2333
if (ret)
2334
goto out;
2335
2336
/* if trust anchor is not self signed, don't check sig */
2337
if (!selfsigned)
2338
continue;
2339
} else {
2340
/* take next certificate in chain */
2341
signer = path.val[i + 1];
2342
}
2343
2344
/* verify signatureValue */
2345
ret = _hx509_verify_signature_bitstring(context,
2346
signer,
2347
&c->signatureAlgorithm,
2348
&c->tbsCertificate._save,
2349
&c->signatureValue);
2350
if (ret) {
2351
hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
2352
"Failed to verify signature of certificate");
2353
goto out;
2354
}
2355
/*
2356
* Verify that the sigature algorithm "best-before" date is
2357
* before the creation date of the certificate, do this for
2358
* trust anchors too, since any trust anchor that is created
2359
* after a algorithm is known to be bad deserved to be invalid.
2360
*
2361
* Skip the leaf certificate for now...
2362
*/
2363
2364
if (i != 0 && (ctx->flags & HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK) == 0) {
2365
time_t notBefore =
2366
_hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2367
ret = _hx509_signature_best_before(context,
2368
&c->signatureAlgorithm,
2369
notBefore);
2370
if (ret)
2371
goto out;
2372
}
2373
}
2374
2375
out:
2376
hx509_certs_free(&anchors);
2377
free_Name(&proxy_issuer);
2378
free_name_constraints(&nc);
2379
_hx509_path_free(&path);
2380
2381
return ret;
2382
}
2383
2384
/**
2385
* Verify a signature made using the private key of an certificate.
2386
*
2387
* @param context A hx509 context.
2388
* @param signer the certificate that made the signature.
2389
* @param alg algorthm that was used to sign the data.
2390
* @param data the data that was signed.
2391
* @param sig the sigature to verify.
2392
*
2393
* @return An hx509 error code, see hx509_get_error_string().
2394
*
2395
* @ingroup hx509_crypto
2396
*/
2397
2398
int
2399
hx509_verify_signature(hx509_context context,
2400
const hx509_cert signer,
2401
const AlgorithmIdentifier *alg,
2402
const heim_octet_string *data,
2403
const heim_octet_string *sig)
2404
{
2405
return _hx509_verify_signature(context, signer, alg, data, sig);
2406
}
2407
2408
int
2409
_hx509_verify_signature_bitstring(hx509_context context,
2410
const hx509_cert signer,
2411
const AlgorithmIdentifier *alg,
2412
const heim_octet_string *data,
2413
const heim_bit_string *sig)
2414
{
2415
heim_octet_string os;
2416
2417
if (sig->length & 7) {
2418
hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT,
2419
"signature not multiple of 8 bits");
2420
return HX509_CRYPTO_SIG_INVALID_FORMAT;
2421
}
2422
2423
os.data = sig->data;
2424
os.length = sig->length / 8;
2425
2426
return _hx509_verify_signature(context, signer, alg, data, &os);
2427
}
2428
2429
2430
2431
/**
2432
* Verify that the certificate is allowed to be used for the hostname
2433
* and address.
2434
*
2435
* @param context A hx509 context.
2436
* @param cert the certificate to match with
2437
* @param flags Flags to modify the behavior:
2438
* - HX509_VHN_F_ALLOW_NO_MATCH no match is ok
2439
* @param type type of hostname:
2440
* - HX509_HN_HOSTNAME for plain hostname.
2441
* - HX509_HN_DNSSRV for DNS SRV names.
2442
* @param hostname the hostname to check
2443
* @param sa address of the host
2444
* @param sa_size length of address
2445
*
2446
* @return An hx509 error code, see hx509_get_error_string().
2447
*
2448
* @ingroup hx509_cert
2449
*/
2450
2451
int
2452
hx509_verify_hostname(hx509_context context,
2453
const hx509_cert cert,
2454
int flags,
2455
hx509_hostname_type type,
2456
const char *hostname,
2457
const struct sockaddr *sa,
2458
/* XXX krb5_socklen_t */ int sa_size)
2459
{
2460
GeneralNames san;
2461
const Name *name;
2462
int ret;
2463
size_t i, j, k;
2464
2465
if (sa && sa_size <= 0)
2466
return EINVAL;
2467
2468
memset(&san, 0, sizeof(san));
2469
2470
i = 0;
2471
do {
2472
ret = find_extension_subject_alt_name(cert->data, &i, &san);
2473
if (ret == HX509_EXTENSION_NOT_FOUND)
2474
break;
2475
else if (ret != 0)
2476
return HX509_PARSING_NAME_FAILED;
2477
2478
for (j = 0; j < san.len; j++) {
2479
switch (san.val[j].element) {
2480
case choice_GeneralName_dNSName: {
2481
heim_printable_string hn;
2482
hn.data = rk_UNCONST(hostname);
2483
hn.length = strlen(hostname);
2484
2485
if (der_printable_string_cmp(&san.val[j].u.dNSName, &hn) == 0) {
2486
free_GeneralNames(&san);
2487
return 0;
2488
}
2489
break;
2490
}
2491
default:
2492
break;
2493
}
2494
}
2495
free_GeneralNames(&san);
2496
} while (1);
2497
2498
name = &cert->data->tbsCertificate.subject;
2499
2500
/* Find first CN= in the name, and try to match the hostname on that */
2501
for (ret = 0, k = name->u.rdnSequence.len; ret == 0 && k > 0; k--) {
2502
i = k - 1;
2503
for (j = 0; ret == 0 && j < name->u.rdnSequence.val[i].len; j++) {
2504
AttributeTypeAndValue *n = &name->u.rdnSequence.val[i].val[j];
2505
2506
if (der_heim_oid_cmp(&n->type, &asn1_oid_id_at_commonName) == 0) {
2507
DirectoryString *ds = &n->value;
2508
switch (ds->element) {
2509
case choice_DirectoryString_printableString: {
2510
heim_printable_string hn;
2511
hn.data = rk_UNCONST(hostname);
2512
hn.length = strlen(hostname);
2513
2514
if (der_printable_string_cmp(&ds->u.printableString, &hn) == 0)
2515
return 0;
2516
break;
2517
}
2518
case choice_DirectoryString_ia5String: {
2519
heim_ia5_string hn;
2520
hn.data = rk_UNCONST(hostname);
2521
hn.length = strlen(hostname);
2522
2523
if (der_ia5_string_cmp(&ds->u.ia5String, &hn) == 0)
2524
return 0;
2525
break;
2526
}
2527
case choice_DirectoryString_utf8String:
2528
if (strcasecmp(ds->u.utf8String, hostname) == 0)
2529
return 0;
2530
default:
2531
break;
2532
}
2533
ret = HX509_NAME_CONSTRAINT_ERROR;
2534
}
2535
}
2536
}
2537
2538
if ((flags & HX509_VHN_F_ALLOW_NO_MATCH) == 0)
2539
ret = HX509_NAME_CONSTRAINT_ERROR;
2540
2541
return ret;
2542
}
2543
2544
int
2545
_hx509_set_cert_attribute(hx509_context context,
2546
hx509_cert cert,
2547
const heim_oid *oid,
2548
const heim_octet_string *attr)
2549
{
2550
hx509_cert_attribute a;
2551
void *d;
2552
2553
if (hx509_cert_get_attribute(cert, oid) != NULL)
2554
return 0;
2555
2556
d = realloc(cert->attrs.val,
2557
sizeof(cert->attrs.val[0]) * (cert->attrs.len + 1));
2558
if (d == NULL) {
2559
hx509_clear_error_string(context);
2560
return ENOMEM;
2561
}
2562
cert->attrs.val = d;
2563
2564
a = malloc(sizeof(*a));
2565
if (a == NULL)
2566
return ENOMEM;
2567
2568
der_copy_octet_string(attr, &a->data);
2569
der_copy_oid(oid, &a->oid);
2570
2571
cert->attrs.val[cert->attrs.len] = a;
2572
cert->attrs.len++;
2573
2574
return 0;
2575
}
2576
2577
/**
2578
* Get an external attribute for the certificate, examples are
2579
* friendly name and id.
2580
*
2581
* @param cert hx509 certificate object to search
2582
* @param oid an oid to search for.
2583
*
2584
* @return an hx509_cert_attribute, only valid as long as the
2585
* certificate is referenced.
2586
*
2587
* @ingroup hx509_cert
2588
*/
2589
2590
hx509_cert_attribute
2591
hx509_cert_get_attribute(hx509_cert cert, const heim_oid *oid)
2592
{
2593
size_t i;
2594
for (i = 0; i < cert->attrs.len; i++)
2595
if (der_heim_oid_cmp(oid, &cert->attrs.val[i]->oid) == 0)
2596
return cert->attrs.val[i];
2597
return NULL;
2598
}
2599
2600
/**
2601
* Set the friendly name on the certificate.
2602
*
2603
* @param cert The certificate to set the friendly name on
2604
* @param name Friendly name.
2605
*
2606
* @return An hx509 error code, see hx509_get_error_string().
2607
*
2608
* @ingroup hx509_cert
2609
*/
2610
2611
int
2612
hx509_cert_set_friendly_name(hx509_cert cert, const char *name)
2613
{
2614
if (cert->friendlyname)
2615
free(cert->friendlyname);
2616
cert->friendlyname = strdup(name);
2617
if (cert->friendlyname == NULL)
2618
return ENOMEM;
2619
return 0;
2620
}
2621
2622
/**
2623
* Get friendly name of the certificate.
2624
*
2625
* @param cert cert to get the friendly name from.
2626
*
2627
* @return an friendly name or NULL if there is. The friendly name is
2628
* only valid as long as the certificate is referenced.
2629
*
2630
* @ingroup hx509_cert
2631
*/
2632
2633
const char *
2634
hx509_cert_get_friendly_name(hx509_cert cert)
2635
{
2636
hx509_cert_attribute a;
2637
PKCS9_friendlyName n;
2638
size_t sz;
2639
int ret;
2640
size_t i;
2641
2642
if (cert->friendlyname)
2643
return cert->friendlyname;
2644
2645
a = hx509_cert_get_attribute(cert, &asn1_oid_id_pkcs_9_at_friendlyName);
2646
if (a == NULL) {
2647
hx509_name name;
2648
2649
ret = hx509_cert_get_subject(cert, &name);
2650
if (ret)
2651
return NULL;
2652
ret = hx509_name_to_string(name, &cert->friendlyname);
2653
hx509_name_free(&name);
2654
if (ret)
2655
return NULL;
2656
return cert->friendlyname;
2657
}
2658
2659
ret = decode_PKCS9_friendlyName(a->data.data, a->data.length, &n, &sz);
2660
if (ret)
2661
return NULL;
2662
2663
if (n.len != 1) {
2664
free_PKCS9_friendlyName(&n);
2665
return NULL;
2666
}
2667
2668
cert->friendlyname = malloc(n.val[0].length + 1);
2669
if (cert->friendlyname == NULL) {
2670
free_PKCS9_friendlyName(&n);
2671
return NULL;
2672
}
2673
2674
for (i = 0; i < n.val[0].length; i++) {
2675
if (n.val[0].data[i] <= 0xff)
2676
cert->friendlyname[i] = n.val[0].data[i] & 0xff;
2677
else
2678
cert->friendlyname[i] = 'X';
2679
}
2680
cert->friendlyname[i] = '\0';
2681
free_PKCS9_friendlyName(&n);
2682
2683
return cert->friendlyname;
2684
}
2685
2686
void
2687
_hx509_query_clear(hx509_query *q)
2688
{
2689
memset(q, 0, sizeof(*q));
2690
}
2691
2692
/**
2693
* Allocate an query controller. Free using hx509_query_free().
2694
*
2695
* @param context A hx509 context.
2696
* @param q return pointer to a hx509_query.
2697
*
2698
* @return An hx509 error code, see hx509_get_error_string().
2699
*
2700
* @ingroup hx509_cert
2701
*/
2702
2703
int
2704
hx509_query_alloc(hx509_context context, hx509_query **q)
2705
{
2706
*q = calloc(1, sizeof(**q));
2707
if (*q == NULL)
2708
return ENOMEM;
2709
return 0;
2710
}
2711
2712
2713
/**
2714
* Set match options for the hx509 query controller.
2715
*
2716
* @param q query controller.
2717
* @param option options to control the query controller.
2718
*
2719
* @return An hx509 error code, see hx509_get_error_string().
2720
*
2721
* @ingroup hx509_cert
2722
*/
2723
2724
void
2725
hx509_query_match_option(hx509_query *q, hx509_query_option option)
2726
{
2727
switch(option) {
2728
case HX509_QUERY_OPTION_PRIVATE_KEY:
2729
q->match |= HX509_QUERY_PRIVATE_KEY;
2730
break;
2731
case HX509_QUERY_OPTION_KU_ENCIPHERMENT:
2732
q->match |= HX509_QUERY_KU_ENCIPHERMENT;
2733
break;
2734
case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE:
2735
q->match |= HX509_QUERY_KU_DIGITALSIGNATURE;
2736
break;
2737
case HX509_QUERY_OPTION_KU_KEYCERTSIGN:
2738
q->match |= HX509_QUERY_KU_KEYCERTSIGN;
2739
break;
2740
case HX509_QUERY_OPTION_END:
2741
default:
2742
break;
2743
}
2744
}
2745
2746
/**
2747
* Set the issuer and serial number of match in the query
2748
* controller. The function make copies of the isser and serial number.
2749
*
2750
* @param q a hx509 query controller
2751
* @param issuer issuer to search for
2752
* @param serialNumber the serialNumber of the issuer.
2753
*
2754
* @return An hx509 error code, see hx509_get_error_string().
2755
*
2756
* @ingroup hx509_cert
2757
*/
2758
2759
int
2760
hx509_query_match_issuer_serial(hx509_query *q,
2761
const Name *issuer,
2762
const heim_integer *serialNumber)
2763
{
2764
int ret;
2765
if (q->serial) {
2766
der_free_heim_integer(q->serial);
2767
free(q->serial);
2768
}
2769
q->serial = malloc(sizeof(*q->serial));
2770
if (q->serial == NULL)
2771
return ENOMEM;
2772
ret = der_copy_heim_integer(serialNumber, q->serial);
2773
if (ret) {
2774
free(q->serial);
2775
q->serial = NULL;
2776
return ret;
2777
}
2778
if (q->issuer_name) {
2779
free_Name(q->issuer_name);
2780
free(q->issuer_name);
2781
}
2782
q->issuer_name = malloc(sizeof(*q->issuer_name));
2783
if (q->issuer_name == NULL)
2784
return ENOMEM;
2785
ret = copy_Name(issuer, q->issuer_name);
2786
if (ret) {
2787
free(q->issuer_name);
2788
q->issuer_name = NULL;
2789
return ret;
2790
}
2791
q->match |= HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME;
2792
return 0;
2793
}
2794
2795
/**
2796
* Set the query controller to match on a friendly name
2797
*
2798
* @param q a hx509 query controller.
2799
* @param name a friendly name to match on
2800
*
2801
* @return An hx509 error code, see hx509_get_error_string().
2802
*
2803
* @ingroup hx509_cert
2804
*/
2805
2806
int
2807
hx509_query_match_friendly_name(hx509_query *q, const char *name)
2808
{
2809
if (q->friendlyname)
2810
free(q->friendlyname);
2811
q->friendlyname = strdup(name);
2812
if (q->friendlyname == NULL)
2813
return ENOMEM;
2814
q->match |= HX509_QUERY_MATCH_FRIENDLY_NAME;
2815
return 0;
2816
}
2817
2818
/**
2819
* Set the query controller to require an one specific EKU (extended
2820
* key usage). Any previous EKU matching is overwitten. If NULL is
2821
* passed in as the eku, the EKU requirement is reset.
2822
*
2823
* @param q a hx509 query controller.
2824
* @param eku an EKU to match on.
2825
*
2826
* @return An hx509 error code, see hx509_get_error_string().
2827
*
2828
* @ingroup hx509_cert
2829
*/
2830
2831
int
2832
hx509_query_match_eku(hx509_query *q, const heim_oid *eku)
2833
{
2834
int ret;
2835
2836
if (eku == NULL) {
2837
if (q->eku) {
2838
der_free_oid(q->eku);
2839
free(q->eku);
2840
q->eku = NULL;
2841
}
2842
q->match &= ~HX509_QUERY_MATCH_EKU;
2843
} else {
2844
if (q->eku) {
2845
der_free_oid(q->eku);
2846
} else {
2847
q->eku = calloc(1, sizeof(*q->eku));
2848
if (q->eku == NULL)
2849
return ENOMEM;
2850
}
2851
ret = der_copy_oid(eku, q->eku);
2852
if (ret) {
2853
free(q->eku);
2854
q->eku = NULL;
2855
return ret;
2856
}
2857
q->match |= HX509_QUERY_MATCH_EKU;
2858
}
2859
return 0;
2860
}
2861
2862
int
2863
hx509_query_match_expr(hx509_context context, hx509_query *q, const char *expr)
2864
{
2865
if (q->expr) {
2866
_hx509_expr_free(q->expr);
2867
q->expr = NULL;
2868
}
2869
2870
if (expr == NULL) {
2871
q->match &= ~HX509_QUERY_MATCH_EXPR;
2872
} else {
2873
q->expr = _hx509_expr_parse(expr);
2874
if (q->expr)
2875
q->match |= HX509_QUERY_MATCH_EXPR;
2876
}
2877
2878
return 0;
2879
}
2880
2881
/**
2882
* Set the query controller to match using a specific match function.
2883
*
2884
* @param q a hx509 query controller.
2885
* @param func function to use for matching, if the argument is NULL,
2886
* the match function is removed.
2887
* @param ctx context passed to the function.
2888
*
2889
* @return An hx509 error code, see hx509_get_error_string().
2890
*
2891
* @ingroup hx509_cert
2892
*/
2893
2894
int
2895
hx509_query_match_cmp_func(hx509_query *q,
2896
int (*func)(hx509_context, hx509_cert, void *),
2897
void *ctx)
2898
{
2899
if (func)
2900
q->match |= HX509_QUERY_MATCH_FUNCTION;
2901
else
2902
q->match &= ~HX509_QUERY_MATCH_FUNCTION;
2903
q->cmp_func = func;
2904
q->cmp_func_ctx = ctx;
2905
return 0;
2906
}
2907
2908
/**
2909
* Free the query controller.
2910
*
2911
* @param context A hx509 context.
2912
* @param q a pointer to the query controller.
2913
*
2914
* @ingroup hx509_cert
2915
*/
2916
2917
void
2918
hx509_query_free(hx509_context context, hx509_query *q)
2919
{
2920
if (q == NULL)
2921
return;
2922
2923
if (q->serial) {
2924
der_free_heim_integer(q->serial);
2925
free(q->serial);
2926
}
2927
if (q->issuer_name) {
2928
free_Name(q->issuer_name);
2929
free(q->issuer_name);
2930
}
2931
if (q->eku) {
2932
der_free_oid(q->eku);
2933
free(q->eku);
2934
}
2935
if (q->friendlyname)
2936
free(q->friendlyname);
2937
if (q->expr)
2938
_hx509_expr_free(q->expr);
2939
2940
memset(q, 0, sizeof(*q));
2941
free(q);
2942
}
2943
2944
int
2945
_hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert cert)
2946
{
2947
Certificate *c = _hx509_get_cert(cert);
2948
int ret, diff;
2949
2950
_hx509_query_statistic(context, 1, q);
2951
2952
if ((q->match & HX509_QUERY_FIND_ISSUER_CERT) &&
2953
_hx509_cert_is_parent_cmp(q->subject, c, 0) != 0)
2954
return 0;
2955
2956
if ((q->match & HX509_QUERY_MATCH_CERTIFICATE) &&
2957
_hx509_Certificate_cmp(q->certificate, c) != 0)
2958
return 0;
2959
2960
if ((q->match & HX509_QUERY_MATCH_SERIALNUMBER)
2961
&& der_heim_integer_cmp(&c->tbsCertificate.serialNumber, q->serial) != 0)
2962
return 0;
2963
2964
if (q->match & HX509_QUERY_MATCH_ISSUER_NAME) {
2965
ret = _hx509_name_cmp(&c->tbsCertificate.issuer, q->issuer_name, &diff);
2966
if (ret || diff)
2967
return 0;
2968
}
2969
2970
if (q->match & HX509_QUERY_MATCH_SUBJECT_NAME) {
2971
ret = _hx509_name_cmp(&c->tbsCertificate.subject, q->subject_name, &diff);
2972
if (ret || diff)
2973
return 0;
2974
}
2975
2976
if (q->match & HX509_QUERY_MATCH_SUBJECT_KEY_ID) {
2977
SubjectKeyIdentifier si;
2978
2979
ret = _hx509_find_extension_subject_key_id(c, &si);
2980
if (ret == 0) {
2981
if (der_heim_octet_string_cmp(&si, q->subject_id) != 0)
2982
ret = 1;
2983
free_SubjectKeyIdentifier(&si);
2984
}
2985
if (ret)
2986
return 0;
2987
}
2988
if ((q->match & HX509_QUERY_MATCH_ISSUER_ID))
2989
return 0;
2990
if ((q->match & HX509_QUERY_PRIVATE_KEY) &&
2991
_hx509_cert_private_key(cert) == NULL)
2992
return 0;
2993
2994
{
2995
unsigned ku = 0;
2996
if (q->match & HX509_QUERY_KU_DIGITALSIGNATURE)
2997
ku |= (1 << 0);
2998
if (q->match & HX509_QUERY_KU_NONREPUDIATION)
2999
ku |= (1 << 1);
3000
if (q->match & HX509_QUERY_KU_ENCIPHERMENT)
3001
ku |= (1 << 2);
3002
if (q->match & HX509_QUERY_KU_DATAENCIPHERMENT)
3003
ku |= (1 << 3);
3004
if (q->match & HX509_QUERY_KU_KEYAGREEMENT)
3005
ku |= (1 << 4);
3006
if (q->match & HX509_QUERY_KU_KEYCERTSIGN)
3007
ku |= (1 << 5);
3008
if (q->match & HX509_QUERY_KU_CRLSIGN)
3009
ku |= (1 << 6);
3010
if (ku && check_key_usage(context, c, ku, TRUE))
3011
return 0;
3012
}
3013
if ((q->match & HX509_QUERY_ANCHOR))
3014
return 0;
3015
3016
if (q->match & HX509_QUERY_MATCH_LOCAL_KEY_ID) {
3017
hx509_cert_attribute a;
3018
3019
a = hx509_cert_get_attribute(cert, &asn1_oid_id_pkcs_9_at_localKeyId);
3020
if (a == NULL)
3021
return 0;
3022
if (der_heim_octet_string_cmp(&a->data, q->local_key_id) != 0)
3023
return 0;
3024
}
3025
3026
if (q->match & HX509_QUERY_NO_MATCH_PATH) {
3027
size_t i;
3028
3029
for (i = 0; i < q->path->len; i++)
3030
if (hx509_cert_cmp(q->path->val[i], cert) == 0)
3031
return 0;
3032
}
3033
if (q->match & HX509_QUERY_MATCH_FRIENDLY_NAME) {
3034
const char *name = hx509_cert_get_friendly_name(cert);
3035
if (name == NULL)
3036
return 0;
3037
if (strcasecmp(q->friendlyname, name) != 0)
3038
return 0;
3039
}
3040
if (q->match & HX509_QUERY_MATCH_FUNCTION) {
3041
ret = (*q->cmp_func)(context, cert, q->cmp_func_ctx);
3042
if (ret != 0)
3043
return 0;
3044
}
3045
3046
if (q->match & HX509_QUERY_MATCH_KEY_HASH_SHA1) {
3047
heim_octet_string os;
3048
3049
os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
3050
os.length =
3051
c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
3052
3053
ret = _hx509_verify_signature(context,
3054
NULL,
3055
hx509_signature_sha1(),
3056
&os,
3057
q->keyhash_sha1);
3058
if (ret != 0)
3059
return 0;
3060
}
3061
3062
if (q->match & HX509_QUERY_MATCH_TIME) {
3063
time_t t;
3064
t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
3065
if (t > q->timenow)
3066
return 0;
3067
t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
3068
if (t < q->timenow)
3069
return 0;
3070
}
3071
3072
/* If an EKU is required, check the cert for it. */
3073
if ((q->match & HX509_QUERY_MATCH_EKU) &&
3074
hx509_cert_check_eku(context, cert, q->eku, 0))
3075
return 0;
3076
3077
if ((q->match & HX509_QUERY_MATCH_EXPR)) {
3078
hx509_env env = NULL;
3079
3080
ret = _hx509_cert_to_env(context, cert, &env);
3081
if (ret)
3082
return 0;
3083
3084
ret = _hx509_expr_eval(context, env, q->expr);
3085
hx509_env_free(&env);
3086
if (ret == 0)
3087
return 0;
3088
}
3089
3090
if (q->match & ~HX509_QUERY_MASK)
3091
return 0;
3092
3093
return 1;
3094
}
3095
3096
/**
3097
* Set a statistic file for the query statistics.
3098
*
3099
* @param context A hx509 context.
3100
* @param fn statistics file name
3101
*
3102
* @ingroup hx509_cert
3103
*/
3104
3105
void
3106
hx509_query_statistic_file(hx509_context context, const char *fn)
3107
{
3108
if (context->querystat)
3109
free(context->querystat);
3110
context->querystat = strdup(fn);
3111
}
3112
3113
void
3114
_hx509_query_statistic(hx509_context context, int type, const hx509_query *q)
3115
{
3116
FILE *f;
3117
if (context->querystat == NULL)
3118
return;
3119
f = fopen(context->querystat, "a");
3120
if (f == NULL)
3121
return;
3122
rk_cloexec_file(f);
3123
fprintf(f, "%d %d\n", type, q->match);
3124
fclose(f);
3125
}
3126
3127
static const char *statname[] = {
3128
"find issuer cert",
3129
"match serialnumber",
3130
"match issuer name",
3131
"match subject name",
3132
"match subject key id",
3133
"match issuer id",
3134
"private key",
3135
"ku encipherment",
3136
"ku digitalsignature",
3137
"ku keycertsign",
3138
"ku crlsign",
3139
"ku nonrepudiation",
3140
"ku keyagreement",
3141
"ku dataencipherment",
3142
"anchor",
3143
"match certificate",
3144
"match local key id",
3145
"no match path",
3146
"match friendly name",
3147
"match function",
3148
"match key hash sha1",
3149
"match time"
3150
};
3151
3152
struct stat_el {
3153
unsigned long stats;
3154
unsigned int index;
3155
};
3156
3157
3158
static int
3159
stat_sort(const void *a, const void *b)
3160
{
3161
const struct stat_el *ae = a;
3162
const struct stat_el *be = b;
3163
return be->stats - ae->stats;
3164
}
3165
3166
/**
3167
* Unparse the statistics file and print the result on a FILE descriptor.
3168
*
3169
* @param context A hx509 context.
3170
* @param printtype tyep to print
3171
* @param out the FILE to write the data on.
3172
*
3173
* @ingroup hx509_cert
3174
*/
3175
3176
void
3177
hx509_query_unparse_stats(hx509_context context, int printtype, FILE *out)
3178
{
3179
rtbl_t t;
3180
FILE *f;
3181
int type, mask, num;
3182
size_t i;
3183
unsigned long multiqueries = 0, totalqueries = 0;
3184
struct stat_el stats[32];
3185
3186
if (context->querystat == NULL)
3187
return;
3188
f = fopen(context->querystat, "r");
3189
if (f == NULL) {
3190
fprintf(out, "No statistic file %s: %s.\n",
3191
context->querystat, strerror(errno));
3192
return;
3193
}
3194
rk_cloexec_file(f);
3195
3196
for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
3197
stats[i].index = i;
3198
stats[i].stats = 0;
3199
}
3200
3201
while (fscanf(f, "%d %d\n", &type, &mask) == 2) {
3202
if (type != printtype)
3203
continue;
3204
num = i = 0;
3205
while (mask && i < sizeof(stats)/sizeof(stats[0])) {
3206
if (mask & 1) {
3207
stats[i].stats++;
3208
num++;
3209
}
3210
mask = mask >>1 ;
3211
i++;
3212
}
3213
if (num > 1)
3214
multiqueries++;
3215
totalqueries++;
3216
}
3217
fclose(f);
3218
3219
qsort(stats, sizeof(stats)/sizeof(stats[0]), sizeof(stats[0]), stat_sort);
3220
3221
t = rtbl_create();
3222
if (t == NULL)
3223
errx(1, "out of memory");
3224
3225
rtbl_set_separator (t, " ");
3226
3227
rtbl_add_column_by_id (t, 0, "Name", 0);
3228
rtbl_add_column_by_id (t, 1, "Counter", 0);
3229
3230
3231
for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
3232
char str[10];
3233
3234
if (stats[i].index < sizeof(statname)/sizeof(statname[0]))
3235
rtbl_add_column_entry_by_id (t, 0, statname[stats[i].index]);
3236
else {
3237
snprintf(str, sizeof(str), "%d", stats[i].index);
3238
rtbl_add_column_entry_by_id (t, 0, str);
3239
}
3240
snprintf(str, sizeof(str), "%lu", stats[i].stats);
3241
rtbl_add_column_entry_by_id (t, 1, str);
3242
}
3243
3244
rtbl_format(t, out);
3245
rtbl_destroy(t);
3246
3247
fprintf(out, "\nQueries: multi %lu total %lu\n",
3248
multiqueries, totalqueries);
3249
}
3250
3251
/**
3252
* Check the extended key usage on the hx509 certificate.
3253
*
3254
* @param context A hx509 context.
3255
* @param cert A hx509 context.
3256
* @param eku the EKU to check for
3257
* @param allow_any_eku if the any EKU is set, allow that to be a
3258
* substitute.
3259
*
3260
* @return An hx509 error code, see hx509_get_error_string().
3261
*
3262
* @ingroup hx509_cert
3263
*/
3264
3265
int
3266
hx509_cert_check_eku(hx509_context context, hx509_cert cert,
3267
const heim_oid *eku, int allow_any_eku)
3268
{
3269
ExtKeyUsage e;
3270
int ret;
3271
size_t i;
3272
3273
ret = find_extension_eku(_hx509_get_cert(cert), &e);
3274
if (ret) {
3275
hx509_clear_error_string(context);
3276
return ret;
3277
}
3278
3279
for (i = 0; i < e.len; i++) {
3280
if (der_heim_oid_cmp(eku, &e.val[i]) == 0) {
3281
free_ExtKeyUsage(&e);
3282
return 0;
3283
}
3284
if (allow_any_eku) {
3285
#if 0
3286
if (der_heim_oid_cmp(id_any_eku, &e.val[i]) == 0) {
3287
free_ExtKeyUsage(&e);
3288
return 0;
3289
}
3290
#endif
3291
}
3292
}
3293
free_ExtKeyUsage(&e);
3294
hx509_clear_error_string(context);
3295
return HX509_CERTIFICATE_MISSING_EKU;
3296
}
3297
3298
int
3299
_hx509_cert_get_keyusage(hx509_context context,
3300
hx509_cert c,
3301
KeyUsage *ku)
3302
{
3303
Certificate *cert;
3304
const Extension *e;
3305
size_t size;
3306
int ret;
3307
size_t i = 0;
3308
3309
memset(ku, 0, sizeof(*ku));
3310
3311
cert = _hx509_get_cert(c);
3312
3313
if (_hx509_cert_get_version(cert) < 3)
3314
return 0;
3315
3316
e = find_extension(cert, &asn1_oid_id_x509_ce_keyUsage, &i);
3317
if (e == NULL)
3318
return HX509_KU_CERT_MISSING;
3319
3320
ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, ku, &size);
3321
if (ret)
3322
return ret;
3323
return 0;
3324
}
3325
3326
int
3327
_hx509_cert_get_eku(hx509_context context,
3328
hx509_cert cert,
3329
ExtKeyUsage *e)
3330
{
3331
int ret;
3332
3333
memset(e, 0, sizeof(*e));
3334
3335
ret = find_extension_eku(_hx509_get_cert(cert), e);
3336
if (ret && ret != HX509_EXTENSION_NOT_FOUND) {
3337
hx509_clear_error_string(context);
3338
return ret;
3339
}
3340
return 0;
3341
}
3342
3343
/**
3344
* Encodes the hx509 certificate as a DER encode binary.
3345
*
3346
* @param context A hx509 context.
3347
* @param c the certificate to encode.
3348
* @param os the encode certificate, set to NULL, 0 on case of
3349
* error. Free the os->data with hx509_xfree().
3350
*
3351
* @return An hx509 error code, see hx509_get_error_string().
3352
*
3353
* @ingroup hx509_cert
3354
*/
3355
3356
int
3357
hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os)
3358
{
3359
size_t size;
3360
int ret;
3361
3362
os->data = NULL;
3363
os->length = 0;
3364
3365
ASN1_MALLOC_ENCODE(Certificate, os->data, os->length,
3366
_hx509_get_cert(c), &size, ret);
3367
if (ret) {
3368
os->data = NULL;
3369
os->length = 0;
3370
return ret;
3371
}
3372
if (os->length != size)
3373
_hx509_abort("internal ASN.1 encoder error");
3374
3375
return ret;
3376
}
3377
3378
/*
3379
* Last to avoid lost __attribute__s due to #undef.
3380
*/
3381
3382
#undef __attribute__
3383
#define __attribute__(X)
3384
3385
void
3386
_hx509_abort(const char *fmt, ...)
3387
__attribute__ ((noreturn, format (printf, 1, 2)))
3388
{
3389
va_list ap;
3390
va_start(ap, fmt);
3391
vprintf(fmt, ap);
3392
va_end(ap);
3393
printf("\n");
3394
fflush(stdout);
3395
abort();
3396
}
3397
3398
/**
3399
* Free a data element allocated in the library.
3400
*
3401
* @param ptr data to be freed.
3402
*
3403
* @ingroup hx509_misc
3404
*/
3405
3406
void
3407
hx509_xfree(void *ptr)
3408
{
3409
free(ptr);
3410
}
3411
3412
/**
3413
*
3414
*/
3415
3416
int
3417
_hx509_cert_to_env(hx509_context context, hx509_cert cert, hx509_env *env)
3418
{
3419
ExtKeyUsage eku;
3420
hx509_name name;
3421
char *buf;
3422
int ret;
3423
hx509_env envcert = NULL;
3424
3425
*env = NULL;
3426
3427
/* version */
3428
asprintf(&buf, "%d", _hx509_cert_get_version(_hx509_get_cert(cert)));
3429
ret = hx509_env_add(context, &envcert, "version", buf);
3430
free(buf);
3431
if (ret)
3432
goto out;
3433
3434
/* subject */
3435
ret = hx509_cert_get_subject(cert, &name);
3436
if (ret)
3437
goto out;
3438
3439
ret = hx509_name_to_string(name, &buf);
3440
if (ret) {
3441
hx509_name_free(&name);
3442
goto out;
3443
}
3444
3445
ret = hx509_env_add(context, &envcert, "subject", buf);
3446
hx509_name_free(&name);
3447
if (ret)
3448
goto out;
3449
3450
/* issuer */
3451
ret = hx509_cert_get_issuer(cert, &name);
3452
if (ret)
3453
goto out;
3454
3455
ret = hx509_name_to_string(name, &buf);
3456
hx509_name_free(&name);
3457
if (ret)
3458
goto out;
3459
3460
ret = hx509_env_add(context, &envcert, "issuer", buf);
3461
hx509_xfree(buf);
3462
if (ret)
3463
goto out;
3464
3465
/* eku */
3466
3467
ret = _hx509_cert_get_eku(context, cert, &eku);
3468
if (ret == HX509_EXTENSION_NOT_FOUND)
3469
;
3470
else if (ret != 0)
3471
goto out;
3472
else {
3473
size_t i;
3474
hx509_env enveku = NULL;
3475
3476
for (i = 0; i < eku.len; i++) {
3477
3478
ret = der_print_heim_oid(&eku.val[i], '.', &buf);
3479
if (ret) {
3480
free_ExtKeyUsage(&eku);
3481
hx509_env_free(&enveku);
3482
goto out;
3483
}
3484
ret = hx509_env_add(context, &enveku, buf, "oid-name-here");
3485
free(buf);
3486
if (ret) {
3487
free_ExtKeyUsage(&eku);
3488
hx509_env_free(&enveku);
3489
goto out;
3490
}
3491
}
3492
free_ExtKeyUsage(&eku);
3493
3494
ret = hx509_env_add_binding(context, &envcert, "eku", enveku);
3495
if (ret) {
3496
hx509_env_free(&enveku);
3497
goto out;
3498
}
3499
}
3500
3501
{
3502
Certificate *c = _hx509_get_cert(cert);
3503
heim_octet_string os, sig;
3504
hx509_env envhash = NULL;
3505
3506
os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
3507
os.length =
3508
c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
3509
3510
ret = _hx509_create_signature(context,
3511
NULL,
3512
hx509_signature_sha1(),
3513
&os,
3514
NULL,
3515
&sig);
3516
if (ret != 0)
3517
goto out;
3518
3519
ret = hex_encode(sig.data, sig.length, &buf);
3520
der_free_octet_string(&sig);
3521
if (ret < 0) {
3522
ret = ENOMEM;
3523
hx509_set_error_string(context, 0, ret,
3524
"Out of memory");
3525
goto out;
3526
}
3527
3528
ret = hx509_env_add(context, &envhash, "sha1", buf);
3529
free(buf);
3530
if (ret)
3531
goto out;
3532
3533
ret = hx509_env_add_binding(context, &envcert, "hash", envhash);
3534
if (ret) {
3535
hx509_env_free(&envhash);
3536
goto out;
3537
}
3538
}
3539
3540
ret = hx509_env_add_binding(context, env, "certificate", envcert);
3541
if (ret)
3542
goto out;
3543
3544
return 0;
3545
3546
out:
3547
hx509_env_free(&envcert);
3548
return ret;
3549
}
3550
3551
/**
3552
* Print a simple representation of a certificate
3553
*
3554
* @param context A hx509 context, can be NULL
3555
* @param cert certificate to print
3556
* @param out the stdio output stream, if NULL, stdout is used
3557
*
3558
* @return An hx509 error code
3559
*
3560
* @ingroup hx509_cert
3561
*/
3562
3563
int
3564
hx509_print_cert(hx509_context context, hx509_cert cert, FILE *out)
3565
{
3566
hx509_name name;
3567
char *str;
3568
int ret;
3569
3570
if (out == NULL)
3571
out = stderr;
3572
3573
ret = hx509_cert_get_issuer(cert, &name);
3574
if (ret)
3575
return ret;
3576
hx509_name_to_string(name, &str);
3577
hx509_name_free(&name);
3578
fprintf(out, " issuer: \"%s\"\n", str);
3579
free(str);
3580
3581
ret = hx509_cert_get_subject(cert, &name);
3582
if (ret)
3583
return ret;
3584
hx509_name_to_string(name, &str);
3585
hx509_name_free(&name);
3586
fprintf(out, " subject: \"%s\"\n", str);
3587
free(str);
3588
3589
{
3590
heim_integer serialNumber;
3591
3592
ret = hx509_cert_get_serialnumber(cert, &serialNumber);
3593
if (ret)
3594
return ret;
3595
ret = der_print_hex_heim_integer(&serialNumber, &str);
3596
if (ret)
3597
return ret;
3598
der_free_heim_integer(&serialNumber);
3599
fprintf(out, " serial: %s\n", str);
3600
free(str);
3601
}
3602
3603
printf(" keyusage: ");
3604
ret = hx509_cert_keyusage_print(context, cert, &str);
3605
if (ret == 0) {
3606
fprintf(out, "%s\n", str);
3607
free(str);
3608
} else
3609
fprintf(out, "no");
3610
3611
return 0;
3612
}
3613
3614