Home | History | Annotate | Line # | Download | only in dist
      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