Solokey Concepts, Configuration and Use

Categories: Security

Introduction

Solokeys is an organisation which sells a family of physical devices that connect to a PC, mobile phone, or similar device (via USB or NFC) and provide encryption services of various types - most importantly U2F (FIDO1) and WebAuthentication (FIDO2). A Solokey can be used for login authentication - and in future for encrypting/decrypting files, signing emails, and similar purposes.

There are similar devices from other providers (Yubikey, Google Titan, etc), but what makes Solokeys very interesting is that all hardware and software are completely open-source with an active development community and a site for technical documentation (though it needs improvement IMO). Given the open hardware specifications, you can theoretically build your own physical Solokey if you have the necessary skills - though in practice most people would want to buy devices from the Solokeys shop! The initial version of Solokey was developed using funding gathered via Kickstarter.

Solokeys are currently very new; some functionality is still being developed.

This site has an article specifically on Yubikey which also contains a significant amount of background information on FIDO1, FIDO2, OpenPGP, and similar topics. I recommend reading that article if you are not familiar with these areas. This article is primarily about Solokey itself.

This article is currently very short - I only discovered the Solokey project recently. My key is on order and once I have had time to play with it, I will update this article.

Solokeys is effectively an “update” of the successful (but simpler) U2F-Zero project, with the same primary technical architect.

WARNING: I encountered the Solokeys project only recently. All information in this article should therefore be read with caution - corrections welcome!

Status

At the current time (mid April 2019), Solokey versions with USB-A and USB-C support are available. The Solotap versions which add NFC support are expected to ship in the next few weeks (ie by end of April 2019).

Unfortunately, the software lags behind the hardware design somewhat. U2F (aka FIDO1) and WebAuthentication (aka FIDO2) support is implemented but other features are still in development. However given the active community, I don’t expect it will be long until Solokey is feature-compatible with Yubikey (their explicit goal). In particular, it is expected that the following will be implemented:

  • OpenPGP support (for signing documents and encrypting/decrypting files)
  • SSH key support (for logging in via SSH servers)
  • OATH-TOTP
  • OATH-HOTP
  • static password storage

Hardware

The Solokey has either a USB-A or USB-C connector. The NFC-enabled variants have (obviously) NFC as well.

The NFC variant is slightly larger than the non-NFC one. However both fit comfortably on a keyring.

All Solokeys have an embedded button for confirmation of operations (important so that rogue software on a PC or other device the Solokey is connected to cannot initiate operations without your explicit approval). The keys also have a single multi-colour-capable LED, controlled by software.

The USB-A/USB-C connector is not retractable, nor does it have a cover. However this is also the case for the Yubikey, and I have not had any problems with that.

TODO: does the device have a battery?

TODO: does the device have a clock?

The Solokey includes dedicated hardware for random number generation.

Software

All hardware and software development is done via a set of Github projects. Issue-tracking also occurs via Github.

Software running on the Solokey is divided into the following categories:

  • Device Firmware Update (DFU)
  • Bootloader
  • Solo Application

The DFU is the lowest level of embedded firmware; the DFU provides just enough IO support to allow new firmware to be uploaded. An “uninitialized” Solokey boots into the DFU; a “hacker mode” device can be forced to boot the DFU by holding down the device button for 5 seconds. A “production mode” device cannot be forced to boot the DFU.

The standard bootloader is low-level code that initializes the device, and provides support for uploading new firmware - but only when the new firmware is properly signed by private keys whose public components are in the existing firmware. In other words, the standard bootloader allows its host system to replace the entire firmware (including the bootloader itself) but only under specific conditions. Because this bootloader needs support for signature verification, it is more complex than the DFU - and requires the hardware to be more completely initialised.

The Solo application code is linked with the bootloader to form a full firmware image. Code in the Solo application module does not deal with low-level hardware initialisation (that is done in the bootloader); instead it concentrates on providing user-level functionality (such as U2F and FIDO2 support). Making coding errors at the Solo application level are not as serious as making errors at the bootloader level because, as long as the bootloader still runs correctly, a bad version can be replaced by uploading an older or newer firmware version.

Client-side administration/configuration tools are implemented in Python3.

Note that there is no kernel-space/user-space separation for code in the Solokey - it is an embedded system, not a traditional PC. In effect, the device runs one single application - but that application can expose multiple USB devices to the host it is attached to and thus provide distinct functions.

TODO: where is the bootloader code in the github repos? Is this under “CBOR”?

Development Tools

When building a firmware image, a “debug mode” can be enabled. When a Solokey with such firmware is attached to a host it registers an additional USB “serial port” device in addition to the usual USB devices used for FIDO1/FIDO2/etc. The key then sends any “debug messages” embedded in its code to that serial port, allowing a developer to monitor behaviour of software on the device.

Compiling on a standard developer setup but targeting the embedded platform requires a cross-compiler; to make this easy, a docker image containing the necessary cross-compiler is provided by the project. Alternatively you can install the necessary ARM-targeting cross compiler explicitly.

The manufacturer of the ARM-based chip on which the Solokey hardware is based sells a “development board”, allowing hardware-in-the-loop testing. Or you can test directly (though less conveniently) on a “hacker mode” Solokey.

Although the Solokey hardware uses an ARM-based CPU, the Solo application code can also be compiled to x86 and run on a standard PC for development and testing purposes. When run in this way, the Solo application accepts USB data packets over a UDP socket rather than via a USB device node; a modified FIDO2 client app is provided which supports this USB-over-UDP hack. The Solokey bootloader code is very hardware-specific and cannot be tested in this way.

When compiled for running on a developer’s system (see above), the resulting binary application also provides a set of admin tools (presumably this code is not linked in when building firmware for installation on the key itself). These admin tools include:

  • support for signing firmware images
  • support for uploading new firmware to a Solokey device
  • support for displaying debug-messages emitted from a Solokey device

Hacker vs Production Mode

A Solokey configured in “hacker mode” allows the “operating system” to be replaced (booting to the DFU is possible). However when a device is switched from “hacker mode” to “production mode” the DFU is disabled. This means that the exisiting firmware on the device (bootloader component) controls whether new firmware updates are allowed.

The standard bootloader implementation includes a set of public keys, and allows new firmware to be uploaded (ie to replace the current firmware) as long as the new app software package is signed with a private key that corresponds to a public key embedded in the current firmware. This allows firmware to be safely updated on a Solokey in production mode.

Solokeys can be purchased in either hacker mode or production mode; both have the standard software preinstalled. When purchased in production mode, the firmware contains only keys belonging to the core Solokey organisation - and thus new versions of apps can only be installed when signed by that organisation. This is effectively the same as purchasing a Yubikey, Titan, or similar except that:

  • device sourcecode is available to read
  • client (admin) software is open-source and modifiable
  • and contributions to either device or client software can be submitted via the github project

When purchased in hacker mode, the device is fully functional; you can use it for holding your U2F/FIDO2 keys etc. However if it is stolen then an attacker could potentially replace the firmware with a different version that reveals keys stored on the device.

It is relatively easy to modify the official firmware to add your own public keys as “supported app signing keys”. This makes it possible for you to update firmware on the device even after it is set to production mode (as long as you do not lose the corresponding private key!).

Backing Up Credentials

One of the significant concerns I had with Yubikey’s FIDO2 support is the issue of backups. With FIDO2, each service you authenticate with requires its own public/private key pair stored in the device. This is nice, as there are no “shared credentials” between sites. However these keys are generated on the key itself, and Yubikey currently provides no way at all to back up such keys. This means that if you lose the key, you lose access to that account unless you also define “alternative credentials”.

One alternative credential would be to sign up using a different Yubikey, ie to have two keys. However you would need to have access to both keys whenever signing up to a new service - and having the “backup device” always near the “primary device” creates a high risk of losing both at the same time.

An alternative is to have an “account recovery” process based around email/sms/etc. But that is a significant weakpoint in security - an attacker can potentially use the “recovery” process to access your account.

It isn’t currently clear whether Solokey’s official software has a “backup” concept - but if not, someone (possibly me) can implement one.

Host-to-Device Communications

In order to provide FIDO2 (CTAP2) support compatible with existing clients, the Solokey needs to support the CTAP2 protocol. This in turn means it needs to register itself with the host device as a USB HID device, and exchange CTAP2-specific messages over this USBHID connection.

U2F (FIDO1/CTAP1) support is also provided via a USB HID device node. As far as I know, the same device node is used, with different USB data packet types.

When the standard firmware is compiled with the appropriate DEBUG flag then the Solokey also registers itself as a USB Serial Port device, and outputs logmessages from the application over this port (one-way only).

If support for other protocols is added (eg TOTP/HOTP) then the device may in future register itself as a device providing additional USB interfaces.