Question about webauthn signatures?

Damien Miller djm at mindrot.org
Fri May 7 12:41:17 AEST 2021


On Thu, 6 May 2021, Tyson Whitehead wrote:

> > The webauthn signature type (note: note a key type) was added to support
> > browser-based SSH clients that can only interact with FIDO keys via the
> > webauthn APIs. These APIs do not allow "bare" FIDO signatures, but
> > implictly include weborigin information in the signed data.
> 
> Thank you for the clarification. I believe I understand now it is for the
> signature in the SSH_MSG_USERAUTH_REQUEST when the client only has access to
> the device via the webauthn API. That makes sense.
> 
> Many of our non-unix savvy users just use passwords as settings up keys is
> difficult for them. From reading up on the FIDO2 standard, it would seem that
> it should be possible to just have server-side FIDO2 keys. This could be a
> huge plus as we could generate and register these keys on our clusters for
> them off our website. They could just use them without having to setup
> anything on their end.

That's true of FIDO web authentication. What we implemented in SSH
(ab-)uses the FIDO spec to fit SSH's existing publickey user
authentication, because users and lots of tooling is built around that.

This unfortunately precluded the use of server-side keys, as there is no
mechanism for the server to communicate key handles to the client.

I do have vague plans to do a more web-like FIDO authentication method
for OpenSSH in the future, but haven't got around to it yet.

> I was looking at RFC4252 (The SSH Authentication Protocol) to see if
> FIDO2-based server-side could be retrofitted into the SSH protocol, and it
> seemed to me like it could be done. Specifically, the "publickey"
> authentication protocol has the client send
> 
>   byte      SSH_MSG_USERAUTH_REQUEST
>   string    user name in ISO-10646 UTF-8 encoding
>   string    service name in US-ASCII
>   string    "publickey"
>   boolean   FALSE
>   string    public key algorithm name
>   string    public key blob
> 
> and the server respond with
> 
>   byte      SSH_MSG_USERAUTH_PK_OK
>   string    public key algorithm name from the request
>   string    public key blob from the request
> 
> so I am thinking it could be (slightly) abused by
> 
> 1. creating a another esk-ecdsa key type where the key handle was stored with
> the public key
> 2. have the client pass an empty "public key blob" when sending the
> SSH_MSG_USERAUTH_REQUEST message for this key type
> 3. have the server respond back with the key handle (or the entire public key
> with the key handle) in the "public key blob" of its SSH_MSG_USERAUTH_PK_OK
> response
> 
> Support for multiple keys could be done by having repeated queries return
> subsequent ones. The server could also reply with fakes to avoid leaking
> information about whether any such keys actually exist.

I was thinking something like:

c->s

byte		SSH_MSG_USERAUTH_REQUEST
string		username
string		service name
string		"fido-discover-v00 at openssh.com"
string		reserved

s->c

byte		SSH_MSG_USERAUTH_INFO_REQUEST
string		reserved
string[]	key_info

(this message number was defined for GSS authentication, w/
SSH_MSG_USERAUTH_INFO_REQUEST always going in the s->c direction and
SSH_MSG_USERAUTH_INFO_RESPONSE always going c->s).

where each key_info member contains

string		pkblob
string		key handle
uint8		flags
string		reserved

The client could then try the key handles supplied against their attached
security keys to find one that will sign a challenge and then make a
regular public key authentication attempt:

byte		SSH_MSG_USERAUTH_INFO_RESPONSE
string		username
string		service name
string		"publickey"
bool		true
string		pkalg
string		pkblob
string		signature

**

The protocol bits are pretty easy, the UI is a bit more complicated. The
main problem is that we need some way to store the keys eligible for
fido-discover-v00 at openssh.com.

One possibility is marking them using some tag in authorized_keys, but
the information we need to return is more than currently exists in the
sk-* public key formats. So we'd need a new encoding that stores the
extra information and likely some ugly special-casing to glue it all
together.

Perhaps authorized_keys entries like

fido[,option...] sk-ecdsa-sha2-nistp256 at openssh.com pubkeyblob keyhandleblob

flags would be reconstructed from the options listed on the key:
no-touch-required, verify-required, etc.

Another alternative would be to define a pubkey blob format that includes
all the information. Not sure which is nicer...

> > The only thing that AFAIK uses it is the test Javascript that I wrote:
> > regress/unittests/sshsig/webauthn.html in the source distribution. If you
> > stick it on a web server then you can generate FIDO keys and webauthn
> > signatures that you can verify using ssh-keygen -Y. It's the basis of
> > the webauthn signature unit tests.
> 
> Very interesting. I added a bit on top of your javascript to also export the
> private key to see if we could do the key generation sever side in order to
> make things easier for our non-unix-savvy users
> 
> https://staff.sharcnet.ca/tyson/webauthnkey.html

ah good idea, this inspired me to add a similar feature to mine now too.
https://github.com/openssh/openssh-portable/commit/c0d7e36e979

> The resulting keys seem to work fine in SSH, which makes me think, if SSH
> could support pure server-side key, and we could generate these keys with
> Webauthn, it would actually make things even easier for our non-unix-savvy
> users (buy a key, press a button on our website to register it) while really
> tightening up user accounts and thereby decreasing the attack vectors against
> us.

yep, agree. I think a FIDO-style authn method would be a nice addition.

-d


More information about the openssh-unix-dev mailing list