]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: implement loading of resident keys in ssh-sk-helper
authordjm@openbsd.org <djm@openbsd.org>
Mon, 30 Dec 2019 09:21:59 +0000 (09:21 +0000)
committerDamien Miller <djm@mindrot.org>
Mon, 30 Dec 2019 09:58:19 +0000 (20:58 +1100)
feedback and ok markus@

OpenBSD-Commit-ID: b273c23769ea182c55c4a7b8f9cbd9181722011a

ssh-sk-client.c
ssh-sk-helper.c
sshkey.h

index 8a7ac97c423f5aa2de027d62ccabaf1a5126ff3b..b2f0624552aee9b5a9b1459cbe67037b8c145ad3 100644 (file)
@@ -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;
+}
index 3dc149b950cad72a3c3f5bc78033316fcd612811..ac528cfcf71f7ab35db3812e1ff1e290de886b5b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-sk-helper.c,v 1.4 2019/12/13 19:11:14 djm Exp $ */
+/* $OpenBSD: ssh-sk-helper.c,v 1.5 2019/12/30 09:21:59 djm Exp $ */
 /*
  * Copyright (c) 2019 Google LLC
  *
@@ -148,6 +148,50 @@ process_enroll(struct sshbuf *req)
        return resp;
 }
 
+static struct sshbuf *
+process_load_resident(struct sshbuf *req)
+{
+       int r;
+       char *provider, *pin;
+       struct sshbuf *kbuf, *resp;
+       struct sshkey **keys = NULL;
+       size_t nkeys = 0, i;
+
+       if ((resp = sshbuf_new()) == NULL ||
+           (kbuf = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __progname);
+
+       if ((r = sshbuf_get_cstring(req, &provider, NULL)) != 0 ||
+           (r = sshbuf_get_cstring(req, &pin, NULL)) != 0)
+               fatal("%s: buffer error: %s", __progname, ssh_err(r));
+       if (sshbuf_len(req) != 0)
+               fatal("%s: trailing data in request", __progname);
+
+       if ((r = sshsk_load_resident(provider, pin, &keys, &nkeys)) != 0)
+               fatal("%s: sshsk_load_resident failed: %s",
+                   __progname, ssh_err(r));
+
+       for (i = 0; i < nkeys; i++) {
+               debug("%s: key %zu %s %s", __func__, i,
+                   sshkey_type(keys[i]), keys[i]->sk_application);
+               sshbuf_reset(kbuf);
+               if ((r = sshkey_private_serialize(keys[i], kbuf)) != 0)
+                       fatal("%s: serialize private key: %s",
+                           __progname, ssh_err(r));
+               if ((r = sshbuf_put_stringb(resp, kbuf)) != 0 ||
+                   (r = sshbuf_put_cstring(resp, "")) != 0) /* comment */
+                       fatal("%s: buffer error: %s", __progname, ssh_err(r));
+       }
+
+       for (i = 0; i < nkeys; i++)
+               sshkey_free(keys[i]);
+       free(keys);
+       sshbuf_free(kbuf);
+       free(provider);
+       freezero(pin, strlen(pin));
+       return resp;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -212,6 +256,9 @@ main(int argc, char **argv)
        case SSH_SK_HELPER_ENROLL:
                resp = process_enroll(req);
                break;
+       case SSH_SK_HELPER_LOAD_RESIDENT:
+               resp = process_load_resident(req);
+               break;
        default:
                fatal("%s: unsupported request type %u", __progname, rtype);
        }
index 21ac802dc2e6b858f675b231dbf5b9ec536f16c8..699c6b817a2fdc37ebba77e3ab204b9be617f420 100644 (file)
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.h,v 1.42 2019/12/13 19:11:14 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.43 2019/12/30 09:21:59 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -57,6 +57,7 @@
 /* ssh-sk-helper messages */
 #define SSH_SK_HELPER_SIGN             1
 #define SSH_SK_HELPER_ENROLL           2
+#define SSH_SK_HELPER_LOAD_RESIDENT    3
 
 struct sshbuf;