diff options
-rw-r--r-- | PROTOCOL.u2f | 10 | ||||
-rw-r--r-- | sk-api.h | 12 | ||||
-rw-r--r-- | ssh-sk.c | 21 |
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: | |||
138 | For use in the SSH protocol, we wish to avoid server-side parsing of ASN.1 | 138 | For use in the SSH protocol, we wish to avoid server-side parsing of ASN.1 |
139 | format data in the pre-authentication attack surface. Therefore, the | 139 | format data in the pre-authentication attack surface. Therefore, the |
140 | signature format used on the wire in SSH2_USERAUTH_REQUEST packets will | 140 | signature format used on the wire in SSH2_USERAUTH_REQUEST packets will |
141 | be reformatted slightly: | 141 | be 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); |
@@ -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 | |||
29 | struct sk_enroll_response { | 33 | struct 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 */ |
53 | uint32_t sk_api_version(void); | 57 | uint32_t sk_api_version(void); |
54 | 58 | ||
55 | /* Enroll a U2F key (private key generation) */ | 59 | /* Enroll a U2F key (private key generation) */ |
56 | int sk_enroll(const uint8_t *challenge, size_t challenge_len, | 60 | int 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 */ |
61 | int sk_sign(const uint8_t *message, size_t message_len, | 65 | int 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 | ||
@@ -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) { |