2 * Copyright (c) 2012 Damien Miller <djm@mindrot.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 /* $OpenBSD: krl.c,v 1.17 2014/06/24 01:13:21 djm Exp $ */
21 #include <sys/types.h>
22 #include <sys/param.h>
23 #include <openbsd-compat/sys-tree.h>
24 #include <openbsd-compat/sys-queue.h>
42 /* #define DEBUG_KRL */
44 # define KRL_DBG(x) debug3 x
50 * Trees of revoked serial numbers, key IDs and keys. This allows
51 * quick searching, querying and producing lists in canonical order.
54 /* Tree of serial numbers. XXX make smarter: really need a real sparse bitmap */
55 struct revoked_serial
{
57 RB_ENTRY(revoked_serial
) tree_entry
;
59 static int serial_cmp(struct revoked_serial
*a
, struct revoked_serial
*b
);
60 RB_HEAD(revoked_serial_tree
, revoked_serial
);
61 RB_GENERATE_STATIC(revoked_serial_tree
, revoked_serial
, tree_entry
, serial_cmp
);
64 struct revoked_key_id
{
66 RB_ENTRY(revoked_key_id
) tree_entry
;
68 static int key_id_cmp(struct revoked_key_id
*a
, struct revoked_key_id
*b
);
69 RB_HEAD(revoked_key_id_tree
, revoked_key_id
);
70 RB_GENERATE_STATIC(revoked_key_id_tree
, revoked_key_id
, tree_entry
, key_id_cmp
);
72 /* Tree of blobs (used for keys and fingerprints) */
76 RB_ENTRY(revoked_blob
) tree_entry
;
78 static int blob_cmp(struct revoked_blob
*a
, struct revoked_blob
*b
);
79 RB_HEAD(revoked_blob_tree
, revoked_blob
);
80 RB_GENERATE_STATIC(revoked_blob_tree
, revoked_blob
, tree_entry
, blob_cmp
);
82 /* Tracks revoked certs for a single CA */
83 struct revoked_certs
{
85 struct revoked_serial_tree revoked_serials
;
86 struct revoked_key_id_tree revoked_key_ids
;
87 TAILQ_ENTRY(revoked_certs
) entry
;
89 TAILQ_HEAD(revoked_certs_list
, revoked_certs
);
92 u_int64_t krl_version
;
93 u_int64_t generated_date
;
96 struct revoked_blob_tree revoked_keys
;
97 struct revoked_blob_tree revoked_sha1s
;
98 struct revoked_certs_list revoked_certs
;
101 /* Return equal if a and b overlap */
103 serial_cmp(struct revoked_serial
*a
, struct revoked_serial
*b
)
105 if (a
->hi
>= b
->lo
&& a
->lo
<= b
->hi
)
107 return a
->lo
< b
->lo
? -1 : 1;
111 key_id_cmp(struct revoked_key_id
*a
, struct revoked_key_id
*b
)
113 return strcmp(a
->key_id
, b
->key_id
);
117 blob_cmp(struct revoked_blob
*a
, struct revoked_blob
*b
)
121 if (a
->len
!= b
->len
) {
122 if ((r
= memcmp(a
->blob
, b
->blob
, MIN(a
->len
, b
->len
))) != 0)
124 return a
->len
> b
->len
? 1 : -1;
126 return memcmp(a
->blob
, b
->blob
, a
->len
);
134 if ((krl
= calloc(1, sizeof(*krl
))) == NULL
)
136 RB_INIT(&krl
->revoked_keys
);
137 RB_INIT(&krl
->revoked_sha1s
);
138 TAILQ_INIT(&krl
->revoked_certs
);
143 revoked_certs_free(struct revoked_certs
*rc
)
145 struct revoked_serial
*rs
, *trs
;
146 struct revoked_key_id
*rki
, *trki
;
148 RB_FOREACH_SAFE(rs
, revoked_serial_tree
, &rc
->revoked_serials
, trs
) {
149 RB_REMOVE(revoked_serial_tree
, &rc
->revoked_serials
, rs
);
152 RB_FOREACH_SAFE(rki
, revoked_key_id_tree
, &rc
->revoked_key_ids
, trki
) {
153 RB_REMOVE(revoked_key_id_tree
, &rc
->revoked_key_ids
, rki
);
157 if (rc
->ca_key
!= NULL
)
158 key_free(rc
->ca_key
);
162 ssh_krl_free(struct ssh_krl
*krl
)
164 struct revoked_blob
*rb
, *trb
;
165 struct revoked_certs
*rc
, *trc
;
171 RB_FOREACH_SAFE(rb
, revoked_blob_tree
, &krl
->revoked_keys
, trb
) {
172 RB_REMOVE(revoked_blob_tree
, &krl
->revoked_keys
, rb
);
176 RB_FOREACH_SAFE(rb
, revoked_blob_tree
, &krl
->revoked_sha1s
, trb
) {
177 RB_REMOVE(revoked_blob_tree
, &krl
->revoked_sha1s
, rb
);
181 TAILQ_FOREACH_SAFE(rc
, &krl
->revoked_certs
, entry
, trc
) {
182 TAILQ_REMOVE(&krl
->revoked_certs
, rc
, entry
);
183 revoked_certs_free(rc
);
188 ssh_krl_set_version(struct ssh_krl
*krl
, u_int64_t version
)
190 krl
->krl_version
= version
;
194 ssh_krl_set_comment(struct ssh_krl
*krl
, const char *comment
)
197 if ((krl
->comment
= strdup(comment
)) == NULL
)
198 fatal("%s: strdup", __func__
);
202 * Find the revoked_certs struct for a CA key. If allow_create is set then
203 * create a new one in the tree if one did not exist already.
206 revoked_certs_for_ca_key(struct ssh_krl
*krl
, const Key
*ca_key
,
207 struct revoked_certs
**rcp
, int allow_create
)
209 struct revoked_certs
*rc
;
212 TAILQ_FOREACH(rc
, &krl
->revoked_certs
, entry
) {
213 if (key_equal(rc
->ca_key
, ca_key
)) {
220 /* If this CA doesn't exist in the list then add it now */
221 if ((rc
= calloc(1, sizeof(*rc
))) == NULL
)
223 if ((rc
->ca_key
= key_from_private(ca_key
)) == NULL
) {
227 RB_INIT(&rc
->revoked_serials
);
228 RB_INIT(&rc
->revoked_key_ids
);
229 TAILQ_INSERT_TAIL(&krl
->revoked_certs
, rc
, entry
);
230 debug3("%s: new CA %s", __func__
, key_type(ca_key
));
236 insert_serial_range(struct revoked_serial_tree
*rt
, u_int64_t lo
, u_int64_t hi
)
238 struct revoked_serial rs
, *ers
, *crs
, *irs
;
240 KRL_DBG(("%s: insert %llu:%llu", __func__
, lo
, hi
));
241 memset(&rs
, 0, sizeof(rs
));
244 ers
= RB_NFIND(revoked_serial_tree
, rt
, &rs
);
245 if (ers
== NULL
|| serial_cmp(ers
, &rs
) != 0) {
246 /* No entry matches. Just insert */
247 if ((irs
= malloc(sizeof(rs
))) == NULL
)
249 memcpy(irs
, &rs
, sizeof(*irs
));
250 ers
= RB_INSERT(revoked_serial_tree
, rt
, irs
);
252 KRL_DBG(("%s: bad: ers != NULL", __func__
));
253 /* Shouldn't happen */
259 KRL_DBG(("%s: overlap found %llu:%llu", __func__
,
262 * The inserted entry overlaps an existing one. Grow the
271 * The inserted or revised range might overlap or abut adjacent ones;
272 * coalesce as necessary.
275 /* Check predecessors */
276 while ((crs
= RB_PREV(revoked_serial_tree
, rt
, ers
)) != NULL
) {
277 KRL_DBG(("%s: pred %llu:%llu", __func__
, crs
->lo
, crs
->hi
));
278 if (ers
->lo
!= 0 && crs
->hi
< ers
->lo
- 1)
280 /* This entry overlaps. */
281 if (crs
->lo
< ers
->lo
) {
283 KRL_DBG(("%s: pred extend %llu:%llu", __func__
,
286 RB_REMOVE(revoked_serial_tree
, rt
, crs
);
289 /* Check successors */
290 while ((crs
= RB_NEXT(revoked_serial_tree
, rt
, ers
)) != NULL
) {
291 KRL_DBG(("%s: succ %llu:%llu", __func__
, crs
->lo
, crs
->hi
));
292 if (ers
->hi
!= (u_int64_t
)-1 && crs
->lo
> ers
->hi
+ 1)
294 /* This entry overlaps. */
295 if (crs
->hi
> ers
->hi
) {
297 KRL_DBG(("%s: succ extend %llu:%llu", __func__
,
300 RB_REMOVE(revoked_serial_tree
, rt
, crs
);
303 KRL_DBG(("%s: done, final %llu:%llu", __func__
, ers
->lo
, ers
->hi
));
308 ssh_krl_revoke_cert_by_serial(struct ssh_krl
*krl
, const Key
*ca_key
,
311 return ssh_krl_revoke_cert_by_serial_range(krl
, ca_key
, serial
, serial
);
315 ssh_krl_revoke_cert_by_serial_range(struct ssh_krl
*krl
, const Key
*ca_key
,
316 u_int64_t lo
, u_int64_t hi
)
318 struct revoked_certs
*rc
;
320 if (lo
> hi
|| lo
== 0)
322 if (revoked_certs_for_ca_key(krl
, ca_key
, &rc
, 1) != 0)
324 return insert_serial_range(&rc
->revoked_serials
, lo
, hi
);
328 ssh_krl_revoke_cert_by_key_id(struct ssh_krl
*krl
, const Key
*ca_key
,
331 struct revoked_key_id
*rki
, *erki
;
332 struct revoked_certs
*rc
;
334 if (revoked_certs_for_ca_key(krl
, ca_key
, &rc
, 1) != 0)
337 debug3("%s: revoke %s", __func__
, key_id
);
338 if ((rki
= calloc(1, sizeof(*rki
))) == NULL
||
339 (rki
->key_id
= strdup(key_id
)) == NULL
) {
341 fatal("%s: strdup", __func__
);
343 erki
= RB_INSERT(revoked_key_id_tree
, &rc
->revoked_key_ids
, rki
);
351 /* Convert "key" to a public key blob without any certificate information */
353 plain_key_blob(const Key
*key
, u_char
**blob
, u_int
*blen
)
358 if ((kcopy
= key_from_private(key
)) == NULL
)
360 if (key_is_cert(kcopy
)) {
361 if (key_drop_cert(kcopy
) != 0) {
362 error("%s: key_drop_cert", __func__
);
367 r
= key_to_blob(kcopy
, blob
, blen
);
372 /* Revoke a key blob. Ownership of blob is transferred to the tree */
374 revoke_blob(struct revoked_blob_tree
*rbt
, u_char
*blob
, u_int len
)
376 struct revoked_blob
*rb
, *erb
;
378 if ((rb
= calloc(1, sizeof(*rb
))) == NULL
)
382 erb
= RB_INSERT(revoked_blob_tree
, rbt
, rb
);
391 ssh_krl_revoke_key_explicit(struct ssh_krl
*krl
, const Key
*key
)
396 debug3("%s: revoke type %s", __func__
, key_type(key
));
397 if (plain_key_blob(key
, &blob
, &len
) < 0)
399 return revoke_blob(&krl
->revoked_keys
, blob
, len
);
403 ssh_krl_revoke_key_sha1(struct ssh_krl
*krl
, const Key
*key
)
408 debug3("%s: revoke type %s by sha1", __func__
, key_type(key
));
409 if ((blob
= key_fingerprint_raw(key
, SSH_FP_SHA1
, &len
)) == NULL
)
411 return revoke_blob(&krl
->revoked_sha1s
, blob
, len
);
415 ssh_krl_revoke_key(struct ssh_krl
*krl
, const Key
*key
)
417 if (!key_is_cert(key
))
418 return ssh_krl_revoke_key_sha1(krl
, key
);
420 if (key_cert_is_legacy(key
) || key
->cert
->serial
== 0) {
421 return ssh_krl_revoke_cert_by_key_id(krl
,
422 key
->cert
->signature_key
,
425 return ssh_krl_revoke_cert_by_serial(krl
,
426 key
->cert
->signature_key
,
432 * Select a copact next section type to emit in a KRL based on the
433 * current section type, the run length of contiguous revoked serial
434 * numbers and the gaps from the last and to the next revoked serial.
435 * Applies a mostly-accurate bit cost model to select the section type
436 * that will minimise the size of the resultant KRL.
439 choose_next_state(int current_state
, u_int64_t contig
, int final
,
440 u_int64_t last_gap
, u_int64_t next_gap
, int *force_new_section
)
443 u_int64_t cost
, cost_list
, cost_range
, cost_bitmap
, cost_bitmap_restart
;
446 * Avoid unsigned overflows.
447 * The limits are high enough to avoid confusing the calculations.
449 contig
= MIN(contig
, 1ULL<<31);
450 last_gap
= MIN(last_gap
, 1ULL<<31);
451 next_gap
= MIN(next_gap
, 1ULL<<31);
454 * Calculate the cost to switch from the current state to candidates.
455 * NB. range sections only ever contain a single range, so their
456 * switching cost is independent of the current_state.
458 cost_list
= cost_bitmap
= cost_bitmap_restart
= 0;
460 switch (current_state
) {
461 case KRL_SECTION_CERT_SERIAL_LIST
:
462 cost_bitmap_restart
= cost_bitmap
= 8 + 64;
464 case KRL_SECTION_CERT_SERIAL_BITMAP
:
466 cost_bitmap_restart
= 8 + 64;
468 case KRL_SECTION_CERT_SERIAL_RANGE
:
470 cost_bitmap_restart
= cost_bitmap
= 8 + 64;
474 /* Estimate base cost in bits of each section type */
475 cost_list
+= 64 * contig
+ (final
? 0 : 8+64);
476 cost_range
+= (2 * 64) + (final
? 0 : 8+64);
477 cost_bitmap
+= last_gap
+ contig
+ (final
? 0 : MIN(next_gap
, 8+64));
478 cost_bitmap_restart
+= contig
+ (final
? 0 : MIN(next_gap
, 8+64));
480 /* Convert to byte costs for actual comparison */
481 cost_list
= (cost_list
+ 7) / 8;
482 cost_bitmap
= (cost_bitmap
+ 7) / 8;
483 cost_bitmap_restart
= (cost_bitmap_restart
+ 7) / 8;
484 cost_range
= (cost_range
+ 7) / 8;
486 /* Now pick the best choice */
487 *force_new_section
= 0;
488 new_state
= KRL_SECTION_CERT_SERIAL_BITMAP
;
490 if (cost_range
< cost
) {
491 new_state
= KRL_SECTION_CERT_SERIAL_RANGE
;
494 if (cost_list
< cost
) {
495 new_state
= KRL_SECTION_CERT_SERIAL_LIST
;
498 if (cost_bitmap_restart
< cost
) {
499 new_state
= KRL_SECTION_CERT_SERIAL_BITMAP
;
500 *force_new_section
= 1;
501 cost
= cost_bitmap_restart
;
503 debug3("%s: contig %llu last_gap %llu next_gap %llu final %d, costs:"
504 "list %llu range %llu bitmap %llu new bitmap %llu, "
505 "selected 0x%02x%s", __func__
, (long long unsigned)contig
,
506 (long long unsigned)last_gap
, (long long unsigned)next_gap
, final
,
507 (long long unsigned)cost_list
, (long long unsigned)cost_range
,
508 (long long unsigned)cost_bitmap
,
509 (long long unsigned)cost_bitmap_restart
, new_state
,
510 *force_new_section
? " restart" : "");
514 /* Generate a KRL_SECTION_CERTIFICATES KRL section */
516 revoked_certs_generate(struct revoked_certs
*rc
, Buffer
*buf
)
518 int final
, force_new_sect
, r
= -1;
519 u_int64_t i
, contig
, gap
, last
= 0, bitmap_start
= 0;
520 struct revoked_serial
*rs
, *nrs
;
521 struct revoked_key_id
*rki
;
522 int next_state
, state
= 0;
524 u_char
*kblob
= NULL
;
526 BIGNUM
*bitmap
= NULL
;
528 /* Prepare CA scope key blob if we have one supplied */
529 if (key_to_blob(rc
->ca_key
, &kblob
, &klen
) == 0)
534 /* Store the header */
535 buffer_put_string(buf
, kblob
, klen
);
536 buffer_put_string(buf
, NULL
, 0); /* Reserved */
540 /* Store the revoked serials. */
541 for (rs
= RB_MIN(revoked_serial_tree
, &rc
->revoked_serials
);
543 rs
= RB_NEXT(revoked_serial_tree
, &rc
->revoked_serials
, rs
)) {
544 debug3("%s: serial %llu:%llu state 0x%02x", __func__
,
545 (long long unsigned)rs
->lo
, (long long unsigned)rs
->hi
,
548 /* Check contiguous length and gap to next section (if any) */
549 nrs
= RB_NEXT(revoked_serial_tree
, &rc
->revoked_serials
, rs
);
551 gap
= nrs
== NULL
? 0 : nrs
->lo
- rs
->hi
;
552 contig
= 1 + (rs
->hi
- rs
->lo
);
554 /* Choose next state based on these */
555 next_state
= choose_next_state(state
, contig
, final
,
556 state
== 0 ? 0 : rs
->lo
- last
, gap
, &force_new_sect
);
559 * If the current section is a range section or has a different
560 * type to the next section, then finish it off now.
562 if (state
!= 0 && (force_new_sect
|| next_state
!= state
||
563 state
== KRL_SECTION_CERT_SERIAL_RANGE
)) {
564 debug3("%s: finish state 0x%02x", __func__
, state
);
566 case KRL_SECTION_CERT_SERIAL_LIST
:
567 case KRL_SECTION_CERT_SERIAL_RANGE
:
569 case KRL_SECTION_CERT_SERIAL_BITMAP
:
570 buffer_put_bignum2(§
, bitmap
);
575 buffer_put_char(buf
, state
);
576 buffer_put_string(buf
,
577 buffer_ptr(§
), buffer_len(§
));
581 /* If we are starting a new section then prepare it now */
582 if (next_state
!= state
|| force_new_sect
) {
583 debug3("%s: start state 0x%02x", __func__
, next_state
);
587 case KRL_SECTION_CERT_SERIAL_LIST
:
588 case KRL_SECTION_CERT_SERIAL_RANGE
:
590 case KRL_SECTION_CERT_SERIAL_BITMAP
:
591 if ((bitmap
= BN_new()) == NULL
)
593 bitmap_start
= rs
->lo
;
594 buffer_put_int64(§
, bitmap_start
);
599 /* Perform section-specific processing */
601 case KRL_SECTION_CERT_SERIAL_LIST
:
602 for (i
= 0; i
< contig
; i
++)
603 buffer_put_int64(§
, rs
->lo
+ i
);
605 case KRL_SECTION_CERT_SERIAL_RANGE
:
606 buffer_put_int64(§
, rs
->lo
);
607 buffer_put_int64(§
, rs
->hi
);
609 case KRL_SECTION_CERT_SERIAL_BITMAP
:
610 if (rs
->lo
- bitmap_start
> INT_MAX
) {
611 error("%s: insane bitmap gap", __func__
);
614 for (i
= 0; i
< contig
; i
++) {
615 if (BN_set_bit(bitmap
,
616 rs
->lo
+ i
- bitmap_start
) != 1)
623 /* Flush the remaining section, if any */
625 debug3("%s: serial final flush for state 0x%02x",
628 case KRL_SECTION_CERT_SERIAL_LIST
:
629 case KRL_SECTION_CERT_SERIAL_RANGE
:
631 case KRL_SECTION_CERT_SERIAL_BITMAP
:
632 buffer_put_bignum2(§
, bitmap
);
637 buffer_put_char(buf
, state
);
638 buffer_put_string(buf
,
639 buffer_ptr(§
), buffer_len(§
));
641 debug3("%s: serial done ", __func__
);
643 /* Now output a section for any revocations by key ID */
645 RB_FOREACH(rki
, revoked_key_id_tree
, &rc
->revoked_key_ids
) {
646 debug3("%s: key ID %s", __func__
, rki
->key_id
);
647 buffer_put_cstring(§
, rki
->key_id
);
649 if (buffer_len(§
) != 0) {
650 buffer_put_char(buf
, KRL_SECTION_CERT_KEY_ID
);
651 buffer_put_string(buf
, buffer_ptr(§
),
663 ssh_krl_to_blob(struct ssh_krl
*krl
, Buffer
*buf
, const Key
**sign_keys
,
667 struct revoked_certs
*rc
;
668 struct revoked_blob
*rb
;
670 u_char
*kblob
= NULL
, *sblob
= NULL
;
673 if (krl
->generated_date
== 0)
674 krl
->generated_date
= time(NULL
);
678 /* Store the header */
679 buffer_append(buf
, KRL_MAGIC
, sizeof(KRL_MAGIC
) - 1);
680 buffer_put_int(buf
, KRL_FORMAT_VERSION
);
681 buffer_put_int64(buf
, krl
->krl_version
);
682 buffer_put_int64(buf
, krl
->generated_date
);
683 buffer_put_int64(buf
, krl
->flags
);
684 buffer_put_string(buf
, NULL
, 0);
685 buffer_put_cstring(buf
, krl
->comment
? krl
->comment
: "");
687 /* Store sections for revoked certificates */
688 TAILQ_FOREACH(rc
, &krl
->revoked_certs
, entry
) {
689 if (revoked_certs_generate(rc
, §
) != 0)
691 buffer_put_char(buf
, KRL_SECTION_CERTIFICATES
);
692 buffer_put_string(buf
, buffer_ptr(§
),
696 /* Finally, output sections for revocations by public key/hash */
698 RB_FOREACH(rb
, revoked_blob_tree
, &krl
->revoked_keys
) {
699 debug3("%s: key len %u ", __func__
, rb
->len
);
700 buffer_put_string(§
, rb
->blob
, rb
->len
);
702 if (buffer_len(§
) != 0) {
703 buffer_put_char(buf
, KRL_SECTION_EXPLICIT_KEY
);
704 buffer_put_string(buf
, buffer_ptr(§
),
708 RB_FOREACH(rb
, revoked_blob_tree
, &krl
->revoked_sha1s
) {
709 debug3("%s: hash len %u ", __func__
, rb
->len
);
710 buffer_put_string(§
, rb
->blob
, rb
->len
);
712 if (buffer_len(§
) != 0) {
713 buffer_put_char(buf
, KRL_SECTION_FINGERPRINT_SHA1
);
714 buffer_put_string(buf
, buffer_ptr(§
),
718 for (i
= 0; i
< nsign_keys
; i
++) {
719 if (key_to_blob(sign_keys
[i
], &kblob
, &klen
) == 0)
722 debug3("%s: signature key len %u", __func__
, klen
);
723 buffer_put_char(buf
, KRL_SECTION_SIGNATURE
);
724 buffer_put_string(buf
, kblob
, klen
);
726 if (key_sign(sign_keys
[i
], &sblob
, &slen
,
727 buffer_ptr(buf
), buffer_len(buf
)) == -1)
729 debug3("%s: signature sig len %u", __func__
, slen
);
730 buffer_put_string(buf
, sblob
, slen
);
742 format_timestamp(u_int64_t timestamp
, char *ts
, size_t nts
)
750 strftime(ts
, nts
, "%Y%m%dT%H%M%S", tm
);
754 parse_revoked_certs(Buffer
*buf
, struct ssh_krl
*krl
)
761 u_int64_t serial
, serial_lo
, serial_hi
;
762 BIGNUM
*bitmap
= NULL
;
766 buffer_init(&subsect
);
768 if ((blob
= buffer_get_string_ptr_ret(buf
, &blen
)) == NULL
||
769 buffer_get_string_ptr_ret(buf
, NULL
) == NULL
) { /* reserved */
770 error("%s: buffer error", __func__
);
773 if ((ca_key
= key_from_blob(blob
, blen
)) == NULL
)
776 while (buffer_len(buf
) > 0) {
777 if (buffer_get_char_ret(&type
, buf
) != 0 ||
778 (blob
= buffer_get_string_ptr_ret(buf
, &blen
)) == NULL
) {
779 error("%s: buffer error", __func__
);
782 buffer_clear(&subsect
);
783 buffer_append(&subsect
, blob
, blen
);
784 debug3("%s: subsection type 0x%02x", __func__
, type
);
785 /* buffer_dump(&subsect); */
788 case KRL_SECTION_CERT_SERIAL_LIST
:
789 while (buffer_len(&subsect
) > 0) {
790 if (buffer_get_int64_ret(&serial
,
792 error("%s: buffer error", __func__
);
795 if (ssh_krl_revoke_cert_by_serial(krl
, ca_key
,
797 error("%s: update failed", __func__
);
802 case KRL_SECTION_CERT_SERIAL_RANGE
:
803 if (buffer_get_int64_ret(&serial_lo
, &subsect
) != 0 ||
804 buffer_get_int64_ret(&serial_hi
, &subsect
) != 0) {
805 error("%s: buffer error", __func__
);
808 if (ssh_krl_revoke_cert_by_serial_range(krl
, ca_key
,
809 serial_lo
, serial_hi
) != 0) {
810 error("%s: update failed", __func__
);
814 case KRL_SECTION_CERT_SERIAL_BITMAP
:
815 if ((bitmap
= BN_new()) == NULL
) {
816 error("%s: BN_new", __func__
);
819 if (buffer_get_int64_ret(&serial_lo
, &subsect
) != 0 ||
820 buffer_get_bignum2_ret(&subsect
, bitmap
) != 0) {
821 error("%s: buffer error", __func__
);
824 if ((nbits
= BN_num_bits(bitmap
)) < 0) {
825 error("%s: bitmap bits < 0", __func__
);
828 for (serial
= 0; serial
< (u_int
)nbits
; serial
++) {
829 if (serial
> 0 && serial_lo
+ serial
== 0) {
830 error("%s: bitmap wraps u64", __func__
);
833 if (!BN_is_bit_set(bitmap
, serial
))
835 if (ssh_krl_revoke_cert_by_serial(krl
, ca_key
,
836 serial_lo
+ serial
) != 0) {
837 error("%s: update failed", __func__
);
844 case KRL_SECTION_CERT_KEY_ID
:
845 while (buffer_len(&subsect
) > 0) {
846 if ((key_id
= buffer_get_cstring_ret(&subsect
,
848 error("%s: buffer error", __func__
);
851 if (ssh_krl_revoke_cert_by_key_id(krl
, ca_key
,
853 error("%s: update failed", __func__
);
861 error("Unsupported KRL certificate section %u", type
);
864 if (buffer_len(&subsect
) > 0) {
865 error("KRL certificate section contains unparsed data");
877 buffer_free(&subsect
);
882 /* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. */
884 ssh_krl_from_blob(Buffer
*buf
, struct ssh_krl
**krlp
,
885 const Key
**sign_ca_keys
, u_int nsign_ca_keys
)
890 int ret
= -1, r
, sig_seen
;
891 Key
*key
= NULL
, **ca_used
= NULL
;
892 u_char type
, *rdata
= NULL
;
894 u_int i
, j
, sig_off
, sects_off
, rlen
, blen
, format_version
, nca_used
;
898 if (buffer_len(buf
) < sizeof(KRL_MAGIC
) - 1 ||
899 memcmp(buffer_ptr(buf
), KRL_MAGIC
, sizeof(KRL_MAGIC
) - 1) != 0) {
900 debug3("%s: not a KRL", __func__
);
902 * Return success but a NULL *krlp here to signal that the
903 * file might be a simple list of keys.
908 /* Take a copy of the KRL buffer so we can verify its signature later */
910 buffer_append(©
, buffer_ptr(buf
), buffer_len(buf
));
913 buffer_consume(©
, sizeof(KRL_MAGIC
) - 1);
915 if ((krl
= ssh_krl_init()) == NULL
) {
916 error("%s: alloc failed", __func__
);
920 if (buffer_get_int_ret(&format_version
, ©
) != 0) {
921 error("%s: KRL truncated", __func__
);
924 if (format_version
!= KRL_FORMAT_VERSION
) {
925 error("%s: KRL unsupported format version %u",
926 __func__
, format_version
);
929 if (buffer_get_int64_ret(&krl
->krl_version
, ©
) != 0 ||
930 buffer_get_int64_ret(&krl
->generated_date
, ©
) != 0 ||
931 buffer_get_int64_ret(&krl
->flags
, ©
) != 0 ||
932 buffer_get_string_ptr_ret(©
, NULL
) == NULL
|| /* reserved */
933 (krl
->comment
= buffer_get_cstring_ret(©
, NULL
)) == NULL
) {
934 error("%s: buffer error", __func__
);
938 format_timestamp(krl
->generated_date
, timestamp
, sizeof(timestamp
));
939 debug("KRL version %llu generated at %s%s%s",
940 (long long unsigned)krl
->krl_version
, timestamp
,
941 *krl
->comment
? ": " : "", krl
->comment
);
944 * 1st pass: verify signatures, if any. This is done to avoid
945 * detailed parsing of data whose provenance is unverified.
948 sects_off
= buffer_len(buf
) - buffer_len(©
);
949 while (buffer_len(©
) > 0) {
950 if (buffer_get_char_ret(&type
, ©
) != 0 ||
951 (blob
= buffer_get_string_ptr_ret(©
, &blen
)) == NULL
) {
952 error("%s: buffer error", __func__
);
955 debug3("%s: first pass, section 0x%02x", __func__
, type
);
956 if (type
!= KRL_SECTION_SIGNATURE
) {
958 error("KRL contains non-signature section "
962 /* Not interested for now. */
966 /* First string component is the signing key */
967 if ((key
= key_from_blob(blob
, blen
)) == NULL
) {
968 error("%s: invalid signature key", __func__
);
971 sig_off
= buffer_len(buf
) - buffer_len(©
);
972 /* Second string component is the signature itself */
973 if ((blob
= buffer_get_string_ptr_ret(©
, &blen
)) == NULL
) {
974 error("%s: buffer error", __func__
);
977 /* Check signature over entire KRL up to this point */
978 if (key_verify(key
, blob
, blen
,
979 buffer_ptr(buf
), buffer_len(buf
) - sig_off
) != 1) {
980 error("bad signaure on KRL");
983 /* Check if this key has already signed this KRL */
984 for (i
= 0; i
< nca_used
; i
++) {
985 if (key_equal(ca_used
[i
], key
)) {
986 error("KRL signed more than once with "
991 /* Record keys used to sign the KRL */
992 ca_used
= xrealloc(ca_used
, nca_used
+ 1, sizeof(*ca_used
));
993 ca_used
[nca_used
++] = key
;
999 * 2nd pass: parse and load the KRL, skipping the header to the point
1000 * where the section start.
1002 buffer_append(©
, (u_char
*)buffer_ptr(buf
) + sects_off
,
1003 buffer_len(buf
) - sects_off
);
1004 while (buffer_len(©
) > 0) {
1005 if (buffer_get_char_ret(&type
, ©
) != 0 ||
1006 (blob
= buffer_get_string_ptr_ret(©
, &blen
)) == NULL
) {
1007 error("%s: buffer error", __func__
);
1010 debug3("%s: second pass, section 0x%02x", __func__
, type
);
1011 buffer_clear(§
);
1012 buffer_append(§
, blob
, blen
);
1015 case KRL_SECTION_CERTIFICATES
:
1016 if ((r
= parse_revoked_certs(§
, krl
)) != 0)
1019 case KRL_SECTION_EXPLICIT_KEY
:
1020 case KRL_SECTION_FINGERPRINT_SHA1
:
1021 while (buffer_len(§
) > 0) {
1022 if ((rdata
= buffer_get_string_ret(§
,
1024 error("%s: buffer error", __func__
);
1027 if (type
== KRL_SECTION_FINGERPRINT_SHA1
&&
1029 error("%s: bad SHA1 length", __func__
);
1033 type
== KRL_SECTION_EXPLICIT_KEY
?
1034 &krl
->revoked_keys
: &krl
->revoked_sha1s
,
1037 rdata
= NULL
; /* revoke_blob frees blob */
1040 case KRL_SECTION_SIGNATURE
:
1041 /* Handled above, but still need to stay in synch */
1042 buffer_clear(§
);
1043 if ((blob
= buffer_get_string_ptr_ret(©
,
1045 error("%s: buffer error", __func__
);
1050 error("Unsupported KRL section %u", type
);
1053 if (buffer_len(§
) > 0) {
1054 error("KRL section contains unparsed data");
1059 /* Check that the key(s) used to sign the KRL weren't revoked */
1061 for (i
= 0; i
< nca_used
; i
++) {
1062 if (ssh_krl_check_key(krl
, ca_used
[i
]) == 0)
1065 key_free(ca_used
[i
]);
1069 if (nca_used
&& !sig_seen
) {
1070 error("All keys used to sign KRL were revoked");
1074 /* If we have CA keys, then verify that one was used to sign the KRL */
1075 if (sig_seen
&& nsign_ca_keys
!= 0) {
1077 for (i
= 0; !sig_seen
&& i
< nsign_ca_keys
; i
++) {
1078 for (j
= 0; j
< nca_used
; j
++) {
1079 if (ca_used
[j
] == NULL
)
1081 if (key_equal(ca_used
[j
], sign_ca_keys
[i
])) {
1088 error("KRL not signed with any trusted key");
1098 for (i
= 0; i
< nca_used
; i
++) {
1099 if (ca_used
[i
] != NULL
)
1100 key_free(ca_used
[i
]);
1111 /* Checks whether a given key/cert is revoked. Does not check its CA */
1113 is_key_revoked(struct ssh_krl
*krl
, const Key
*key
)
1115 struct revoked_blob rb
, *erb
;
1116 struct revoked_serial rs
, *ers
;
1117 struct revoked_key_id rki
, *erki
;
1118 struct revoked_certs
*rc
;
1120 /* Check explicitly revoked hashes first */
1121 memset(&rb
, 0, sizeof(rb
));
1122 if ((rb
.blob
= key_fingerprint_raw(key
, SSH_FP_SHA1
, &rb
.len
)) == NULL
)
1124 erb
= RB_FIND(revoked_blob_tree
, &krl
->revoked_sha1s
, &rb
);
1127 debug("%s: revoked by key SHA1", __func__
);
1131 /* Next, explicit keys */
1132 memset(&rb
, 0, sizeof(rb
));
1133 if (plain_key_blob(key
, &rb
.blob
, &rb
.len
) < 0)
1135 erb
= RB_FIND(revoked_blob_tree
, &krl
->revoked_keys
, &rb
);
1138 debug("%s: revoked by explicit key", __func__
);
1142 if (!key_is_cert(key
))
1145 /* Check cert revocation */
1146 if (revoked_certs_for_ca_key(krl
, key
->cert
->signature_key
,
1150 return 0; /* No entry for this CA */
1152 /* Check revocation by cert key ID */
1153 memset(&rki
, 0, sizeof(rki
));
1154 rki
.key_id
= key
->cert
->key_id
;
1155 erki
= RB_FIND(revoked_key_id_tree
, &rc
->revoked_key_ids
, &rki
);
1157 debug("%s: revoked by key ID", __func__
);
1162 * Legacy cert formats lack serial numbers. Zero serials numbers
1163 * are ignored (it's the default when the CA doesn't specify one).
1165 if (key_cert_is_legacy(key
) || key
->cert
->serial
== 0)
1168 memset(&rs
, 0, sizeof(rs
));
1169 rs
.lo
= rs
.hi
= key
->cert
->serial
;
1170 ers
= RB_FIND(revoked_serial_tree
, &rc
->revoked_serials
, &rs
);
1172 KRL_DBG(("%s: %llu matched %llu:%llu", __func__
,
1173 key
->cert
->serial
, ers
->lo
, ers
->hi
));
1174 debug("%s: revoked by serial", __func__
);
1177 KRL_DBG(("%s: %llu no match", __func__
, key
->cert
->serial
));
1183 ssh_krl_check_key(struct ssh_krl
*krl
, const Key
*key
)
1187 debug2("%s: checking key", __func__
);
1188 if ((r
= is_key_revoked(krl
, key
)) != 0)
1190 if (key_is_cert(key
)) {
1191 debug2("%s: checking CA key", __func__
);
1192 if ((r
= is_key_revoked(krl
, key
->cert
->signature_key
)) != 0)
1195 debug3("%s: key okay", __func__
);
1199 /* Returns 0 on success, -1 on error or key revoked, -2 if path is not a KRL */
1201 ssh_krl_file_contains_key(const char *path
, const Key
*key
)
1204 struct ssh_krl
*krl
;
1210 if ((fd
= open(path
, O_RDONLY
)) == -1) {
1211 error("open %s: %s", path
, strerror(errno
));
1212 error("Revoked keys file not accessible - refusing public key "
1216 buffer_init(&krlbuf
);
1217 if (!key_load_file(fd
, path
, &krlbuf
)) {
1219 buffer_free(&krlbuf
);
1220 error("Revoked keys file not readable - refusing public key "
1225 if (ssh_krl_from_blob(&krlbuf
, &krl
, NULL
, 0) != 0) {
1226 buffer_free(&krlbuf
);
1227 error("Invalid KRL, refusing public key "
1231 buffer_free(&krlbuf
);
1233 debug3("%s: %s is not a KRL file", __func__
, path
);
1236 debug2("%s: checking KRL %s", __func__
, path
);
1237 revoked
= ssh_krl_check_key(krl
, key
) != 0;
1239 return revoked
? -1 : 0;