/openssh-sk-winhello

A helper for OpenSSH to interact with FIDO2 and U2F security keys through native Windows Hello API

Primary LanguageCGNU Lesser General Public License v3.0LGPL-3.0

OpenSSH SK WinHello Release Platform License

A plugin for OpenSSH to connect to FIDO/U2F security keys through native Windows Hello APIs. demo

Introduction

OpenSSH version 8.2 added support for authentication using FIDO/U2F hardware security keys. There are two new key type ecdsa-sk and ed25519-sk which can be used for this.

Communicating with keys is done through a helper app named ssh-sk-helper(by default it is in /usr/lib/ssh). This helper has an internal implementation to connect to FIDO/U2F keys using libfido2 library and support connecting to keys via HID protocol on USB(no Bluetooth or other things). ssh-sk-helper also supports dynamically loaded middleware libraries to be used instead of internal implementation so you could be able to connect to security keys through other ways. Details about how to implement those middlewares are described in OpenSSH source in file PROTOCOL.u2f.

Internal implementation works well in Windows. However, in Windows 10 version 1903 or higher, you need administrator privileges to be able to access any FIDO device, which means you need to run Bash or other apps calling OpenSSH as administrator or they won't detect your keys, and this is painful.

Windows provides an API set called Windows Hello to access to FIDO/U2F keys without administrator privileges, these APIs are being used in major browsers(Chrome, Firefox, Edge) in Windows for JavaScript WebAuthn implementation. Windows Hello also supports other types of authenticators like internal TPM device(if they support generating ECDSA or Ed25519 keys, they can be used instead of FIDO/U2F security keys).

So I created this middleware module for OpenSSH to access FIDO/U2F keys through Windows Hello APIs and make everything easier.

Install

Compiled files of this project are available on GitHub releases. It is compiled for the MSYS environment(Git for Windows is using MSYS). For other environments like Cygwin please download the source code and compile it yourself according to Build instructions.

  1. Download a version of this module which matches your installed OpenSSH Version: Run ssh -V to detect your OpenSSH version.

    • OpenSSH v8.4+: Get latest 2.x
    • OpenSSH v8.3 : Get latest 1.x
    • OpenSSH v8.2 : Get latest 1.x and custom openssh-sk-helper
  2. Copy files:

    • Copy winhello.dll wherever you want, /usr/lib directory is preferred.
  3. Configure OpenSSH to use winhello:

    1. Configure ssh:

      • open your local config file on ~/.ssh/config(or global config file on /etc/ssh/ssh_config) and add this:

        Host *
            SecurityKeyProvider winhello.dll
        
      • Or use -oSecurityKeyProvider every time you use ssh command:

        ssh -oSecurityKeyProvider=winhello.dll user@host
    2. Configure ssh-keygen and ssh-add/ssh-agent:

      • You can set an environment variable in your shell init code. For example if you are using Bash, add this line in ~/.bashrc file:

        export SSH_SK_PROVIDER=/usr/lib/winhello.dll

        Use absolute path to winhello.dll or ssh-agent will refuse to add your key.

      • Or set it on every call:

        SSH_SK_PROVIDER=winhello.dll ssh-keygen -t  ecdsa-sk
        SSH_SK_PROVIDER=/usr/lib/winhello.dll ssh-add ~/.ssh/id_ecdsa_sk
      • Or use argument like this:

        ssh-keygen -w winhello.dll -t ecdsa-sk
        ssh-add -S /usr/lib/winhello.dll ~/.ssh/id_ecdsa_sk

        Note: Use absolute path in ssh-add, or ssh-agent will block you.

Supported flags

You can use some flags during key generation with ssh-keygen, there are some small notes about them:

no-touch-required

Using the -O no-touch-required option you can generate a key that doesn't need interacting(e.g touching) with your security key during login(during key generation you should always interact with security key). You should also add no-touch-required into the server's authorized_keys file or it will prevent you from logging in, for example:

no-touch-required sk-ecdsa-sha2-nistp256@openssh.com AAA..... user@host

However, Windows API does not support this option(meaning you should always interact with your security key).

Before version 1.1.0 of this module, it would have prevented you from creating or using these keys. But since version 1.1.0, you can create and use them. However, you need to interact with your security key anyway regardless of key settings when you are logging in to a server. This won't make the server becoming angry at you, since you touched your security key when it said it's not necessary.

resident

By using -O resident you can make your key stored inside your security key(it should be FIDO2 compatible). With this, when you want to use your key on a new machine, you don't need to transfer your private/public key files. You can simply run ssh-keygen -K command and it will regenerate same private/public keys on new machine.

Using this module can generate these type of keys, but it doesn't support copying resident keys. You need to do it with internal module of OpenSSH. Check known issues for more info.

verify-required

Using the -O verify-required you can force ssh to ask for your security key's pin every time you try to connect.

credProt Extension

Since OpenSSH version 8.4, if you use OpenSSH internal module and set any of the resident or verify-required flag, it will also force you to use credProt extension(Before v8.4 there was no verify-required option and resident option wasn't forced to be this way). I should also note that using or not using this extension has no effect on your login process.

I tried to write this module as close as possible to the internal implementation, but for now seems like credProt is not working correctly in Windows Hello. You can't create keys with this extension and you can't use keys created with this extension(you will get "the key doesn't seems to be familiar" message). So:

  • If you use internal module to create key with credprot enabled: You can use it to login with internal module, but not this module.
  • If you use this module to generate keys with verify-required and/or resident flag: You can use it anywhere.

application

You can change application name with -O application=ssh:something, name can be anything starts with ssh:.

user

You can set user name with -O user=name, this module use SSH User as default name, I strongly recommend you to set your desired name if you are using more than one key.

device

With multiple security keys attached to one system, you can specify which one you are working with using -O device=id option.

Windows Hello automatically find your device, so this is not needed and not supported.

attestation

use -O attestation=/path/to/newfile to store attestation data created.

Use inside WSL

Security keys are not available inside WSL, but you can use a ssh-sk-helper on windows and configure your WSL to use it, Check WSL.md for more info.

Build

Requirements

make, gcc and libssl-dev are required, you also need autoconf automake libtool if you are cloning from git.

If you are downloading tarball:

./configure
make

If you are cloning from Git:

autoreconf --install
./configure
make

You can use make install to copy the DLL file into /usr/lib but that also copies some static files for linking, those files are not needed because OpenSSH uses dlopen to access to middlewares.

Known issues and limitations

  • credProt extension is not working with Windows Hello, you can't create keys with credProt extension and you can't use keys created with this extension.

  • because credProt is affecting Attestation data, output attestation of this module will be different with internal module when you use verify-required or resident flag(both are correct, they are different because configurations are different).

  • Windows Hello API does not support empty user ID, so if you do not specify any user ID(using -O user=myusername option) this module uses a default user ID SSH User. This behavior is different with the internal implementation which uses empty user ID.

  • Support for copying resident keys from security key is not available, use internal implementation for this(do not add -w to ssh-key or -S to ssh-add or use the word internal as the path to the middleware if you have env variable set):

    ssh-keygen -K
    ssh-add -K
    OR
    ssh-keygen -K -w internal
    ssh-add -K -S internal

    Be sure that you are running Bash as administrator whenever you use internal implementation or you get "Device not found" error.

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

License

OpenSSH project uses BSD license. Microsoft webauthn.h interface uses MIT license. This project is available through LGPLv3 license.