diff options
author | djm@openbsd.org <djm@openbsd.org> | 2020-01-28 08:01:34 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2020-01-29 18:52:55 +1100 |
commit | 24c0f752adf9021277a7b0a84931bb5fe48ea379 (patch) | |
tree | cd1b9474e73ad7647b4ad88775365e7430d3fe64 /ssh-keygen.c | |
parent | 156bef36f93a48212383235bb8e3d71eaf2b2777 (diff) |
upstream: changes to support FIDO attestation
Allow writing to disk the attestation certificate that is generated by
the FIDO token at key enrollment time. These certificates may be used
by an out-of-band workflow to prove that a particular key is held in
trustworthy hardware.
Allow passing in a challenge that will be sent to the card during
key enrollment. These are needed to build an attestation workflow
that resists replay attacks.
ok markus@
OpenBSD-Commit-ID: 457dc3c3d689ba39eed328f0817ed9b91a5f78f6
Diffstat (limited to 'ssh-keygen.c')
-rw-r--r-- | ssh-keygen.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/ssh-keygen.c b/ssh-keygen.c index 8df55f2c2..4ee43ab98 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keygen.c,v 1.394 2020/01/25 23:13:09 djm Exp $ */ | 1 | /* $OpenBSD: ssh-keygen.c,v 1.395 2020/01/28 08:01:34 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 |
@@ -3114,6 +3114,8 @@ main(int argc, char **argv) | |||
3114 | unsigned long long cert_serial = 0; | 3114 | unsigned long long cert_serial = 0; |
3115 | char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL; | 3115 | char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL; |
3116 | char *sk_application = NULL, *sk_device = NULL, *sk_user = NULL; | 3116 | char *sk_application = NULL, *sk_device = NULL, *sk_user = NULL; |
3117 | char *sk_attestaion_path = NULL; | ||
3118 | struct sshbuf *challenge = NULL, *attest = NULL; | ||
3117 | size_t i, nopts = 0; | 3119 | size_t i, nopts = 0; |
3118 | u_int32_t bits = 0; | 3120 | u_int32_t bits = 0; |
3119 | uint8_t sk_flags = SSH_SK_USER_PRESENCE_REQD; | 3121 | uint8_t sk_flags = SSH_SK_USER_PRESENCE_REQD; |
@@ -3557,6 +3559,16 @@ main(int argc, char **argv) | |||
3557 | sk_device = xstrdup(opts[i] + 7); | 3559 | sk_device = xstrdup(opts[i] + 7); |
3558 | } else if (strncasecmp(opts[i], "user=", 5) == 0) { | 3560 | } else if (strncasecmp(opts[i], "user=", 5) == 0) { |
3559 | sk_user = xstrdup(opts[i] + 5); | 3561 | sk_user = xstrdup(opts[i] + 5); |
3562 | } else if (strncasecmp(opts[i], "challenge=", 10) == 0) { | ||
3563 | if ((r = sshbuf_load_file(opts[i] + 10, | ||
3564 | &challenge)) != 0) { | ||
3565 | fatal("Unable to load FIDO enrollment " | ||
3566 | "challenge \"%s\": %s", | ||
3567 | opts[i] + 10, ssh_err(r)); | ||
3568 | } | ||
3569 | } else if (strncasecmp(opts[i], | ||
3570 | "write-attestation=", 18) == 0) { | ||
3571 | sk_attestaion_path = opts[i] + 18; | ||
3560 | } else if (strncasecmp(opts[i], | 3572 | } else if (strncasecmp(opts[i], |
3561 | "application=", 12) == 0) { | 3573 | "application=", 12) == 0) { |
3562 | sk_application = xstrdup(opts[i] + 12); | 3574 | sk_application = xstrdup(opts[i] + 12); |
@@ -3570,12 +3582,14 @@ main(int argc, char **argv) | |||
3570 | "to authorize key generation.\n"); | 3582 | "to authorize key generation.\n"); |
3571 | } | 3583 | } |
3572 | passphrase = NULL; | 3584 | passphrase = NULL; |
3585 | if ((attest = sshbuf_new()) == NULL) | ||
3586 | fatal("sshbuf_new failed"); | ||
3573 | for (i = 0 ; i < 3; i++) { | 3587 | for (i = 0 ; i < 3; i++) { |
3574 | fflush(stdout); | 3588 | fflush(stdout); |
3575 | r = sshsk_enroll(type, sk_provider, sk_device, | 3589 | r = sshsk_enroll(type, sk_provider, sk_device, |
3576 | sk_application == NULL ? "ssh:" : sk_application, | 3590 | sk_application == NULL ? "ssh:" : sk_application, |
3577 | sk_user, sk_flags, passphrase, NULL, | 3591 | sk_user, sk_flags, passphrase, challenge, |
3578 | &private, NULL); | 3592 | &private, attest); |
3579 | if (r == 0) | 3593 | if (r == 0) |
3580 | break; | 3594 | break; |
3581 | if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) | 3595 | if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) |
@@ -3668,6 +3682,22 @@ main(int argc, char **argv) | |||
3668 | free(fp); | 3682 | free(fp); |
3669 | } | 3683 | } |
3670 | 3684 | ||
3685 | if (sk_attestaion_path != NULL) { | ||
3686 | if (attest == NULL || sshbuf_len(attest) == 0) { | ||
3687 | fatal("Enrollment did not return attestation " | ||
3688 | "certificate"); | ||
3689 | } | ||
3690 | if ((r = sshbuf_write_file(sk_attestaion_path, attest)) != 0) { | ||
3691 | fatal("Unable to write attestation certificate " | ||
3692 | "\"%s\": %s", sk_attestaion_path, ssh_err(r)); | ||
3693 | } | ||
3694 | if (!quiet) { | ||
3695 | printf("Your FIDO attestation certificate has been " | ||
3696 | "saved in %s\n", sk_attestaion_path); | ||
3697 | } | ||
3698 | } | ||
3699 | sshbuf_free(attest); | ||
3671 | sshkey_free(public); | 3700 | sshkey_free(public); |
3701 | |||
3672 | exit(0); | 3702 | exit(0); |
3673 | } | 3703 | } |