summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2020-01-25 23:13:09 +0000
committerDamien Miller <djm@mindrot.org>2020-01-26 10:18:42 +1100
commit59d01f1d720ebede4da42882f592d1093dac7adc (patch)
treed79871dcec88b95a6df86dd6821cbdf5e467f719
parent99aa8035554ddb976348d2a9253ab3653019728d (diff)
upstream: improve the error message for u2f enrollment errors by
making ssh-keygen be solely responsible for printing the error message and convertint some more common error responses from the middleware to a useful ssherr.h status code. more detail remains visible via -v of course. also remove indepedent copy of sk-api.h declarations in sk-usbhid.c and just include it. feedback & ok markus@ OpenBSD-Commit-ID: a4a8ffa870d9a3e0cfd76544bcdeef5c9fb1f1bb
-rw-r--r--PROTOCOL.u2f1
-rw-r--r--sk-api.h3
-rw-r--r--sk-usbhid.c99
-rw-r--r--ssh-keygen.c4
-rw-r--r--ssh-sk-helper.c4
-rw-r--r--ssh-sk.c6
-rw-r--r--ssherr.c4
-rw-r--r--ssherr.h3
8 files changed, 43 insertions, 81 deletions
diff --git a/PROTOCOL.u2f b/PROTOCOL.u2f
index fd0cd0de0..58f75ba28 100644
--- a/PROTOCOL.u2f
+++ b/PROTOCOL.u2f
@@ -249,6 +249,7 @@ The middleware library need only expose a handful of functions:
249 #define SSH_SK_ERR_GENERAL -1 249 #define SSH_SK_ERR_GENERAL -1
250 #define SSH_SK_ERR_UNSUPPORTED -2 250 #define SSH_SK_ERR_UNSUPPORTED -2
251 #define SSH_SK_ERR_PIN_REQUIRED -3 251 #define SSH_SK_ERR_PIN_REQUIRED -3
252 #define SSH_SK_ERR_DEVICE_NOT_FOUND -4
252 253
253 struct sk_enroll_response { 254 struct sk_enroll_response {
254 uint8_t *public_key; 255 uint8_t *public_key;
diff --git a/sk-api.h b/sk-api.h
index 93d6a1229..170fd4470 100644
--- a/sk-api.h
+++ b/sk-api.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: sk-api.h,v 1.7 2020/01/06 02:00:46 djm Exp $ */ 1/* $OpenBSD: sk-api.h,v 1.8 2020/01/25 23:13:09 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2019 Google LLC 3 * Copyright (c) 2019 Google LLC
4 * 4 *
@@ -36,6 +36,7 @@
36#define SSH_SK_ERR_GENERAL -1 36#define SSH_SK_ERR_GENERAL -1
37#define SSH_SK_ERR_UNSUPPORTED -2 37#define SSH_SK_ERR_UNSUPPORTED -2
38#define SSH_SK_ERR_PIN_REQUIRED -3 38#define SSH_SK_ERR_PIN_REQUIRED -3
39#define SSH_SK_ERR_DEVICE_NOT_FOUND -4
39 40
40struct sk_enroll_response { 41struct sk_enroll_response {
41 uint8_t *public_key; 42 uint8_t *public_key;
diff --git a/sk-usbhid.c b/sk-usbhid.c
index cf783e205..2148e1d79 100644
--- a/sk-usbhid.c
+++ b/sk-usbhid.c
@@ -37,9 +37,19 @@
37#include <fido/credman.h> 37#include <fido/credman.h>
38 38
39#ifndef SK_STANDALONE 39#ifndef SK_STANDALONE
40#include "log.h" 40# include "log.h"
41#include "xmalloc.h" 41# include "xmalloc.h"
42#endif 42/*
43 * If building as part of OpenSSH, then rename exported functions.
44 * This must be done before including sk-api.h.
45 */
46# define sk_api_version ssh_sk_api_version
47# define sk_enroll ssh_sk_enroll
48# define sk_sign ssh_sk_sign
49# define sk_load_resident_keys ssh_sk_load_resident_keys
50#endif /* !SK_STANDALONE */
51
52#include "sk-api.h"
43 53
44/* #define SK_DEBUG 1 */ 54/* #define SK_DEBUG 1 */
45 55
@@ -54,63 +64,6 @@
54 } while (0) 64 } while (0)
55#endif 65#endif
56 66
57#define SK_VERSION_MAJOR 0x00040000 /* current API version */
58
59/* Flags */
60#define SK_USER_PRESENCE_REQD 0x01
61#define SK_USER_VERIFICATION_REQD 0x04
62#define SK_RESIDENT_KEY 0x20
63
64/* Algs */
65#define SK_ECDSA 0x00
66#define SK_ED25519 0x01
67
68/* Error codes */
69#define SSH_SK_ERR_GENERAL -1
70#define SSH_SK_ERR_UNSUPPORTED -2
71#define SSH_SK_ERR_PIN_REQUIRED -3
72
73struct sk_enroll_response {
74 uint8_t *public_key;
75 size_t public_key_len;
76 uint8_t *key_handle;
77 size_t key_handle_len;
78 uint8_t *signature;
79 size_t signature_len;
80 uint8_t *attestation_cert;
81 size_t attestation_cert_len;
82};
83
84struct sk_sign_response {
85 uint8_t flags;
86 uint32_t counter;
87 uint8_t *sig_r;
88 size_t sig_r_len;
89 uint8_t *sig_s;
90 size_t sig_s_len;
91};
92
93struct sk_resident_key {
94 uint32_t alg;
95 size_t slot;
96 char *application;
97 struct sk_enroll_response key;
98};
99
100struct sk_option {
101 char *name;
102 char *value;
103 uint8_t required;
104};
105
106/* If building as part of OpenSSH, then rename exported functions */
107#if !defined(SK_STANDALONE)
108#define sk_api_version ssh_sk_api_version
109#define sk_enroll ssh_sk_enroll
110#define sk_sign ssh_sk_sign
111#define sk_load_resident_keys ssh_sk_load_resident_keys
112#endif
113
114/* Return the version of the middleware API */ 67/* Return the version of the middleware API */
115uint32_t sk_api_version(void); 68uint32_t sk_api_version(void);
116 69
@@ -161,7 +114,7 @@ skdebug(const char *func, const char *fmt, ...)
161uint32_t 114uint32_t
162sk_api_version(void) 115sk_api_version(void)
163{ 116{
164 return SK_VERSION_MAJOR; 117 return SSH_SK_VERSION_MAJOR;
165} 118}
166 119
167/* Select the first identified FIDO device attached to the system */ 120/* Select the first identified FIDO device attached to the system */
@@ -426,10 +379,10 @@ pack_public_key(uint32_t alg, const fido_cred_t *cred,
426{ 379{
427 switch(alg) { 380 switch(alg) {
428#ifdef WITH_OPENSSL 381#ifdef WITH_OPENSSL
429 case SK_ECDSA: 382 case SSH_SK_ECDSA:
430 return pack_public_key_ecdsa(cred, response); 383 return pack_public_key_ecdsa(cred, response);
431#endif /* WITH_OPENSSL */ 384#endif /* WITH_OPENSSL */
432 case SK_ED25519: 385 case SSH_SK_ED25519:
433 return pack_public_key_ed25519(cred, response); 386 return pack_public_key_ed25519(cred, response);
434 default: 387 default:
435 return -1; 388 return -1;
@@ -441,6 +394,7 @@ fidoerr_to_skerr(int fidoerr)
441{ 394{
442 switch (fidoerr) { 395 switch (fidoerr) {
443 case FIDO_ERR_UNSUPPORTED_OPTION: 396 case FIDO_ERR_UNSUPPORTED_OPTION:
397 case FIDO_ERR_UNSUPPORTED_ALGORITHM:
444 return SSH_SK_ERR_UNSUPPORTED; 398 return SSH_SK_ERR_UNSUPPORTED;
445 case FIDO_ERR_PIN_REQUIRED: 399 case FIDO_ERR_PIN_REQUIRED:
446 case FIDO_ERR_PIN_INVALID: 400 case FIDO_ERR_PIN_INVALID:
@@ -516,11 +470,11 @@ sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
516 *enroll_response = NULL; 470 *enroll_response = NULL;
517 switch(alg) { 471 switch(alg) {
518#ifdef WITH_OPENSSL 472#ifdef WITH_OPENSSL
519 case SK_ECDSA: 473 case SSH_SK_ECDSA:
520 cose_alg = COSE_ES256; 474 cose_alg = COSE_ES256;
521 break; 475 break;
522#endif /* WITH_OPENSSL */ 476#endif /* WITH_OPENSSL */
523 case SK_ED25519: 477 case SSH_SK_ED25519:
524 cose_alg = COSE_EDDSA; 478 cose_alg = COSE_EDDSA;
525 break; 479 break;
526 default: 480 default:
@@ -528,6 +482,7 @@ sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
528 goto out; 482 goto out;
529 } 483 }
530 if (device == NULL && (device = pick_first_device()) == NULL) { 484 if (device == NULL && (device = pick_first_device()) == NULL) {
485 ret = SSH_SK_ERR_DEVICE_NOT_FOUND;
531 skdebug(__func__, "pick_first_device failed"); 486 skdebug(__func__, "pick_first_device failed");
532 goto out; 487 goto out;
533 } 488 }
@@ -546,7 +501,7 @@ sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
546 fido_strerr(r)); 501 fido_strerr(r));
547 goto out; 502 goto out;
548 } 503 }
549 if ((r = fido_cred_set_rk(cred, (flags & SK_RESIDENT_KEY) != 0 ? 504 if ((r = fido_cred_set_rk(cred, (flags & SSH_SK_RESIDENT_KEY) != 0 ?
550 FIDO_OPT_TRUE : FIDO_OPT_OMIT)) != FIDO_OK) { 505 FIDO_OPT_TRUE : FIDO_OPT_OMIT)) != FIDO_OK) {
551 skdebug(__func__, "fido_cred_set_rk: %s", fido_strerr(r)); 506 skdebug(__func__, "fido_cred_set_rk: %s", fido_strerr(r));
552 goto out; 507 goto out;
@@ -717,10 +672,10 @@ pack_sig(uint32_t alg, fido_assert_t *assert,
717{ 672{
718 switch(alg) { 673 switch(alg) {
719#ifdef WITH_OPENSSL 674#ifdef WITH_OPENSSL
720 case SK_ECDSA: 675 case SSH_SK_ECDSA:
721 return pack_sig_ecdsa(assert, response); 676 return pack_sig_ecdsa(assert, response);
722#endif /* WITH_OPENSSL */ 677#endif /* WITH_OPENSSL */
723 case SK_ED25519: 678 case SSH_SK_ED25519:
724 return pack_sig_ed25519(assert, response); 679 return pack_sig_ed25519(assert, response);
725 default: 680 default:
726 return -1; 681 return -1;
@@ -804,7 +759,7 @@ sk_sign(uint32_t alg, const uint8_t *message, size_t message_len,
804 goto out; 759 goto out;
805 } 760 }
806 if ((r = fido_assert_set_up(assert, 761 if ((r = fido_assert_set_up(assert,
807 (flags & SK_USER_PRESENCE_REQD) ? 762 (flags & SSH_SK_USER_PRESENCE_REQD) ?
808 FIDO_OPT_TRUE : FIDO_OPT_FALSE)) != FIDO_OK) { 763 FIDO_OPT_TRUE : FIDO_OPT_FALSE)) != FIDO_OK) {
809 skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r)); 764 skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r));
810 goto out; 765 goto out;
@@ -951,15 +906,15 @@ read_rks(const char *devpath, const char *pin,
951 906
952 switch (fido_cred_type(cred)) { 907 switch (fido_cred_type(cred)) {
953 case COSE_ES256: 908 case COSE_ES256:
954 srk->alg = SK_ECDSA; 909 srk->alg = SSH_SK_ECDSA;
955 break; 910 break;
956 case COSE_EDDSA: 911 case COSE_EDDSA:
957 srk->alg = SK_ED25519; 912 srk->alg = SSH_SK_ED25519;
958 break; 913 break;
959 default: 914 default:
960 skdebug(__func__, "unsupported key type %d", 915 skdebug(__func__, "unsupported key type %d",
961 fido_cred_type(cred)); 916 fido_cred_type(cred));
962 goto out; 917 goto out; /* XXX free rk and continue */
963 } 918 }
964 919
965 if ((r = pack_public_key(srk->alg, cred, 920 if ((r = pack_public_key(srk->alg, cred,
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 29013a20f..8df55f2c2 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.393 2020/01/25 23:02:13 djm Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.394 2020/01/25 23:13:09 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -3579,7 +3579,7 @@ main(int argc, char **argv)
3579 if (r == 0) 3579 if (r == 0)
3580 break; 3580 break;
3581 if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) 3581 if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
3582 exit(1); /* error message already printed */ 3582 fatal("Key enrollment failed: %s", ssh_err(r));
3583 if (passphrase != NULL) 3583 if (passphrase != NULL)
3584 freezero(passphrase, strlen(passphrase)); 3584 freezero(passphrase, strlen(passphrase));
3585 passphrase = read_passphrase("Enter PIN for security " 3585 passphrase = read_passphrase("Enter PIN for security "
diff --git a/ssh-sk-helper.c b/ssh-sk-helper.c
index a4be9d369..2f93ad716 100644
--- a/ssh-sk-helper.c
+++ b/ssh-sk-helper.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-sk-helper.c,v 1.8 2020/01/10 23:43:26 djm Exp $ */ 1/* $OpenBSD: ssh-sk-helper.c,v 1.9 2020/01/25 23:13:09 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2019 Google LLC 3 * Copyright (c) 2019 Google LLC
4 * 4 *
@@ -63,7 +63,7 @@ reply_error(int r, char *fmt, ...)
63 va_start(ap, fmt); 63 va_start(ap, fmt);
64 xvasprintf(&msg, fmt, ap); 64 xvasprintf(&msg, fmt, ap);
65 va_end(ap); 65 va_end(ap);
66 error("%s: %s", __progname, msg); 66 debug("%s: %s", __progname, msg);
67 free(msg); 67 free(msg);
68 68
69 if (r >= 0) 69 if (r >= 0)
diff --git a/ssh-sk.c b/ssh-sk.c
index 3f5eed62d..a8d4de832 100644
--- a/ssh-sk.c
+++ b/ssh-sk.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-sk.c,v 1.24 2020/01/06 02:00:47 djm Exp $ */ 1/* $OpenBSD: ssh-sk.c,v 1.25 2020/01/25 23:13:09 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2019 Google LLC 3 * Copyright (c) 2019 Google LLC
4 * 4 *
@@ -338,6 +338,8 @@ skerr_to_ssherr(int skerr)
338 return SSH_ERR_FEATURE_UNSUPPORTED; 338 return SSH_ERR_FEATURE_UNSUPPORTED;
339 case SSH_SK_ERR_PIN_REQUIRED: 339 case SSH_SK_ERR_PIN_REQUIRED:
340 return SSH_ERR_KEY_WRONG_PASSPHRASE; 340 return SSH_ERR_KEY_WRONG_PASSPHRASE;
341 case SSH_SK_ERR_DEVICE_NOT_FOUND:
342 return SSH_ERR_DEVICE_NOT_FOUND;
341 case SSH_SK_ERR_GENERAL: 343 case SSH_SK_ERR_GENERAL:
342 default: 344 default:
343 return SSH_ERR_INVALID_FORMAT; 345 return SSH_ERR_INVALID_FORMAT;
@@ -490,7 +492,7 @@ sshsk_enroll(int type, const char *provider_path, const char *device,
490 /* enroll key */ 492 /* enroll key */
491 if ((r = skp->sk_enroll(alg, challenge, challenge_len, application, 493 if ((r = skp->sk_enroll(alg, challenge, challenge_len, application,
492 flags, pin, opts, &resp)) != 0) { 494 flags, pin, opts, &resp)) != 0) {
493 error("Security key provider \"%s\" returned failure %d", 495 debug("%s: provider \"%s\" returned failure %d", __func__,
494 provider_path, r); 496 provider_path, r);
495 r = skerr_to_ssherr(r); 497 r = skerr_to_ssherr(r);
496 goto out; 498 goto out;
diff --git a/ssherr.c b/ssherr.c
index 38974f51b..bd954aadd 100644
--- a/ssherr.c
+++ b/ssherr.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssherr.c,v 1.9 2019/12/30 09:24:45 djm Exp $ */ 1/* $OpenBSD: ssherr.c,v 1.10 2020/01/25 23:13:09 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2011 Damien Miller 3 * Copyright (c) 2011 Damien Miller
4 * 4 *
@@ -143,6 +143,8 @@ ssh_err(int n)
143 return "signature algorithm not supported"; 143 return "signature algorithm not supported";
144 case SSH_ERR_FEATURE_UNSUPPORTED: 144 case SSH_ERR_FEATURE_UNSUPPORTED:
145 return "requested feature not supported"; 145 return "requested feature not supported";
146 case SSH_ERR_DEVICE_NOT_FOUND:
147 return "device not found";
146 default: 148 default:
147 return "unknown error"; 149 return "unknown error";
148 } 150 }
diff --git a/ssherr.h b/ssherr.h
index 520bd4964..085e75274 100644
--- a/ssherr.h
+++ b/ssherr.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssherr.h,v 1.7 2019/12/30 09:24:45 djm Exp $ */ 1/* $OpenBSD: ssherr.h,v 1.8 2020/01/25 23:13:09 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2011 Damien Miller 3 * Copyright (c) 2011 Damien Miller
4 * 4 *
@@ -81,6 +81,7 @@
81#define SSH_ERR_NUMBER_TOO_LARGE -57 81#define SSH_ERR_NUMBER_TOO_LARGE -57
82#define SSH_ERR_SIGN_ALG_UNSUPPORTED -58 82#define SSH_ERR_SIGN_ALG_UNSUPPORTED -58
83#define SSH_ERR_FEATURE_UNSUPPORTED -59 83#define SSH_ERR_FEATURE_UNSUPPORTED -59
84#define SSH_ERR_DEVICE_NOT_FOUND -60
84 85
85/* Translate a numeric error code to a human-readable error string */ 86/* Translate a numeric error code to a human-readable error string */
86const char *ssh_err(int n); 87const char *ssh_err(int n);