krl.c revision 1.3.4.2
1/*	$NetBSD: krl.c,v 1.3.4.2 2014/05/22 13:21:35 yamt Exp $	*/
2/*
3 * Copyright (c) 2012 Damien Miller <djm@mindrot.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* $OpenBSD: krl.c,v 1.13 2013/07/20 22:20:42 djm Exp $ */
19#include <sys/cdefs.h>
20__RCSID("$NetBSD: krl.c,v 1.3.4.2 2014/05/22 13:21:35 yamt Exp $");
21
22#include "includes.h"
23#include <sys/types.h>
24#include <sys/param.h>
25#include <sys/tree.h>
26#include <sys/queue.h>
27
28#include <errno.h>
29#include <fcntl.h>
30#include <limits.h>
31#include <string.h>
32#include <time.h>
33#include <unistd.h>
34
35#include "buffer.h"
36#include "key.h"
37#include "authfile.h"
38#include "misc.h"
39#include "log.h"
40#include "xmalloc.h"
41
42#include "krl.h"
43
44/* #define DEBUG_KRL */
45#ifdef DEBUG_KRL
46# define KRL_DBG(x) debug3 x
47#else
48# define KRL_DBG(x)
49#endif
50
51/*
52 * Trees of revoked serial numbers, key IDs and keys. This allows
53 * quick searching, querying and producing lists in canonical order.
54 */
55
56/* Tree of serial numbers. XXX make smarter: really need a real sparse bitmap */
57struct revoked_serial {
58	u_int64_t lo, hi;
59	RB_ENTRY(revoked_serial) tree_entry;
60};
61static int serial_cmp(struct revoked_serial *a, struct revoked_serial *b);
62RB_HEAD(revoked_serial_tree, revoked_serial);
63RB_GENERATE_STATIC(revoked_serial_tree, revoked_serial, tree_entry, serial_cmp);
64
65/* Tree of key IDs */
66struct revoked_key_id {
67	char *key_id;
68	RB_ENTRY(revoked_key_id) tree_entry;
69};
70static int key_id_cmp(struct revoked_key_id *a, struct revoked_key_id *b);
71RB_HEAD(revoked_key_id_tree, revoked_key_id);
72RB_GENERATE_STATIC(revoked_key_id_tree, revoked_key_id, tree_entry, key_id_cmp);
73
74/* Tree of blobs (used for keys and fingerprints) */
75struct revoked_blob {
76	u_char *blob;
77	u_int len;
78	RB_ENTRY(revoked_blob) tree_entry;
79};
80static int blob_cmp(struct revoked_blob *a, struct revoked_blob *b);
81RB_HEAD(revoked_blob_tree, revoked_blob);
82RB_GENERATE_STATIC(revoked_blob_tree, revoked_blob, tree_entry, blob_cmp);
83
84/* Tracks revoked certs for a single CA */
85struct revoked_certs {
86	Key *ca_key;
87	struct revoked_serial_tree revoked_serials;
88	struct revoked_key_id_tree revoked_key_ids;
89	TAILQ_ENTRY(revoked_certs) entry;
90};
91TAILQ_HEAD(revoked_certs_list, revoked_certs);
92
93struct ssh_krl {
94	u_int64_t krl_version;
95	u_int64_t generated_date;
96	u_int64_t flags;
97	char *comment;
98	struct revoked_blob_tree revoked_keys;
99	struct revoked_blob_tree revoked_sha1s;
100	struct revoked_certs_list revoked_certs;
101};
102
103/* Return equal if a and b overlap */
104static int
105serial_cmp(struct revoked_serial *a, struct revoked_serial *b)
106{
107	if (a->hi >= b->lo && a->lo <= b->hi)
108		return 0;
109	return a->lo < b->lo ? -1 : 1;
110}
111
112static int
113key_id_cmp(struct revoked_key_id *a, struct revoked_key_id *b)
114{
115	return strcmp(a->key_id, b->key_id);
116}
117
118static int
119blob_cmp(struct revoked_blob *a, struct revoked_blob *b)
120{
121	int r;
122
123	if (a->len != b->len) {
124		if ((r = memcmp(a->blob, b->blob, MIN(a->len, b->len))) != 0)
125			return r;
126		return a->len > b->len ? 1 : -1;
127	} else
128		return memcmp(a->blob, b->blob, a->len);
129}
130
131struct ssh_krl *
132ssh_krl_init(void)
133{
134	struct ssh_krl *krl;
135
136	if ((krl = calloc(1, sizeof(*krl))) == NULL)
137		return NULL;
138	RB_INIT(&krl->revoked_keys);
139	RB_INIT(&krl->revoked_sha1s);
140	TAILQ_INIT(&krl->revoked_certs);
141	return krl;
142}
143
144static void
145revoked_certs_free(struct revoked_certs *rc)
146{
147	struct revoked_serial *rs, *trs;
148	struct revoked_key_id *rki, *trki;
149
150	RB_FOREACH_SAFE(rs, revoked_serial_tree, &rc->revoked_serials, trs) {
151		RB_REMOVE(revoked_serial_tree, &rc->revoked_serials, rs);
152		free(rs);
153	}
154	RB_FOREACH_SAFE(rki, revoked_key_id_tree, &rc->revoked_key_ids, trki) {
155		RB_REMOVE(revoked_key_id_tree, &rc->revoked_key_ids, rki);
156		free(rki->key_id);
157		free(rki);
158	}
159	if (rc->ca_key != NULL)
160		key_free(rc->ca_key);
161}
162
163void
164ssh_krl_free(struct ssh_krl *krl)
165{
166	struct revoked_blob *rb, *trb;
167	struct revoked_certs *rc, *trc;
168
169	if (krl == NULL)
170		return;
171
172	free(krl->comment);
173	RB_FOREACH_SAFE(rb, revoked_blob_tree, &krl->revoked_keys, trb) {
174		RB_REMOVE(revoked_blob_tree, &krl->revoked_keys, rb);
175		free(rb->blob);
176		free(rb);
177	}
178	RB_FOREACH_SAFE(rb, revoked_blob_tree, &krl->revoked_sha1s, trb) {
179		RB_REMOVE(revoked_blob_tree, &krl->revoked_sha1s, rb);
180		free(rb->blob);
181		free(rb);
182	}
183	TAILQ_FOREACH_SAFE(rc, &krl->revoked_certs, entry, trc) {
184		TAILQ_REMOVE(&krl->revoked_certs, rc, entry);
185		revoked_certs_free(rc);
186	}
187}
188
189void
190ssh_krl_set_version(struct ssh_krl *krl, u_int64_t version)
191{
192	krl->krl_version = version;
193}
194
195void
196ssh_krl_set_comment(struct ssh_krl *krl, const char *comment)
197{
198	free(krl->comment);
199	if ((krl->comment = strdup(comment)) == NULL)
200		fatal("%s: strdup", __func__);
201}
202
203/*
204 * Find the revoked_certs struct for a CA key. If allow_create is set then
205 * create a new one in the tree if one did not exist already.
206 */
207static int
208revoked_certs_for_ca_key(struct ssh_krl *krl, const Key *ca_key,
209    struct revoked_certs **rcp, int allow_create)
210{
211	struct revoked_certs *rc;
212
213	*rcp = NULL;
214	TAILQ_FOREACH(rc, &krl->revoked_certs, entry) {
215		if (key_equal(rc->ca_key, ca_key)) {
216			*rcp = rc;
217			return 0;
218		}
219	}
220	if (!allow_create)
221		return 0;
222	/* If this CA doesn't exist in the list then add it now */
223	if ((rc = calloc(1, sizeof(*rc))) == NULL)
224		return -1;
225	if ((rc->ca_key = key_from_private(ca_key)) == NULL) {
226		free(rc);
227		return -1;
228	}
229	RB_INIT(&rc->revoked_serials);
230	RB_INIT(&rc->revoked_key_ids);
231	TAILQ_INSERT_TAIL(&krl->revoked_certs, rc, entry);
232	debug3("%s: new CA %s", __func__, key_type(ca_key));
233	*rcp = rc;
234	return 0;
235}
236
237static int
238insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi)
239{
240	struct revoked_serial rs, *ers, *crs, *irs;
241
242	KRL_DBG(("%s: insert %"PRIu64":%"PRIu64, __func__, lo, hi));
243	bzero(&rs, sizeof(rs));
244	rs.lo = lo;
245	rs.hi = hi;
246	ers = RB_NFIND(revoked_serial_tree, rt, &rs);
247	if (ers == NULL || serial_cmp(ers, &rs) != 0) {
248		/* No entry matches. Just insert */
249		if ((irs = malloc(sizeof(rs))) == NULL)
250			return -1;
251		memcpy(irs, &rs, sizeof(*irs));
252		ers = RB_INSERT(revoked_serial_tree, rt, irs);
253		if (ers != NULL) {
254			KRL_DBG(("%s: bad: ers != NULL", __func__));
255			/* Shouldn't happen */
256			free(irs);
257			return -1;
258		}
259		ers = irs;
260	} else {
261		KRL_DBG(("%s: overlap found %"PRIu64":%"PRIu64, __func__,
262		    ers->lo, ers->hi));
263		/*
264		 * The inserted entry overlaps an existing one. Grow the
265		 * existing entry.
266		 */
267		if (ers->lo > lo)
268			ers->lo = lo;
269		if (ers->hi < hi)
270			ers->hi = hi;
271	}
272	/*
273	 * The inserted or revised range might overlap or abut adjacent ones;
274	 * coalesce as necessary.
275	 */
276
277	/* Check predecessors */
278	while ((crs = RB_PREV(revoked_serial_tree, rt, ers)) != NULL) {
279		KRL_DBG(("%s: pred %"PRIu64":%"PRIu64, __func__,
280		    crs->lo, crs->hi));
281		if (ers->lo != 0 && crs->hi < ers->lo - 1)
282			break;
283		/* This entry overlaps. */
284		if (crs->lo < ers->lo) {
285			ers->lo = crs->lo;
286			KRL_DBG(("%s: pred extend %"PRIu64":%"PRIu64, __func__,
287			    ers->lo, ers->hi));
288		}
289		RB_REMOVE(revoked_serial_tree, rt, crs);
290		free(crs);
291	}
292	/* Check successors */
293	while ((crs = RB_NEXT(revoked_serial_tree, rt, ers)) != NULL) {
294		KRL_DBG(("%s: succ %"PRIu64":%"PRIu64, __func__, crs->lo,
295		    crs->hi));
296		if (ers->hi != (u_int64_t)-1 && crs->lo > ers->hi + 1)
297			break;
298		/* This entry overlaps. */
299		if (crs->hi > ers->hi) {
300			ers->hi = crs->hi;
301			KRL_DBG(("%s: succ extend %"PRIu64":%"PRIu64, __func__,
302			    ers->lo, ers->hi));
303		}
304		RB_REMOVE(revoked_serial_tree, rt, crs);
305		free(crs);
306	}
307	KRL_DBG(("%s: done, final %"PRIu64":%"PRIu64, __func__, ers->lo,
308	    ers->hi));
309	return 0;
310}
311
312int
313ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, const Key *ca_key,
314    u_int64_t serial)
315{
316	return ssh_krl_revoke_cert_by_serial_range(krl, ca_key, serial, serial);
317}
318
319int
320ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, const Key *ca_key,
321    u_int64_t lo, u_int64_t hi)
322{
323	struct revoked_certs *rc;
324
325	if (lo > hi || lo == 0)
326		return -1;
327	if (revoked_certs_for_ca_key(krl, ca_key, &rc, 1) != 0)
328		return -1;
329	return insert_serial_range(&rc->revoked_serials, lo, hi);
330}
331
332int
333ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const Key *ca_key,
334    const char *key_id)
335{
336	struct revoked_key_id *rki, *erki;
337	struct revoked_certs *rc;
338
339	if (revoked_certs_for_ca_key(krl, ca_key, &rc, 1) != 0)
340		return -1;
341
342	debug3("%s: revoke %s", __func__, key_id);
343	if ((rki = calloc(1, sizeof(*rki))) == NULL ||
344	    (rki->key_id = strdup(key_id)) == NULL) {
345		free(rki);
346		fatal("%s: strdup", __func__);
347	}
348	erki = RB_INSERT(revoked_key_id_tree, &rc->revoked_key_ids, rki);
349	if (erki != NULL) {
350		free(rki->key_id);
351		free(rki);
352	}
353	return 0;
354}
355
356/* Convert "key" to a public key blob without any certificate information */
357static int
358plain_key_blob(const Key *key, u_char **blob, u_int *blen)
359{
360	Key *kcopy;
361	int r;
362
363	if ((kcopy = key_from_private(key)) == NULL)
364		return -1;
365	if (key_is_cert(kcopy)) {
366		if (key_drop_cert(kcopy) != 0) {
367			error("%s: key_drop_cert", __func__);
368			key_free(kcopy);
369			return -1;
370		}
371	}
372	r = key_to_blob(kcopy, blob, blen);
373	free(kcopy);
374	return r == 0 ? -1 : 0;
375}
376
377/* Revoke a key blob. Ownership of blob is transferred to the tree */
378static int
379revoke_blob(struct revoked_blob_tree *rbt, u_char *blob, u_int len)
380{
381	struct revoked_blob *rb, *erb;
382
383	if ((rb = calloc(1, sizeof(*rb))) == NULL)
384		return -1;
385	rb->blob = blob;
386	rb->len = len;
387	erb = RB_INSERT(revoked_blob_tree, rbt, rb);
388	if (erb != NULL) {
389		free(rb->blob);
390		free(rb);
391	}
392	return 0;
393}
394
395int
396ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const Key *key)
397{
398	u_char *blob;
399	u_int len;
400
401	debug3("%s: revoke type %s", __func__, key_type(key));
402	if (plain_key_blob(key, &blob, &len) != 0)
403		return -1;
404	return revoke_blob(&krl->revoked_keys, blob, len);
405}
406
407int
408ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const Key *key)
409{
410	u_char *blob;
411	u_int len;
412
413	debug3("%s: revoke type %s by sha1", __func__, key_type(key));
414	if ((blob = key_fingerprint_raw(key, SSH_FP_SHA1, &len)) == NULL)
415		return -1;
416	return revoke_blob(&krl->revoked_sha1s, blob, len);
417}
418
419int
420ssh_krl_revoke_key(struct ssh_krl *krl, const Key *key)
421{
422	if (!key_is_cert(key))
423		return ssh_krl_revoke_key_sha1(krl, key);
424
425	if (key_cert_is_legacy(key) || key->cert->serial == 0) {
426		return ssh_krl_revoke_cert_by_key_id(krl,
427		    key->cert->signature_key,
428		    key->cert->key_id);
429	} else {
430		return ssh_krl_revoke_cert_by_serial(krl,
431		    key->cert->signature_key,
432		    key->cert->serial);
433	}
434}
435
436/*
437 * Select a copact next section type to emit in a KRL based on the
438 * current section type, the run length of contiguous revoked serial
439 * numbers and the gaps from the last and to the next revoked serial.
440 * Applies a mostly-accurate bit cost model to select the section type
441 * that will minimise the size of the resultant KRL.
442 */
443static int
444choose_next_state(int current_state, u_int64_t contig, int final,
445    u_int64_t last_gap, u_int64_t next_gap, int *force_new_section)
446{
447	int new_state;
448	u_int64_t cost, cost_list, cost_range, cost_bitmap, cost_bitmap_restart;
449
450	/*
451	 * Avoid unsigned overflows.
452	 * The limits are high enough to avoid confusing the calculations.
453	 */
454	contig = MIN(contig, 1ULL<<31);
455	last_gap = MIN(last_gap, 1ULL<<31);
456	next_gap = MIN(next_gap, 1ULL<<31);
457
458	/*
459	 * Calculate the cost to switch from the current state to candidates.
460	 * NB. range sections only ever contain a single range, so their
461	 * switching cost is independent of the current_state.
462	 */
463	cost_list = cost_bitmap = cost_bitmap_restart = 0;
464	cost_range = 8;
465	switch (current_state) {
466	case KRL_SECTION_CERT_SERIAL_LIST:
467		cost_bitmap_restart = cost_bitmap = 8 + 64;
468		break;
469	case KRL_SECTION_CERT_SERIAL_BITMAP:
470		cost_list = 8;
471		cost_bitmap_restart = 8 + 64;
472		break;
473	case KRL_SECTION_CERT_SERIAL_RANGE:
474	case 0:
475		cost_bitmap_restart = cost_bitmap = 8 + 64;
476		cost_list = 8;
477	}
478
479	/* Estimate base cost in bits of each section type */
480	cost_list += 64 * contig + (final ? 0 : 8+64);
481	cost_range += (2 * 64) + (final ? 0 : 8+64);
482	cost_bitmap += last_gap + contig + (final ? 0 : MIN(next_gap, 8+64));
483	cost_bitmap_restart += contig + (final ? 0 : MIN(next_gap, 8+64));
484
485	/* Convert to byte costs for actual comparison */
486	cost_list = (cost_list + 7) / 8;
487	cost_bitmap = (cost_bitmap + 7) / 8;
488	cost_bitmap_restart = (cost_bitmap_restart + 7) / 8;
489	cost_range = (cost_range + 7) / 8;
490
491	/* Now pick the best choice */
492	*force_new_section = 0;
493	new_state = KRL_SECTION_CERT_SERIAL_BITMAP;
494	cost = cost_bitmap;
495	if (cost_range < cost) {
496		new_state = KRL_SECTION_CERT_SERIAL_RANGE;
497		cost = cost_range;
498	}
499	if (cost_list < cost) {
500		new_state = KRL_SECTION_CERT_SERIAL_LIST;
501		cost = cost_list;
502	}
503	if (cost_bitmap_restart < cost) {
504		new_state = KRL_SECTION_CERT_SERIAL_BITMAP;
505		*force_new_section = 1;
506		cost = cost_bitmap_restart;
507	}
508	debug3("%s: contig %llu last_gap %llu next_gap %llu final %d, costs:"
509	    "list %llu range %llu bitmap %llu new bitmap %llu, "
510	    "selected 0x%02x%s", __func__, (long long unsigned)contig,
511	    (long long unsigned)last_gap, (long long unsigned)next_gap, final,
512	    (long long unsigned)cost_list, (long long unsigned)cost_range,
513	    (long long unsigned)cost_bitmap,
514	    (long long unsigned)cost_bitmap_restart, new_state,
515	    *force_new_section ? " restart" : "");
516	return new_state;
517}
518
519/* Generate a KRL_SECTION_CERTIFICATES KRL section */
520static int
521revoked_certs_generate(struct revoked_certs *rc, Buffer *buf)
522{
523	int final, force_new_sect, r = -1;
524	u_int64_t i, contig, gap, last = 0, bitmap_start = 0;
525	struct revoked_serial *rs, *nrs;
526	struct revoked_key_id *rki;
527	int next_state, state = 0;
528	Buffer sect;
529	u_char *kblob = NULL;
530	u_int klen;
531	BIGNUM *bitmap = NULL;
532
533	/* Prepare CA scope key blob if we have one supplied */
534	if (key_to_blob(rc->ca_key, &kblob, &klen) == 0)
535		return -1;
536
537	buffer_init(&sect);
538
539	/* Store the header */
540	buffer_put_string(buf, kblob, klen);
541	buffer_put_string(buf, NULL, 0); /* Reserved */
542
543	free(kblob);
544
545	/* Store the revoked serials.  */
546	for (rs = RB_MIN(revoked_serial_tree, &rc->revoked_serials);
547	     rs != NULL;
548	     rs = RB_NEXT(revoked_serial_tree, &rc->revoked_serials, rs)) {
549		debug3("%s: serial %llu:%llu state 0x%02x", __func__,
550		    (long long unsigned)rs->lo, (long long unsigned)rs->hi,
551		    state);
552
553		/* Check contiguous length and gap to next section (if any) */
554		nrs = RB_NEXT(revoked_serial_tree, &rc->revoked_serials, rs);
555		final = nrs == NULL;
556		gap = nrs == NULL ? 0 : nrs->lo - rs->hi;
557		contig = 1 + (rs->hi - rs->lo);
558
559		/* Choose next state based on these */
560		next_state = choose_next_state(state, contig, final,
561		    state == 0 ? 0 : rs->lo - last, gap, &force_new_sect);
562
563		/*
564		 * If the current section is a range section or has a different
565		 * type to the next section, then finish it off now.
566		 */
567		if (state != 0 && (force_new_sect || next_state != state ||
568		    state == KRL_SECTION_CERT_SERIAL_RANGE)) {
569			debug3("%s: finish state 0x%02x", __func__, state);
570			switch (state) {
571			case KRL_SECTION_CERT_SERIAL_LIST:
572			case KRL_SECTION_CERT_SERIAL_RANGE:
573				break;
574			case KRL_SECTION_CERT_SERIAL_BITMAP:
575				buffer_put_bignum2(&sect, bitmap);
576				BN_free(bitmap);
577				bitmap = NULL;
578				break;
579			}
580			buffer_put_char(buf, state);
581			buffer_put_string(buf,
582			    buffer_ptr(&sect), buffer_len(&sect));
583		}
584
585		/* If we are starting a new section then prepare it now */
586		if (next_state != state || force_new_sect) {
587			debug3("%s: start state 0x%02x", __func__, next_state);
588			state = next_state;
589			buffer_clear(&sect);
590			switch (state) {
591			case KRL_SECTION_CERT_SERIAL_LIST:
592			case KRL_SECTION_CERT_SERIAL_RANGE:
593				break;
594			case KRL_SECTION_CERT_SERIAL_BITMAP:
595				if ((bitmap = BN_new()) == NULL)
596					goto out;
597				bitmap_start = rs->lo;
598				buffer_put_int64(&sect, bitmap_start);
599				break;
600			}
601		}
602
603		/* Perform section-specific processing */
604		switch (state) {
605		case KRL_SECTION_CERT_SERIAL_LIST:
606			for (i = 0; i < contig; i++)
607				buffer_put_int64(&sect, rs->lo + i);
608			break;
609		case KRL_SECTION_CERT_SERIAL_RANGE:
610			buffer_put_int64(&sect, rs->lo);
611			buffer_put_int64(&sect, rs->hi);
612			break;
613		case KRL_SECTION_CERT_SERIAL_BITMAP:
614			if (rs->lo - bitmap_start > INT_MAX) {
615				error("%s: insane bitmap gap", __func__);
616				goto out;
617			}
618			for (i = 0; i < contig; i++) {
619				if (BN_set_bit(bitmap,
620				    rs->lo + i - bitmap_start) != 1)
621					goto out;
622			}
623			break;
624		}
625		last = rs->hi;
626	}
627	/* Flush the remaining section, if any */
628	if (state != 0) {
629		debug3("%s: serial final flush for state 0x%02x",
630		    __func__, state);
631		switch (state) {
632		case KRL_SECTION_CERT_SERIAL_LIST:
633		case KRL_SECTION_CERT_SERIAL_RANGE:
634			break;
635		case KRL_SECTION_CERT_SERIAL_BITMAP:
636			buffer_put_bignum2(&sect, bitmap);
637			BN_free(bitmap);
638			bitmap = NULL;
639			break;
640		}
641		buffer_put_char(buf, state);
642		buffer_put_string(buf,
643		    buffer_ptr(&sect), buffer_len(&sect));
644	}
645	debug3("%s: serial done ", __func__);
646
647	/* Now output a section for any revocations by key ID */
648	buffer_clear(&sect);
649	RB_FOREACH(rki, revoked_key_id_tree, &rc->revoked_key_ids) {
650		debug3("%s: key ID %s", __func__, rki->key_id);
651		buffer_put_cstring(&sect, rki->key_id);
652	}
653	if (buffer_len(&sect) != 0) {
654		buffer_put_char(buf, KRL_SECTION_CERT_KEY_ID);
655		buffer_put_string(buf, buffer_ptr(&sect),
656		    buffer_len(&sect));
657	}
658	r = 0;
659 out:
660	if (bitmap != NULL)
661		BN_free(bitmap);
662	buffer_free(&sect);
663	return r;
664}
665
666int
667ssh_krl_to_blob(struct ssh_krl *krl, Buffer *buf, const Key **sign_keys,
668    u_int nsign_keys)
669{
670	int r = -1;
671	struct revoked_certs *rc;
672	struct revoked_blob *rb;
673	Buffer sect;
674	u_char *kblob = NULL, *sblob = NULL;
675	u_int klen, slen, i;
676
677	if (krl->generated_date == 0)
678		krl->generated_date = time(NULL);
679
680	buffer_init(&sect);
681
682	/* Store the header */
683	buffer_append(buf, KRL_MAGIC, sizeof(KRL_MAGIC) - 1);
684	buffer_put_int(buf, KRL_FORMAT_VERSION);
685	buffer_put_int64(buf, krl->krl_version);
686	buffer_put_int64(buf, krl->generated_date);
687	buffer_put_int64(buf, krl->flags);
688	buffer_put_string(buf, NULL, 0);
689	buffer_put_cstring(buf, krl->comment ? krl->comment : "");
690
691	/* Store sections for revoked certificates */
692	TAILQ_FOREACH(rc, &krl->revoked_certs, entry) {
693		if (revoked_certs_generate(rc, &sect) != 0)
694			goto out;
695		buffer_put_char(buf, KRL_SECTION_CERTIFICATES);
696		buffer_put_string(buf, buffer_ptr(&sect),
697		    buffer_len(&sect));
698	}
699
700	/* Finally, output sections for revocations by public key/hash */
701	buffer_clear(&sect);
702	RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) {
703		debug3("%s: key len %u ", __func__, rb->len);
704		buffer_put_string(&sect, rb->blob, rb->len);
705	}
706	if (buffer_len(&sect) != 0) {
707		buffer_put_char(buf, KRL_SECTION_EXPLICIT_KEY);
708		buffer_put_string(buf, buffer_ptr(&sect),
709		    buffer_len(&sect));
710	}
711	buffer_clear(&sect);
712	RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha1s) {
713		debug3("%s: hash len %u ", __func__, rb->len);
714		buffer_put_string(&sect, rb->blob, rb->len);
715	}
716	if (buffer_len(&sect) != 0) {
717		buffer_put_char(buf, KRL_SECTION_FINGERPRINT_SHA1);
718		buffer_put_string(buf, buffer_ptr(&sect),
719		    buffer_len(&sect));
720	}
721
722	for (i = 0; i < nsign_keys; i++) {
723		if (key_to_blob(sign_keys[i], &kblob, &klen) == 0)
724			goto out;
725
726		debug3("%s: signature key len %u", __func__, klen);
727		buffer_put_char(buf, KRL_SECTION_SIGNATURE);
728		buffer_put_string(buf, kblob, klen);
729
730		if (key_sign(sign_keys[i], &sblob, &slen,
731		    buffer_ptr(buf), buffer_len(buf)) == -1)
732			goto out;
733		debug3("%s: signature sig len %u", __func__, slen);
734		buffer_put_string(buf, sblob, slen);
735	}
736
737	r = 0;
738 out:
739	free(kblob);
740	free(sblob);
741	buffer_free(&sect);
742	return r;
743}
744
745static void
746format_timestamp(u_int64_t timestamp, char *ts, size_t nts)
747{
748	time_t t;
749	struct tm *tm;
750
751	t = timestamp;
752	tm = localtime(&t);
753	*ts = '\0';
754	strftime(ts, nts, "%Y%m%dT%H%M%S", tm);
755}
756
757static int
758parse_revoked_certs(Buffer *buf, struct ssh_krl *krl)
759{
760	int ret = -1, nbits;
761	u_char type;
762	u_char *blob;
763	u_int blen;
764	Buffer subsect;
765	u_int64_t serial, serial_lo, serial_hi;
766	BIGNUM *bitmap = NULL;
767	char *key_id = NULL;
768	Key *ca_key = NULL;
769
770	buffer_init(&subsect);
771
772	if ((blob = buffer_get_string_ptr_ret(buf, &blen)) == NULL ||
773	    buffer_get_string_ptr_ret(buf, NULL) == NULL) { /* reserved */
774		error("%s: buffer error", __func__);
775		goto out;
776	}
777	if ((ca_key = key_from_blob(blob, blen)) == NULL)
778		goto out;
779
780	while (buffer_len(buf) > 0) {
781		if (buffer_get_char_ret(&type, buf) != 0 ||
782		    (blob = buffer_get_string_ptr_ret(buf, &blen)) == NULL) {
783			error("%s: buffer error", __func__);
784			goto out;
785		}
786		buffer_clear(&subsect);
787		buffer_append(&subsect, blob, blen);
788		debug3("%s: subsection type 0x%02x", __func__, type);
789		/* buffer_dump(&subsect); */
790
791		switch (type) {
792		case KRL_SECTION_CERT_SERIAL_LIST:
793			while (buffer_len(&subsect) > 0) {
794				if (buffer_get_int64_ret(&serial,
795				    &subsect) != 0) {
796					error("%s: buffer error", __func__);
797					goto out;
798				}
799				if (ssh_krl_revoke_cert_by_serial(krl, ca_key,
800				    serial) != 0) {
801					error("%s: update failed", __func__);
802					goto out;
803				}
804			}
805			break;
806		case KRL_SECTION_CERT_SERIAL_RANGE:
807			if (buffer_get_int64_ret(&serial_lo, &subsect) != 0 ||
808			    buffer_get_int64_ret(&serial_hi, &subsect) != 0) {
809				error("%s: buffer error", __func__);
810				goto out;
811			}
812			if (ssh_krl_revoke_cert_by_serial_range(krl, ca_key,
813			    serial_lo, serial_hi) != 0) {
814				error("%s: update failed", __func__);
815				goto out;
816			}
817			break;
818		case KRL_SECTION_CERT_SERIAL_BITMAP:
819			if ((bitmap = BN_new()) == NULL) {
820				error("%s: BN_new", __func__);
821				goto out;
822			}
823			if (buffer_get_int64_ret(&serial_lo, &subsect) != 0 ||
824			    buffer_get_bignum2_ret(&subsect, bitmap) != 0) {
825				error("%s: buffer error", __func__);
826				goto out;
827			}
828			if ((nbits = BN_num_bits(bitmap)) < 0) {
829				error("%s: bitmap bits < 0", __func__);
830				goto out;
831			}
832			for (serial = 0; serial < (u_int)nbits; serial++) {
833				if (serial > 0 && serial_lo + serial == 0) {
834					error("%s: bitmap wraps u64", __func__);
835					goto out;
836				}
837				if (!BN_is_bit_set(bitmap, serial))
838					continue;
839				if (ssh_krl_revoke_cert_by_serial(krl, ca_key,
840				    serial_lo + serial) != 0) {
841					error("%s: update failed", __func__);
842					goto out;
843				}
844			}
845			BN_free(bitmap);
846			bitmap = NULL;
847			break;
848		case KRL_SECTION_CERT_KEY_ID:
849			while (buffer_len(&subsect) > 0) {
850				if ((key_id = buffer_get_cstring_ret(&subsect,
851				    NULL)) == NULL) {
852					error("%s: buffer error", __func__);
853					goto out;
854				}
855				if (ssh_krl_revoke_cert_by_key_id(krl, ca_key,
856				    key_id) != 0) {
857					error("%s: update failed", __func__);
858					goto out;
859				}
860				free(key_id);
861				key_id = NULL;
862			}
863			break;
864		default:
865			error("Unsupported KRL certificate section %u", type);
866			goto out;
867		}
868		if (buffer_len(&subsect) > 0) {
869			error("KRL certificate section contains unparsed data");
870			goto out;
871		}
872	}
873
874	ret = 0;
875 out:
876	if (ca_key != NULL)
877		key_free(ca_key);
878	if (bitmap != NULL)
879		BN_free(bitmap);
880	free(key_id);
881	buffer_free(&subsect);
882	return ret;
883}
884
885
886/* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. */
887int
888ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp,
889    const Key **sign_ca_keys, u_int nsign_ca_keys)
890{
891	Buffer copy, sect;
892	struct ssh_krl *krl;
893	char timestamp[64];
894	int ret = -1, r, sig_seen;
895	Key *key = NULL, **ca_used = NULL;
896	u_char type, *blob, *rdata = NULL;
897	u_int i, j, sig_off, sects_off, rlen, blen, format_version, nca_used;
898
899	nca_used = 0;
900	*krlp = NULL;
901	if (buffer_len(buf) < sizeof(KRL_MAGIC) - 1 ||
902	    memcmp(buffer_ptr(buf), KRL_MAGIC, sizeof(KRL_MAGIC) - 1) != 0) {
903		debug3("%s: not a KRL", __func__);
904		/*
905		 * Return success but a NULL *krlp here to signal that the
906		 * file might be a simple list of keys.
907		 */
908		return 0;
909	}
910
911	/* Take a copy of the KRL buffer so we can verify its signature later */
912	buffer_init(&copy);
913	buffer_append(&copy, buffer_ptr(buf), buffer_len(buf));
914
915	buffer_init(&sect);
916	buffer_consume(&copy, sizeof(KRL_MAGIC) - 1);
917
918	if ((krl = ssh_krl_init()) == NULL) {
919		error("%s: alloc failed", __func__);
920		goto out;
921	}
922
923	if (buffer_get_int_ret(&format_version, &copy) != 0) {
924		error("%s: KRL truncated", __func__);
925		goto out;
926	}
927	if (format_version != KRL_FORMAT_VERSION) {
928		error("%s: KRL unsupported format version %u",
929		    __func__, format_version);
930		goto out;
931	}
932	if (buffer_get_int64_ret(&krl->krl_version, &copy) != 0 ||
933	    buffer_get_int64_ret(&krl->generated_date, &copy) != 0 ||
934	    buffer_get_int64_ret(&krl->flags, &copy) != 0 ||
935	    buffer_get_string_ptr_ret(&copy, NULL) == NULL || /* reserved */
936	    (krl->comment = buffer_get_cstring_ret(&copy, NULL)) == NULL) {
937		error("%s: buffer error", __func__);
938		goto out;
939	}
940
941	format_timestamp(krl->generated_date, timestamp, sizeof(timestamp));
942	debug("KRL version %llu generated at %s%s%s",
943	    (long long unsigned)krl->krl_version, timestamp,
944	    *krl->comment ? ": " : "", krl->comment);
945
946	/*
947	 * 1st pass: verify signatures, if any. This is done to avoid
948	 * detailed parsing of data whose provenance is unverified.
949	 */
950	sig_seen = 0;
951	sects_off = buffer_len(buf) - buffer_len(&copy);
952	while (buffer_len(&copy) > 0) {
953		if (buffer_get_char_ret(&type, &copy) != 0 ||
954		    (blob = buffer_get_string_ptr_ret(&copy, &blen)) == NULL) {
955			error("%s: buffer error", __func__);
956			goto out;
957		}
958		debug3("%s: first pass, section 0x%02x", __func__, type);
959		if (type != KRL_SECTION_SIGNATURE) {
960			if (sig_seen) {
961				error("KRL contains non-signature section "
962				    "after signature");
963				goto out;
964			}
965			/* Not interested for now. */
966			continue;
967		}
968		sig_seen = 1;
969		/* First string component is the signing key */
970		if ((key = key_from_blob(blob, blen)) == NULL) {
971			error("%s: invalid signature key", __func__);
972			goto out;
973		}
974		sig_off = buffer_len(buf) - buffer_len(&copy);
975		/* Second string component is the signature itself */
976		if ((blob = buffer_get_string_ptr_ret(&copy, &blen)) == NULL) {
977			error("%s: buffer error", __func__);
978			goto out;
979		}
980		/* Check signature over entire KRL up to this point */
981		if (key_verify(key, blob, blen,
982		    buffer_ptr(buf), buffer_len(buf) - sig_off) != 1) {
983			error("bad signaure on KRL");
984			goto out;
985		}
986		/* Check if this key has already signed this KRL */
987		for (i = 0; i < nca_used; i++) {
988			if (key_equal(ca_used[i], key)) {
989				error("KRL signed more than once with "
990				    "the same key");
991				goto out;
992			}
993		}
994		/* Record keys used to sign the KRL */
995		ca_used = xrealloc(ca_used, nca_used + 1, sizeof(*ca_used));
996		ca_used[nca_used++] = key;
997		key = NULL;
998		break;
999	}
1000
1001	/*
1002	 * 2nd pass: parse and load the KRL, skipping the header to the point
1003	 * where the section start.
1004	 */
1005	buffer_append(&copy, (u_char*)buffer_ptr(buf) + sects_off,
1006	    buffer_len(buf) - sects_off);
1007	while (buffer_len(&copy) > 0) {
1008		if (buffer_get_char_ret(&type, &copy) != 0 ||
1009		    (blob = buffer_get_string_ptr_ret(&copy, &blen)) == NULL) {
1010			error("%s: buffer error", __func__);
1011			goto out;
1012		}
1013		debug3("%s: second pass, section 0x%02x", __func__, type);
1014		buffer_clear(&sect);
1015		buffer_append(&sect, blob, blen);
1016
1017		switch (type) {
1018		case KRL_SECTION_CERTIFICATES:
1019			if ((r = parse_revoked_certs(&sect, krl)) != 0)
1020				goto out;
1021			break;
1022		case KRL_SECTION_EXPLICIT_KEY:
1023		case KRL_SECTION_FINGERPRINT_SHA1:
1024			while (buffer_len(&sect) > 0) {
1025				if ((rdata = buffer_get_string_ret(&sect,
1026				    &rlen)) == NULL) {
1027					error("%s: buffer error", __func__);
1028					goto out;
1029				}
1030				if (type == KRL_SECTION_FINGERPRINT_SHA1 &&
1031				    rlen != 20) {
1032					error("%s: bad SHA1 length", __func__);
1033					goto out;
1034				}
1035				if (revoke_blob(
1036				    type == KRL_SECTION_EXPLICIT_KEY ?
1037				    &krl->revoked_keys : &krl->revoked_sha1s,
1038				    rdata, rlen) != 0)
1039					goto out;
1040				rdata = NULL; /* revoke_blob frees blob */
1041			}
1042			break;
1043		case KRL_SECTION_SIGNATURE:
1044			/* Handled above, but still need to stay in synch */
1045			buffer_clear(&sect);
1046			if ((blob = buffer_get_string_ptr_ret(&copy,
1047			    &blen)) == NULL) {
1048				error("%s: buffer error", __func__);
1049				goto out;
1050			}
1051			break;
1052		default:
1053			error("Unsupported KRL section %u", type);
1054			goto out;
1055		}
1056		if (buffer_len(&sect) > 0) {
1057			error("KRL section contains unparsed data");
1058			goto out;
1059		}
1060	}
1061
1062	/* Check that the key(s) used to sign the KRL weren't revoked */
1063	sig_seen = 0;
1064	for (i = 0; i < nca_used; i++) {
1065		if (ssh_krl_check_key(krl, ca_used[i]) == 0)
1066			sig_seen = 1;
1067		else {
1068			key_free(ca_used[i]);
1069			ca_used[i] = NULL;
1070		}
1071	}
1072	if (nca_used && !sig_seen) {
1073		error("All keys used to sign KRL were revoked");
1074		goto out;
1075	}
1076
1077	/* If we have CA keys, then verify that one was used to sign the KRL */
1078	if (sig_seen && nsign_ca_keys != 0) {
1079		sig_seen = 0;
1080		for (i = 0; !sig_seen && i < nsign_ca_keys; i++) {
1081			for (j = 0; j < nca_used; j++) {
1082				if (ca_used[j] == NULL)
1083					continue;
1084				if (key_equal(ca_used[j], sign_ca_keys[i])) {
1085					sig_seen = 1;
1086					break;
1087				}
1088			}
1089		}
1090		if (!sig_seen) {
1091			error("KRL not signed with any trusted key");
1092			goto out;
1093		}
1094	}
1095
1096	*krlp = krl;
1097	ret = 0;
1098 out:
1099	if (ret != 0)
1100		ssh_krl_free(krl);
1101	for (i = 0; i < nca_used; i++) {
1102		if (ca_used[i] != NULL)
1103			key_free(ca_used[i]);
1104	}
1105	free(ca_used);
1106	free(rdata);
1107	if (key != NULL)
1108		key_free(key);
1109	buffer_free(&copy);
1110	buffer_free(&sect);
1111	return ret;
1112}
1113
1114/* Checks whether a given key/cert is revoked. Does not check its CA */
1115static int
1116is_key_revoked(struct ssh_krl *krl, const Key *key)
1117{
1118	struct revoked_blob rb, *erb;
1119	struct revoked_serial rs, *ers;
1120	struct revoked_key_id rki, *erki;
1121	struct revoked_certs *rc;
1122
1123	/* Check explicitly revoked hashes first */
1124	bzero(&rb, sizeof(rb));
1125	if ((rb.blob = key_fingerprint_raw(key, SSH_FP_SHA1, &rb.len)) == NULL)
1126		return -1;
1127	erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb);
1128	free(rb.blob);
1129	if (erb != NULL) {
1130		debug("%s: revoked by key SHA1", __func__);
1131		return -1;
1132	}
1133
1134	/* Next, explicit keys */
1135	bzero(&rb, sizeof(rb));
1136	if (plain_key_blob(key, &rb.blob, &rb.len) != 0)
1137		return -1;
1138	erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb);
1139	free(rb.blob);
1140	if (erb != NULL) {
1141		debug("%s: revoked by explicit key", __func__);
1142		return -1;
1143	}
1144
1145	if (!key_is_cert(key))
1146		return 0;
1147
1148	/* Check cert revocation */
1149	if (revoked_certs_for_ca_key(krl, key->cert->signature_key,
1150	    &rc, 0) != 0)
1151		return -1;
1152	if (rc == NULL)
1153		return 0; /* No entry for this CA */
1154
1155	/* Check revocation by cert key ID */
1156	bzero(&rki, sizeof(rki));
1157	rki.key_id = key->cert->key_id;
1158	erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki);
1159	if (erki != NULL) {
1160		debug("%s: revoked by key ID", __func__);
1161		return -1;
1162	}
1163
1164	/*
1165	 * Legacy cert formats lack serial numbers. Zero serials numbers
1166	 * are ignored (it's the default when the CA doesn't specify one).
1167	 */
1168	if (key_cert_is_legacy(key) || key->cert->serial == 0)
1169		return 0;
1170
1171	bzero(&rs, sizeof(rs));
1172	rs.lo = rs.hi = key->cert->serial;
1173	ers = RB_FIND(revoked_serial_tree, &rc->revoked_serials, &rs);
1174	if (ers != NULL) {
1175		KRL_DBG(("%s: %"PRIu64" matched %"PRIu64":%"PRiu64, __func__,
1176		    key->cert->serial, ers->lo, ers->hi));
1177		debug("%s: revoked by serial", __func__);
1178		return -1;
1179	}
1180	KRL_DBG(("%s: %"PRIu64" no match", __func__, key->cert->serial));
1181
1182	return 0;
1183}
1184
1185int
1186ssh_krl_check_key(struct ssh_krl *krl, const Key *key)
1187{
1188	int r;
1189
1190	debug2("%s: checking key", __func__);
1191	if ((r = is_key_revoked(krl, key)) != 0)
1192		return r;
1193	if (key_is_cert(key)) {
1194		debug2("%s: checking CA key", __func__);
1195		if ((r = is_key_revoked(krl, key->cert->signature_key)) != 0)
1196			return r;
1197	}
1198	debug3("%s: key okay", __func__);
1199	return 0;
1200}
1201
1202/* Returns 0 on success, -1 on error or key revoked, -2 if path is not a KRL */
1203int
1204ssh_krl_file_contains_key(const char *path, const Key *key)
1205{
1206	Buffer krlbuf;
1207	struct ssh_krl *krl;
1208	int revoked, fd;
1209
1210	if (path == NULL)
1211		return 0;
1212
1213	if ((fd = open(path, O_RDONLY)) == -1) {
1214		error("open %s: %s", path, strerror(errno));
1215		error("Revoked keys file not accessible - refusing public key "
1216		    "authentication");
1217		return -1;
1218	}
1219	buffer_init(&krlbuf);
1220	if (!key_load_file(fd, path, &krlbuf)) {
1221		close(fd);
1222		buffer_free(&krlbuf);
1223		error("Revoked keys file not readable - refusing public key "
1224		    "authentication");
1225		return -1;
1226	}
1227	close(fd);
1228	if (ssh_krl_from_blob(&krlbuf, &krl, NULL, 0) != 0) {
1229		buffer_free(&krlbuf);
1230		error("Invalid KRL, refusing public key "
1231		    "authentication");
1232		return -1;
1233	}
1234	buffer_free(&krlbuf);
1235	if (krl == NULL) {
1236		debug3("%s: %s is not a KRL file", __func__, path);
1237		return -2;
1238	}
1239	debug2("%s: checking KRL %s", __func__, path);
1240	revoked = ssh_krl_check_key(krl, key) != 0;
1241	ssh_krl_free(krl);
1242	return revoked ? -1 : 0;
1243}
1244