summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--krl.c651
-rw-r--r--krl.h38
-rw-r--r--sshbuf-getput-basic.c4
3 files changed, 357 insertions, 336 deletions
diff --git a/krl.c b/krl.c
index e56f884f6..5a5cdde02 100644
--- a/krl.c
+++ b/krl.c
@@ -14,7 +14,7 @@
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */ 15 */
16 16
17/* $OpenBSD: krl.c,v 1.19 2014/11/21 01:00:38 djm Exp $ */ 17/* $OpenBSD: krl.c,v 1.20 2014/12/04 01:49:59 djm Exp $ */
18 18
19#include "includes.h" 19#include "includes.h"
20 20
@@ -30,12 +30,12 @@
30#include <time.h> 30#include <time.h>
31#include <unistd.h> 31#include <unistd.h>
32 32
33#include "buffer.h" 33#include "sshbuf.h"
34#include "key.h" 34#include "sshkey.h"
35#include "authfile.h" 35#include "authfile.h"
36#include "misc.h" 36#include "misc.h"
37#include "log.h" 37#include "log.h"
38#include "xmalloc.h" 38#include "ssherr.h"
39 39
40#include "krl.h" 40#include "krl.h"
41 41
@@ -72,7 +72,7 @@ RB_GENERATE_STATIC(revoked_key_id_tree, revoked_key_id, tree_entry, key_id_cmp);
72/* Tree of blobs (used for keys and fingerprints) */ 72/* Tree of blobs (used for keys and fingerprints) */
73struct revoked_blob { 73struct revoked_blob {
74 u_char *blob; 74 u_char *blob;
75 u_int len; 75 size_t len;
76 RB_ENTRY(revoked_blob) tree_entry; 76 RB_ENTRY(revoked_blob) tree_entry;
77}; 77};
78static int blob_cmp(struct revoked_blob *a, struct revoked_blob *b); 78static int blob_cmp(struct revoked_blob *a, struct revoked_blob *b);
@@ -81,7 +81,7 @@ RB_GENERATE_STATIC(revoked_blob_tree, revoked_blob, tree_entry, blob_cmp);
81 81
82/* Tracks revoked certs for a single CA */ 82/* Tracks revoked certs for a single CA */
83struct revoked_certs { 83struct revoked_certs {
84 Key *ca_key; 84 struct sshkey *ca_key;
85 struct revoked_serial_tree revoked_serials; 85 struct revoked_serial_tree revoked_serials;
86 struct revoked_key_id_tree revoked_key_ids; 86 struct revoked_key_id_tree revoked_key_ids;
87 TAILQ_ENTRY(revoked_certs) entry; 87 TAILQ_ENTRY(revoked_certs) entry;
@@ -155,7 +155,7 @@ revoked_certs_free(struct revoked_certs *rc)
155 free(rki); 155 free(rki);
156 } 156 }
157 if (rc->ca_key != NULL) 157 if (rc->ca_key != NULL)
158 key_free(rc->ca_key); 158 sshkey_free(rc->ca_key);
159} 159}
160 160
161void 161void
@@ -190,12 +190,13 @@ ssh_krl_set_version(struct ssh_krl *krl, u_int64_t version)
190 krl->krl_version = version; 190 krl->krl_version = version;
191} 191}
192 192
193void 193int
194ssh_krl_set_comment(struct ssh_krl *krl, const char *comment) 194ssh_krl_set_comment(struct ssh_krl *krl, const char *comment)
195{ 195{
196 free(krl->comment); 196 free(krl->comment);
197 if ((krl->comment = strdup(comment)) == NULL) 197 if ((krl->comment = strdup(comment)) == NULL)
198 fatal("%s: strdup", __func__); 198 return SSH_ERR_ALLOC_FAIL;
199 return 0;
199} 200}
200 201
201/* 202/*
@@ -203,14 +204,15 @@ ssh_krl_set_comment(struct ssh_krl *krl, const char *comment)
203 * create a new one in the tree if one did not exist already. 204 * create a new one in the tree if one did not exist already.
204 */ 205 */
205static int 206static int
206revoked_certs_for_ca_key(struct ssh_krl *krl, const Key *ca_key, 207revoked_certs_for_ca_key(struct ssh_krl *krl, const struct sshkey *ca_key,
207 struct revoked_certs **rcp, int allow_create) 208 struct revoked_certs **rcp, int allow_create)
208{ 209{
209 struct revoked_certs *rc; 210 struct revoked_certs *rc;
211 int r;
210 212
211 *rcp = NULL; 213 *rcp = NULL;
212 TAILQ_FOREACH(rc, &krl->revoked_certs, entry) { 214 TAILQ_FOREACH(rc, &krl->revoked_certs, entry) {
213 if (key_equal(rc->ca_key, ca_key)) { 215 if (sshkey_equal(rc->ca_key, ca_key)) {
214 *rcp = rc; 216 *rcp = rc;
215 return 0; 217 return 0;
216 } 218 }
@@ -219,15 +221,15 @@ revoked_certs_for_ca_key(struct ssh_krl *krl, const Key *ca_key,
219 return 0; 221 return 0;
220 /* If this CA doesn't exist in the list then add it now */ 222 /* If this CA doesn't exist in the list then add it now */
221 if ((rc = calloc(1, sizeof(*rc))) == NULL) 223 if ((rc = calloc(1, sizeof(*rc))) == NULL)
222 return -1; 224 return SSH_ERR_ALLOC_FAIL;
223 if ((rc->ca_key = key_from_private(ca_key)) == NULL) { 225 if ((r = sshkey_from_private(ca_key, &rc->ca_key)) != 0) {
224 free(rc); 226 free(rc);
225 return -1; 227 return r;
226 } 228 }
227 RB_INIT(&rc->revoked_serials); 229 RB_INIT(&rc->revoked_serials);
228 RB_INIT(&rc->revoked_key_ids); 230 RB_INIT(&rc->revoked_key_ids);
229 TAILQ_INSERT_TAIL(&krl->revoked_certs, rc, entry); 231 TAILQ_INSERT_TAIL(&krl->revoked_certs, rc, entry);
230 debug3("%s: new CA %s", __func__, key_type(ca_key)); 232 debug3("%s: new CA %s", __func__, sshkey_type(ca_key));
231 *rcp = rc; 233 *rcp = rc;
232 return 0; 234 return 0;
233} 235}
@@ -245,14 +247,14 @@ insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi)
245 if (ers == NULL || serial_cmp(ers, &rs) != 0) { 247 if (ers == NULL || serial_cmp(ers, &rs) != 0) {
246 /* No entry matches. Just insert */ 248 /* No entry matches. Just insert */
247 if ((irs = malloc(sizeof(rs))) == NULL) 249 if ((irs = malloc(sizeof(rs))) == NULL)
248 return -1; 250 return SSH_ERR_ALLOC_FAIL;
249 memcpy(irs, &rs, sizeof(*irs)); 251 memcpy(irs, &rs, sizeof(*irs));
250 ers = RB_INSERT(revoked_serial_tree, rt, irs); 252 ers = RB_INSERT(revoked_serial_tree, rt, irs);
251 if (ers != NULL) { 253 if (ers != NULL) {
252 KRL_DBG(("%s: bad: ers != NULL", __func__)); 254 KRL_DBG(("%s: bad: ers != NULL", __func__));
253 /* Shouldn't happen */ 255 /* Shouldn't happen */
254 free(irs); 256 free(irs);
255 return -1; 257 return SSH_ERR_ALLOC_FAIL;
256 } 258 }
257 ers = irs; 259 ers = irs;
258 } else { 260 } else {
@@ -305,40 +307,42 @@ insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi)
305} 307}
306 308
307int 309int
308ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, const Key *ca_key, 310ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, const struct sshkey *ca_key,
309 u_int64_t serial) 311 u_int64_t serial)
310{ 312{
311 return ssh_krl_revoke_cert_by_serial_range(krl, ca_key, serial, serial); 313 return ssh_krl_revoke_cert_by_serial_range(krl, ca_key, serial, serial);
312} 314}
313 315
314int 316int
315ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, const Key *ca_key, 317ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, const struct sshkey *ca_key,
316 u_int64_t lo, u_int64_t hi) 318 u_int64_t lo, u_int64_t hi)
317{ 319{
318 struct revoked_certs *rc; 320 struct revoked_certs *rc;
321 int r;
319 322
320 if (lo > hi || lo == 0) 323 if (lo > hi || lo == 0)
321 return -1; 324 return -1;
322 if (revoked_certs_for_ca_key(krl, ca_key, &rc, 1) != 0) 325 if ((r = revoked_certs_for_ca_key(krl, ca_key, &rc, 1)) != 0)
323 return -1; 326 return r;
324 return insert_serial_range(&rc->revoked_serials, lo, hi); 327 return insert_serial_range(&rc->revoked_serials, lo, hi);
325} 328}
326 329
327int 330int
328ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const Key *ca_key, 331ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const struct sshkey *ca_key,
329 const char *key_id) 332 const char *key_id)
330{ 333{
331 struct revoked_key_id *rki, *erki; 334 struct revoked_key_id *rki, *erki;
332 struct revoked_certs *rc; 335 struct revoked_certs *rc;
336 int r;
333 337
334 if (revoked_certs_for_ca_key(krl, ca_key, &rc, 1) != 0) 338 if ((r = revoked_certs_for_ca_key(krl, ca_key, &rc, 1)) != 0)
335 return -1; 339 return r;
336 340
337 debug3("%s: revoke %s", __func__, key_id); 341 debug3("%s: revoke %s", __func__, key_id);
338 if ((rki = calloc(1, sizeof(*rki))) == NULL || 342 if ((rki = calloc(1, sizeof(*rki))) == NULL ||
339 (rki->key_id = strdup(key_id)) == NULL) { 343 (rki->key_id = strdup(key_id)) == NULL) {
340 free(rki); 344 free(rki);
341 fatal("%s: strdup", __func__); 345 return SSH_ERR_ALLOC_FAIL;
342 } 346 }
343 erki = RB_INSERT(revoked_key_id_tree, &rc->revoked_key_ids, rki); 347 erki = RB_INSERT(revoked_key_id_tree, &rc->revoked_key_ids, rki);
344 if (erki != NULL) { 348 if (erki != NULL) {
@@ -350,21 +354,20 @@ ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const Key *ca_key,
350 354
351/* Convert "key" to a public key blob without any certificate information */ 355/* Convert "key" to a public key blob without any certificate information */
352static int 356static int
353plain_key_blob(const Key *key, u_char **blob, u_int *blen) 357plain_key_blob(const struct sshkey *key, u_char **blob, size_t *blen)
354{ 358{
355 Key *kcopy; 359 struct sshkey *kcopy;
356 int r; 360 int r;
357 361
358 if ((kcopy = key_from_private(key)) == NULL) 362 if ((r = sshkey_from_private(key, &kcopy)) != 0)
359 return -1; 363 return r;
360 if (key_is_cert(kcopy)) { 364 if (sshkey_is_cert(kcopy)) {
361 if (key_drop_cert(kcopy) != 0) { 365 if ((r = sshkey_drop_cert(kcopy)) != 0) {
362 error("%s: key_drop_cert", __func__); 366 sshkey_free(kcopy);
363 key_free(kcopy); 367 return r;
364 return -1;
365 } 368 }
366 } 369 }
367 r = key_to_blob(kcopy, blob, blen); 370 r = sshkey_to_blob(kcopy, blob, blen);
368 free(kcopy); 371 free(kcopy);
369 return r; 372 return r;
370} 373}
@@ -376,7 +379,7 @@ revoke_blob(struct revoked_blob_tree *rbt, u_char *blob, u_int len)
376 struct revoked_blob *rb, *erb; 379 struct revoked_blob *rb, *erb;
377 380
378 if ((rb = calloc(1, sizeof(*rb))) == NULL) 381 if ((rb = calloc(1, sizeof(*rb))) == NULL)
379 return -1; 382 return SSH_ERR_ALLOC_FAIL;
380 rb->blob = blob; 383 rb->blob = blob;
381 rb->len = len; 384 rb->len = len;
382 erb = RB_INSERT(revoked_blob_tree, rbt, rb); 385 erb = RB_INSERT(revoked_blob_tree, rbt, rb);
@@ -388,36 +391,38 @@ revoke_blob(struct revoked_blob_tree *rbt, u_char *blob, u_int len)
388} 391}
389 392
390int 393int
391ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const Key *key) 394ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const struct sshkey *key)
392{ 395{
393 u_char *blob; 396 u_char *blob;
394 u_int len; 397 size_t len;
398 int r;
395 399
396 debug3("%s: revoke type %s", __func__, key_type(key)); 400 debug3("%s: revoke type %s", __func__, sshkey_type(key));
397 if (plain_key_blob(key, &blob, &len) < 0) 401 if ((r = plain_key_blob(key, &blob, &len)) != 0)
398 return -1; 402 return r;
399 return revoke_blob(&krl->revoked_keys, blob, len); 403 return revoke_blob(&krl->revoked_keys, blob, len);
400} 404}
401 405
402int 406int
403ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const Key *key) 407ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const struct sshkey *key)
404{ 408{
405 u_char *blob; 409 u_char *blob;
406 u_int len; 410 size_t len;
411 int r;
407 412
408 debug3("%s: revoke type %s by sha1", __func__, key_type(key)); 413 debug3("%s: revoke type %s by sha1", __func__, sshkey_type(key));
409 if ((blob = key_fingerprint_raw(key, SSH_FP_SHA1, &len)) == NULL) 414 if ((r = sshkey_fingerprint_raw(key, SSH_FP_SHA1, &blob, &len)) != 0)
410 return -1; 415 return r;
411 return revoke_blob(&krl->revoked_sha1s, blob, len); 416 return revoke_blob(&krl->revoked_sha1s, blob, len);
412} 417}
413 418
414int 419int
415ssh_krl_revoke_key(struct ssh_krl *krl, const Key *key) 420ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key)
416{ 421{
417 if (!key_is_cert(key)) 422 if (!sshkey_is_cert(key))
418 return ssh_krl_revoke_key_sha1(krl, key); 423 return ssh_krl_revoke_key_sha1(krl, key);
419 424
420 if (key_cert_is_legacy(key) || key->cert->serial == 0) { 425 if (sshkey_cert_is_legacy(key) || key->cert->serial == 0) {
421 return ssh_krl_revoke_cert_by_key_id(krl, 426 return ssh_krl_revoke_cert_by_key_id(krl,
422 key->cert->signature_key, 427 key->cert->signature_key,
423 key->cert->key_id); 428 key->cert->key_id);
@@ -429,8 +434,8 @@ ssh_krl_revoke_key(struct ssh_krl *krl, const Key *key)
429} 434}
430 435
431/* 436/*
432 * Select a copact next section type to emit in a KRL based on the 437 * Select the most compact section type to emit next in a KRL based on
433 * current section type, the run length of contiguous revoked serial 438 * the current section type, the run length of contiguous revoked serial
434 * numbers and the gaps from the last and to the next revoked serial. 439 * 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 440 * Applies a mostly-accurate bit cost model to select the section type
436 * that will minimise the size of the resultant KRL. 441 * that will minimise the size of the resultant KRL.
@@ -513,29 +518,26 @@ choose_next_state(int current_state, u_int64_t contig, int final,
513 518
514/* Generate a KRL_SECTION_CERTIFICATES KRL section */ 519/* Generate a KRL_SECTION_CERTIFICATES KRL section */
515static int 520static int
516revoked_certs_generate(struct revoked_certs *rc, Buffer *buf) 521revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf)
517{ 522{
518 int final, force_new_sect, r = -1; 523 int final, force_new_sect, r = -1;
519 u_int64_t i, contig, gap, last = 0, bitmap_start = 0; 524 u_int64_t i, contig, gap, last = 0, bitmap_start = 0;
520 struct revoked_serial *rs, *nrs; 525 struct revoked_serial *rs, *nrs;
521 struct revoked_key_id *rki; 526 struct revoked_key_id *rki;
522 int next_state, state = 0; 527 int next_state, state = 0;
523 Buffer sect; 528 struct sshbuf *sect;
524 u_char *kblob = NULL;
525 u_int klen;
526 BIGNUM *bitmap = NULL; 529 BIGNUM *bitmap = NULL;
527 530
528 /* Prepare CA scope key blob if we have one supplied */ 531 if ((sect = sshbuf_new()) == NULL)
529 if (key_to_blob(rc->ca_key, &kblob, &klen) == 0) 532 return SSH_ERR_ALLOC_FAIL;
530 return -1;
531
532 buffer_init(&sect);
533 533
534 /* Store the header */ 534 /* Store the header: CA scope key, reserved */
535 buffer_put_string(buf, kblob, klen); 535 if ((r = sshkey_to_blob_buf(rc->ca_key, sect)) != 0 ||
536 buffer_put_string(buf, NULL, 0); /* Reserved */ 536 (r = sshbuf_put_stringb(buf, sect)) != 0 ||
537 (r = sshbuf_put_string(buf, NULL, 0)) != 0)
538 goto out;
537 539
538 free(kblob); 540 sshbuf_reset(sect);
539 541
540 /* Store the revoked serials. */ 542 /* Store the revoked serials. */
541 for (rs = RB_MIN(revoked_serial_tree, &rc->revoked_serials); 543 for (rs = RB_MIN(revoked_serial_tree, &rc->revoked_serials);
@@ -567,31 +569,36 @@ revoked_certs_generate(struct revoked_certs *rc, Buffer *buf)
567 case KRL_SECTION_CERT_SERIAL_RANGE: 569 case KRL_SECTION_CERT_SERIAL_RANGE:
568 break; 570 break;
569 case KRL_SECTION_CERT_SERIAL_BITMAP: 571 case KRL_SECTION_CERT_SERIAL_BITMAP:
570 buffer_put_bignum2(&sect, bitmap); 572 if ((r = sshbuf_put_bignum2(sect, bitmap)) != 0)
573 goto out;
571 BN_free(bitmap); 574 BN_free(bitmap);
572 bitmap = NULL; 575 bitmap = NULL;
573 break; 576 break;
574 } 577 }
575 buffer_put_char(buf, state); 578 if ((r = sshbuf_put_u8(buf, state)) != 0 ||
576 buffer_put_string(buf, 579 (r = sshbuf_put_stringb(buf, sect)) != 0)
577 buffer_ptr(&sect), buffer_len(&sect)); 580 goto out;
578 buffer_clear(&sect); 581 sshbuf_reset(sect);
579 } 582 }
580 583
581 /* If we are starting a new section then prepare it now */ 584 /* If we are starting a new section then prepare it now */
582 if (next_state != state || force_new_sect) { 585 if (next_state != state || force_new_sect) {
583 debug3("%s: start state 0x%02x", __func__, next_state); 586 debug3("%s: start state 0x%02x", __func__, next_state);
584 state = next_state; 587 state = next_state;
585 buffer_clear(&sect); 588 sshbuf_reset(sect);
586 switch (state) { 589 switch (state) {
587 case KRL_SECTION_CERT_SERIAL_LIST: 590 case KRL_SECTION_CERT_SERIAL_LIST:
588 case KRL_SECTION_CERT_SERIAL_RANGE: 591 case KRL_SECTION_CERT_SERIAL_RANGE:
589 break; 592 break;
590 case KRL_SECTION_CERT_SERIAL_BITMAP: 593 case KRL_SECTION_CERT_SERIAL_BITMAP:
591 if ((bitmap = BN_new()) == NULL) 594 if ((bitmap = BN_new()) == NULL) {
595 r = SSH_ERR_ALLOC_FAIL;
592 goto out; 596 goto out;
597 }
593 bitmap_start = rs->lo; 598 bitmap_start = rs->lo;
594 buffer_put_int64(&sect, bitmap_start); 599 if ((r = sshbuf_put_u64(sect,
600 bitmap_start)) != 0)
601 goto out;
595 break; 602 break;
596 } 603 }
597 } 604 }
@@ -599,12 +606,15 @@ revoked_certs_generate(struct revoked_certs *rc, Buffer *buf)
599 /* Perform section-specific processing */ 606 /* Perform section-specific processing */
600 switch (state) { 607 switch (state) {
601 case KRL_SECTION_CERT_SERIAL_LIST: 608 case KRL_SECTION_CERT_SERIAL_LIST:
602 for (i = 0; i < contig; i++) 609 for (i = 0; i < contig; i++) {
603 buffer_put_int64(&sect, rs->lo + i); 610 if ((r = sshbuf_put_u64(sect, rs->lo + i)) != 0)
611 goto out;
612 }
604 break; 613 break;
605 case KRL_SECTION_CERT_SERIAL_RANGE: 614 case KRL_SECTION_CERT_SERIAL_RANGE:
606 buffer_put_int64(&sect, rs->lo); 615 if ((r = sshbuf_put_u64(sect, rs->lo)) != 0 ||
607 buffer_put_int64(&sect, rs->hi); 616 (r = sshbuf_put_u64(sect, rs->hi)) != 0)
617 goto out;
608 break; 618 break;
609 case KRL_SECTION_CERT_SERIAL_BITMAP: 619 case KRL_SECTION_CERT_SERIAL_BITMAP:
610 if (rs->lo - bitmap_start > INT_MAX) { 620 if (rs->lo - bitmap_start > INT_MAX) {
@@ -613,8 +623,10 @@ revoked_certs_generate(struct revoked_certs *rc, Buffer *buf)
613 } 623 }
614 for (i = 0; i < contig; i++) { 624 for (i = 0; i < contig; i++) {
615 if (BN_set_bit(bitmap, 625 if (BN_set_bit(bitmap,
616 rs->lo + i - bitmap_start) != 1) 626 rs->lo + i - bitmap_start) != 1) {
627 r = SSH_ERR_ALLOC_FAIL;
617 goto out; 628 goto out;
629 }
618 } 630 }
619 break; 631 break;
620 } 632 }
@@ -629,113 +641,122 @@ revoked_certs_generate(struct revoked_certs *rc, Buffer *buf)
629 case KRL_SECTION_CERT_SERIAL_RANGE: 641 case KRL_SECTION_CERT_SERIAL_RANGE:
630 break; 642 break;
631 case KRL_SECTION_CERT_SERIAL_BITMAP: 643 case KRL_SECTION_CERT_SERIAL_BITMAP:
632 buffer_put_bignum2(&sect, bitmap); 644 if ((r = sshbuf_put_bignum2(sect, bitmap)) != 0)
645 goto out;
633 BN_free(bitmap); 646 BN_free(bitmap);
634 bitmap = NULL; 647 bitmap = NULL;
635 break; 648 break;
636 } 649 }
637 buffer_put_char(buf, state); 650 if ((r = sshbuf_put_u8(buf, state)) != 0 ||
638 buffer_put_string(buf, 651 (r = sshbuf_put_stringb(buf, sect)) != 0)
639 buffer_ptr(&sect), buffer_len(&sect)); 652 goto out;
640 } 653 }
641 debug3("%s: serial done ", __func__); 654 debug3("%s: serial done ", __func__);
642 655
643 /* Now output a section for any revocations by key ID */ 656 /* Now output a section for any revocations by key ID */
644 buffer_clear(&sect); 657 sshbuf_reset(sect);
645 RB_FOREACH(rki, revoked_key_id_tree, &rc->revoked_key_ids) { 658 RB_FOREACH(rki, revoked_key_id_tree, &rc->revoked_key_ids) {
646 debug3("%s: key ID %s", __func__, rki->key_id); 659 debug3("%s: key ID %s", __func__, rki->key_id);
647 buffer_put_cstring(&sect, rki->key_id); 660 if ((r = sshbuf_put_cstring(sect, rki->key_id)) != 0)
661 goto out;
648 } 662 }
649 if (buffer_len(&sect) != 0) { 663 if (sshbuf_len(sect) != 0) {
650 buffer_put_char(buf, KRL_SECTION_CERT_KEY_ID); 664 if ((r = sshbuf_put_u8(buf, KRL_SECTION_CERT_KEY_ID)) != 0 ||
651 buffer_put_string(buf, buffer_ptr(&sect), 665 (r = sshbuf_put_stringb(buf, sect)) != 0)
652 buffer_len(&sect)); 666 goto out;
653 } 667 }
654 r = 0; 668 r = 0;
655 out: 669 out:
656 if (bitmap != NULL) 670 if (bitmap != NULL)
657 BN_free(bitmap); 671 BN_free(bitmap);
658 buffer_free(&sect); 672 sshbuf_free(sect);
659 return r; 673 return r;
660} 674}
661 675
662int 676int
663ssh_krl_to_blob(struct ssh_krl *krl, Buffer *buf, const Key **sign_keys, 677ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
664 u_int nsign_keys) 678 const struct sshkey **sign_keys, u_int nsign_keys)
665{ 679{
666 int r = -1; 680 int r = -1;
667 struct revoked_certs *rc; 681 struct revoked_certs *rc;
668 struct revoked_blob *rb; 682 struct revoked_blob *rb;
669 Buffer sect; 683 struct sshbuf *sect;
670 u_char *kblob = NULL, *sblob = NULL; 684 u_char *sblob = NULL;
671 u_int klen, slen, i; 685 size_t slen, i;
672 686
673 if (krl->generated_date == 0) 687 if (krl->generated_date == 0)
674 krl->generated_date = time(NULL); 688 krl->generated_date = time(NULL);
675 689
676 buffer_init(&sect); 690 if ((sect = sshbuf_new()) == NULL)
691 return SSH_ERR_ALLOC_FAIL;
677 692
678 /* Store the header */ 693 /* Store the header */
679 buffer_append(buf, KRL_MAGIC, sizeof(KRL_MAGIC) - 1); 694 if ((r = sshbuf_put(buf, KRL_MAGIC, sizeof(KRL_MAGIC) - 1)) != 0 ||
680 buffer_put_int(buf, KRL_FORMAT_VERSION); 695 (r = sshbuf_put_u32(buf, KRL_FORMAT_VERSION)) != 0 ||
681 buffer_put_int64(buf, krl->krl_version); 696 (r = sshbuf_put_u64(buf, krl->krl_version)) != 0 ||
682 buffer_put_int64(buf, krl->generated_date); 697 (r = sshbuf_put_u64(buf, krl->generated_date) != 0) ||
683 buffer_put_int64(buf, krl->flags); 698 (r = sshbuf_put_u64(buf, krl->flags)) != 0 ||
684 buffer_put_string(buf, NULL, 0); 699 (r = sshbuf_put_string(buf, NULL, 0)) != 0 ||
685 buffer_put_cstring(buf, krl->comment ? krl->comment : ""); 700 (r = sshbuf_put_cstring(buf, krl->comment)) != 0)
701 goto out;
686 702
687 /* Store sections for revoked certificates */ 703 /* Store sections for revoked certificates */
688 TAILQ_FOREACH(rc, &krl->revoked_certs, entry) { 704 TAILQ_FOREACH(rc, &krl->revoked_certs, entry) {
689 buffer_clear(&sect); 705 sshbuf_reset(sect);
690 if (revoked_certs_generate(rc, &sect) != 0) 706 if ((r = revoked_certs_generate(rc, sect)) != 0)
707 goto out;
708 if ((r = sshbuf_put_u8(buf, KRL_SECTION_CERTIFICATES)) != 0 ||
709 (r = sshbuf_put_stringb(buf, sect)) != 0)
691 goto out; 710 goto out;
692 buffer_put_char(buf, KRL_SECTION_CERTIFICATES);
693 buffer_put_string(buf, buffer_ptr(&sect),
694 buffer_len(&sect));
695 } 711 }
696 712
697 /* Finally, output sections for revocations by public key/hash */ 713 /* Finally, output sections for revocations by public key/hash */
698 buffer_clear(&sect); 714 sshbuf_reset(sect);
699 RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) { 715 RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) {
700 debug3("%s: key len %u ", __func__, rb->len); 716 debug3("%s: key len %zu ", __func__, rb->len);
701 buffer_put_string(&sect, rb->blob, rb->len); 717 if ((sshbuf_put_string(sect, rb->blob, rb->len)) != 0)
718 goto out;
702 } 719 }
703 if (buffer_len(&sect) != 0) { 720 if (sshbuf_len(sect) != 0) {
704 buffer_put_char(buf, KRL_SECTION_EXPLICIT_KEY); 721 if ((r = sshbuf_put_u8(buf, KRL_SECTION_EXPLICIT_KEY)) != 0 ||
705 buffer_put_string(buf, buffer_ptr(&sect), 722 (r = sshbuf_put_stringb(buf, sect)) != 0)
706 buffer_len(&sect)); 723 goto out;
707 } 724 }
708 buffer_clear(&sect); 725 sshbuf_reset(sect);
709 RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha1s) { 726 RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha1s) {
710 debug3("%s: hash len %u ", __func__, rb->len); 727 debug3("%s: hash len %zu ", __func__, rb->len);
711 buffer_put_string(&sect, rb->blob, rb->len); 728 if ((sshbuf_put_string(sect, rb->blob, rb->len)) != 0)
729 goto out;
712 } 730 }
713 if (buffer_len(&sect) != 0) { 731 if (sshbuf_len(sect) != 0) {
714 buffer_put_char(buf, KRL_SECTION_FINGERPRINT_SHA1); 732 if ((r = sshbuf_put_u8(buf,
715 buffer_put_string(buf, buffer_ptr(&sect), 733 KRL_SECTION_FINGERPRINT_SHA1)) != 0 ||
716 buffer_len(&sect)); 734 (r = sshbuf_put_stringb(buf, sect)) != 0)
735 goto out;
717 } 736 }
718 737
719 for (i = 0; i < nsign_keys; i++) { 738 for (i = 0; i < nsign_keys; i++) {
720 if (key_to_blob(sign_keys[i], &kblob, &klen) == 0) 739 sshbuf_reset(sect);
740 if ((r = sshkey_to_blob_buf(sign_keys[i], sect)) != 0)
721 goto out; 741 goto out;
722 742
723 debug3("%s: signature key len %u", __func__, klen); 743 debug3("%s: signature key len %zu", __func__, sshbuf_len(sect));
724 buffer_put_char(buf, KRL_SECTION_SIGNATURE); 744 if ((r = sshbuf_put_u8(buf, KRL_SECTION_SIGNATURE)) != 0 ||
725 buffer_put_string(buf, kblob, klen); 745 (r = sshbuf_put_stringb(buf, sect)) != 0)
746 goto out;
726 747
727 if (key_sign(sign_keys[i], &sblob, &slen, 748 if ((r = sshkey_sign(sign_keys[i], &sblob, &slen,
728 buffer_ptr(buf), buffer_len(buf)) == -1) 749 sshbuf_ptr(buf), sshbuf_len(buf), 0)) == -1)
750 goto out;
751 debug3("%s: signature sig len %zu", __func__, slen);
752 if ((r = sshbuf_put_string(buf, sblob, slen)) != 0)
729 goto out; 753 goto out;
730 debug3("%s: signature sig len %u", __func__, slen);
731 buffer_put_string(buf, sblob, slen);
732 } 754 }
733 755
734 r = 0; 756 r = 0;
735 out: 757 out:
736 free(kblob);
737 free(sblob); 758 free(sblob);
738 buffer_free(&sect); 759 sshbuf_free(sect);
739 return r; 760 return r;
740} 761}
741 762
@@ -756,189 +777,167 @@ format_timestamp(u_int64_t timestamp, char *ts, size_t nts)
756} 777}
757 778
758static int 779static int
759parse_revoked_certs(Buffer *buf, struct ssh_krl *krl) 780parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl)
760{ 781{
761 int ret = -1, nbits; 782 int r = -1, nbits;
762 u_char type; 783 u_char type;
763 const u_char *blob; 784 const u_char *blob;
764 u_int blen; 785 size_t blen;
765 Buffer subsect; 786 struct sshbuf *subsect = NULL;
766 u_int64_t serial, serial_lo, serial_hi; 787 u_int64_t serial, serial_lo, serial_hi;
767 BIGNUM *bitmap = NULL; 788 BIGNUM *bitmap = NULL;
768 char *key_id = NULL; 789 char *key_id = NULL;
769 Key *ca_key = NULL; 790 struct sshkey *ca_key = NULL;
770 791
771 buffer_init(&subsect); 792 if ((subsect = sshbuf_new()) == NULL)
793 return SSH_ERR_ALLOC_FAIL;
772 794
773 if ((blob = buffer_get_string_ptr_ret(buf, &blen)) == NULL || 795 /* Header: key, reserved */
774 buffer_get_string_ptr_ret(buf, NULL) == NULL) { /* reserved */ 796 if ((r = sshbuf_get_string_direct(buf, &blob, &blen)) != 0 ||
775 error("%s: buffer error", __func__); 797 (r = sshbuf_skip_string(buf)) != 0)
776 goto out; 798 goto out;
777 } 799 if ((r = sshkey_from_blob(blob, blen, &ca_key)) != 0)
778 if ((ca_key = key_from_blob(blob, blen)) == NULL)
779 goto out; 800 goto out;
780 801
781 while (buffer_len(buf) > 0) { 802 while (sshbuf_len(buf) > 0) {
782 if (buffer_get_char_ret(&type, buf) != 0 || 803 if (subsect != NULL) {
783 (blob = buffer_get_string_ptr_ret(buf, &blen)) == NULL) { 804 sshbuf_free(subsect);
784 error("%s: buffer error", __func__); 805 subsect = NULL;
785 goto out;
786 } 806 }
787 buffer_clear(&subsect); 807 if ((r = sshbuf_get_u8(buf, &type)) != 0 ||
788 buffer_append(&subsect, blob, blen); 808 (r = sshbuf_froms(buf, &subsect)) != 0)
809 goto out;
789 debug3("%s: subsection type 0x%02x", __func__, type); 810 debug3("%s: subsection type 0x%02x", __func__, type);
790 /* buffer_dump(&subsect); */
791 811
792 switch (type) { 812 switch (type) {
793 case KRL_SECTION_CERT_SERIAL_LIST: 813 case KRL_SECTION_CERT_SERIAL_LIST:
794 while (buffer_len(&subsect) > 0) { 814 while (sshbuf_len(subsect) > 0) {
795 if (buffer_get_int64_ret(&serial, 815 if ((r = sshbuf_get_u64(subsect, &serial)) != 0)
796 &subsect) != 0) {
797 error("%s: buffer error", __func__);
798 goto out; 816 goto out;
799 } 817 if ((r = ssh_krl_revoke_cert_by_serial(krl,
800 if (ssh_krl_revoke_cert_by_serial(krl, ca_key, 818 ca_key, serial)) != 0)
801 serial) != 0) {
802 error("%s: update failed", __func__);
803 goto out; 819 goto out;
804 }
805 } 820 }
806 break; 821 break;
807 case KRL_SECTION_CERT_SERIAL_RANGE: 822 case KRL_SECTION_CERT_SERIAL_RANGE:
808 if (buffer_get_int64_ret(&serial_lo, &subsect) != 0 || 823 if ((r = sshbuf_get_u64(subsect, &serial_lo)) != 0 ||
809 buffer_get_int64_ret(&serial_hi, &subsect) != 0) { 824 (r = sshbuf_get_u64(subsect, &serial_hi)) != 0)
810 error("%s: buffer error", __func__);
811 goto out; 825 goto out;
812 } 826 if ((r = ssh_krl_revoke_cert_by_serial_range(krl,
813 if (ssh_krl_revoke_cert_by_serial_range(krl, ca_key, 827 ca_key, serial_lo, serial_hi)) != 0)
814 serial_lo, serial_hi) != 0) {
815 error("%s: update failed", __func__);
816 goto out; 828 goto out;
817 }
818 break; 829 break;
819 case KRL_SECTION_CERT_SERIAL_BITMAP: 830 case KRL_SECTION_CERT_SERIAL_BITMAP:
820 if ((bitmap = BN_new()) == NULL) { 831 if ((bitmap = BN_new()) == NULL) {
821 error("%s: BN_new", __func__); 832 r = SSH_ERR_ALLOC_FAIL;
822 goto out; 833 goto out;
823 } 834 }
824 if (buffer_get_int64_ret(&serial_lo, &subsect) != 0 || 835 if ((r = sshbuf_get_u64(subsect, &serial_lo)) != 0 ||
825 buffer_get_bignum2_ret(&subsect, bitmap) != 0) { 836 (r = sshbuf_get_bignum2(subsect, bitmap)) != 0)
826 error("%s: buffer error", __func__);
827 goto out; 837 goto out;
828 }
829 if ((nbits = BN_num_bits(bitmap)) < 0) { 838 if ((nbits = BN_num_bits(bitmap)) < 0) {
830 error("%s: bitmap bits < 0", __func__); 839 error("%s: bitmap bits < 0", __func__);
840 r = SSH_ERR_INVALID_FORMAT;
831 goto out; 841 goto out;
832 } 842 }
833 for (serial = 0; serial < (u_int)nbits; serial++) { 843 for (serial = 0; serial < (u_int)nbits; serial++) {
834 if (serial > 0 && serial_lo + serial == 0) { 844 if (serial > 0 && serial_lo + serial == 0) {
835 error("%s: bitmap wraps u64", __func__); 845 error("%s: bitmap wraps u64", __func__);
846 r = SSH_ERR_INVALID_FORMAT;
836 goto out; 847 goto out;
837 } 848 }
838 if (!BN_is_bit_set(bitmap, serial)) 849 if (!BN_is_bit_set(bitmap, serial))
839 continue; 850 continue;
840 if (ssh_krl_revoke_cert_by_serial(krl, ca_key, 851 if ((r = ssh_krl_revoke_cert_by_serial(krl,
841 serial_lo + serial) != 0) { 852 ca_key, serial_lo + serial)) != 0)
842 error("%s: update failed", __func__);
843 goto out; 853 goto out;
844 }
845 } 854 }
846 BN_free(bitmap); 855 BN_free(bitmap);
847 bitmap = NULL; 856 bitmap = NULL;
848 break; 857 break;
849 case KRL_SECTION_CERT_KEY_ID: 858 case KRL_SECTION_CERT_KEY_ID:
850 while (buffer_len(&subsect) > 0) { 859 while (sshbuf_len(subsect) > 0) {
851 if ((key_id = buffer_get_cstring_ret(&subsect, 860 if ((r = sshbuf_get_cstring(subsect,
852 NULL)) == NULL) { 861 &key_id, NULL)) != 0)
853 error("%s: buffer error", __func__);
854 goto out; 862 goto out;
855 } 863 if ((r = ssh_krl_revoke_cert_by_key_id(krl,
856 if (ssh_krl_revoke_cert_by_key_id(krl, ca_key, 864 ca_key, key_id)) != 0)
857 key_id) != 0) {
858 error("%s: update failed", __func__);
859 goto out; 865 goto out;
860 }
861 free(key_id); 866 free(key_id);
862 key_id = NULL; 867 key_id = NULL;
863 } 868 }
864 break; 869 break;
865 default: 870 default:
866 error("Unsupported KRL certificate section %u", type); 871 error("Unsupported KRL certificate section %u", type);
872 r = SSH_ERR_INVALID_FORMAT;
867 goto out; 873 goto out;
868 } 874 }
869 if (buffer_len(&subsect) > 0) { 875 if (sshbuf_len(subsect) > 0) {
870 error("KRL certificate section contains unparsed data"); 876 error("KRL certificate section contains unparsed data");
877 r = SSH_ERR_INVALID_FORMAT;
871 goto out; 878 goto out;
872 } 879 }
873 } 880 }
874 881
875 ret = 0; 882 r = 0;
876 out: 883 out:
877 if (ca_key != NULL)
878 key_free(ca_key);
879 if (bitmap != NULL) 884 if (bitmap != NULL)
880 BN_free(bitmap); 885 BN_free(bitmap);
881 free(key_id); 886 free(key_id);
882 buffer_free(&subsect); 887 sshkey_free(ca_key);
883 return ret; 888 sshbuf_free(subsect);
889 return r;
884} 890}
885 891
886 892
887/* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. */ 893/* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. */
888int 894int
889ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp, 895ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
890 const Key **sign_ca_keys, u_int nsign_ca_keys) 896 const struct sshkey **sign_ca_keys, u_int nsign_ca_keys)
891{ 897{
892 Buffer copy, sect; 898 struct sshbuf *copy = NULL, *sect = NULL;
893 struct ssh_krl *krl; 899 struct ssh_krl *krl = NULL;
894 char timestamp[64]; 900 char timestamp[64];
895 int ret = -1, r, sig_seen; 901 int r = -1, sig_seen;
896 Key *key = NULL, **ca_used = NULL; 902 struct sshkey *key = NULL, **ca_used = NULL, **tmp_ca_used;
897 u_char type, *rdata = NULL; 903 u_char type, *rdata = NULL;
898 const u_char *blob; 904 const u_char *blob;
899 u_int i, j, sig_off, sects_off, rlen, blen, format_version, nca_used; 905 size_t i, j, sig_off, sects_off, rlen, blen, nca_used;
906 u_int format_version;
900 907
901 nca_used = 0; 908 nca_used = 0;
902 *krlp = NULL; 909 *krlp = NULL;
903 if (buffer_len(buf) < sizeof(KRL_MAGIC) - 1 || 910 if (sshbuf_len(buf) < sizeof(KRL_MAGIC) - 1 ||
904 memcmp(buffer_ptr(buf), KRL_MAGIC, sizeof(KRL_MAGIC) - 1) != 0) { 911 memcmp(sshbuf_ptr(buf), KRL_MAGIC, sizeof(KRL_MAGIC) - 1) != 0) {
905 debug3("%s: not a KRL", __func__); 912 debug3("%s: not a KRL", __func__);
906 /* 913 return SSH_ERR_KRL_BAD_MAGIC;
907 * Return success but a NULL *krlp here to signal that the
908 * file might be a simple list of keys.
909 */
910 return 0;
911 } 914 }
912 915
913 /* Take a copy of the KRL buffer so we can verify its signature later */ 916 /* Take a copy of the KRL buffer so we can verify its signature later */
914 buffer_init(&copy); 917 if ((copy = sshbuf_fromb(buf)) == NULL) {
915 buffer_append(&copy, buffer_ptr(buf), buffer_len(buf)); 918 r = SSH_ERR_ALLOC_FAIL;
916 919 goto out;
917 buffer_init(&sect); 920 }
918 buffer_consume(&copy, sizeof(KRL_MAGIC) - 1); 921 if ((r = sshbuf_consume(copy, sizeof(KRL_MAGIC) - 1)) != 0)
922 goto out;
919 923
920 if ((krl = ssh_krl_init()) == NULL) { 924 if ((krl = ssh_krl_init()) == NULL) {
921 error("%s: alloc failed", __func__); 925 error("%s: alloc failed", __func__);
922 goto out; 926 goto out;
923 } 927 }
924 928
925 if (buffer_get_int_ret(&format_version, &copy) != 0) { 929 if ((r = sshbuf_get_u32(copy, &format_version)) != 0)
926 error("%s: KRL truncated", __func__);
927 goto out; 930 goto out;
928 }
929 if (format_version != KRL_FORMAT_VERSION) { 931 if (format_version != KRL_FORMAT_VERSION) {
930 error("%s: KRL unsupported format version %u", 932 r = SSH_ERR_INVALID_FORMAT;
931 __func__, format_version);
932 goto out; 933 goto out;
933 } 934 }
934 if (buffer_get_int64_ret(&krl->krl_version, &copy) != 0 || 935 if ((r = sshbuf_get_u64(copy, &krl->krl_version)) != 0 ||
935 buffer_get_int64_ret(&krl->generated_date, &copy) != 0 || 936 (r = sshbuf_get_u64(copy, &krl->generated_date)) != 0 ||
936 buffer_get_int64_ret(&krl->flags, &copy) != 0 || 937 (r = sshbuf_get_u64(copy, &krl->flags)) != 0 ||
937 buffer_get_string_ptr_ret(&copy, NULL) == NULL || /* reserved */ 938 (r = sshbuf_skip_string(copy)) != 0 ||
938 (krl->comment = buffer_get_cstring_ret(&copy, NULL)) == NULL) { 939 (r = sshbuf_get_cstring(copy, &krl->comment, NULL)) != 0)
939 error("%s: buffer error", __func__);
940 goto out; 940 goto out;
941 }
942 941
943 format_timestamp(krl->generated_date, timestamp, sizeof(timestamp)); 942 format_timestamp(krl->generated_date, timestamp, sizeof(timestamp));
944 debug("KRL version %llu generated at %s%s%s", 943 debug("KRL version %llu generated at %s%s%s",
@@ -950,16 +949,20 @@ ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp,
950 * detailed parsing of data whose provenance is unverified. 949 * detailed parsing of data whose provenance is unverified.
951 */ 950 */
952 sig_seen = 0; 951 sig_seen = 0;
953 sects_off = buffer_len(buf) - buffer_len(&copy); 952 if (sshbuf_len(buf) < sshbuf_len(copy)) {
954 while (buffer_len(&copy) > 0) { 953 /* Shouldn't happen */
955 if (buffer_get_char_ret(&type, &copy) != 0 || 954 r = SSH_ERR_INTERNAL_ERROR;
956 (blob = buffer_get_string_ptr_ret(&copy, &blen)) == NULL) { 955 goto out;
957 error("%s: buffer error", __func__); 956 }
957 sects_off = sshbuf_len(buf) - sshbuf_len(copy);
958 while (sshbuf_len(copy) > 0) {
959 if ((r = sshbuf_get_u8(copy, &type)) != 0 ||
960 (r = sshbuf_get_string_direct(copy, &blob, &blen)) != 0)
958 goto out; 961 goto out;
959 }
960 debug3("%s: first pass, section 0x%02x", __func__, type); 962 debug3("%s: first pass, section 0x%02x", __func__, type);
961 if (type != KRL_SECTION_SIGNATURE) { 963 if (type != KRL_SECTION_SIGNATURE) {
962 if (sig_seen) { 964 if (sig_seen) {
965 r = SSH_ERR_INVALID_FORMAT;
963 error("KRL contains non-signature section " 966 error("KRL contains non-signature section "
964 "after signature"); 967 "after signature");
965 goto out; 968 goto out;
@@ -969,94 +972,118 @@ ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp,
969 } 972 }
970 sig_seen = 1; 973 sig_seen = 1;
971 /* First string component is the signing key */ 974 /* First string component is the signing key */
972 if ((key = key_from_blob(blob, blen)) == NULL) { 975 if ((r = sshkey_from_blob(blob, blen, &key)) != 0) {
976 r = SSH_ERR_INVALID_FORMAT;
973 error("%s: invalid signature key", __func__); 977 error("%s: invalid signature key", __func__);
974 goto out; 978 goto out;
975 } 979 }
976 sig_off = buffer_len(buf) - buffer_len(&copy); 980 if (sshbuf_len(buf) < sshbuf_len(copy)) {
981 /* Shouldn't happen */
982 r = SSH_ERR_INTERNAL_ERROR;
983 goto out;
984 }
985 sig_off = sshbuf_len(buf) - sshbuf_len(copy);
977 /* Second string component is the signature itself */ 986 /* Second string component is the signature itself */
978 if ((blob = buffer_get_string_ptr_ret(&copy, &blen)) == NULL) { 987 if ((r = sshbuf_get_string_direct(copy, &blob, &blen)) != 0) {
979 error("%s: buffer error", __func__); 988 r = SSH_ERR_INVALID_FORMAT;
980 goto out; 989 goto out;
981 } 990 }
982 /* Check signature over entire KRL up to this point */ 991 /* Check signature over entire KRL up to this point */
983 if (key_verify(key, blob, blen, 992 if ((r = sshkey_verify(key, blob, blen,
984 buffer_ptr(buf), buffer_len(buf) - sig_off) != 1) { 993 sshbuf_ptr(buf), sshbuf_len(buf) - sig_off, 0)) != 0) {
985 error("bad signaure on KRL"); 994 error("bad signaure on KRL");
986 goto out; 995 goto out;
987 } 996 }
988 /* Check if this key has already signed this KRL */ 997 /* Check if this key has already signed this KRL */
989 for (i = 0; i < nca_used; i++) { 998 for (i = 0; i < nca_used; i++) {
990 if (key_equal(ca_used[i], key)) { 999 if (sshkey_equal(ca_used[i], key)) {
991 error("KRL signed more than once with " 1000 error("KRL signed more than once with "
992 "the same key"); 1001 "the same key");
1002 r = SSH_ERR_SIGNATURE_INVALID;
993 goto out; 1003 goto out;
994 } 1004 }
995 } 1005 }
996 /* Record keys used to sign the KRL */ 1006 /* Record keys used to sign the KRL */
997 ca_used = xrealloc(ca_used, nca_used + 1, sizeof(*ca_used)); 1007 tmp_ca_used = reallocarray(ca_used, nca_used + 1,
1008 sizeof(*ca_used));
1009 if (tmp_ca_used == NULL) {
1010 r = SSH_ERR_ALLOC_FAIL;
1011 goto out;
1012 }
1013 ca_used = tmp_ca_used;
998 ca_used[nca_used++] = key; 1014 ca_used[nca_used++] = key;
999 key = NULL; 1015 key = NULL;
1000 break; 1016 break;
1001 } 1017 }
1002 1018
1019 if (sshbuf_len(copy) != 0) {
1020 /* Shouldn't happen */
1021 r = SSH_ERR_INTERNAL_ERROR;
1022 goto out;
1023 }
1024
1003 /* 1025 /*
1004 * 2nd pass: parse and load the KRL, skipping the header to the point 1026 * 2nd pass: parse and load the KRL, skipping the header to the point
1005 * where the section start. 1027 * where the section start.
1006 */ 1028 */
1007 buffer_append(&copy, (u_char*)buffer_ptr(buf) + sects_off, 1029 sshbuf_free(copy);
1008 buffer_len(buf) - sects_off); 1030 if ((copy = sshbuf_fromb(buf)) == NULL) {
1009 while (buffer_len(&copy) > 0) { 1031 r = SSH_ERR_ALLOC_FAIL;
1010 if (buffer_get_char_ret(&type, &copy) != 0 || 1032 goto out;
1011 (blob = buffer_get_string_ptr_ret(&copy, &blen)) == NULL) { 1033 }
1012 error("%s: buffer error", __func__); 1034 if ((r = sshbuf_consume(copy, sects_off)) != 0)
1035 goto out;
1036 while (sshbuf_len(copy) > 0) {
1037 if (sect != NULL) {
1038 sshbuf_free(sect);
1039 sect = NULL;
1040 }
1041 if ((r = sshbuf_get_u8(copy, &type)) != 0 ||
1042 (r = sshbuf_froms(copy, &sect)) != 0) {
1013 goto out; 1043 goto out;
1014 } 1044 }
1015 debug3("%s: second pass, section 0x%02x", __func__, type); 1045 debug3("%s: second pass, section 0x%02x", __func__, type);
1016 buffer_clear(&sect);
1017 buffer_append(&sect, blob, blen);
1018 1046
1019 switch (type) { 1047 switch (type) {
1020 case KRL_SECTION_CERTIFICATES: 1048 case KRL_SECTION_CERTIFICATES:
1021 if ((r = parse_revoked_certs(&sect, krl)) != 0) 1049 if ((r = parse_revoked_certs(sect, krl)) != 0)
1022 goto out; 1050 goto out;
1023 break; 1051 break;
1024 case KRL_SECTION_EXPLICIT_KEY: 1052 case KRL_SECTION_EXPLICIT_KEY:
1025 case KRL_SECTION_FINGERPRINT_SHA1: 1053 case KRL_SECTION_FINGERPRINT_SHA1:
1026 while (buffer_len(&sect) > 0) { 1054 while (sshbuf_len(sect) > 0) {
1027 if ((rdata = buffer_get_string_ret(&sect, 1055 if ((r = sshbuf_get_string(sect,
1028 &rlen)) == NULL) { 1056 &rdata, &rlen)) != 0)
1029 error("%s: buffer error", __func__);
1030 goto out; 1057 goto out;
1031 }
1032 if (type == KRL_SECTION_FINGERPRINT_SHA1 && 1058 if (type == KRL_SECTION_FINGERPRINT_SHA1 &&
1033 rlen != 20) { 1059 rlen != 20) {
1034 error("%s: bad SHA1 length", __func__); 1060 error("%s: bad SHA1 length", __func__);
1061 r = SSH_ERR_INVALID_FORMAT;
1035 goto out; 1062 goto out;
1036 } 1063 }
1037 if (revoke_blob( 1064 if ((r = revoke_blob(
1038 type == KRL_SECTION_EXPLICIT_KEY ? 1065 type == KRL_SECTION_EXPLICIT_KEY ?
1039 &krl->revoked_keys : &krl->revoked_sha1s, 1066 &krl->revoked_keys : &krl->revoked_sha1s,
1040 rdata, rlen) != 0) 1067 rdata, rlen)) != 0)
1041 goto out; 1068 goto out;
1042 rdata = NULL; /* revoke_blob frees blob */ 1069 rdata = NULL; /* revoke_blob frees blob */
1043 } 1070 }
1044 break; 1071 break;
1045 case KRL_SECTION_SIGNATURE: 1072 case KRL_SECTION_SIGNATURE:
1046 /* Handled above, but still need to stay in synch */ 1073 /* Handled above, but still need to stay in synch */
1047 buffer_clear(&sect); 1074 sshbuf_reset(sect);
1048 if ((blob = buffer_get_string_ptr_ret(&copy, 1075 sect = NULL;
1049 &blen)) == NULL) { 1076 if ((r = sshbuf_skip_string(copy)) != 0)
1050 error("%s: buffer error", __func__);
1051 goto out; 1077 goto out;
1052 }
1053 break; 1078 break;
1054 default: 1079 default:
1055 error("Unsupported KRL section %u", type); 1080 error("Unsupported KRL section %u", type);
1081 r = SSH_ERR_INVALID_FORMAT;
1056 goto out; 1082 goto out;
1057 } 1083 }
1058 if (buffer_len(&sect) > 0) { 1084 if (sshbuf_len(sect) > 0) {
1059 error("KRL section contains unparsed data"); 1085 error("KRL section contains unparsed data");
1086 r = SSH_ERR_INVALID_FORMAT;
1060 goto out; 1087 goto out;
1061 } 1088 }
1062 } 1089 }
@@ -1067,11 +1094,12 @@ ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp,
1067 if (ssh_krl_check_key(krl, ca_used[i]) == 0) 1094 if (ssh_krl_check_key(krl, ca_used[i]) == 0)
1068 sig_seen = 1; 1095 sig_seen = 1;
1069 else { 1096 else {
1070 key_free(ca_used[i]); 1097 sshkey_free(ca_used[i]);
1071 ca_used[i] = NULL; 1098 ca_used[i] = NULL;
1072 } 1099 }
1073 } 1100 }
1074 if (nca_used && !sig_seen) { 1101 if (nca_used && !sig_seen) {
1102 r = SSH_ERR_SIGNATURE_INVALID;
1075 error("All keys used to sign KRL were revoked"); 1103 error("All keys used to sign KRL were revoked");
1076 goto out; 1104 goto out;
1077 } 1105 }
@@ -1083,74 +1111,74 @@ ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp,
1083 for (j = 0; j < nca_used; j++) { 1111 for (j = 0; j < nca_used; j++) {
1084 if (ca_used[j] == NULL) 1112 if (ca_used[j] == NULL)
1085 continue; 1113 continue;
1086 if (key_equal(ca_used[j], sign_ca_keys[i])) { 1114 if (sshkey_equal(ca_used[j], sign_ca_keys[i])) {
1087 sig_seen = 1; 1115 sig_seen = 1;
1088 break; 1116 break;
1089 } 1117 }
1090 } 1118 }
1091 } 1119 }
1092 if (!sig_seen) { 1120 if (!sig_seen) {
1121 r = SSH_ERR_SIGNATURE_INVALID;
1093 error("KRL not signed with any trusted key"); 1122 error("KRL not signed with any trusted key");
1094 goto out; 1123 goto out;
1095 } 1124 }
1096 } 1125 }
1097 1126
1098 *krlp = krl; 1127 *krlp = krl;
1099 ret = 0; 1128 r = 0;
1100 out: 1129 out:
1101 if (ret != 0) 1130 if (r != 0)
1102 ssh_krl_free(krl); 1131 ssh_krl_free(krl);
1103 for (i = 0; i < nca_used; i++) { 1132 for (i = 0; i < nca_used; i++)
1104 if (ca_used[i] != NULL) 1133 sshkey_free(ca_used[i]);
1105 key_free(ca_used[i]);
1106 }
1107 free(ca_used); 1134 free(ca_used);
1108 free(rdata); 1135 free(rdata);
1109 if (key != NULL) 1136 sshkey_free(key);
1110 key_free(key); 1137 sshbuf_free(copy);
1111 buffer_free(&copy); 1138 sshbuf_free(sect);
1112 buffer_free(&sect); 1139 return r;
1113 return ret;
1114} 1140}
1115 1141
1116/* Checks whether a given key/cert is revoked. Does not check its CA */ 1142/* Checks whether a given key/cert is revoked. Does not check its CA */
1117static int 1143static int
1118is_key_revoked(struct ssh_krl *krl, const Key *key) 1144is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
1119{ 1145{
1120 struct revoked_blob rb, *erb; 1146 struct revoked_blob rb, *erb;
1121 struct revoked_serial rs, *ers; 1147 struct revoked_serial rs, *ers;
1122 struct revoked_key_id rki, *erki; 1148 struct revoked_key_id rki, *erki;
1123 struct revoked_certs *rc; 1149 struct revoked_certs *rc;
1150 int r;
1124 1151
1125 /* Check explicitly revoked hashes first */ 1152 /* Check explicitly revoked hashes first */
1126 memset(&rb, 0, sizeof(rb)); 1153 memset(&rb, 0, sizeof(rb));
1127 if ((rb.blob = key_fingerprint_raw(key, SSH_FP_SHA1, &rb.len)) == NULL) 1154 if ((r = sshkey_fingerprint_raw(key, SSH_FP_SHA1,
1128 return -1; 1155 &rb.blob, &rb.len)) != 0)
1156 return r;
1129 erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); 1157 erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb);
1130 free(rb.blob); 1158 free(rb.blob);
1131 if (erb != NULL) { 1159 if (erb != NULL) {
1132 debug("%s: revoked by key SHA1", __func__); 1160 debug("%s: revoked by key SHA1", __func__);
1133 return -1; 1161 return SSH_ERR_KEY_REVOKED;
1134 } 1162 }
1135 1163
1136 /* Next, explicit keys */ 1164 /* Next, explicit keys */
1137 memset(&rb, 0, sizeof(rb)); 1165 memset(&rb, 0, sizeof(rb));
1138 if (plain_key_blob(key, &rb.blob, &rb.len) < 0) 1166 if ((r = plain_key_blob(key, &rb.blob, &rb.len)) != 0)
1139 return -1; 1167 return r;
1140 erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb); 1168 erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb);
1141 free(rb.blob); 1169 free(rb.blob);
1142 if (erb != NULL) { 1170 if (erb != NULL) {
1143 debug("%s: revoked by explicit key", __func__); 1171 debug("%s: revoked by explicit key", __func__);
1144 return -1; 1172 return SSH_ERR_KEY_REVOKED;
1145 } 1173 }
1146 1174
1147 if (!key_is_cert(key)) 1175 if (!sshkey_is_cert(key))
1148 return 0; 1176 return 0;
1149 1177
1150 /* Check cert revocation */ 1178 /* Check cert revocation */
1151 if (revoked_certs_for_ca_key(krl, key->cert->signature_key, 1179 if ((r = revoked_certs_for_ca_key(krl, key->cert->signature_key,
1152 &rc, 0) != 0) 1180 &rc, 0)) != 0)
1153 return -1; 1181 return r;
1154 if (rc == NULL) 1182 if (rc == NULL)
1155 return 0; /* No entry for this CA */ 1183 return 0; /* No entry for this CA */
1156 1184
@@ -1160,14 +1188,14 @@ is_key_revoked(struct ssh_krl *krl, const Key *key)
1160 erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki); 1188 erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki);
1161 if (erki != NULL) { 1189 if (erki != NULL) {
1162 debug("%s: revoked by key ID", __func__); 1190 debug("%s: revoked by key ID", __func__);
1163 return -1; 1191 return SSH_ERR_KEY_REVOKED;
1164 } 1192 }
1165 1193
1166 /* 1194 /*
1167 * Legacy cert formats lack serial numbers. Zero serials numbers 1195 * Legacy cert formats lack serial numbers. Zero serials numbers
1168 * are ignored (it's the default when the CA doesn't specify one). 1196 * are ignored (it's the default when the CA doesn't specify one).
1169 */ 1197 */
1170 if (key_cert_is_legacy(key) || key->cert->serial == 0) 1198 if (sshkey_cert_is_legacy(key) || key->cert->serial == 0)
1171 return 0; 1199 return 0;
1172 1200
1173 memset(&rs, 0, sizeof(rs)); 1201 memset(&rs, 0, sizeof(rs));
@@ -1177,7 +1205,7 @@ is_key_revoked(struct ssh_krl *krl, const Key *key)
1177 KRL_DBG(("%s: %llu matched %llu:%llu", __func__, 1205 KRL_DBG(("%s: %llu matched %llu:%llu", __func__,
1178 key->cert->serial, ers->lo, ers->hi)); 1206 key->cert->serial, ers->lo, ers->hi));
1179 debug("%s: revoked by serial", __func__); 1207 debug("%s: revoked by serial", __func__);
1180 return -1; 1208 return SSH_ERR_KEY_REVOKED;
1181 } 1209 }
1182 KRL_DBG(("%s: %llu no match", __func__, key->cert->serial)); 1210 KRL_DBG(("%s: %llu no match", __func__, key->cert->serial));
1183 1211
@@ -1185,14 +1213,14 @@ is_key_revoked(struct ssh_krl *krl, const Key *key)
1185} 1213}
1186 1214
1187int 1215int
1188ssh_krl_check_key(struct ssh_krl *krl, const Key *key) 1216ssh_krl_check_key(struct ssh_krl *krl, const struct sshkey *key)
1189{ 1217{
1190 int r; 1218 int r;
1191 1219
1192 debug2("%s: checking key", __func__); 1220 debug2("%s: checking key", __func__);
1193 if ((r = is_key_revoked(krl, key)) != 0) 1221 if ((r = is_key_revoked(krl, key)) != 0)
1194 return r; 1222 return r;
1195 if (key_is_cert(key)) { 1223 if (sshkey_is_cert(key)) {
1196 debug2("%s: checking CA key", __func__); 1224 debug2("%s: checking CA key", __func__);
1197 if ((r = is_key_revoked(krl, key->cert->signature_key)) != 0) 1225 if ((r = is_key_revoked(krl, key->cert->signature_key)) != 0)
1198 return r; 1226 return r;
@@ -1201,45 +1229,36 @@ ssh_krl_check_key(struct ssh_krl *krl, const Key *key)
1201 return 0; 1229 return 0;
1202} 1230}
1203 1231
1204/* Returns 0 on success, -1 on error or key revoked, -2 if path is not a KRL */
1205int 1232int
1206ssh_krl_file_contains_key(const char *path, const Key *key) 1233ssh_krl_file_contains_key(const char *path, const struct sshkey *key)
1207{ 1234{
1208 Buffer krlbuf; 1235 struct sshbuf *krlbuf = NULL;
1209 struct ssh_krl *krl; 1236 struct ssh_krl *krl = NULL;
1210 int revoked, fd; 1237 int oerrno = 0, r, fd;
1211 1238
1212 if (path == NULL) 1239 if (path == NULL)
1213 return 0; 1240 return 0;
1214 1241
1242 if ((krlbuf = sshbuf_new()) == NULL)
1243 return SSH_ERR_ALLOC_FAIL;
1215 if ((fd = open(path, O_RDONLY)) == -1) { 1244 if ((fd = open(path, O_RDONLY)) == -1) {
1216 error("open %s: %s", path, strerror(errno)); 1245 r = SSH_ERR_SYSTEM_ERROR;
1217 error("Revoked keys file not accessible - refusing public key " 1246 oerrno = errno;
1218 "authentication"); 1247 goto out;
1219 return -1;
1220 }
1221 buffer_init(&krlbuf);
1222 if (!key_load_file(fd, path, &krlbuf)) {
1223 close(fd);
1224 buffer_free(&krlbuf);
1225 error("Revoked keys file not readable - refusing public key "
1226 "authentication");
1227 return -1;
1228 }
1229 close(fd);
1230 if (ssh_krl_from_blob(&krlbuf, &krl, NULL, 0) != 0) {
1231 buffer_free(&krlbuf);
1232 error("Invalid KRL, refusing public key "
1233 "authentication");
1234 return -1;
1235 } 1248 }
1236 buffer_free(&krlbuf); 1249 if ((r = sshkey_load_file(fd, path, krlbuf)) != 0) {
1237 if (krl == NULL) { 1250 oerrno = errno;
1238 debug3("%s: %s is not a KRL file", __func__, path); 1251 goto out;
1239 return -2;
1240 } 1252 }
1253 if ((r = ssh_krl_from_blob(krlbuf, &krl, NULL, 0)) != 0)
1254 goto out;
1241 debug2("%s: checking KRL %s", __func__, path); 1255 debug2("%s: checking KRL %s", __func__, path);
1242 revoked = ssh_krl_check_key(krl, key) != 0; 1256 r = ssh_krl_check_key(krl, key);
1257 out:
1258 close(fd);
1259 sshbuf_free(krlbuf);
1243 ssh_krl_free(krl); 1260 ssh_krl_free(krl);
1244 return revoked ? -1 : 0; 1261 if (r != 0)
1262 errno = oerrno;
1263 return r;
1245} 1264}
diff --git a/krl.h b/krl.h
index 2c43f5bb2..c98cc139d 100644
--- a/krl.h
+++ b/krl.h
@@ -14,7 +14,7 @@
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */ 15 */
16 16
17/* $OpenBSD: krl.h,v 1.2 2013/01/18 00:24:58 djm Exp $ */ 17/* $OpenBSD: krl.h,v 1.3 2014/12/04 01:49:59 djm Exp $ */
18 18
19#ifndef _KRL_H 19#ifndef _KRL_H
20#define _KRL_H 20#define _KRL_H
@@ -36,28 +36,30 @@
36#define KRL_SECTION_CERT_SERIAL_BITMAP 0x22 36#define KRL_SECTION_CERT_SERIAL_BITMAP 0x22
37#define KRL_SECTION_CERT_KEY_ID 0x23 37#define KRL_SECTION_CERT_KEY_ID 0x23
38 38
39struct sshkey;
40struct sshbuf;
39struct ssh_krl; 41struct ssh_krl;
40 42
41struct ssh_krl *ssh_krl_init(void); 43struct ssh_krl *ssh_krl_init(void);
42void ssh_krl_free(struct ssh_krl *krl); 44void ssh_krl_free(struct ssh_krl *krl);
43void ssh_krl_set_version(struct ssh_krl *krl, u_int64_t version); 45void ssh_krl_set_version(struct ssh_krl *krl, u_int64_t version);
44void ssh_krl_set_sign_key(struct ssh_krl *krl, const Key *sign_key); 46void ssh_krl_set_sign_key(struct ssh_krl *krl, const struct sshkey *sign_key);
45void ssh_krl_set_comment(struct ssh_krl *krl, const char *comment); 47int ssh_krl_set_comment(struct ssh_krl *krl, const char *comment);
46int ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, const Key *ca_key, 48int ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl,
47 u_int64_t serial); 49 const struct sshkey *ca_key, u_int64_t serial);
48int ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, const Key *ca_key, 50int ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl,
49 u_int64_t lo, u_int64_t hi); 51 const struct sshkey *ca_key, u_int64_t lo, u_int64_t hi);
50int ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const Key *ca_key, 52int ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl,
51 const char *key_id); 53 const struct sshkey *ca_key, const char *key_id);
52int ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const Key *key); 54int ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const struct sshkey *key);
53int ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const Key *key); 55int ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const struct sshkey *key);
54int ssh_krl_revoke_key(struct ssh_krl *krl, const Key *key); 56int ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key);
55int ssh_krl_to_blob(struct ssh_krl *krl, Buffer *buf, const Key **sign_keys, 57int ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
56 u_int nsign_keys); 58 const struct sshkey **sign_keys, u_int nsign_keys);
57int ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp, 59int ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
58 const Key **sign_ca_keys, u_int nsign_ca_keys); 60 const struct sshkey **sign_ca_keys, u_int nsign_ca_keys);
59int ssh_krl_check_key(struct ssh_krl *krl, const Key *key); 61int ssh_krl_check_key(struct ssh_krl *krl, const struct sshkey *key);
60int ssh_krl_file_contains_key(const char *path, const Key *key); 62int ssh_krl_file_contains_key(const char *path, const struct sshkey *key);
61 63
62#endif /* _KRL_H */ 64#endif /* _KRL_H */
63 65
diff --git a/sshbuf-getput-basic.c b/sshbuf-getput-basic.c
index b7d0758c2..682b68d58 100644
--- a/sshbuf-getput-basic.c
+++ b/sshbuf-getput-basic.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshbuf-getput-basic.c,v 1.1 2014/04/30 05:29:56 djm Exp $ */ 1/* $OpenBSD: sshbuf-getput-basic.c,v 1.2 2014/12/04 01:49:59 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2011 Damien Miller 3 * Copyright (c) 2011 Damien Miller
4 * 4 *
@@ -359,7 +359,7 @@ sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len)
359int 359int
360sshbuf_put_cstring(struct sshbuf *buf, const char *v) 360sshbuf_put_cstring(struct sshbuf *buf, const char *v)
361{ 361{
362 return sshbuf_put_string(buf, (u_char *)v, strlen(v)); 362 return sshbuf_put_string(buf, (u_char *)v, v == NULL ? 0 : strlen(v));
363} 363}
364 364
365int 365int