summaryrefslogtreecommitdiff
path: root/PROTOCOL.u2f
diff options
context:
space:
mode:
Diffstat (limited to 'PROTOCOL.u2f')
-rw-r--r--PROTOCOL.u2f337
1 files changed, 337 insertions, 0 deletions
diff --git a/PROTOCOL.u2f b/PROTOCOL.u2f
new file mode 100644
index 000000000..748111d56
--- /dev/null
+++ b/PROTOCOL.u2f
@@ -0,0 +1,337 @@
1This document describes OpenSSH's support for U2F/FIDO security keys.
2
3Background
4----------
5
6U2F is an open standard for two-factor authentication hardware, widely
7used for user authentication to websites. U2F tokens are ubiquitous,
8available from a number of manufacturers and are currently by far the
9cheapest way for users to achieve hardware-backed credential storage.
10
11The U2F protocol however cannot be trivially used as an SSH protocol key
12type as both the inputs to the signature operation and the resultant
13signature differ from those specified for SSH. For similar reasons,
14integration of U2F devices cannot be achieved via the PKCS#11 API.
15
16U2F also offers a number of features that are attractive in the context
17of SSH authentication. They can be configured to require indication
18of "user presence" for each signature operation (typically achieved
19by requiring the user touch the key). They also offer an attestation
20mechanism at key enrollment time that can be used to prove that a
21given key is backed by hardware. Finally the signature format includes
22a monotonic signature counter that can be used (at scale) to detect
23concurrent use of a private key, should it be extracted from hardware.
24
25U2F private keys are generated through an enrollment operation,
26which takes an application ID - a URL-like string, typically "ssh:"
27in this case, but a HTTP origin for the case of web authentication,
28and a challenge string (typically randomly generated). The enrollment
29operation returns a public key, a key handle that must be used to invoke
30the hardware-backed private key, some flags and signed attestation
31information that may be used to verify that a private key is hosted on a
32particular hardware instance.
33
34It is common for U2F hardware to derive private keys from the key handle
35in conjunction with a small per-device secret that is unique to the
36hardware, thus requiring little on-device storage for an effectively
37unlimited number of supported keys. This drives the requirement that
38the key handle be supplied for each signature operation. U2F tokens
39primarily use ECDSA signatures in the NIST-P256 field, though the FIDO2
40standard specifies additional key types, including one based on Ed25519.
41
42SSH U2F Key formats
43-------------------
44
45OpenSSH integrates U2F as new key and corresponding certificate types:
46
47 sk-ecdsa-sha2-nistp256@openssh.com
48 sk-ecdsa-sha2-nistp256-cert-v01@openssh.com
49 sk-ssh-ed25519@openssh.com
50 sk-ssh-ed25519-cert-v01@openssh.com
51
52While each uses ecdsa-sha256-nistp256 as the underlying signature primitive,
53keys require extra information in the public and private keys, and in
54the signature object itself. As such they cannot be made compatible with
55the existing ecdsa-sha2-nistp* key types.
56
57The format of a sk-ecdsa-sha2-nistp256@openssh.com public key is:
58
59 string "sk-ecdsa-sha2-nistp256@openssh.com"
60 string curve name
61 ec_point Q
62 string application (user-specified, but typically "ssh:")
63
64The corresponding private key contains:
65
66 string "sk-ecdsa-sha2-nistp256@openssh.com"
67 string curve name
68 ec_point Q
69 string application (user-specified, but typically "ssh:")
70 uint8 flags
71 string key_handle
72 string reserved
73
74The format of a sk-ssh-ed25519@openssh.com public key is:
75
76 string "sk-ssh-ed25519@openssh.com"
77 string public key
78 string application (user-specified, but typically "ssh:")
79
80With a private half consisting of:
81
82 string "sk-ssh-ed25519@openssh.com"
83 string public key
84 string application (user-specified, but typically "ssh:")
85 uint8 flags
86 string key_handle
87 string reserved
88
89The certificate form for SSH U2F keys appends the usual certificate
90information to the public key:
91
92 string "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com"
93 string nonce
94 string curve name
95 ec_point Q
96 string application
97 uint64 serial
98 uint32 type
99 string key id
100 string valid principals
101 uint64 valid after
102 uint64 valid before
103 string critical options
104 string extensions
105 string reserved
106 string signature key
107 string signature
108
109and for security key ed25519 certificates:
110
111 string "sk-ssh-ed25519-cert-v01@openssh.com"
112 string nonce
113 string public key
114 string application
115 uint64 serial
116 uint32 type
117 string key id
118 string valid principals
119 uint64 valid after
120 uint64 valid before
121 string critical options
122 string extensions
123 string reserved
124 string signature key
125 string signature
126
127Both security key certificates use the following encoding for private keys:
128
129 string type (e.g. "sk-ssh-ed25519-cert-v01@openssh.com")
130 string pubkey (the above key/cert structure)
131 string application
132 uint8 flags
133 string key_handle
134 string reserved
135
136During key generation, the hardware also returns attestation information
137that may be used to cryptographically prove that a given key is
138hardware-backed. Unfortunately, the protocol required for this proof is
139not privacy-preserving and may be used to identify U2F tokens with at
140least manufacturer and batch number granularity. For this reason, we
141choose not to include this information in the public key or save it by
142default.
143
144Attestation information is useful for out-of-band key and certificate
145registration worksflows, e.g. proving to a CA that a key is backed
146by trusted hardware before it will issue a certificate. To support this
147case, OpenSSH optionally allows retaining the attestation information
148at the time of key generation. It will take the following format:
149
150 string "ssh-sk-attest-v00"
151 string attestation certificate
152 string enrollment signature
153 uint32 reserved flags
154 string reserved string
155
156OpenSSH treats the attestation certificate and enrollment signatures as
157opaque objects and does no interpretation of them itself.
158
159SSH U2F signatures
160------------------
161
162In addition to the message to be signed, the U2F signature operation
163requires the key handle and a few additional parameters. The signature
164is signed over a blob that consists of:
165
166 byte[32] SHA256(application)
167 byte flags (including "user present", extensions present)
168 uint32 counter
169 byte[] extensions
170 byte[32] SHA256(message)
171
172No extensons are yet defined for SSH use. If any are defined in the future,
173it will be possible to infer their presence from the contents of the "flags"
174value.
175
176The signature returned from U2F hardware takes the following format:
177
178 byte flags (including "user present")
179 uint32 counter
180 byte[] ecdsa_signature (in X9.62 format).
181
182For use in the SSH protocol, we wish to avoid server-side parsing of ASN.1
183format data in the pre-authentication attack surface. Therefore, the
184signature format used on the wire in SSH2_USERAUTH_REQUEST packets will
185be reformatted to better match the existing signature encoding:
186
187 string "sk-ecdsa-sha2-nistp256@openssh.com"
188 string ecdsa_signature
189 byte flags
190 uint32 counter
191
192Where the "ecdsa_signature" field follows the RFC5656 ECDSA signature
193encoding:
194
195 mpint r
196 mpint s
197
198For Ed25519 keys the signature is encoded as:
199
200 string "sk-ssh-ed25519@openssh.com"
201 string signature
202 byte flags
203 uint32 counter
204
205ssh-agent protocol extensions
206-----------------------------
207
208ssh-agent requires a protocol extension to support U2F keys. At
209present the closest analogue to Security Keys in ssh-agent are PKCS#11
210tokens, insofar as they require a middleware library to communicate with
211the device that holds the keys. Unfortunately, the protocol message used
212to add PKCS#11 keys to ssh-agent does not include any way to send the
213key handle to the agent as U2F keys require.
214
215To avoid this, without having to add wholly new messages to the agent
216protocol, we will use the existing SSH2_AGENTC_ADD_ID_CONSTRAINED message
217with a new key constraint extension to encode a path to the middleware
218library for the key. The format of this constraint extension would be:
219
220 byte SSH_AGENT_CONSTRAIN_EXTENSION
221 string sk-provider@openssh.com
222 string middleware path
223
224This constraint-based approach does not present any compatibility
225problems.
226
227OpenSSH integration
228-------------------
229
230U2F tokens may be attached via a number of means, including USB and NFC.
231The USB interface is standardised around a HID protocol, but we want to
232be able to support other transports as well as dummy implementations for
233regress testing. For this reason, OpenSSH shall support a dynamically-
234loaded middleware libraries to communicate with security keys, but offer
235support for the common case of USB HID security keys internally.
236
237The middleware library need only expose a handful of functions:
238
239 #define SSH_SK_VERSION_MAJOR 0x00040000 /* API version */
240 #define SSH_SK_VERSION_MAJOR_MASK 0xffff0000
241
242 /* Flags */
243 #define SSH_SK_USER_PRESENCE_REQD 0x01
244 #define SSH_SK_USER_VERIFICATION_REQD 0x04
245 #define SSH_SK_RESIDENT_KEY 0x20
246
247 /* Algs */
248 #define SSH_SK_ECDSA 0x00
249 #define SSH_SK_ED25519 0x01
250
251 /* Error codes */
252 #define SSH_SK_ERR_GENERAL -1
253 #define SSH_SK_ERR_UNSUPPORTED -2
254 #define SSH_SK_ERR_PIN_REQUIRED -3
255 #define SSH_SK_ERR_DEVICE_NOT_FOUND -4
256
257 struct sk_enroll_response {
258 uint8_t *public_key;
259 size_t public_key_len;
260 uint8_t *key_handle;
261 size_t key_handle_len;
262 uint8_t *signature;
263 size_t signature_len;
264 uint8_t *attestation_cert;
265 size_t attestation_cert_len;
266 };
267
268 struct sk_sign_response {
269 uint8_t flags;
270 uint32_t counter;
271 uint8_t *sig_r;
272 size_t sig_r_len;
273 uint8_t *sig_s;
274 size_t sig_s_len;
275 };
276
277 struct sk_resident_key {
278 uint32_t alg;
279 size_t slot;
280 char *application;
281 struct sk_enroll_response key;
282 };
283
284 struct sk_option {
285 char *name;
286 char *value;
287 uint8_t important;
288 };
289
290 /* Return the version of the middleware API */
291 uint32_t sk_api_version(void);
292
293 /* Enroll a U2F key (private key generation) */
294 int sk_enroll(uint32_t alg,
295 const uint8_t *challenge, size_t challenge_len,
296 const char *application, uint8_t flags, const char *pin,
297 struct sk_option **options,
298 struct sk_enroll_response **enroll_response);
299
300 /* Sign a challenge */
301 int sk_sign(uint32_t alg, const uint8_t *message, size_t message_len,
302 const char *application,
303 const uint8_t *key_handle, size_t key_handle_len,
304 uint8_t flags, const char *pin, struct sk_option **options,
305 struct sk_sign_response **sign_response);
306
307 /* Enumerate all resident keys */
308 int sk_load_resident_keys(const char *pin, struct sk_option **options,
309 struct sk_resident_key ***rks, size_t *nrks);
310
311The SSH_SK_VERSION_MAJOR should be incremented for each incompatible
312API change.
313
314The options may be used to pass miscellaneous options to the middleware
315as a NULL-terminated array of pointers to struct sk_option. The middleware
316may ignore unsupported or unknown options unless the "important" flag is
317set, in which case it should return failure if an unsupported option is
318requested.
319
320At present the following options names are supported:
321
322 "device"
323
324 Specifies a specific FIDO device on which to perform the
325 operation. The value in this field is interpreted by the
326 middleware but it would be typical to specify a path to
327 a /dev node for the device in question.
328
329 "user"
330
331 Specifies the FIDO2 username used when enrolling a key,
332 overriding OpenSSH's default of using an all-zero username.
333
334In OpenSSH, the middleware will be invoked by using a similar mechanism to
335ssh-pkcs11-helper to provide address-space containment of the
336middleware from ssh-agent.
337