Mailing List Archive

Webauthn signatures working in the wild, and client-agent support
Hey everyone!

We just added support (maybe a first?) for Webauthn keys in Blink.
Everything seems to be working great except in one scenario, using
them with our agent. You can see a quick demo here:
https://twitter.com/BlinkShell/status/1570427813819486212?s=20&t=2GNv08ro2zyBcI14DK4tIA

The implementation is making use of Passkeys and Secure Keys with
Webauthn support. I think the interesting part is how easy creating
and using keys like this is, and maybe future use cases would showcase
more possibilities for Webauthn keys.

This is all based on Damien Miller’s test projects (thanks a lot!) but
as mentioned, the Client-Agent (at sshconnect2.c) will not accept
webauthn-sk signatures at the moment. The setup is that we use our
Agent to forward a key to the remote. Then when trying to sign with
this key, the SSH Client is expecting a sk-ecdsa signature type, but
our agent can only provide a webauthn-sk-ecdsa type.

The issue seems to be that the sign_and_send_pubkey will expect a
sk-ecdsa signature in all cases, and not a webauthn-sk-ecdsa. We have
been reading the code to see if we could bend things somehow, but it
looks like everywhere that a transform from key to signature-algorithm
happens, will always result in the sk-ecdsa type. We also tried
different flags for Accepted Pubkeys, disabling sk-ecdsa, trying to
set webauthn-sk type at the top, all with no luck. On the SSHD side
when logging in, this is not an issue as both are accommodated during
validation.

Are we missing something that could make things work? Is there
anything from our side that we could do to try things out or to
support this scenario?

Tons of thanks for any guidance!!
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
Re: Webauthn signatures working in the wild, and client-agent support [ In reply to ]
On Mon, 19 Sep 2022, Carlos Cabanero wrote:

> Hey everyone!
>
> We just added support (maybe a first?) for Webauthn keys in Blink.
> Everything seems to be working great except in one scenario, using
> them with our agent. You can see a quick demo here:
> https://twitter.com/BlinkShell/status/1570427813819486212?s=20&t=2GNv08ro2zyBcI14DK4tIA
>
> The implementation is making use of Passkeys and Secure Keys with
> Webauthn support. I think the interesting part is how easy creating
> and using keys like this is, and maybe future use cases would showcase
> more possibilities for Webauthn keys.
>
> This is all based on Damien Miller’s test projects (thanks a lot!) but
> as mentioned, the Client-Agent (at sshconnect2.c) will not accept
> webauthn-sk signatures at the moment. The setup is that we use our
> Agent to forward a key to the remote. Then when trying to sign with
> this key, the SSH Client is expecting a sk-ecdsa signature type, but
> our agent can only provide a webauthn-sk-ecdsa type.

Oh wow, I have not heard of anyone else using this for real before.
Nice work!

> The issue seems to be that the sign_and_send_pubkey will expect a
> sk-ecdsa signature in all cases, and not a webauthn-sk-ecdsa. We have
> been reading the code to see if we could bend things somehow, but it
> looks like everywhere that a transform from key to signature-algorithm
> happens, will always result in the sk-ecdsa type. We also tried
> different flags for Accepted Pubkeys, disabling sk-ecdsa, trying to
> set webauthn-sk type at the top, all with no luck. On the SSHD side
> when logging in, this is not an issue as both are accommodated during
> validation.
>
> Are we missing something that could make things work? Is there
> anything from our side that we could do to try things out or to
> support this scenario?

Unfortunately this webauthn keys via the agent isn't going to
work ATM and I'm not immediately sure how to fix it.

The problem is between sshconnect2.c:sign_and_send_pubkey() and
identity_sign().

In sign_and_send_pubkey() we have to assembled the data to be
signed (basically the SSH2_MSG_USERAUTH_REQUEST we're about to
send), and that includes the signature algorithm:

> if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
> (r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 ||
> (r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
> (r = sshbuf_put_cstring(b, method)) != 0 ||
> (r = sshbuf_put_u8(b, 1)) != 0 ||
> (r = sshbuf_put_cstring(b, alg)) != 0 ||
> (r = sshkey_puts(id->key, b)) != 0) {
> fatal_fr(r, "assemble signed data");

Unfortunately, we don't learn that the key is only capable of making
webauthn signatures until we attempt signing via identity_sign() and
observe (via sshkey_check_sigtype()) that we got a webauthn signature
back.

Perhaps there should be some way for ssh-agent to signal to the client
that a particular key can only make webauthn signatures, but I'm not
sure how best to do this.

It would be best if the agent simply told the client about it but, at
the moment, the SSH_AGENTC_REQUEST_IDENTITIES agent request used to
obtain the list of keys from the agent has no extra data fields that
could be used to signal this.

Now, we could extend the agent protocol to add an extra field to
carry stuff like this, but that has a number of costs including
time-to-deploy (this is less of a problem if you control the agent
and the ssh client).

One uglier IMO option would be to use the key comment field returned by
SSH_AGENTC_REQUEST_IDENTITIES to signal that a key is webauthn only.
This is possible, but since comments are user-specified, a user could
break their key if they put the magic signalling string in a key
comment.

Another possibility is abusing the key blob format returned by
SSH_AGENTC_REQUEST_IDENTITIES and having the webauthn keys identify
themselves as webauthn-sk-ecdsa-sha2-nistp256@openssh.com rather than
as sk-ecdsa-sha2-nistp256@openssh.com, and add associated plumbing to
carry the webauthn-only status of these keys through to sshconnect2.c.
IDK how other tools will handle this, as it's strictly a spec
violation to use a signature algorithm name in place of a key name
(though OpenSSH has hardly been sinless in this regard historically...)

Hope this clarifies the problem a little (it sure doesn't solve it
though).

-d
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
Re: Webauthn signatures working in the wild, and client-agent support [ In reply to ]
Thanks a lot for the prompt reply!

It definitely does not sound like there is an easy way out of this
one. I want to put on the table one more possibility though.

On Mon, Sep 19, 2022 at 6:15 PM Damien Miller <djm@mindrot.org> wrote:

> Unfortunately this webauthn keys via the agent isn't going to
> work ATM and I'm not immediately sure how to fix it.
>
> The problem is between sshconnect2.c:sign_and_send_pubkey() and
> identity_sign().
>
> In sign_and_send_pubkey() we have to assembled the data to be
> signed (basically the SSH2_MSG_USERAUTH_REQUEST we're about to
> send), and that includes the signature algorithm:
>
> > if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
> > (r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 ||
> > (r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
> > (r = sshbuf_put_cstring(b, method)) != 0 ||
> > (r = sshbuf_put_u8(b, 1)) != 0 ||
> > (r = sshbuf_put_cstring(b, alg)) != 0 ||
> > (r = sshkey_puts(id->key, b)) != 0) {
> > fatal_fr(r, "assemble signed data");
>
> Unfortunately, we don't learn that the key is only capable of making
> webauthn signatures until we attempt signing via identity_sign() and
> observe (via sshkey_check_sigtype()) that we got a webauthn signature
> back.
>
> Perhaps there should be some way for ssh-agent to signal to the client
> that a particular key can only make webauthn signatures, but I'm not
> sure how best to do this.
>

Between sshconnect2.c:sign_and_send_pubkey() and identity_sign(),
there is a call to key_sig_algorithm and its output is used for
SSH2_MSG_USERAUTH, and so on... key_sig_algorithm makes use of
sshkey:sshkey_ssh_name_from_type_nid. The issue there is that webauthn
and sk both are declared as the same type: KEY_ECDSA_SK.

At the moment webauthn-sk is considered just a signature only type,
per sshkey:keytypes, and per your "experiment", the pubkey type is
made sk-ecdsa. But, trying to force things, if you create the pubkey
as webauthn-sk-ecdsa, sshd will log you in if you add webkey-sk-ecdsa
as an Allowed Pubkey Method.

As you said, it is a violation that the key and signature are
different, but could a case be made to grant webauthn-sk-ecdsa the
full "key type" status? At the end of the day, it is not fully true
that KEY_ECDSA_SK and Webauthn represent the same type of key, even if
until now things have been "forced" to fit that way.

I may be missing something or not have the full scope of a change like
that, but just want to run it through you to see if it may be a viable
possibility.

Thanks again!
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
Re: Webauthn signatures working in the wild, and client-agent support [ In reply to ]
On Mon, 19 Sep 2022, Carlos Cabanero wrote:

> Between sshconnect2.c:sign_and_send_pubkey() and identity_sign(),
> there is a call to key_sig_algorithm and its output is used for
> SSH2_MSG_USERAUTH, and so on... key_sig_algorithm makes use of
> sshkey:sshkey_ssh_name_from_type_nid. The issue there is that webauthn
> and sk both are declared as the same type: KEY_ECDSA_SK.
>
> At the moment webauthn-sk is considered just a signature only type,
> per sshkey:keytypes, and per your "experiment", the pubkey type is
> made sk-ecdsa. But, trying to force things, if you create the pubkey
> as webauthn-sk-ecdsa, sshd will log you in if you add webkey-sk-ecdsa
> as an Allowed Pubkey Method.
>
> As you said, it is a violation that the key and signature are
> different, but could a case be made to grant webauthn-sk-ecdsa the
> full "key type" status? At the end of the day, it is not fully true
> that KEY_ECDSA_SK and Webauthn represent the same type of key, even if
> until now things have been "forced" to fit that way.

Well, this is similar to what I suggested wrt having the agent send the
keys back as "webauthn-sk-ecdsa-sha2-nistp256" but a little more
officially :)

There are two ways to do this. One is keeping the key type id
as KEY_ECDSA_SK and adding a key->flags entry to indicate that it's
webauthn-only. Another is a whole separate key type.

At the moment, adding a new key type means a lot of duplicated
boilerplate code. I have some WIP changes to reduce this[1], but even
after they land it there is so much overlap with regular ecdsa-sk keys
it probably makes more sense to go the other way.

-d

[1] https://github.com/djmdjm/openssh-wip/pull/10/commits
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
Re: Webauthn signatures working in the wild, and client-agent support [ In reply to ]
On Mon, Sep 19, 2022 at 8:05 PM Damien Miller <djm@mindrot.org> wrote:
>
> On Mon, 19 Sep 2022, Carlos Cabanero wrote:
>
> > Between sshconnect2.c:sign_and_send_pubkey() and identity_sign(),
> > there is a call to key_sig_algorithm and its output is used for
> > SSH2_MSG_USERAUTH, and so on... key_sig_algorithm makes use of
> > sshkey:sshkey_ssh_name_from_type_nid. The issue there is that webauthn
> > and sk both are declared as the same type: KEY_ECDSA_SK.
> >
> > At the moment webauthn-sk is considered just a signature only type,
> > per sshkey:keytypes, and per your "experiment", the pubkey type is
> > made sk-ecdsa. But, trying to force things, if you create the pubkey
> > as webauthn-sk-ecdsa, sshd will log you in if you add webkey-sk-ecdsa
> > as an Allowed Pubkey Method.
> >
> > As you said, it is a violation that the key and signature are
> > different, but could a case be made to grant webauthn-sk-ecdsa the
> > full "key type" status? At the end of the day, it is not fully true
> > that KEY_ECDSA_SK and Webauthn represent the same type of key, even if
> > until now things have been "forced" to fit that way.
>
> Well, this is similar to what I suggested wrt having the agent send the
> keys back as "webauthn-sk-ecdsa-sha2-nistp256" but a little more
> officially :)
>
> There are two ways to do this. One is keeping the key type id
> as KEY_ECDSA_SK and adding a key->flags entry to indicate that it's
> webauthn-only. Another is a whole separate key type.
>
> At the moment, adding a new key type means a lot of duplicated
> boilerplate code. I have some WIP changes to reduce this[1], but even
> after they land it there is so much overlap with regular ecdsa-sk keys
> it probably makes more sense to go the other way.
>
> -d
>
> [1] https://github.com/djmdjm/openssh-wip/pull/10/commits

Ahhh I think I see now. Using key->flags we could indicate that it is
webauthn only, but as you mentioned in your first message, we would
also need some way for the agent to communicate that when listing, or
to make it fallback to a webauthn-signature at one point, correct?

Now that I have an idea of the scope I think it is doable, but we will
definitely not make it for v1. We will launch as-is to see what
adoption we get, and if we get requests to add forwarding capabilities
at least we know there could be a way. Hopefully we can contribute
that to the project :)
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev