summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ssh-sk-client.c72
-rw-r--r--ssh-sk-helper.c49
-rw-r--r--sshkey.h3
3 files changed, 121 insertions, 3 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 @@
1/* $OpenBSD: ssh-sk-client.c,v 1.1 2019/12/13 20:16:56 djm Exp $ */ 1/* $OpenBSD: ssh-sk-client.c,v 1.2 2019/12/30 09:21:59 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2019 Google LLC 3 * Copyright (c) 2019 Google LLC
4 * 4 *
@@ -331,3 +331,73 @@ sshsk_enroll(int type, const char *provider_path, const char *application,
331 errno = oerrno; 331 errno = oerrno;
332 return r; 332 return r;
333} 333}
334
335int
336sshsk_load_resident(const char *provider_path, const char *pin,
337 struct sshkey ***keysp, size_t *nkeysp)
338{
339 int oerrno, r = SSH_ERR_INTERNAL_ERROR;
340 struct sshbuf *kbuf = NULL, *req = NULL, *resp = NULL;
341 struct sshkey *key = NULL, **keys = NULL, **tmp;
342 size_t i, nkeys = 0;
343
344 *keysp = NULL;
345 *nkeysp = 0;
346
347 if ((resp = sshbuf_new()) == NULL ||
348 (kbuf = sshbuf_new()) == NULL ||
349 (req = sshbuf_new()) == NULL) {
350 r = SSH_ERR_ALLOC_FAIL;
351 goto out;
352 }
353
354 if ((r = sshbuf_put_u32(req, SSH_SK_HELPER_LOAD_RESIDENT)) != 0 ||
355 (r = sshbuf_put_cstring(req, provider_path)) != 0 ||
356 (r = sshbuf_put_cstring(req, pin)) != 0) {
357 error("%s: compose: %s", __func__, ssh_err(r));
358 goto out;
359 }
360
361 if ((r = client_converse(req, &resp)) != 0)
362 goto out;
363
364 while (sshbuf_len(resp) != 0) {
365 /* key, comment */
366 if ((r = sshbuf_get_stringb(resp, kbuf)) != 0 ||
367 (r = sshbuf_get_cstring(resp, NULL, NULL)) != 0) {
368 error("%s: parse signature: %s", __func__, ssh_err(r));
369 r = SSH_ERR_INVALID_FORMAT;
370 goto out;
371 }
372 if ((r = sshkey_private_deserialize(kbuf, &key)) != 0) {
373 error("Unable to parse private key: %s", ssh_err(r));
374 goto out;
375 }
376 if ((tmp = recallocarray(keys, nkeys, nkeys + 1,
377 sizeof(*keys))) == NULL) {
378 error("%s: recallocarray keys failed", __func__);
379 goto out;
380 }
381 keys = tmp;
382 keys[nkeys++] = key;
383 key = NULL;
384 }
385
386 /* success */
387 r = 0;
388 *keysp = keys;
389 *nkeysp = nkeys;
390 keys = NULL;
391 nkeys = 0;
392 out:
393 oerrno = errno;
394 for (i = 0; i < nkeys; i++)
395 sshkey_free(keys[i]);
396 free(keys);
397 sshkey_free(key);
398 sshbuf_free(kbuf);
399 sshbuf_free(req);
400 sshbuf_free(resp);
401 errno = oerrno;
402 return r;
403}
diff --git a/ssh-sk-helper.c b/ssh-sk-helper.c
index 3dc149b95..ac528cfcf 100644
--- a/ssh-sk-helper.c
+++ b/ssh-sk-helper.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-sk-helper.c,v 1.4 2019/12/13 19:11:14 djm Exp $ */ 1/* $OpenBSD: ssh-sk-helper.c,v 1.5 2019/12/30 09:21:59 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2019 Google LLC 3 * Copyright (c) 2019 Google LLC
4 * 4 *
@@ -148,6 +148,50 @@ process_enroll(struct sshbuf *req)
148 return resp; 148 return resp;
149} 149}
150 150
151static struct sshbuf *
152process_load_resident(struct sshbuf *req)
153{
154 int r;
155 char *provider, *pin;
156 struct sshbuf *kbuf, *resp;
157 struct sshkey **keys = NULL;
158 size_t nkeys = 0, i;
159
160 if ((resp = sshbuf_new()) == NULL ||
161 (kbuf = sshbuf_new()) == NULL)
162 fatal("%s: sshbuf_new failed", __progname);
163
164 if ((r = sshbuf_get_cstring(req, &provider, NULL)) != 0 ||
165 (r = sshbuf_get_cstring(req, &pin, NULL)) != 0)
166 fatal("%s: buffer error: %s", __progname, ssh_err(r));
167 if (sshbuf_len(req) != 0)
168 fatal("%s: trailing data in request", __progname);
169
170 if ((r = sshsk_load_resident(provider, pin, &keys, &nkeys)) != 0)
171 fatal("%s: sshsk_load_resident failed: %s",
172 __progname, ssh_err(r));
173
174 for (i = 0; i < nkeys; i++) {
175 debug("%s: key %zu %s %s", __func__, i,
176 sshkey_type(keys[i]), keys[i]->sk_application);
177 sshbuf_reset(kbuf);
178 if ((r = sshkey_private_serialize(keys[i], kbuf)) != 0)
179 fatal("%s: serialize private key: %s",
180 __progname, ssh_err(r));
181 if ((r = sshbuf_put_stringb(resp, kbuf)) != 0 ||
182 (r = sshbuf_put_cstring(resp, "")) != 0) /* comment */
183 fatal("%s: buffer error: %s", __progname, ssh_err(r));
184 }
185
186 for (i = 0; i < nkeys; i++)
187 sshkey_free(keys[i]);
188 free(keys);
189 sshbuf_free(kbuf);
190 free(provider);
191 freezero(pin, strlen(pin));
192 return resp;
193}
194
151int 195int
152main(int argc, char **argv) 196main(int argc, char **argv)
153{ 197{
@@ -212,6 +256,9 @@ main(int argc, char **argv)
212 case SSH_SK_HELPER_ENROLL: 256 case SSH_SK_HELPER_ENROLL:
213 resp = process_enroll(req); 257 resp = process_enroll(req);
214 break; 258 break;
259 case SSH_SK_HELPER_LOAD_RESIDENT:
260 resp = process_load_resident(req);
261 break;
215 default: 262 default:
216 fatal("%s: unsupported request type %u", __progname, rtype); 263 fatal("%s: unsupported request type %u", __progname, rtype);
217 } 264 }
diff --git a/sshkey.h b/sshkey.h
index 21ac802dc..699c6b817 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.h,v 1.42 2019/12/13 19:11:14 djm Exp $ */ 1/* $OpenBSD: sshkey.h,v 1.43 2019/12/30 09:21:59 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -57,6 +57,7 @@
57/* ssh-sk-helper messages */ 57/* ssh-sk-helper messages */
58#define SSH_SK_HELPER_SIGN 1 58#define SSH_SK_HELPER_SIGN 1
59#define SSH_SK_HELPER_ENROLL 2 59#define SSH_SK_HELPER_ENROLL 2
60#define SSH_SK_HELPER_LOAD_RESIDENT 3
60 61
61struct sshbuf; 62struct sshbuf;
62 63