diff options
-rw-r--r-- | ssh-agent.c | 160 | ||||
-rw-r--r-- | ssh-sk.c | 4 | ||||
-rw-r--r-- | ssh-sk.h | 7 | ||||
-rw-r--r-- | sshkey.c | 15 | ||||
-rw-r--r-- | sshkey.h | 5 |
5 files changed, 33 insertions, 158 deletions
diff --git a/ssh-agent.c b/ssh-agent.c index 1d4b779f6..09d12dc3f 100644 --- a/ssh-agent.c +++ b/ssh-agent.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-agent.c,v 1.250 2019/11/19 16:02:32 jmc Exp $ */ | 1 | /* $OpenBSD: ssh-agent.c,v 1.251 2019/12/13 19:09:10 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -90,7 +90,7 @@ | |||
90 | #include "ssherr.h" | 90 | #include "ssherr.h" |
91 | #include "pathnames.h" | 91 | #include "pathnames.h" |
92 | #include "ssh-pkcs11.h" | 92 | #include "ssh-pkcs11.h" |
93 | #include "ssh-sk.h" | 93 | #include "sk-api.h" |
94 | 94 | ||
95 | #ifndef DEFAULT_PROVIDER_WHITELIST | 95 | #ifndef DEFAULT_PROVIDER_WHITELIST |
96 | # define DEFAULT_PROVIDER_WHITELIST "/usr/lib*/*,/usr/local/lib*/*" | 96 | # define DEFAULT_PROVIDER_WHITELIST "/usr/lib*/*,/usr/local/lib*/*" |
@@ -282,130 +282,6 @@ agent_decode_alg(struct sshkey *key, u_int flags) | |||
282 | return NULL; | 282 | return NULL; |
283 | } | 283 | } |
284 | 284 | ||
285 | static int | ||
286 | provider_sign(const char *provider, struct sshkey *key, | ||
287 | u_char **sigp, size_t *lenp, | ||
288 | const u_char *data, size_t datalen, | ||
289 | const char *alg, u_int compat) | ||
290 | { | ||
291 | int status, pair[2], r = SSH_ERR_INTERNAL_ERROR; | ||
292 | pid_t pid; | ||
293 | char *helper, *verbosity = NULL, *fp = NULL; | ||
294 | struct sshbuf *kbuf, *req, *resp; | ||
295 | u_char version; | ||
296 | struct notifier_ctx *notifier = NULL; | ||
297 | |||
298 | debug3("%s: start for provider %s", __func__, provider); | ||
299 | |||
300 | *sigp = NULL; | ||
301 | *lenp = 0; | ||
302 | |||
303 | helper = getenv("SSH_SK_HELPER"); | ||
304 | if (helper == NULL || strlen(helper) == 0) | ||
305 | helper = _PATH_SSH_SK_HELPER; | ||
306 | if (log_level_get() >= SYSLOG_LEVEL_DEBUG1) | ||
307 | verbosity = "-vvv"; | ||
308 | |||
309 | /* Start helper */ | ||
310 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { | ||
311 | error("socketpair: %s", strerror(errno)); | ||
312 | return SSH_ERR_SYSTEM_ERROR; | ||
313 | } | ||
314 | if ((pid = fork()) == -1) { | ||
315 | error("fork: %s", strerror(errno)); | ||
316 | close(pair[0]); | ||
317 | close(pair[1]); | ||
318 | return SSH_ERR_SYSTEM_ERROR; | ||
319 | } | ||
320 | if (pid == 0) { | ||
321 | if ((dup2(pair[1], STDIN_FILENO) == -1) || | ||
322 | (dup2(pair[1], STDOUT_FILENO) == -1)) | ||
323 | fatal("%s: dup2: %s", __func__, ssh_err(r)); | ||
324 | close(pair[0]); | ||
325 | close(pair[1]); | ||
326 | closefrom(STDERR_FILENO + 1); | ||
327 | debug("%s: starting %s %s", __func__, helper, | ||
328 | verbosity == NULL ? "" : verbosity); | ||
329 | execlp(helper, helper, verbosity, (char *)NULL); | ||
330 | fatal("%s: execlp: %s", __func__, strerror(errno)); | ||
331 | } | ||
332 | close(pair[1]); | ||
333 | |||
334 | if ((kbuf = sshbuf_new()) == NULL || | ||
335 | (req = sshbuf_new()) == NULL || | ||
336 | (resp = sshbuf_new()) == NULL) | ||
337 | fatal("%s: sshbuf_new failed", __func__); | ||
338 | |||
339 | if ((r = sshkey_private_serialize(key, kbuf)) != 0 || | ||
340 | (r = sshbuf_put_stringb(req, kbuf)) != 0 || | ||
341 | (r = sshbuf_put_cstring(req, provider)) != 0 || | ||
342 | (r = sshbuf_put_string(req, data, datalen)) != 0 || | ||
343 | (r = sshbuf_put_u32(req, compat)) != 0) | ||
344 | fatal("%s: compose: %s", __func__, ssh_err(r)); | ||
345 | |||
346 | if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, | ||
347 | SSH_FP_DEFAULT)) == NULL) | ||
348 | fatal("%s: sshkey_fingerprint failed", __func__); | ||
349 | notifier = notify_start(0, | ||
350 | "Confirm user presence for key %s %s", sshkey_type(key), fp); | ||
351 | |||
352 | if ((r = ssh_msg_send(pair[0], SSH_SK_HELPER_VERSION, req)) != 0) { | ||
353 | error("%s: send: %s", __func__, ssh_err(r)); | ||
354 | goto out; | ||
355 | } | ||
356 | if ((r = ssh_msg_recv(pair[0], resp)) != 0) { | ||
357 | error("%s: receive: %s", __func__, ssh_err(r)); | ||
358 | goto out; | ||
359 | } | ||
360 | if ((r = sshbuf_get_u8(resp, &version)) != 0) { | ||
361 | error("%s: parse version: %s", __func__, ssh_err(r)); | ||
362 | goto out; | ||
363 | } | ||
364 | if (version != SSH_SK_HELPER_VERSION) { | ||
365 | error("%s: unsupported version: got %u, expected %u", | ||
366 | __func__, version, SSH_SK_HELPER_VERSION); | ||
367 | r = SSH_ERR_INVALID_FORMAT; | ||
368 | goto out; | ||
369 | } | ||
370 | if ((r = sshbuf_get_string(resp, sigp, lenp)) != 0) { | ||
371 | error("%s: parse signature: %s", __func__, ssh_err(r)); | ||
372 | r = SSH_ERR_INVALID_FORMAT; | ||
373 | goto out; | ||
374 | } | ||
375 | if (sshbuf_len(resp) != 0) { | ||
376 | error("%s: trailing data in response", __func__); | ||
377 | r = SSH_ERR_INVALID_FORMAT; | ||
378 | goto out; | ||
379 | } | ||
380 | /* success */ | ||
381 | r = 0; | ||
382 | out: | ||
383 | while (waitpid(pid, &status, 0) == -1) { | ||
384 | if (errno != EINTR) | ||
385 | fatal("%s: waitpid: %s", __func__, ssh_err(r)); | ||
386 | } | ||
387 | notify_complete(notifier); | ||
388 | if (!WIFEXITED(status)) { | ||
389 | error("%s: helper %s exited abnormally", __func__, helper); | ||
390 | if (r == 0) | ||
391 | r = SSH_ERR_SYSTEM_ERROR; | ||
392 | } else if (WEXITSTATUS(status) != 0) { | ||
393 | error("%s: helper %s exited with non-zero exit status", | ||
394 | __func__, helper); | ||
395 | if (r == 0) | ||
396 | r = SSH_ERR_SYSTEM_ERROR; | ||
397 | } | ||
398 | if (r != 0) { | ||
399 | freezero(*sigp, *lenp); | ||
400 | *sigp = NULL; | ||
401 | *lenp = 0; | ||
402 | } | ||
403 | sshbuf_free(kbuf); | ||
404 | sshbuf_free(req); | ||
405 | sshbuf_free(resp); | ||
406 | return r; | ||
407 | } | ||
408 | |||
409 | /* ssh2 only */ | 285 | /* ssh2 only */ |
410 | static void | 286 | static void |
411 | process_sign_request2(SocketEntry *e) | 287 | process_sign_request2(SocketEntry *e) |
@@ -415,9 +291,11 @@ process_sign_request2(SocketEntry *e) | |||
415 | size_t dlen, slen = 0; | 291 | size_t dlen, slen = 0; |
416 | u_int compat = 0, flags; | 292 | u_int compat = 0, flags; |
417 | int r, ok = -1; | 293 | int r, ok = -1; |
294 | char *fp = NULL; | ||
418 | struct sshbuf *msg; | 295 | struct sshbuf *msg; |
419 | struct sshkey *key = NULL; | 296 | struct sshkey *key = NULL; |
420 | struct identity *id; | 297 | struct identity *id; |
298 | struct notifier_ctx *notifier = NULL; | ||
421 | 299 | ||
422 | if ((msg = sshbuf_new()) == NULL) | 300 | if ((msg = sshbuf_new()) == NULL) |
423 | fatal("%s: sshbuf_new failed", __func__); | 301 | fatal("%s: sshbuf_new failed", __func__); |
@@ -436,25 +314,27 @@ process_sign_request2(SocketEntry *e) | |||
436 | verbose("%s: user refused key", __func__); | 314 | verbose("%s: user refused key", __func__); |
437 | goto send; | 315 | goto send; |
438 | } | 316 | } |
439 | if (id->sk_provider != NULL) { | 317 | if (sshkey_is_sk(id->key) && |
440 | if ((r = provider_sign(id->sk_provider, id->key, &signature, | 318 | (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { |
441 | &slen, data, dlen, agent_decode_alg(key, flags), | 319 | if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, |
442 | compat)) != 0) { | 320 | SSH_FP_DEFAULT)) == NULL) |
443 | error("%s: sign: %s", __func__, ssh_err(r)); | 321 | fatal("%s: fingerprint failed", __func__); |
444 | goto send; | 322 | notifier = notify_start(0, |
445 | } | 323 | "Confirm user presence for key %s %s", |
446 | } else { | 324 | sshkey_type(id->key), fp); |
447 | if ((r = sshkey_sign(id->key, &signature, &slen, | 325 | } |
448 | data, dlen, agent_decode_alg(key, flags), | 326 | if ((r = sshkey_sign(id->key, &signature, &slen, |
449 | NULL, compat)) != 0) { | 327 | data, dlen, agent_decode_alg(key, flags), |
450 | error("%s: sshkey_sign: %s", __func__, ssh_err(r)); | 328 | id->sk_provider, compat)) != 0) { |
451 | goto send; | 329 | error("%s: sshkey_sign: %s", __func__, ssh_err(r)); |
452 | } | 330 | goto send; |
453 | } | 331 | } |
454 | /* Success */ | 332 | /* Success */ |
455 | ok = 0; | 333 | ok = 0; |
456 | send: | 334 | send: |
335 | notify_complete(notifier); | ||
457 | sshkey_free(key); | 336 | sshkey_free(key); |
337 | free(fp); | ||
458 | if (ok == 0) { | 338 | if (ok == 0) { |
459 | if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 || | 339 | if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 || |
460 | (r = sshbuf_put_string(msg, signature, slen)) != 0) | 340 | (r = sshbuf_put_string(msg, signature, slen)) != 0) |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-sk.c,v 1.17 2019/11/27 22:32:11 djm Exp $ */ | 1 | /* $OpenBSD: ssh-sk.c,v 1.18 2019/12/13 19:09:10 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2019 Google LLC | 3 | * Copyright (c) 2019 Google LLC |
4 | * | 4 | * |
@@ -464,7 +464,7 @@ sshsk_ed25519_sig(struct sk_sign_response *resp, struct sshbuf *sig) | |||
464 | } | 464 | } |
465 | 465 | ||
466 | int | 466 | int |
467 | sshsk_sign(const char *provider_path, const struct sshkey *key, | 467 | sshsk_sign(const char *provider_path, struct sshkey *key, |
468 | u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, | 468 | u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, |
469 | u_int compat) | 469 | u_int compat) |
470 | { | 470 | { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-sk.h,v 1.5 2019/11/12 19:31:45 markus Exp $ */ | 1 | /* $OpenBSD: ssh-sk.h,v 1.6 2019/12/13 19:09:10 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2019 Google LLC | 3 | * Copyright (c) 2019 Google LLC |
4 | * | 4 | * |
@@ -21,9 +21,6 @@ | |||
21 | struct sshbuf; | 21 | struct sshbuf; |
22 | struct sshkey; | 22 | struct sshkey; |
23 | 23 | ||
24 | /* Version of protocol between ssh-agent and ssh-sk-helper */ | ||
25 | #define SSH_SK_HELPER_VERSION 1 | ||
26 | |||
27 | /* | 24 | /* |
28 | * Enroll (generate) a new security-key hosted private key of given type | 25 | * Enroll (generate) a new security-key hosted private key of given type |
29 | * via the specified provider middleware. | 26 | * via the specified provider middleware. |
@@ -44,7 +41,7 @@ int sshsk_enroll(int type, const char *provider_path, const char *application, | |||
44 | * | 41 | * |
45 | * Returns 0 on success or a ssherr.h error code on failure. | 42 | * Returns 0 on success or a ssherr.h error code on failure. |
46 | */ | 43 | */ |
47 | int sshsk_sign(const char *provider_path, const struct sshkey *key, | 44 | int sshsk_sign(const char *provider_path, struct sshkey *key, |
48 | u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, | 45 | u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, |
49 | u_int compat); | 46 | u_int compat); |
50 | 47 | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshkey.c,v 1.96 2019/11/25 00:51:37 djm Exp $ */ | 1 | /* $OpenBSD: sshkey.c,v 1.97 2019/12/13 19:09:10 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. | 4 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. |
@@ -2750,13 +2750,6 @@ sshkey_sign(struct sshkey *key, | |||
2750 | case KEY_ECDSA: | 2750 | case KEY_ECDSA: |
2751 | r = ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat); | 2751 | r = ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat); |
2752 | break; | 2752 | break; |
2753 | # ifdef ENABLE_SK | ||
2754 | case KEY_ECDSA_SK_CERT: | ||
2755 | case KEY_ECDSA_SK: | ||
2756 | r = sshsk_sign(sk_provider, key, sigp, lenp, data, datalen, | ||
2757 | compat); | ||
2758 | break; | ||
2759 | # endif /* ENABLE_SK */ | ||
2760 | # endif /* OPENSSL_HAS_ECC */ | 2753 | # endif /* OPENSSL_HAS_ECC */ |
2761 | case KEY_RSA_CERT: | 2754 | case KEY_RSA_CERT: |
2762 | case KEY_RSA: | 2755 | case KEY_RSA: |
@@ -2770,8 +2763,10 @@ sshkey_sign(struct sshkey *key, | |||
2770 | #ifdef ENABLE_SK | 2763 | #ifdef ENABLE_SK |
2771 | case KEY_ED25519_SK: | 2764 | case KEY_ED25519_SK: |
2772 | case KEY_ED25519_SK_CERT: | 2765 | case KEY_ED25519_SK_CERT: |
2773 | r = sshsk_sign(sk_provider, key, sigp, lenp, data, datalen, | 2766 | case KEY_ECDSA_SK_CERT: |
2774 | compat); | 2767 | case KEY_ECDSA_SK: |
2768 | r = sshsk_sign(sk_provider, key, sigp, lenp, data, | ||
2769 | datalen, compat); | ||
2775 | break; | 2770 | break; |
2776 | #endif /* ENABLE_SK */ | 2771 | #endif /* ENABLE_SK */ |
2777 | #ifdef WITH_XMSS | 2772 | #ifdef WITH_XMSS |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshkey.h,v 1.40 2019/11/25 00:51:37 djm Exp $ */ | 1 | /* $OpenBSD: sshkey.h,v 1.41 2019/12/13 19:09:10 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. |
@@ -51,6 +51,9 @@ | |||
51 | #define SSH_RSA_MINIMUM_MODULUS_SIZE 1024 | 51 | #define SSH_RSA_MINIMUM_MODULUS_SIZE 1024 |
52 | #define SSH_KEY_MAX_SIGN_DATA_SIZE (1 << 20) | 52 | #define SSH_KEY_MAX_SIGN_DATA_SIZE (1 << 20) |
53 | 53 | ||
54 | /* Version of protocol expected from ssh-sk-helper */ | ||
55 | #define SSH_SK_HELPER_VERSION 1 | ||
56 | |||
54 | struct sshbuf; | 57 | struct sshbuf; |
55 | 58 | ||
56 | /* Key types */ | 59 | /* Key types */ |