summaryrefslogtreecommitdiff
path: root/sshsig.c
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 /sshsig.c
parent2a9c9f7272c1e8665155118fe6536bebdafb6166 (diff)
upstream: sshsig tweaks and improvements from and suggested by
Markus ok markus/me OpenBSD-Commit-ID: ea4f46ad5a16b27af96e08c4877423918c4253e9
Diffstat (limited to 'sshsig.c')
-rw-r--r--sshsig.c180
1 files changed, 96 insertions, 84 deletions
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 }