diff options
Diffstat (limited to 'ssh-keygen.c')
-rw-r--r-- | ssh-keygen.c | 55 |
1 files changed, 39 insertions, 16 deletions
diff --git a/ssh-keygen.c b/ssh-keygen.c index cc092368e..89ef9a143 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keygen.c,v 1.415 2020/08/03 02:53:51 djm Exp $ */ | 1 | /* $OpenBSD: ssh-keygen.c,v 1.416 2020/08/27 01:06:18 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 |
@@ -589,7 +589,7 @@ do_convert_private_ssh2(struct sshbuf *b) | |||
589 | 589 | ||
590 | /* try the key */ | 590 | /* try the key */ |
591 | if (sshkey_sign(key, &sig, &slen, data, sizeof(data), | 591 | if (sshkey_sign(key, &sig, &slen, data, sizeof(data), |
592 | NULL, NULL, 0) != 0 || | 592 | NULL, NULL, NULL, 0) != 0 || |
593 | sshkey_verify(key, sig, slen, data, sizeof(data), | 593 | sshkey_verify(key, sig, slen, data, sizeof(data), |
594 | NULL, 0, NULL) != 0) { | 594 | NULL, 0, NULL) != 0) { |
595 | sshkey_free(key); | 595 | sshkey_free(key); |
@@ -1727,7 +1727,8 @@ load_pkcs11_key(char *path) | |||
1727 | static int | 1727 | static int |
1728 | agent_signer(struct sshkey *key, u_char **sigp, size_t *lenp, | 1728 | agent_signer(struct sshkey *key, u_char **sigp, size_t *lenp, |
1729 | const u_char *data, size_t datalen, | 1729 | const u_char *data, size_t datalen, |
1730 | const char *alg, const char *provider, u_int compat, void *ctx) | 1730 | const char *alg, const char *provider, const char *pin, |
1731 | u_int compat, void *ctx) | ||
1731 | { | 1732 | { |
1732 | int *agent_fdp = (int *)ctx; | 1733 | int *agent_fdp = (int *)ctx; |
1733 | 1734 | ||
@@ -1744,7 +1745,7 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, | |||
1744 | u_int n; | 1745 | u_int n; |
1745 | struct sshkey *ca, *public; | 1746 | struct sshkey *ca, *public; |
1746 | char valid[64], *otmp, *tmp, *cp, *out, *comment; | 1747 | char valid[64], *otmp, *tmp, *cp, *out, *comment; |
1747 | char *ca_fp = NULL, **plist = NULL; | 1748 | char *ca_fp = NULL, **plist = NULL, *pin = NULL; |
1748 | struct ssh_identitylist *agent_ids; | 1749 | struct ssh_identitylist *agent_ids; |
1749 | size_t j; | 1750 | size_t j; |
1750 | struct notifier_ctx *notifier = NULL; | 1751 | struct notifier_ctx *notifier = NULL; |
@@ -1785,6 +1786,12 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, | |||
1785 | } else { | 1786 | } else { |
1786 | /* CA key is assumed to be a private key on the filesystem */ | 1787 | /* CA key is assumed to be a private key on the filesystem */ |
1787 | ca = load_identity(tmp, NULL); | 1788 | ca = load_identity(tmp, NULL); |
1789 | if (sshkey_is_sk(ca) && | ||
1790 | (ca->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) { | ||
1791 | if ((pin = read_passphrase("Enter PIN for CA key: ", | ||
1792 | RP_ALLOW_STDIN)) == NULL) | ||
1793 | fatal("%s: couldn't read PIN", __func__); | ||
1794 | } | ||
1788 | } | 1795 | } |
1789 | free(tmp); | 1796 | free(tmp); |
1790 | 1797 | ||
@@ -1844,7 +1851,7 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, | |||
1844 | 1851 | ||
1845 | if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) { | 1852 | if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) { |
1846 | if ((r = sshkey_certify_custom(public, ca, | 1853 | if ((r = sshkey_certify_custom(public, ca, |
1847 | key_type_name, sk_provider, agent_signer, | 1854 | key_type_name, sk_provider, NULL, agent_signer, |
1848 | &agent_fd)) != 0) | 1855 | &agent_fd)) != 0) |
1849 | fatal("Couldn't certify key %s via agent: %s", | 1856 | fatal("Couldn't certify key %s via agent: %s", |
1850 | tmp, ssh_err(r)); | 1857 | tmp, ssh_err(r)); |
@@ -1856,7 +1863,7 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, | |||
1856 | sshkey_type(ca), ca_fp); | 1863 | sshkey_type(ca), ca_fp); |
1857 | } | 1864 | } |
1858 | r = sshkey_certify(public, ca, key_type_name, | 1865 | r = sshkey_certify(public, ca, key_type_name, |
1859 | sk_provider); | 1866 | sk_provider, pin); |
1860 | notify_complete(notifier); | 1867 | notify_complete(notifier); |
1861 | if (r != 0) | 1868 | if (r != 0) |
1862 | fatal("Couldn't certify key %s: %s", | 1869 | fatal("Couldn't certify key %s: %s", |
@@ -1890,6 +1897,8 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, | |||
1890 | if (cert_serial_autoinc) | 1897 | if (cert_serial_autoinc) |
1891 | cert_serial++; | 1898 | cert_serial++; |
1892 | } | 1899 | } |
1900 | if (pin != NULL) | ||
1901 | freezero(pin, strlen(pin)); | ||
1893 | free(ca_fp); | 1902 | free(ca_fp); |
1894 | #ifdef ENABLE_PKCS11 | 1903 | #ifdef ENABLE_PKCS11 |
1895 | pkcs11_terminate(); | 1904 | pkcs11_terminate(); |
@@ -2526,6 +2535,7 @@ sign_one(struct sshkey *signkey, const char *filename, int fd, | |||
2526 | struct sshbuf *sigbuf = NULL, *abuf = NULL; | 2535 | struct sshbuf *sigbuf = NULL, *abuf = NULL; |
2527 | int r = SSH_ERR_INTERNAL_ERROR, wfd = -1, oerrno; | 2536 | int r = SSH_ERR_INTERNAL_ERROR, wfd = -1, oerrno; |
2528 | char *wfile = NULL, *asig = NULL, *fp = NULL; | 2537 | char *wfile = NULL, *asig = NULL, *fp = NULL; |
2538 | char *pin = NULL, *prompt = NULL; | ||
2529 | 2539 | ||
2530 | if (!quiet) { | 2540 | if (!quiet) { |
2531 | if (fd == STDIN_FILENO) | 2541 | if (fd == STDIN_FILENO) |
@@ -2533,17 +2543,25 @@ sign_one(struct sshkey *signkey, const char *filename, int fd, | |||
2533 | else | 2543 | else |
2534 | fprintf(stderr, "Signing file %s\n", filename); | 2544 | fprintf(stderr, "Signing file %s\n", filename); |
2535 | } | 2545 | } |
2536 | if (signer == NULL && sshkey_is_sk(signkey) && | 2546 | if (signer == NULL && sshkey_is_sk(signkey)) { |
2537 | (signkey->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { | 2547 | if ((signkey->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) { |
2538 | if ((fp = sshkey_fingerprint(signkey, fingerprint_hash, | 2548 | xasprintf(&prompt, "Enter PIN for %s key: ", |
2539 | SSH_FP_DEFAULT)) == NULL) | 2549 | sshkey_type(signkey)); |
2540 | fatal("%s: sshkey_fingerprint failed", __func__); | 2550 | if ((pin = read_passphrase(prompt, |
2541 | fprintf(stderr, "Confirm user presence for key %s %s\n", | 2551 | RP_ALLOW_STDIN)) == NULL) |
2542 | sshkey_type(signkey), fp); | 2552 | fatal("%s: couldn't read PIN", __func__); |
2543 | free(fp); | 2553 | } |
2554 | if ((signkey->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { | ||
2555 | if ((fp = sshkey_fingerprint(signkey, fingerprint_hash, | ||
2556 | SSH_FP_DEFAULT)) == NULL) | ||
2557 | fatal("%s: fingerprint failed", __func__); | ||
2558 | fprintf(stderr, "Confirm user presence for key %s %s\n", | ||
2559 | sshkey_type(signkey), fp); | ||
2560 | free(fp); | ||
2561 | } | ||
2544 | } | 2562 | } |
2545 | if ((r = sshsig_sign_fd(signkey, NULL, sk_provider, fd, sig_namespace, | 2563 | if ((r = sshsig_sign_fd(signkey, NULL, sk_provider, pin, |
2546 | &sigbuf, signer, signer_ctx)) != 0) { | 2564 | fd, sig_namespace, &sigbuf, signer, signer_ctx)) != 0) { |
2547 | error("Signing %s failed: %s", filename, ssh_err(r)); | 2565 | error("Signing %s failed: %s", filename, ssh_err(r)); |
2548 | goto out; | 2566 | goto out; |
2549 | } | 2567 | } |
@@ -2591,7 +2609,10 @@ sign_one(struct sshkey *signkey, const char *filename, int fd, | |||
2591 | r = 0; | 2609 | r = 0; |
2592 | out: | 2610 | out: |
2593 | free(wfile); | 2611 | free(wfile); |
2612 | free(prompt); | ||
2594 | free(asig); | 2613 | free(asig); |
2614 | if (pin != NULL) | ||
2615 | freezero(pin, strlen(pin)); | ||
2595 | sshbuf_free(abuf); | 2616 | sshbuf_free(abuf); |
2596 | sshbuf_free(sigbuf); | 2617 | sshbuf_free(sigbuf); |
2597 | if (wfd != -1) | 2618 | if (wfd != -1) |
@@ -3554,6 +3575,8 @@ main(int argc, char **argv) | |||
3554 | for (i = 0; i < nopts; i++) { | 3575 | for (i = 0; i < nopts; i++) { |
3555 | if (strcasecmp(opts[i], "no-touch-required") == 0) { | 3576 | if (strcasecmp(opts[i], "no-touch-required") == 0) { |
3556 | sk_flags &= ~SSH_SK_USER_PRESENCE_REQD; | 3577 | sk_flags &= ~SSH_SK_USER_PRESENCE_REQD; |
3578 | } else if (strcasecmp(opts[i], "verify-required") == 0) { | ||
3579 | sk_flags |= SSH_SK_USER_VERIFICATION_REQD; | ||
3557 | } else if (strcasecmp(opts[i], "resident") == 0) { | 3580 | } else if (strcasecmp(opts[i], "resident") == 0) { |
3558 | sk_flags |= SSH_SK_RESIDENT_KEY; | 3581 | sk_flags |= SSH_SK_RESIDENT_KEY; |
3559 | } else if (strncasecmp(opts[i], "device=", 7) == 0) { | 3582 | } else if (strncasecmp(opts[i], "device=", 7) == 0) { |