Support FIDO2/CTAP2 security tokens as keystore
n+wireguard at stalder.io
Fri Aug 30 13:42:15 CEST 2019
Having something like this has been my dream for a while now, and I
intend to make it
possible with my company's open source FIDO2 product (SoloKeys). No ETA as we're
juggling implementation of other functionality with limited resources.
Note that FIDO2 directly won't work, as it only defines signatures of
certain (not all) payloads
(and with the hmac-extension some HMACs).
The main use cases I see are in a "road warrior" kind of setup:
- can use on other people's computers (or even one's own that are
semi-untrusted and infrequently connect)
- no need to synchronize key out of band - use “donglenet”
- once removed, connections are closed
Use as baby HSM on a server may are may not make sense too, as long as
can keep up with the number of connections that need (re)keying. To
make this efficient, I'm separately
working on packaging up Bjoern Haase's Cortex-M4 implementation [a] in
an easily usable
If my understanding is correct, the bare minimum functionality is:
- store key non-extractably on device (unless you're Colin O'Flynn...)
(if there is an issue, just rotate the key)
- periodically do Curve25519 Diffie-Hellman to generate sessions keys
(that are revealed to the client, possibly with some sort of
transport layer security)
Beyond minimal functionality there are questions of how to enroll
keys, how to select if there are multiple...
The threat model would be along the lines of: if the key is in the
port, can connect; if not, cannot.
This does prevent malicious processes in user space (or root) from
stealing the key.
Two layers of security could be added:
- "user presence" check requiring an initial key press on the token.
- "user verification": PIN to unlock key (adding something you know to
something you have)
I assume pressing the key every two minutes (Rekey-After-Time) is
annoying, so perhaps an initial verification
should be good for some time, perhaps per endpoint, perhaps globally.
Regarding implementation I see three basic paths:
- CTAPHID has "vendor" commands , use these. Advantage is that raw
CTAPHID is a super simple protocol,
and with FIDO2 maybe becoming more widespread, udev rules will already
be in place .
- alternative CTAPHID option: instead of raw vendor commands, use
CTAPHID_CBOR and extend the
Authenticator API with "authenticatorVendor" commands . Disadvantage: CBOR :)
- CCID route: entails supporting the full smartcard stack cruft
someway or other.. ugh, but possible.
Maybe based on PIV? That standard doesn't include the required
cryptography, but it's nicely split in
three parts, where parts 2 + 3 constrain general ISO 7816 into a
protocol, whereas specifics on keys
and their cryptography are constrained to part 1, which could then be
modified [c, page 31].
Personally, I'd prefer options 1 or 2, with the goal of eventually
adding the necessary extensions to
the FIDO CTAP spec. Work towards option 3 is very very experimentally
being explored in [d].
What is completely unclear to me (not being a kernel or Wireguard dev
at all) is how Wireguard as part of the
kernel would connect and interface with the token.
Hence it would be useful if someone with Wireguard and kernel
expertise could define a minimal interface
(mostly: "do DH with your secret key against this public key, give me
the secret") for a small shim process to implement against,
which in turn would speak CTAP2 (or ISO 7816) to the token.
Maybe this minimal interface already exists? Is this where netlink comes in?
Should Noise be used to confidentially mutually authenticate Wireguard
and the token?
More information about the WireGuard