The idea is to repurpose the omnipresent st-link v2 clone dongles as a FIDO2/U2F/WebAuthn key. While commercial options exist, I like the idea of being able to build your own with mostly available hardware. Moreover, this allows for cheap/rapid prototyping. Finally, the idea is to add a feature not widely found on existing commercial options, which is an embedded OLED display and two hardware buttons. This allows to visually confirm authentication attempts and select available credentials. Ultimately, the hardware component of this project can be easily re-used for other purposes.
On the software side, this project leverages existing open-source implementation of other FIDO2 devices. The idea is to port this to the NuttX RTOS, which includes many features already. Furthermore, this development would actually mean that the software could be easily ported to other hardware platforms.
The following are targeted features for the hardware:
Based on ST-Link V2 dongle (considering the variants found in the wild)
Two hardware push-buttons
Embedded OLED display (128x32, 0.91', I2C)
3D printed case, including hole for carrying around in your keychain
Based on SoloKey FIDO2 open-source firmware, ported to NuttX RTOS.
Last week I've been slowly advancing on the NuttX port. The main difficulty is mostly the reduced SRAM of the STM32F103 (20Kb). The solo firmware requires some considerable RAM, given that some data structures are a bit big, and there are large arrays of these. For testing, I started reducing all these to minimal working sizes. On the other hand, I disabled lots of stuff on the NuttX (no NuttX shell, for example) and played with the stack size. Using the Solo firmware test scripts, I was able to slowly tackle memory issues and pass more and more tests.
At the moment I'm not passing all tests, since they're a bit memory demanding. The main difficulty is that the CTAP protocol is supposed to handle multiple pending assertion requests, which can later be retrieved. Since I had to reduce memory, I'm not passing tests related to this functionality.
I later realized that with the achieved functionality, it should at least be sufficient to use one of the online WebAuthn tests. And, indeed, it is working!
So after playing a lot with OpenSCAD I decided to simply go ahead and build a prototype without a case and later worry about case. Moreover, I was trying to think how would I solder two buttons since there isn't really much space and I/O pins are well distributed on the back of the board. So, I decided to go ahead with just one button, which will be enough for confirming an action or not. Going into menus and options would be possible by holding down the button, but it feels annoying. At the moment I will just use the OLED to display current request which will also make it really simple to program.
I have the (internal) SWD pads soldered so that I can flash it with (another) ST Link. The first thing was to unlock the flash (it usually comes locked) and then use openocd to write a DFU loader (I use generic binary with LED on PA9 from STM32duino project). Then, I used the arduino IDE with the STM32_Arduino package.
With this I could blink the LED and read the button (requires an input pull-down to read correctly). You can see the result here:
Moreover, I could use the SSD1306 library from Adafruit (modified for STM32). Since I made a mistake and soldered SCL with SDA and viceversa (I will fix it tomorrow) I had to resort to SoftWire, which allows me to swap SCL and SDA pins:
I will now continue porting the Solo code to NuttX. I think this will eventually require porting some of this upstream since the project appears to be very active.
So I've continued my attempts to create a 3D case for the device being designed. I still haven't completely decided how to place the two buttons but they will most likely go at the back. Here you can see the dongle with the OLED:
The OLED is (supposedly) positioned as low as it can (the crystal on the dongle limits the height. The buttons will go in the back, slightly increasing the length, but not by much.
The case so far looks something like this:
The idea is to have a cutout for the OLED. The case should be split in two parts for printing and assembly. However, the insides of this are really difficult to get right. I have to provide space for the boards and consider extra space for the components beneath the dongle. Moreover, it should be possible to slide the device in, which I don't think is really easy.
Since I'm just learning to do this I'm thinking I will simplify things initially. I only really need a case to hold the buttons, since I don't see a way of soldering them in place in the back. I will rethink this and try to simplify this stage and leave it for future improvement.
The last few days I've starting the porting process of the SoloKey firmware to NuttX RTOS. The first step was to actually add a raw HID USB driver to NuttX, which is the underlying transport for CTAP, the FIDO2 standard protocol. This is currently working (with nothing fancy) so I guess I can tick that item off.
The next step (currently working on this) is the porting of the actual logic of the SoloKey firmware to a NuttX application. Luckily, the guys from SoloKey did things right and defined a very simple interface which should be implemented by the target platform. Thus, I need to provide implementation for this interface while at the same time write my own main function. At the moment I managed to build everything without exceeding FLASH size limit (currently at around 81K of the 128K) and there's still room for reduction by disabling unrequired NuttX features. However, I'm currently struggling with the required stack size. For this I had to reduce some internal buffers used by the SoloKey firmware.
Currently I need to finish the implementation of the interface, which mostly involves dealing with the on-board flash as storage for the secret keys and other non-volatile data. There's also the crypto implementation which will be purely done in software. I will simply re-use everything provided with solo and later see what I can take from NuttX instead.
Regarding the hardware side, I already have available a pair of ST-Link dongles (one for programming, the other will be the victim) and the 128x32 OLED, which I must say is the perfect size for this. I'm also trying to see how this would fit along two buttons inside a case, which I think is perfectly doable.