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