summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2019-09-03 08:35:27 +0000
committerDamien Miller <djm@mindrot.org>2019-09-03 18:40:24 +1000
commitd637c4aee6f9b5280c13c020d7653444ac1fcaa5 (patch)
treef4844d9e77f1008b5928f72d5542ec075239dd4e
parent2a9c9f7272c1e8665155118fe6536bebdafb6166 (diff)
upstream: sshsig tweaks and improvements from and suggested by
Markus ok markus/me OpenBSD-Commit-ID: ea4f46ad5a16b27af96e08c4877423918c4253e9
-rw-r--r--PROTOCOL.sshsig4
-rw-r--r--ssh-keygen.14
-rw-r--r--ssh-keygen.c10
-rw-r--r--sshsig.c180
-rw-r--r--sshsig.h28
5 files changed, 122 insertions, 104 deletions
diff --git a/PROTOCOL.sshsig b/PROTOCOL.sshsig
index 806c35da6..720e1f18a 100644
--- a/PROTOCOL.sshsig
+++ b/PROTOCOL.sshsig
@@ -8,9 +8,9 @@ At present, only detached and armored signatures are supported.
8The Armored SSH signatures consist of a header, a base64 8The Armored SSH signatures consist of a header, a base64
9encoded blob, and a footer. 9encoded blob, and a footer.
10 10
11The header is the string -----BEGIN SSH SIGNATURE----- 11The header is the string "-----BEGIN SSH SIGNATURE-----"
12followed by a newline. The footer is the string 12followed by a newline. The footer is the string
13-----END SSH SIGNATURE----- immediately after a newline. 13"-----END SSH SIGNATURE-----" immediately after a newline.
14 14
15The header MUST be present at the start of every signature. 15The header MUST be present at the start of every signature.
16Files containing the signature MUST start with the header. 16Files containing the signature MUST start with the header.
diff --git a/ssh-keygen.1 b/ssh-keygen.1
index 93c76ef8a..cbaf29809 100644
--- a/ssh-keygen.1
+++ b/ssh-keygen.1
@@ -1,4 +1,4 @@
1.\" $OpenBSD: ssh-keygen.1,v 1.163 2019/09/03 08:34:19 djm Exp $ 1.\" $OpenBSD: ssh-keygen.1,v 1.164 2019/09/03 08:35:27 djm Exp $
2.\" 2.\"
3.\" Author: Tatu Ylonen <ylo@cs.hut.fi> 3.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
4.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -986,7 +986,7 @@ Indicates that this key is accepted as a certificate authority (CA) and
986that certificates signed by this CA may be accepted for verification. 986that certificates signed by this CA may be accepted for verification.
987.It Cm namespaces="namespace-list" 987.It Cm namespaces="namespace-list"
988Specifies a pattern-list of namespaces that are accepted for this key. 988Specifies a pattern-list of namespaces that are accepted for this key.
989If this option is present, the the signature namespace embedded in the 989If this option is present, the signature namespace embedded in the
990signature object and presented on the verification command-line must 990signature object and presented on the verification command-line must
991match the specified list before the key will be considered acceptable. 991match the specified list before the key will be considered acceptable.
992.El 992.El
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 76bc41b2f..527cfcf63 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.344 2019/09/03 08:34:19 djm Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.345 2019/09/03 08:35:27 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -2659,10 +2659,10 @@ verify(const char *signature, const char *sig_namespace, const char *principal,
2659 fp = NULL; 2659 fp = NULL;
2660 2660
2661 if (revoked_keys != NULL) { 2661 if (revoked_keys != NULL) {
2662 if ((r = sshkey_check_revoked(sign_key, revoked_keys)) != 0) { 2662 if ((r = sshkey_check_revoked(sign_key, revoked_keys)) != 0) {
2663 debug3("sshkey_check_revoked failed: %s", ssh_err(r)); 2663 debug3("sshkey_check_revoked failed: %s", ssh_err(r));
2664 goto done; 2664 goto done;
2665 } 2665 }
2666 } 2666 }
2667 2667
2668 if ((r = sshsig_check_allowed_keys(allowed_keys, sign_key, 2668 if ((r = sshsig_check_allowed_keys(allowed_keys, sign_key,
diff --git a/sshsig.c b/sshsig.c
index 0a1e14627..c1f2d803f 100644
--- a/sshsig.c
+++ b/sshsig.c
@@ -230,7 +230,7 @@ sshsig_parse_preamble(struct sshbuf *buf)
230 return r; 230 return r;
231 } 231 }
232 232
233 if (sversion < SIG_VERSION) { 233 if (sversion > SIG_VERSION) {
234 error("Signature version %lu is larger than supported " 234 error("Signature version %lu is larger than supported "
235 "version %u", (unsigned long)sversion, SIG_VERSION); 235 "version %u", (unsigned long)sversion, SIG_VERSION);
236 return SSH_ERR_INVALID_FORMAT; 236 return SSH_ERR_INVALID_FORMAT;
@@ -241,7 +241,8 @@ sshsig_parse_preamble(struct sshbuf *buf)
241static int 241static int
242sshsig_check_hashalg(const char *hashalg) 242sshsig_check_hashalg(const char *hashalg)
243{ 243{
244 if (match_pattern_list(hashalg, HASHALG_ALLOWED, 0) == 1) 244 if (hashalg == NULL ||
245 match_pattern_list(hashalg, HASHALG_ALLOWED, 0) == 1)
245 return 0; 246 return 0;
246 error("%s: unsupported hash algorithm \"%.100s\"", __func__, hashalg); 247 error("%s: unsupported hash algorithm \"%.100s\"", __func__, hashalg);
247 return SSH_ERR_SIGN_ALG_UNSUPPORTED; 248 return SSH_ERR_SIGN_ALG_UNSUPPORTED;
@@ -268,8 +269,6 @@ sshsig_peek_hashalg(struct sshbuf *signature, char **hashalgp)
268 error("Couldn't parse signature blob: %s", ssh_err(r)); 269 error("Couldn't parse signature blob: %s", ssh_err(r));
269 goto done; 270 goto done;
270 } 271 }
271 if ((r = sshsig_check_hashalg(hashalg)) != 0)
272 goto done;
273 272
274 /* success */ 273 /* success */
275 r = 0; 274 r = 0;
@@ -293,6 +292,7 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg,
293 char *got_namespace = NULL, *sigtype = NULL, *sig_hashalg = NULL; 292 char *got_namespace = NULL, *sigtype = NULL, *sig_hashalg = NULL;
294 size_t siglen; 293 size_t siglen;
295 294
295 debug("%s: verify message length %zu", __func__, sshbuf_len(h_message));
296 if (sign_keyp != NULL) 296 if (sign_keyp != NULL)
297 *sign_keyp = NULL; 297 *sign_keyp = NULL;
298 298
@@ -301,9 +301,6 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg,
301 r = SSH_ERR_ALLOC_FAIL; 301 r = SSH_ERR_ALLOC_FAIL;
302 goto done; 302 goto done;
303 } 303 }
304 if ((r = sshsig_check_hashalg(hashalg)) != 0)
305 goto done;
306
307 if ((r = sshbuf_put(toverify, MAGIC_PREAMBLE, 304 if ((r = sshbuf_put(toverify, MAGIC_PREAMBLE,
308 MAGIC_PREAMBLE_LEN)) != 0 || 305 MAGIC_PREAMBLE_LEN)) != 0 ||
309 (r = sshbuf_put_cstring(toverify, expect_namespace)) != 0 || 306 (r = sshbuf_put_cstring(toverify, expect_namespace)) != 0 ||
@@ -382,36 +379,65 @@ done:
382 return r; 379 return r;
383} 380}
384 381
385int 382static int
386sshsig_sign_message(struct sshkey *key, const char *hashalg, 383hash_buffer(const struct sshbuf *m, const char *hashalg, struct sshbuf **bp)
387 const struct sshbuf *message, const char *sig_namespace,
388 struct sshbuf **out, sshsig_signer *signer, void *signer_ctx)
389{ 384{
390 u_char hash[SSH_DIGEST_MAX_LENGTH]; 385 char *hex, hash[SSH_DIGEST_MAX_LENGTH];
391 struct sshbuf *b = NULL;
392 int alg, r = SSH_ERR_INTERNAL_ERROR; 386 int alg, r = SSH_ERR_INTERNAL_ERROR;
387 struct sshbuf *b = NULL;
393 388
394 if (out != NULL) 389 *bp = NULL;
395 *out = NULL; 390 memset(hash, 0, sizeof(hash));
396 if (hashalg == NULL)
397 hashalg = HASHALG_DEFAULT;
398 391
399 if ((r = sshsig_check_hashalg(hashalg)) != 0) 392 if ((r = sshsig_check_hashalg(hashalg)) != 0)
400 return r; 393 return r;
401 if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) { 394 if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) {
402 error("%s: can't look up hash algorithm %s", 395 error("%s: can't look up hash algorithm %s",
403 __func__, HASHALG_DEFAULT); 396 __func__, hashalg);
404 return SSH_ERR_INTERNAL_ERROR; 397 return SSH_ERR_INTERNAL_ERROR;
405 } 398 }
406 if ((r = ssh_digest_buffer(alg, message, hash, sizeof(hash))) != 0) { 399 if ((r = ssh_digest_buffer(alg, m, hash, sizeof(hash))) != 0) {
407 error("%s: ssh_digest_buffer failed: %s", __func__, ssh_err(r)); 400 error("%s: ssh_digest_buffer failed: %s", __func__, ssh_err(r));
408 return r; 401 return r;
409 } 402 }
410 if ((b = sshbuf_from(hash, ssh_digest_bytes(alg))) == NULL) { 403 if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) {
411 error("%s: sshbuf_from failed", __func__); 404 debug3("%s: final hash: %s", __func__, hex);
405 freezero(hex, strlen(hex));
406 }
407 if ((b = sshbuf_new()) == NULL) {
412 r = SSH_ERR_ALLOC_FAIL; 408 r = SSH_ERR_ALLOC_FAIL;
413 goto out; 409 goto out;
414 } 410 }
411 if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) {
412 error("%s: sshbuf_put: %s", __func__, ssh_err(r));
413 goto out;
414 }
415 *bp = b;
416 b = NULL; /* transferred */
417 /* success */
418 r = 0;
419 out:
420 sshbuf_free(b);
421 explicit_bzero(hash, sizeof(hash));
422 return 0;
423}
424
425int
426sshsig_signb(struct sshkey *key, const char *hashalg,
427 const struct sshbuf *message, const char *sig_namespace,
428 struct sshbuf **out, sshsig_signer *signer, void *signer_ctx)
429{
430 struct sshbuf *b = NULL;
431 int r = SSH_ERR_INTERNAL_ERROR;
432
433 if (hashalg == NULL)
434 hashalg = HASHALG_DEFAULT;
435 if (out != NULL)
436 *out = NULL;
437 if ((r = hash_buffer(message, hashalg, &b)) != 0) {
438 error("%s: hash_buffer failed: %s", __func__, ssh_err(r));
439 goto out;
440 }
415 if ((r = sshsig_wrap_sign(key, hashalg, b, sig_namespace, out, 441 if ((r = sshsig_wrap_sign(key, hashalg, b, sig_namespace, out,
416 signer, signer_ctx)) != 0) 442 signer, signer_ctx)) != 0)
417 goto out; 443 goto out;
@@ -419,17 +445,15 @@ sshsig_sign_message(struct sshkey *key, const char *hashalg,
419 r = 0; 445 r = 0;
420 out: 446 out:
421 sshbuf_free(b); 447 sshbuf_free(b);
422 explicit_bzero(hash, sizeof(hash));
423 return r; 448 return r;
424} 449}
425 450
426int 451int
427sshsig_verify_message(struct sshbuf *signature, const struct sshbuf *message, 452sshsig_verifyb(struct sshbuf *signature, const struct sshbuf *message,
428 const char *expect_namespace, struct sshkey **sign_keyp) 453 const char *expect_namespace, struct sshkey **sign_keyp)
429{ 454{
430 u_char hash[SSH_DIGEST_MAX_LENGTH];
431 struct sshbuf *b = NULL; 455 struct sshbuf *b = NULL;
432 int alg, r = SSH_ERR_INTERNAL_ERROR; 456 int r = SSH_ERR_INTERNAL_ERROR;
433 char *hashalg = NULL; 457 char *hashalg = NULL;
434 458
435 if (sign_keyp != NULL) 459 if (sign_keyp != NULL)
@@ -437,18 +461,9 @@ sshsig_verify_message(struct sshbuf *signature, const struct sshbuf *message,
437 461
438 if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0) 462 if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0)
439 return r; 463 return r;
440 if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) { 464 debug("%s: signature made with hash \"%s\"", __func__, hashalg);
441 error("%s: can't look up hash algorithm %s", 465 if ((r = hash_buffer(message, hashalg, &b)) != 0) {
442 __func__, HASHALG_DEFAULT); 466 error("%s: hash_buffer failed: %s", __func__, ssh_err(r));
443 return SSH_ERR_INTERNAL_ERROR;
444 }
445 if ((r = ssh_digest_buffer(alg, message, hash, sizeof(hash))) != 0) {
446 error("%s: ssh_digest_buffer failed: %s", __func__, ssh_err(r));
447 goto out;
448 }
449 if ((b = sshbuf_from(hash, ssh_digest_bytes(alg))) == NULL) {
450 error("%s: sshbuf_from failed", __func__);
451 r = SSH_ERR_ALLOC_FAIL;
452 goto out; 467 goto out;
453 } 468 }
454 if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace, 469 if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace,
@@ -459,20 +474,29 @@ sshsig_verify_message(struct sshbuf *signature, const struct sshbuf *message,
459 out: 474 out:
460 sshbuf_free(b); 475 sshbuf_free(b);
461 free(hashalg); 476 free(hashalg);
462 explicit_bzero(hash, sizeof(hash));
463 return r; 477 return r;
464} 478}
465 479
466static int 480static int
467hash_file(int fd, int hashalg, u_char *hash, size_t hashlen) 481hash_file(int fd, const char *hashalg, struct sshbuf **bp)
468{ 482{
469 char *hex, rbuf[8192]; 483 char *hex, rbuf[8192], hash[SSH_DIGEST_MAX_LENGTH];
470 ssize_t n, total = 0; 484 ssize_t n, total = 0;
471 struct ssh_digest_ctx *ctx; 485 struct ssh_digest_ctx *ctx;
472 int r, oerrno; 486 int alg, oerrno, r = SSH_ERR_INTERNAL_ERROR;
487 struct sshbuf *b = NULL;
488
489 *bp = NULL;
490 memset(hash, 0, sizeof(hash));
473 491
474 memset(hash, 0, hashlen); 492 if ((r = sshsig_check_hashalg(hashalg)) != 0)
475 if ((ctx = ssh_digest_start(hashalg)) == NULL) { 493 return r;
494 if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) {
495 error("%s: can't look up hash algorithm %s",
496 __func__, hashalg);
497 return SSH_ERR_INTERNAL_ERROR;
498 }
499 if ((ctx = ssh_digest_start(alg)) == NULL) {
476 error("%s: ssh_digest_start failed", __func__); 500 error("%s: ssh_digest_start failed", __func__);
477 return SSH_ERR_INTERNAL_ERROR; 501 return SSH_ERR_INTERNAL_ERROR;
478 } 502 }
@@ -484,7 +508,8 @@ hash_file(int fd, int hashalg, u_char *hash, size_t hashlen)
484 error("%s: read: %s", __func__, strerror(errno)); 508 error("%s: read: %s", __func__, strerror(errno));
485 ssh_digest_free(ctx); 509 ssh_digest_free(ctx);
486 errno = oerrno; 510 errno = oerrno;
487 return SSH_ERR_SYSTEM_ERROR; 511 r = SSH_ERR_SYSTEM_ERROR;
512 goto out;
488 } else if (n == 0) { 513 } else if (n == 0) {
489 debug2("%s: hashed %zu bytes", __func__, total); 514 debug2("%s: hashed %zu bytes", __func__, total);
490 break; /* EOF */ 515 break; /* EOF */
@@ -493,20 +518,33 @@ hash_file(int fd, int hashalg, u_char *hash, size_t hashlen)
493 if ((r = ssh_digest_update(ctx, rbuf, (size_t)n)) != 0) { 518 if ((r = ssh_digest_update(ctx, rbuf, (size_t)n)) != 0) {
494 error("%s: ssh_digest_update: %s", 519 error("%s: ssh_digest_update: %s",
495 __func__, ssh_err(r)); 520 __func__, ssh_err(r));
496 ssh_digest_free(ctx); 521 goto out;
497 return r;
498 } 522 }
499 } 523 }
500 if ((r = ssh_digest_final(ctx, hash, hashlen)) != 0) { 524 if ((r = ssh_digest_final(ctx, hash, sizeof(hash))) != 0) {
501 error("%s: ssh_digest_final: %s", __func__, ssh_err(r)); 525 error("%s: ssh_digest_final: %s", __func__, ssh_err(r));
502 ssh_digest_free(ctx); 526 goto out;
503 } 527 }
504 if ((hex = tohex(hash, hashlen)) != NULL) { 528 if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) {
505 debug3("%s: final hash: %s", __func__, hex); 529 debug3("%s: final hash: %s", __func__, hex);
506 freezero(hex, strlen(hex)); 530 freezero(hex, strlen(hex));
507 } 531 }
532 if ((b = sshbuf_new()) == NULL) {
533 r = SSH_ERR_ALLOC_FAIL;
534 goto out;
535 }
536 if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) {
537 error("%s: sshbuf_put: %s", __func__, ssh_err(r));
538 goto out;
539 }
540 *bp = b;
541 b = NULL; /* transferred */
508 /* success */ 542 /* success */
543 r = 0;
544 out:
545 sshbuf_free(b);
509 ssh_digest_free(ctx); 546 ssh_digest_free(ctx);
547 explicit_bzero(hash, sizeof(hash));
510 return 0; 548 return 0;
511} 549}
512 550
@@ -515,31 +553,17 @@ sshsig_sign_fd(struct sshkey *key, const char *hashalg,
515 int fd, const char *sig_namespace, struct sshbuf **out, 553 int fd, const char *sig_namespace, struct sshbuf **out,
516 sshsig_signer *signer, void *signer_ctx) 554 sshsig_signer *signer, void *signer_ctx)
517{ 555{
518 u_char hash[SSH_DIGEST_MAX_LENGTH];
519 struct sshbuf *b = NULL; 556 struct sshbuf *b = NULL;
520 int alg, r = SSH_ERR_INTERNAL_ERROR; 557 int r = SSH_ERR_INTERNAL_ERROR;
521 558
559 if (hashalg == NULL)
560 hashalg = HASHALG_DEFAULT;
522 if (out != NULL) 561 if (out != NULL)
523 *out = NULL; 562 *out = NULL;
524 if (hashalg == NULL) 563 if ((r = hash_file(fd, hashalg, &b)) != 0) {
525 hashalg = HASHALG_DEFAULT;
526
527 if ((r = sshsig_check_hashalg(hashalg)) != 0)
528 return r;
529 if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) {
530 error("%s: can't look up hash algorithm %s",
531 __func__, HASHALG_DEFAULT);
532 return SSH_ERR_INTERNAL_ERROR;
533 }
534 if ((r = hash_file(fd, alg, hash, sizeof(hash))) != 0) {
535 error("%s: hash_file failed: %s", __func__, ssh_err(r)); 564 error("%s: hash_file failed: %s", __func__, ssh_err(r));
536 return r; 565 return r;
537 } 566 }
538 if ((b = sshbuf_from(hash, ssh_digest_bytes(alg))) == NULL) {
539 error("%s: sshbuf_from failed", __func__);
540 r = SSH_ERR_ALLOC_FAIL;
541 goto out;
542 }
543 if ((r = sshsig_wrap_sign(key, hashalg, b, sig_namespace, out, 567 if ((r = sshsig_wrap_sign(key, hashalg, b, sig_namespace, out,
544 signer, signer_ctx)) != 0) 568 signer, signer_ctx)) != 0)
545 goto out; 569 goto out;
@@ -547,7 +571,6 @@ sshsig_sign_fd(struct sshkey *key, const char *hashalg,
547 r = 0; 571 r = 0;
548 out: 572 out:
549 sshbuf_free(b); 573 sshbuf_free(b);
550 explicit_bzero(hash, sizeof(hash));
551 return r; 574 return r;
552} 575}
553 576
@@ -555,9 +578,8 @@ int
555sshsig_verify_fd(struct sshbuf *signature, int fd, 578sshsig_verify_fd(struct sshbuf *signature, int fd,
556 const char *expect_namespace, struct sshkey **sign_keyp) 579 const char *expect_namespace, struct sshkey **sign_keyp)
557{ 580{
558 u_char hash[SSH_DIGEST_MAX_LENGTH];
559 struct sshbuf *b = NULL; 581 struct sshbuf *b = NULL;
560 int alg, r = SSH_ERR_INTERNAL_ERROR; 582 int r = SSH_ERR_INTERNAL_ERROR;
561 char *hashalg = NULL; 583 char *hashalg = NULL;
562 584
563 if (sign_keyp != NULL) 585 if (sign_keyp != NULL)
@@ -565,18 +587,9 @@ sshsig_verify_fd(struct sshbuf *signature, int fd,
565 587
566 if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0) 588 if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0)
567 return r; 589 return r;
568 if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) { 590 debug("%s: signature made with hash \"%s\"", __func__, hashalg);
569 error("%s: can't look up hash algorithm %s", 591 if ((r = hash_file(fd, hashalg, &b)) != 0) {
570 __func__, HASHALG_DEFAULT);
571 return SSH_ERR_INTERNAL_ERROR;
572 }
573 if ((r = hash_file(fd, alg, hash, sizeof(hash))) != 0) {
574 error("%s: hash_file failed: %s", __func__, ssh_err(r)); 592 error("%s: hash_file failed: %s", __func__, ssh_err(r));
575 return r;
576 }
577 if ((b = sshbuf_from(hash, ssh_digest_bytes(alg))) == NULL) {
578 error("%s: sshbuf_from failed", __func__);
579 r = SSH_ERR_ALLOC_FAIL;
580 goto out; 593 goto out;
581 } 594 }
582 if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace, 595 if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace,
@@ -587,7 +600,6 @@ sshsig_verify_fd(struct sshbuf *signature, int fd,
587 out: 600 out:
588 sshbuf_free(b); 601 sshbuf_free(b);
589 free(hashalg); 602 free(hashalg);
590 explicit_bzero(hash, sizeof(hash));
591 return r; 603 return r;
592} 604}
593 605
@@ -769,14 +781,14 @@ sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key,
769 linenum++; 781 linenum++;
770 r = check_allowed_keys_line(path, linenum, line, sign_key, 782 r = check_allowed_keys_line(path, linenum, line, sign_key,
771 principal, sig_namespace); 783 principal, sig_namespace);
784 free(line);
785 line = NULL;
772 if (r == SSH_ERR_KEY_NOT_FOUND) 786 if (r == SSH_ERR_KEY_NOT_FOUND)
773 continue; 787 continue;
774 else if (r == 0) { 788 else if (r == 0) {
775 /* success */ 789 /* success */
776 fclose(f); 790 fclose(f);
777 free(line);
778 return 0; 791 return 0;
779 /* XXX continue and check revocation? */
780 } else 792 } else
781 break; 793 break;
782 } 794 }
diff --git a/sshsig.h b/sshsig.h
index 92c675e3a..fc1d607b3 100644
--- a/sshsig.h
+++ b/sshsig.h
@@ -23,16 +23,29 @@ struct sshkey;
23typedef int sshsig_signer(struct sshkey *, u_char **, size_t *, 23typedef int sshsig_signer(struct sshkey *, u_char **, size_t *,
24 const u_char *, size_t, const char *, u_int, void *); 24 const u_char *, size_t, const char *, u_int, void *);
25 25
26/* Buffer-oriented API */
27
26/* 28/*
27 * Creates a detached SSH signature for a given message. 29 * Creates a detached SSH signature for a given buffer.
28 * Returns 0 on success or a negative SSH_ERR_* error code on failure. 30 * Returns 0 on success or a negative SSH_ERR_* error code on failure.
29 * out is populated with the detached signature, or NULL on failure. 31 * out is populated with the detached signature, or NULL on failure.
30 */ 32 */
31int sshsig_sign_message(struct sshkey *key, const char *hashalg, 33int sshsig_signb(struct sshkey *key, const char *hashalg,
32 const struct sshbuf *message, const char *sig_namespace, 34 const struct sshbuf *message, const char *sig_namespace,
33 struct sshbuf **out, sshsig_signer *signer, void *signer_ctx); 35 struct sshbuf **out, sshsig_signer *signer, void *signer_ctx);
34 36
35/* 37/*
38 * Verifies that a detached signature is valid and optionally returns key
39 * used to sign via argument.
40 * Returns 0 on success or a negative SSH_ERR_* error code on failure.
41 */
42int sshsig_verifyb(struct sshbuf *signature,
43 const struct sshbuf *message, const char *sig_namespace,
44 struct sshkey **sign_keyp);
45
46/* File/FD-oriented API */
47
48/*
36 * Creates a detached SSH signature for a given file. 49 * Creates a detached SSH signature for a given file.
37 * Returns 0 on success or a negative SSH_ERR_* error code on failure. 50 * Returns 0 on success or a negative SSH_ERR_* error code on failure.
38 * out is populated with the detached signature, or NULL on failure. 51 * out is populated with the detached signature, or NULL on failure.
@@ -42,15 +55,6 @@ int sshsig_sign_fd(struct sshkey *key, const char *hashalg,
42 sshsig_signer *signer, void *signer_ctx); 55 sshsig_signer *signer, void *signer_ctx);
43 56
44/* 57/*
45 * Verifies that a detached signature is valid and optionally returns key
46 * used to sign via argument.
47 * Returns 0 on success or a negative SSH_ERR_* error code on failure.
48 */
49int sshsig_verify_message(struct sshbuf *signature,
50 const struct sshbuf *message, const char *sig_namespace,
51 struct sshkey **sign_keyp);
52
53/*
54 * Verifies that a detached signature over a file is valid and optionally 58 * Verifies that a detached signature over a file is valid and optionally
55 * returns key used to sign via argument. 59 * returns key used to sign via argument.
56 * Returns 0 on success or a negative SSH_ERR_* error code on failure. 60 * Returns 0 on success or a negative SSH_ERR_* error code on failure.
@@ -58,6 +62,8 @@ int sshsig_verify_message(struct sshbuf *signature,
58int sshsig_verify_fd(struct sshbuf *signature, int fd, 62int sshsig_verify_fd(struct sshbuf *signature, int fd,
59 const char *sig_namespace, struct sshkey **sign_keyp); 63 const char *sig_namespace, struct sshkey **sign_keyp);
60 64
65/* Utility functions */
66
61/* 67/*
62 * Return a base64 encoded "ASCII armoured" version of a raw signature. 68 * Return a base64 encoded "ASCII armoured" version of a raw signature.
63 */ 69 */