diff options
-rw-r--r-- | ssh-sk-client.c | 72 | ||||
-rw-r--r-- | ssh-sk-helper.c | 49 | ||||
-rw-r--r-- | sshkey.h | 3 |
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 | |||
335 | int | ||
336 | sshsk_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 | ||
151 | static struct sshbuf * | ||
152 | process_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 | |||
151 | int | 195 | int |
152 | main(int argc, char **argv) | 196 | main(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 | } |
@@ -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 | ||
61 | struct sshbuf; | 62 | struct sshbuf; |
62 | 63 | ||