diff options
-rw-r--r-- | ssh-sk.c | 101 |
1 files changed, 64 insertions, 37 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-sk.c,v 1.18 2019/12/13 19:09:10 djm Exp $ */ | 1 | /* $OpenBSD: ssh-sk.c,v 1.19 2019/12/30 09:20:36 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2019 Google LLC | 3 | * Copyright (c) 2019 Google LLC |
4 | * | 4 | * |
@@ -254,6 +254,65 @@ sshsk_ed25519_assemble(struct sk_enroll_response *resp, struct sshkey **keyp) | |||
254 | return r; | 254 | return r; |
255 | } | 255 | } |
256 | 256 | ||
257 | static int | ||
258 | sshsk_key_from_response(int alg, const char *application, uint8_t flags, | ||
259 | struct sk_enroll_response *resp, struct sshkey **keyp) | ||
260 | { | ||
261 | struct sshkey *key = NULL; | ||
262 | int r = SSH_ERR_INTERNAL_ERROR; | ||
263 | |||
264 | *keyp = NULL; | ||
265 | |||
266 | /* Check response validity */ | ||
267 | if (resp->public_key == NULL || resp->key_handle == NULL || | ||
268 | resp->signature == NULL || | ||
269 | (resp->attestation_cert == NULL && resp->attestation_cert_len != 0)) { | ||
270 | error("%s: sk_enroll response invalid", __func__); | ||
271 | r = SSH_ERR_INVALID_FORMAT; | ||
272 | goto out; | ||
273 | } | ||
274 | switch (alg) { | ||
275 | #ifdef WITH_OPENSSL | ||
276 | case SSH_SK_ECDSA: | ||
277 | if ((r = sshsk_ecdsa_assemble(resp, &key)) != 0) | ||
278 | goto out; | ||
279 | break; | ||
280 | #endif /* WITH_OPENSSL */ | ||
281 | case SSH_SK_ED25519: | ||
282 | if ((r = sshsk_ed25519_assemble(resp, &key)) != 0) | ||
283 | goto out; | ||
284 | break; | ||
285 | default: | ||
286 | error("%s: unsupported algorithm %d", __func__, alg); | ||
287 | r = SSH_ERR_INVALID_ARGUMENT; | ||
288 | goto out; | ||
289 | } | ||
290 | key->sk_flags = flags; | ||
291 | if ((key->sk_key_handle = sshbuf_new()) == NULL || | ||
292 | (key->sk_reserved = sshbuf_new()) == NULL) { | ||
293 | error("%s: allocation failed", __func__); | ||
294 | r = SSH_ERR_ALLOC_FAIL; | ||
295 | goto out; | ||
296 | } | ||
297 | if ((key->sk_application = strdup(application)) == NULL) { | ||
298 | error("%s: strdup application failed", __func__); | ||
299 | r = SSH_ERR_ALLOC_FAIL; | ||
300 | goto out; | ||
301 | } | ||
302 | if ((r = sshbuf_put(key->sk_key_handle, resp->key_handle, | ||
303 | resp->key_handle_len)) != 0) { | ||
304 | error("%s: buffer error: %s", __func__, ssh_err(r)); | ||
305 | goto out; | ||
306 | } | ||
307 | /* success */ | ||
308 | r = 0; | ||
309 | *keyp = key; | ||
310 | key = NULL; | ||
311 | out: | ||
312 | sshkey_free(key); | ||
313 | return r; | ||
314 | } | ||
315 | |||
257 | int | 316 | int |
258 | sshsk_enroll(int type, const char *provider_path, const char *application, | 317 | sshsk_enroll(int type, const char *provider_path, const char *application, |
259 | uint8_t flags, struct sshbuf *challenge_buf, struct sshkey **keyp, | 318 | uint8_t flags, struct sshbuf *challenge_buf, struct sshkey **keyp, |
@@ -327,43 +386,11 @@ sshsk_enroll(int type, const char *provider_path, const char *application, | |||
327 | r = SSH_ERR_INVALID_FORMAT; /* XXX error codes in API? */ | 386 | r = SSH_ERR_INVALID_FORMAT; /* XXX error codes in API? */ |
328 | goto out; | 387 | goto out; |
329 | } | 388 | } |
330 | /* Check response validity */ | 389 | |
331 | if (resp->public_key == NULL || resp->key_handle == NULL || | 390 | if ((r = sshsk_key_from_response(alg, application, flags, |
332 | resp->signature == NULL || | 391 | resp, &key)) != 0) |
333 | (resp->attestation_cert == NULL && resp->attestation_cert_len != 0)) { | ||
334 | error("%s: sk_enroll response invalid", __func__); | ||
335 | r = SSH_ERR_INVALID_FORMAT; | ||
336 | goto out; | ||
337 | } | ||
338 | switch (type) { | ||
339 | #ifdef WITH_OPENSSL | ||
340 | case KEY_ECDSA_SK: | ||
341 | if ((r = sshsk_ecdsa_assemble(resp, &key)) != 0) | ||
342 | goto out; | ||
343 | break; | ||
344 | #endif /* WITH_OPENSSL */ | ||
345 | case KEY_ED25519_SK: | ||
346 | if ((r = sshsk_ed25519_assemble(resp, &key)) != 0) | ||
347 | goto out; | ||
348 | break; | ||
349 | } | ||
350 | key->sk_flags = flags; | ||
351 | if ((key->sk_key_handle = sshbuf_new()) == NULL || | ||
352 | (key->sk_reserved = sshbuf_new()) == NULL) { | ||
353 | error("%s: allocation failed", __func__); | ||
354 | r = SSH_ERR_ALLOC_FAIL; | ||
355 | goto out; | ||
356 | } | ||
357 | if ((key->sk_application = strdup(application)) == NULL) { | ||
358 | error("%s: strdup application failed", __func__); | ||
359 | r = SSH_ERR_ALLOC_FAIL; | ||
360 | goto out; | ||
361 | } | ||
362 | if ((r = sshbuf_put(key->sk_key_handle, resp->key_handle, | ||
363 | resp->key_handle_len)) != 0) { | ||
364 | error("%s: buffer error: %s", __func__, ssh_err(r)); | ||
365 | goto out; | 392 | goto out; |
366 | } | 393 | |
367 | /* Optionally fill in the attestation information */ | 394 | /* Optionally fill in the attestation information */ |
368 | if (attest != NULL) { | 395 | if (attest != NULL) { |
369 | if ((r = sshbuf_put_cstring(attest, "sk-attest-v00")) != 0 || | 396 | if ((r = sshbuf_put_cstring(attest, "sk-attest-v00")) != 0 || |