Agent protocol changes related to U2F/FIDO2 keys

Damien Miller djm at mindrot.org
Wed Dec 11 10:36:15 AEDT 2019


On Fri, 6 Dec 2019, Ron Frederick wrote:

> I spent some time today implementing support for loading U2F keys into
> the SSH agent from my AsyncSSH library. I got it working, but along
> the way I ran into a few issues I wanted to report:
>
> First, it looks like the value of SSH_AGENT_CONSTRAIN_EXTENSION has
> changed from the value 3 defined at
> https://tools.ietf.org/html/draft-miller-ssh-agent-02 to the value 255
> now, and somewhere along the way the constraint
> SSH_AGENT_CONSTRAIN_MAXSIGN was defined to use the value 3.

Yes, I had already updated the I-D back in July to fix this collision:
https://tools.ietf.org/html/draft-miller-ssh-agent-03

> Second, https://raw.githubusercontent.com/openssh/openssh-portable/master/PROTOCOL.u2f documents the new extension for loading SK keys as:
>
> 	byte		SSH_AGENT_CONSTRAIN_EXTENSION
> 	string		sk at openssh.com
> 	string		middleware path
> However, the current OpenSSH agent code actually expects to receive:
> 	byte		SSH_AGENT_CONSTRAIN_EXTENSION
> 	string		sk-provider at openssh.com
> 	string		middleware path

oops, I'll fix.

> Also, this documentation doesn’t define the format of the key data
> sent to the agent for SK keys with certificates. Similar to plain
> ECDSA keys with certificates, the key data sent for ECDSA SK keys
> omits the curve_id and Q value of the ECDSA key that would normally be
> written out when serializing a local private key. So, the data sent to
> the agent for an ECDSA SK key with certificate looks like:
>
> 	string		"sk-ecdsa-sha2-nistp256-cert-v01 at openssh.com"
> 	string		nonce
> 	string		curve name
> 	ec_point	Q
> 	string		application
> 	uint64		serial
> 	uint32		type
> 	string		key id
> 	string		valid principals
> 	uint64		valid after
> 	uint64		valid before
> 	string		critical options
> 	string		extensions
> 	string		reserved
> 	string		signature key
> 	string		signature
> 	string		application
> 	uint8		flags
> 	string		key_handle
> 	string		reserved

I don't think that's quite right as it has the pubkey/cert expanded rather
than encoded in a string - for all certificates, including sk-* the wire
format for private keys should be:

	string		key type
	string		public key (including certificate data)
	...		private key fields

E.g.

	string		"sk-ecdsa-sha2-nistp256-cert-v01 at openssh.com"
	string		pubkey
	string		application
	uint8		flags
	string		key_handle
	string		reserved

You're correct that this is not documented in PROTOCOL.u2f. I'll update
that now.

> If the instant was to avoid duplicating what was already in the
> certificate, though, I’m not sure why “application” is sent twice. It
> seems like that should have been left out along with the curve_id and
> Q value, appending only the flags, key_handle, and reserved values
> from the private key at the end.

Yeah, application is accidentally repeated. I don't think that I'll touch
it for now, unless there is some other change that requires changing the
serialisation format.

> I also noticed that
https://raw.githubusercontent.com/openssh/openssh-portable/master/PROTOCOL.u2f
> incorrectly documents the flags value as being a uint32 in the Ed25519
> SK private key encoding:

yes, that's a mistake too. I'll fix that now.

Thanks for the detailed feedback!

-d


More information about the openssh-unix-dev mailing list