Finding a resident key stored in an agent without a corresponding file?
Ron Frederick
ronf at timeheart.net
Wed Mar 24 02:45:22 AEDT 2021
On Mar 22, 2021, at 10:17 PM, Damien Miller <djm at mindrot.org> wrote:
> On Sun, 21 Mar 2021, Lars Noodén wrote:
>> I have a question about SK keys when there are more than 6 keys in the
>> agent.
>>
>> If I have added an SK key as resident to a hardware token, using the -O
>> resident option with ssh-keygen(1), then the -K option with ssh-add(1)
>> will get the resident key later from the token and store it in the agent.
>>
>> $ ssh-add -K
>>
>> With six or fewer keys in the agent, assuming default MaxAuthTries in
>> the server, it is then only a matter of having the SSH client use the
>> agent and the right key will be found. However, with many keys already
>> in the agent, the key has to be specified explicitly or the 'wrong' keys
>> will get tried first.
>>
>> I'd like to point the client directly to the resident key without first
>> extracting the resident key and saving it to the file system. How may I
>> tell the SSH client which key to use without a file on disk?
>
> no such facility exists at present.
>
> It wouldn't be hard to add such a capability to ssh, but we'd need to
> figure out a good UI for it. FIDO2 AFAIK stores resident keys by
> { user, application } name, so adding some way to download resident
> keys and match/filter on these attributes would be the place to start.
>
> This will probably require a change to the sk-api.h interface between
> ssh and the FIDO hardware.
>
> A slightly-terrible workaround might be to download all the keys to the
> agent and delete the "wrong" ones.
This is definitely possible. I have it implemented in AsyncSSH using the standard FIDO2 library. For what it’s worth, the AsyncSSH function for this currently looks like the following:
def load_resident_keys(pin, *, application='ssh:', user=None,
touch_required=True):
"""Load keys resident on attached FIDO2 security keys
This function loads keys resident on any FIDO2 security keys
currently attached to the system. The user name associated
with each key is returned in the key's comment field.
:param pin:
The PIN to use to access the security keys, defaulting to `None`.
:param application: (optional)
The application name associated with the keys to load,
defaulting to `'ssh:'`.
:param user: (optional)
The user name associated with the keys to load. By default,
keys for all users are loaded.
:param touch_required: (optional)
Whether or not to require the user to touch the security key
when authenticating with it, defaulting to `True`.
:type application: `str`
:type user: `str`
:type pin: `str`
:type touch_required: `bool`
“""
Given a PIN, this will load the subset of keys matching the requested application and user (if specified), with the application defaulting to ’ssh:’ and the user defaulting to loading keys for all user names with the user name being added to the key’s comment.
Once loaded, you can specify the resulting key objects as a “client_keys” argument in whatever calls you like that require private keys, instead of specifying raw key data or a filename containing a key.
This call also lets you specify whether to require touch on the key when it is used. Of course, the server needs to also specify ’no-touch-required’ for that to be allowed.
--
Ron Frederick
ronf at timeheart.net
More information about the openssh-unix-dev
mailing list