diff options
author | djm@openbsd.org <djm@openbsd.org> | 2019-12-13 19:09:10 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2019-12-14 07:17:44 +1100 |
commit | b52ec0ba3983859514aa7b57d6100fa9759fe696 (patch) | |
tree | 262c9a2ebc4e6972594f45ea75fc15e8ae3bfefb | |
parent | c33d46868c3d88e04a92610cdb429094aeeb5847 (diff) |
upstream: use ssh-sk-helper for all security key signing operations
This extracts and refactors the client interface for ssh-sk-helper
from ssh-agent and generalises it for use by the other programs.
This means that most OpenSSH tools no longer need to link against
libfido2 or directly interact with /dev/uhid*
requested by, feedback and ok markus@
OpenBSD-Commit-ID: 1abcd3aea9a7460eccfbf8ca154cdfa62f1dc93f
-rw-r--r-- | ssh-agent.c | 160 | ||||
-rw-r--r-- | ssh-sk.c | 4 | ||||
-rw-r--r-- | ssh-sk.h | 7 | ||||
-rw-r--r-- | sshkey.c | 15 | ||||
-rw-r--r-- | sshkey.h | 5 |
5 files changed, 33 insertions, 158 deletions
diff --git a/ssh-agent.c b/ssh-agent.c index 1d4b779f6..09d12dc3f 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-agent.c,v 1.250 2019/11/19 16:02:32 jmc Exp $ */ +/* $OpenBSD: ssh-agent.c,v 1.251 2019/12/13 19:09:10 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -90,7 +90,7 @@ #include "ssherr.h" #include "pathnames.h" #include "ssh-pkcs11.h" -#include "ssh-sk.h" +#include "sk-api.h" #ifndef DEFAULT_PROVIDER_WHITELIST # define DEFAULT_PROVIDER_WHITELIST "/usr/lib*/*,/usr/local/lib*/*" @@ -282,130 +282,6 @@ agent_decode_alg(struct sshkey *key, u_int flags) return NULL; } -static int -provider_sign(const char *provider, struct sshkey *key, - u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, - const char *alg, u_int compat) -{ - int status, pair[2], r = SSH_ERR_INTERNAL_ERROR; - pid_t pid; - char *helper, *verbosity = NULL, *fp = NULL; - struct sshbuf *kbuf, *req, *resp; - u_char version; - struct notifier_ctx *notifier = NULL; - - debug3("%s: start for provider %s", __func__, provider); - - *sigp = NULL; - *lenp = 0; - - helper = getenv("SSH_SK_HELPER"); - if (helper == NULL || strlen(helper) == 0) - helper = _PATH_SSH_SK_HELPER; - if (log_level_get() >= SYSLOG_LEVEL_DEBUG1) - verbosity = "-vvv"; - - /* Start helper */ - if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { - error("socketpair: %s", strerror(errno)); - return SSH_ERR_SYSTEM_ERROR; - } - if ((pid = fork()) == -1) { - error("fork: %s", strerror(errno)); - close(pair[0]); - close(pair[1]); - return SSH_ERR_SYSTEM_ERROR; - } - if (pid == 0) { - if ((dup2(pair[1], STDIN_FILENO) == -1) || - (dup2(pair[1], STDOUT_FILENO) == -1)) - fatal("%s: dup2: %s", __func__, ssh_err(r)); - close(pair[0]); - close(pair[1]); - closefrom(STDERR_FILENO + 1); - debug("%s: starting %s %s", __func__, helper, - verbosity == NULL ? "" : verbosity); - execlp(helper, helper, verbosity, (char *)NULL); - fatal("%s: execlp: %s", __func__, strerror(errno)); - } - close(pair[1]); - - if ((kbuf = sshbuf_new()) == NULL || - (req = sshbuf_new()) == NULL || - (resp = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); - - if ((r = sshkey_private_serialize(key, kbuf)) != 0 || - (r = sshbuf_put_stringb(req, kbuf)) != 0 || - (r = sshbuf_put_cstring(req, provider)) != 0 || - (r = sshbuf_put_string(req, data, datalen)) != 0 || - (r = sshbuf_put_u32(req, compat)) != 0) - fatal("%s: compose: %s", __func__, ssh_err(r)); - - if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, - SSH_FP_DEFAULT)) == NULL) - fatal("%s: sshkey_fingerprint failed", __func__); - notifier = notify_start(0, - "Confirm user presence for key %s %s", sshkey_type(key), fp); - - if ((r = ssh_msg_send(pair[0], SSH_SK_HELPER_VERSION, req)) != 0) { - error("%s: send: %s", __func__, ssh_err(r)); - goto out; - } - if ((r = ssh_msg_recv(pair[0], resp)) != 0) { - error("%s: receive: %s", __func__, ssh_err(r)); - goto out; - } - if ((r = sshbuf_get_u8(resp, &version)) != 0) { - error("%s: parse version: %s", __func__, ssh_err(r)); - goto out; - } - if (version != SSH_SK_HELPER_VERSION) { - error("%s: unsupported version: got %u, expected %u", - __func__, version, SSH_SK_HELPER_VERSION); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if ((r = sshbuf_get_string(resp, sigp, lenp)) != 0) { - error("%s: parse signature: %s", __func__, ssh_err(r)); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (sshbuf_len(resp) != 0) { - error("%s: trailing data in response", __func__); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - /* success */ - r = 0; - out: - while (waitpid(pid, &status, 0) == -1) { - if (errno != EINTR) - fatal("%s: waitpid: %s", __func__, ssh_err(r)); - } - notify_complete(notifier); - if (!WIFEXITED(status)) { - error("%s: helper %s exited abnormally", __func__, helper); - if (r == 0) - r = SSH_ERR_SYSTEM_ERROR; - } else if (WEXITSTATUS(status) != 0) { - error("%s: helper %s exited with non-zero exit status", - __func__, helper); - if (r == 0) - r = SSH_ERR_SYSTEM_ERROR; - } - if (r != 0) { - freezero(*sigp, *lenp); - *sigp = NULL; - *lenp = 0; - } - sshbuf_free(kbuf); - sshbuf_free(req); - sshbuf_free(resp); - return r; -} - /* ssh2 only */ static void process_sign_request2(SocketEntry *e) @@ -415,9 +291,11 @@ process_sign_request2(SocketEntry *e) size_t dlen, slen = 0; u_int compat = 0, flags; int r, ok = -1; + char *fp = NULL; struct sshbuf *msg; struct sshkey *key = NULL; struct identity *id; + struct notifier_ctx *notifier = NULL; if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); @@ -436,25 +314,27 @@ process_sign_request2(SocketEntry *e) verbose("%s: user refused key", __func__); goto send; } - if (id->sk_provider != NULL) { - if ((r = provider_sign(id->sk_provider, id->key, &signature, - &slen, data, dlen, agent_decode_alg(key, flags), - compat)) != 0) { - error("%s: sign: %s", __func__, ssh_err(r)); - goto send; - } - } else { - if ((r = sshkey_sign(id->key, &signature, &slen, - data, dlen, agent_decode_alg(key, flags), - NULL, compat)) != 0) { - error("%s: sshkey_sign: %s", __func__, ssh_err(r)); - goto send; - } + if (sshkey_is_sk(id->key) && + (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { + if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, + SSH_FP_DEFAULT)) == NULL) + fatal("%s: fingerprint failed", __func__); + notifier = notify_start(0, + "Confirm user presence for key %s %s", + sshkey_type(id->key), fp); + } + if ((r = sshkey_sign(id->key, &signature, &slen, + data, dlen, agent_decode_alg(key, flags), + id->sk_provider, compat)) != 0) { + error("%s: sshkey_sign: %s", __func__, ssh_err(r)); + goto send; } /* Success */ ok = 0; send: + notify_complete(notifier); sshkey_free(key); + free(fp); if (ok == 0) { if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 || (r = sshbuf_put_string(msg, signature, slen)) != 0) @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-sk.c,v 1.17 2019/11/27 22:32:11 djm Exp $ */ +/* $OpenBSD: ssh-sk.c,v 1.18 2019/12/13 19:09:10 djm Exp $ */ /* * Copyright (c) 2019 Google LLC * @@ -464,7 +464,7 @@ sshsk_ed25519_sig(struct sk_sign_response *resp, struct sshbuf *sig) } int -sshsk_sign(const char *provider_path, const struct sshkey *key, +sshsk_sign(const char *provider_path, struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, u_int compat) { @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-sk.h,v 1.5 2019/11/12 19:31:45 markus Exp $ */ +/* $OpenBSD: ssh-sk.h,v 1.6 2019/12/13 19:09:10 djm Exp $ */ /* * Copyright (c) 2019 Google LLC * @@ -21,9 +21,6 @@ struct sshbuf; struct sshkey; -/* Version of protocol between ssh-agent and ssh-sk-helper */ -#define SSH_SK_HELPER_VERSION 1 - /* * Enroll (generate) a new security-key hosted private key of given type * via the specified provider middleware. @@ -44,7 +41,7 @@ int sshsk_enroll(int type, const char *provider_path, const char *application, * * Returns 0 on success or a ssherr.h error code on failure. */ -int sshsk_sign(const char *provider_path, const struct sshkey *key, +int sshsk_sign(const char *provider_path, struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, u_int compat); @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.c,v 1.96 2019/11/25 00:51:37 djm Exp $ */ +/* $OpenBSD: sshkey.c,v 1.97 2019/12/13 19:09:10 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. @@ -2750,13 +2750,6 @@ sshkey_sign(struct sshkey *key, case KEY_ECDSA: r = ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat); break; -# ifdef ENABLE_SK - case KEY_ECDSA_SK_CERT: - case KEY_ECDSA_SK: - r = sshsk_sign(sk_provider, key, sigp, lenp, data, datalen, - compat); - break; -# endif /* ENABLE_SK */ # endif /* OPENSSL_HAS_ECC */ case KEY_RSA_CERT: case KEY_RSA: @@ -2770,8 +2763,10 @@ sshkey_sign(struct sshkey *key, #ifdef ENABLE_SK case KEY_ED25519_SK: case KEY_ED25519_SK_CERT: - r = sshsk_sign(sk_provider, key, sigp, lenp, data, datalen, - compat); + case KEY_ECDSA_SK_CERT: + case KEY_ECDSA_SK: + r = sshsk_sign(sk_provider, key, sigp, lenp, data, + datalen, compat); break; #endif /* ENABLE_SK */ #ifdef WITH_XMSS @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.h,v 1.40 2019/11/25 00:51:37 djm Exp $ */ +/* $OpenBSD: sshkey.h,v 1.41 2019/12/13 19:09:10 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -51,6 +51,9 @@ #define SSH_RSA_MINIMUM_MODULUS_SIZE 1024 #define SSH_KEY_MAX_SIGN_DATA_SIZE (1 << 20) +/* Version of protocol expected from ssh-sk-helper */ +#define SSH_SK_HELPER_VERSION 1 + struct sshbuf; /* Key types */ |