diff options
author | djm@openbsd.org <djm@openbsd.org> | 2019-12-30 10:21:59 +0100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2019-12-30 10:58:19 +0100 |
commit | 27753a8e21887d47fe6b5c78a4aed0efe558a850 (patch) | |
tree | 761ebebce5fb94c32eef432db246abd81865c7d0 /ssh-sk-client.c | |
parent | upstream: resident keys support in SK API (diff) | |
download | openssh-27753a8e21887d47fe6b5c78a4aed0efe558a850.tar.xz openssh-27753a8e21887d47fe6b5c78a4aed0efe558a850.zip |
upstream: implement loading of resident keys in ssh-sk-helper
feedback and ok markus@
OpenBSD-Commit-ID: b273c23769ea182c55c4a7b8f9cbd9181722011a
Diffstat (limited to 'ssh-sk-client.c')
-rw-r--r-- | ssh-sk-client.c | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/ssh-sk-client.c b/ssh-sk-client.c index 8a7ac97c4..b2f062455 100644 --- a/ssh-sk-client.c +++ b/ssh-sk-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-sk-client.c,v 1.1 2019/12/13 20:16:56 djm Exp $ */ +/* $OpenBSD: ssh-sk-client.c,v 1.2 2019/12/30 09:21:59 djm Exp $ */ /* * Copyright (c) 2019 Google LLC * @@ -331,3 +331,73 @@ sshsk_enroll(int type, const char *provider_path, const char *application, errno = oerrno; return r; } + +int +sshsk_load_resident(const char *provider_path, const char *pin, + struct sshkey ***keysp, size_t *nkeysp) +{ + int oerrno, r = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *kbuf = NULL, *req = NULL, *resp = NULL; + struct sshkey *key = NULL, **keys = NULL, **tmp; + size_t i, nkeys = 0; + + *keysp = NULL; + *nkeysp = 0; + + if ((resp = sshbuf_new()) == NULL || + (kbuf = sshbuf_new()) == NULL || + (req = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + + if ((r = sshbuf_put_u32(req, SSH_SK_HELPER_LOAD_RESIDENT)) != 0 || + (r = sshbuf_put_cstring(req, provider_path)) != 0 || + (r = sshbuf_put_cstring(req, pin)) != 0) { + error("%s: compose: %s", __func__, ssh_err(r)); + goto out; + } + + if ((r = client_converse(req, &resp)) != 0) + goto out; + + while (sshbuf_len(resp) != 0) { + /* key, comment */ + if ((r = sshbuf_get_stringb(resp, kbuf)) != 0 || + (r = sshbuf_get_cstring(resp, NULL, NULL)) != 0) { + error("%s: parse signature: %s", __func__, ssh_err(r)); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((r = sshkey_private_deserialize(kbuf, &key)) != 0) { + error("Unable to parse private key: %s", ssh_err(r)); + goto out; + } + if ((tmp = recallocarray(keys, nkeys, nkeys + 1, + sizeof(*keys))) == NULL) { + error("%s: recallocarray keys failed", __func__); + goto out; + } + keys = tmp; + keys[nkeys++] = key; + key = NULL; + } + + /* success */ + r = 0; + *keysp = keys; + *nkeysp = nkeys; + keys = NULL; + nkeys = 0; + out: + oerrno = errno; + for (i = 0; i < nkeys; i++) + sshkey_free(keys[i]); + free(keys); + sshkey_free(key); + sshbuf_free(kbuf); + sshbuf_free(req); + sshbuf_free(resp); + errno = oerrno; + return r; +} |