summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PROTOCOL.u2f10
-rw-r--r--sk-api.h12
-rw-r--r--ssh-sk.c21
3 files changed, 29 insertions, 14 deletions
diff --git a/PROTOCOL.u2f b/PROTOCOL.u2f
index a587480be..bd60f9fac 100644
--- a/PROTOCOL.u2f
+++ b/PROTOCOL.u2f
@@ -138,7 +138,7 @@ The signature returned from U2F hardware takes the following format:
138For use in the SSH protocol, we wish to avoid server-side parsing of ASN.1 138For use in the SSH protocol, we wish to avoid server-side parsing of ASN.1
139format data in the pre-authentication attack surface. Therefore, the 139format data in the pre-authentication attack surface. Therefore, the
140signature format used on the wire in SSH2_USERAUTH_REQUEST packets will 140signature format used on the wire in SSH2_USERAUTH_REQUEST packets will
141be reformatted slightly: 141be reformatted slightly and the ecdsa_signature_blob value has the encoding:
142 142
143 mpint r 143 mpint r
144 mpint s 144 mpint s
@@ -184,6 +184,10 @@ The middleware library need only expose a handful of functions:
184 /* Flags */ 184 /* Flags */
185 #define SSH_SK_USER_PRESENCE_REQD 0x01 185 #define SSH_SK_USER_PRESENCE_REQD 0x01
186 186
187 /* Algs */
188 #define SSH_SK_ECDSA 0x00
189 #define SSH_SK_ED25519 0x01
190
187 struct sk_enroll_response { 191 struct sk_enroll_response {
188 uint8_t *public_key; 192 uint8_t *public_key;
189 size_t public_key_len; 193 size_t public_key_len;
@@ -208,12 +212,12 @@ The middleware library need only expose a handful of functions:
208 uint32_t sk_api_version(void); 212 uint32_t sk_api_version(void);
209 213
210 /* Enroll a U2F key (private key generation) */ 214 /* Enroll a U2F key (private key generation) */
211 int sk_enroll(const uint8_t *challenge, size_t challenge_len, 215 int sk_enroll(int alg, const uint8_t *challenge, size_t challenge_len,
212 const char *application, uint8_t flags, 216 const char *application, uint8_t flags,
213 struct sk_enroll_response **enroll_response); 217 struct sk_enroll_response **enroll_response);
214 218
215 /* Sign a challenge */ 219 /* Sign a challenge */
216 int sk_sign(const uint8_t *message, size_t message_len, 220 int sk_sign(int alg, const uint8_t *message, size_t message_len,
217 const char *application, 221 const char *application,
218 const uint8_t *key_handle, size_t key_handle_len, 222 const uint8_t *key_handle, size_t key_handle_len,
219 uint8_t flags, struct sk_sign_response **sign_response); 223 uint8_t flags, struct sk_sign_response **sign_response);
diff --git a/sk-api.h b/sk-api.h
index 2af0ef6f0..5ada30a3d 100644
--- a/sk-api.h
+++ b/sk-api.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: sk-api.h,v 1.1 2019/10/31 21:16:20 djm Exp $ */ 1/* $OpenBSD: sk-api.h,v 1.2 2019/11/12 19:32:30 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2019 Google LLC 3 * Copyright (c) 2019 Google LLC
4 * 4 *
@@ -26,6 +26,10 @@
26/* Flags */ 26/* Flags */
27#define SSH_SK_USER_PRESENCE_REQD 0x01 27#define SSH_SK_USER_PRESENCE_REQD 0x01
28 28
29/* Algs */
30#define SSH_SK_ECDSA 0x00
31#define SSH_SK_ED25519 0x01
32
29struct sk_enroll_response { 33struct sk_enroll_response {
30 uint8_t *public_key; 34 uint8_t *public_key;
31 size_t public_key_len; 35 size_t public_key_len;
@@ -46,19 +50,19 @@ struct sk_sign_response {
46 size_t sig_s_len; 50 size_t sig_s_len;
47}; 51};
48 52
49#define SSH_SK_VERSION_MAJOR 0x00010000 /* current API version */ 53#define SSH_SK_VERSION_MAJOR 0x00020000 /* current API version */
50#define SSH_SK_VERSION_MAJOR_MASK 0xffff0000 54#define SSH_SK_VERSION_MAJOR_MASK 0xffff0000
51 55
52/* Return the version of the middleware API */ 56/* Return the version of the middleware API */
53uint32_t sk_api_version(void); 57uint32_t sk_api_version(void);
54 58
55/* Enroll a U2F key (private key generation) */ 59/* Enroll a U2F key (private key generation) */
56int sk_enroll(const uint8_t *challenge, size_t challenge_len, 60int sk_enroll(int alg, const uint8_t *challenge, size_t challenge_len,
57 const char *application, uint8_t flags, 61 const char *application, uint8_t flags,
58 struct sk_enroll_response **enroll_response); 62 struct sk_enroll_response **enroll_response);
59 63
60/* Sign a challenge */ 64/* Sign a challenge */
61int sk_sign(const uint8_t *message, size_t message_len, 65int sk_sign(int alg, const uint8_t *message, size_t message_len,
62 const char *application, const uint8_t *key_handle, size_t key_handle_len, 66 const char *application, const uint8_t *key_handle, size_t key_handle_len,
63 uint8_t flags, struct sk_sign_response **sign_response); 67 uint8_t flags, struct sk_sign_response **sign_response);
64 68
diff --git a/ssh-sk.c b/ssh-sk.c
index 43f808efc..a9da765eb 100644
--- a/ssh-sk.c
+++ b/ssh-sk.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-sk.c,v 1.6 2019/11/12 19:31:45 markus Exp $ */ 1/* $OpenBSD: ssh-sk.c,v 1.7 2019/11/12 19:32:30 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2019 Google LLC 3 * Copyright (c) 2019 Google LLC
4 * 4 *
@@ -49,12 +49,12 @@ struct sshsk_provider {
49 uint32_t (*sk_api_version)(void); 49 uint32_t (*sk_api_version)(void);
50 50
51 /* Enroll a U2F key (private key generation) */ 51 /* Enroll a U2F key (private key generation) */
52 int (*sk_enroll)(const uint8_t *challenge, size_t challenge_len, 52 int (*sk_enroll)(int alg, const uint8_t *challenge,
53 const char *application, uint8_t flags, 53 size_t challenge_len, const char *application, uint8_t flags,
54 struct sk_enroll_response **enroll_response); 54 struct sk_enroll_response **enroll_response);
55 55
56 /* Sign a challenge */ 56 /* Sign a challenge */
57 int (*sk_sign)(const uint8_t *message, size_t message_len, 57 int (*sk_sign)(int alg, const uint8_t *message, size_t message_len,
58 const char *application, 58 const char *application,
59 const uint8_t *key_handle, size_t key_handle_len, 59 const uint8_t *key_handle, size_t key_handle_len,
60 uint8_t flags, struct sk_sign_response **sign_response); 60 uint8_t flags, struct sk_sign_response **sign_response);
@@ -243,13 +243,17 @@ sshsk_enroll(int type, const char *provider_path, const char *application,
243 size_t challenge_len; 243 size_t challenge_len;
244 struct sk_enroll_response *resp = NULL; 244 struct sk_enroll_response *resp = NULL;
245 int r = SSH_ERR_INTERNAL_ERROR; 245 int r = SSH_ERR_INTERNAL_ERROR;
246 int alg;
246 247
247 *keyp = NULL; 248 *keyp = NULL;
248 if (attest) 249 if (attest)
249 sshbuf_reset(attest); 250 sshbuf_reset(attest);
250 switch (type) { 251 switch (type) {
251 case KEY_ECDSA_SK: 252 case KEY_ECDSA_SK:
253 alg = SSH_SK_ECDSA;
254 break;
252 case KEY_ED25519_SK: 255 case KEY_ED25519_SK:
256 alg = SSH_SK_ED25519;
253 break; 257 break;
254 default: 258 default:
255 error("%s: unsupported key type", __func__); 259 error("%s: unsupported key type", __func__);
@@ -287,7 +291,7 @@ sshsk_enroll(int type, const char *provider_path, const char *application,
287 } 291 }
288 /* XXX validate flags? */ 292 /* XXX validate flags? */
289 /* enroll key */ 293 /* enroll key */
290 if ((r = skp->sk_enroll(challenge, challenge_len, application, 294 if ((r = skp->sk_enroll(alg, challenge, challenge_len, application,
291 flags, &resp)) != 0) { 295 flags, &resp)) != 0) {
292 error("Security key provider %s returned failure %d", 296 error("Security key provider %s returned failure %d",
293 provider_path, r); 297 provider_path, r);
@@ -427,7 +431,7 @@ sshsk_sign(const char *provider_path, const struct sshkey *key,
427{ 431{
428 struct sshsk_provider *skp = NULL; 432 struct sshsk_provider *skp = NULL;
429 int r = SSH_ERR_INTERNAL_ERROR; 433 int r = SSH_ERR_INTERNAL_ERROR;
430 int type; 434 int type, alg;
431 struct sk_sign_response *resp = NULL; 435 struct sk_sign_response *resp = NULL;
432 struct sshbuf *inner_sig = NULL, *sig = NULL; 436 struct sshbuf *inner_sig = NULL, *sig = NULL;
433 uint8_t message[32]; 437 uint8_t message[32];
@@ -439,7 +443,10 @@ sshsk_sign(const char *provider_path, const struct sshkey *key,
439 type = sshkey_type_plain(key->type); 443 type = sshkey_type_plain(key->type);
440 switch (type) { 444 switch (type) {
441 case KEY_ECDSA_SK: 445 case KEY_ECDSA_SK:
446 alg = SSH_SK_ECDSA;
447 break;
442 case KEY_ED25519_SK: 448 case KEY_ED25519_SK:
449 alg = SSH_SK_ED25519;
443 break; 450 break;
444 default: 451 default:
445 return SSH_ERR_INVALID_ARGUMENT; 452 return SSH_ERR_INVALID_ARGUMENT;
@@ -462,7 +469,7 @@ sshsk_sign(const char *provider_path, const struct sshkey *key,
462 r = SSH_ERR_INTERNAL_ERROR; 469 r = SSH_ERR_INTERNAL_ERROR;
463 goto out; 470 goto out;
464 } 471 }
465 if ((r = skp->sk_sign(message, sizeof(message), 472 if ((r = skp->sk_sign(alg, message, sizeof(message),
466 key->sk_application, 473 key->sk_application,
467 sshbuf_ptr(key->sk_key_handle), sshbuf_len(key->sk_key_handle), 474 sshbuf_ptr(key->sk_key_handle), sshbuf_len(key->sk_key_handle),
468 key->sk_flags, &resp)) != 0) { 475 key->sk_flags, &resp)) != 0) {