Hardware 2FA TOTP authenticator

Small USB 2FA authenticator for up to 32 profiles

Similar projects worth following
USB 2FA Hardware authenticator. With the following features:

* Supports up to 32 profiles (keys up to 320 bits in length, profile name up to 14 characters)
* USB keyboard simulation for typing tokens with a single button press
* USB mode to enter new profiles using CSV file
* Rechargable RTC battery (has around 6 months of battery life on a single charge)
* Settings menu that allow changing the time and RTC calibration
* Case to protect the PCB

All files can be found at:
BOM can be found at:
  • 1 × LPC1756 Microprocessors, Microcontrollers, DSPs / ARM, RISC-Based Microcontrollers
  • 1 × ST7789 SPI display

  • Timezones + last viewed token

    itzandroidtab05/27/2024 at 23:57 0 comments

    During daylight saving I noticed it was not very convenient to have the timezone in the same menu as the time. You would have to enter through 6 steps to only change the timezone. To make this easier I moved the timezone to a seperate menu item in the settings screen. 

    Timezone in the settings

    I also made it store the last viewed token. On bootup it reads the last used token and shows this instead of the first token. This makes it quicker if you want to enter the same 2fa token multiple times.

  • CSV file / memory changes

    itzandroidtab03/24/2024 at 21:07 0 comments

    CSV file

    When a error is detected in the CSV file there was no way for the user to see what was wrong in a specific profile. To make this clear I added messages that are displayed when parsing the CSV file. These are displayed in every path except for unchanged entries. Currently the following messages are displayed:

    * Profile added

    * Profile deleted

    * Invalid profile name error

    * Invalid interval input error (seperate error for out of range and for invalid characters)

    * Invalid digits input error (seperate error for out of range and for invalid characters)

    * Invalid profile key error

    * Error to signal there is no more space for new profiles

    All these messages are shown in the configuration screen and can be cleared by short pressing the enter button. To clear all messages and go back to the settings screen, long press the enter button.

    Adding a profile
    Removing a profile
    Example of a error message


    To make space for these new messages I reduced the stack size to 0x1000 (was 0x4000). I did a few tests to make sure the authenticator would not run out of memory. To detect if the authenticator ever runs out of memory I added a hardfault handler that will be called when a error is detected. This handler displays the error and a message where to report errors if they keep occuring (the hardfault handler reinitializes all the required hardware and directly writes the pixels to the display. This is done to ensure that we do not trigger DMA interrupts, it also reduces the amount of memory used in the hardfault handler).

    Error screen of the hardfault handler (simulated by decreasing the stack size until a harrdfault occurred)

    With all these new features the current usage the authenticator should be able to run on any LPC175x with more than 20.6k of ram and more than 103.5k of flash. 

    Current usage on a release build with LTO enabled (LTO decreased flash usage by around 1.5k):
    Build logs including these statistics can be found here

  • Variable interval support

    itzandroidtab03/24/2024 at 00:34 0 comments

    Added support for the last missing item to make the authenticator work with most 2FA providers. Support for variable intervals.  This allows the user to set a interval in the CSV file (was already in the file but unused). The interval is used to calculate the counter used in the TOTP algorithm (epoch / interval = TOTP counter value). Most providers use the default of 30 seconds, but I have seen some cases where 60 seconds is used. 

    The authenticator supports intervals from 1 to 180 seconds (dont think less than 30 seconds is used anywhere but just to be sure). The 180 second limit is caused by the division of the circle that shows the amount of time left. The circle is split in 180 parts. By disabling splitting the circle it should be possible to have intervals up to 360 seconds (and by removing the circle the timeout can be any value).

    During testing I also centered the profile text. I was experimenting with some other features and I think this looks better.

    Test profile with a 70 seconds interval
    Test profile with a 15 seconds interval

  • 8-Digit tokens / Base32

    itzandroidtab03/07/2024 at 06:32 0 comments

    To make the authenticator compatible with more 2FA providers I added 2 new features. The first one is 8 digit token support. With this feature tokens of 8 digits can now be generated, displayed and typed using the HID keyboard.

    TOTP authenticator displaying a 8 digit token

    To configure the 8 digit tokens the "digits" field in the CSV file can be set 8 when creating a profile. This changes that specific profile to show 8 digits. Another new feature in the CSV file is supporting base32 strings as key input. These can now be entered with the prefix "b32". See the example in the CSV file for more info. (keys are still limited to 320 bits. If the key has more data it will be ignored) 

    Example of a config file with a 8 digit token and base32 key

    I also added the profiles in the linker script. The code will use the addresses provided by the linkerscript. This makes it easier to change the location without looking into the code. To move the profile section only the section address and length need to be changed. Currently only 2k (64 bytes * 32 entries) is used in the profile section. As we need to erase a whole sector to reprogram flash the profile region is set to the whole sector. When moving this should be taken into account.

    Memory usage with a seperate profiles region

  • Timezone support / UI improvements

    itzandroidtab02/25/2024 at 21:35 0 comments

    To make it easier to set the epoch time correctly I added support for timezones (GMT only). The timezone selection is done in the settings screen where you can set the time. (This is important as TOTP uses the epoch time without timezone. If the user selected the local time without removing the time offset to GMT+0 the codes are not correct). The timezone is stored in the RTC registers. This is done so we do not have to erase any flash memory to update the timezone. (range is GMT -12 to GMT +14)

    Authenticator showing timezone support

    In this update I added a few UI improvements. One is a version screen to make sure what version I am running on what TOTP authenticator.

    Version information on the authenticator

    Another quality of life improvement is the RTC calibration screen now shows proper text instead of 1 and 0. (it now shows enabled / disabled and backward / forward in the RTC calibration direction). The last change I made is now it is posible to hold the up and down button in the numeric popups. (before you would have to click for every increment)

    RTC calibration showing it is enabled

  • Software / UI improvements

    itzandroidtab02/18/2024 at 15:58 0 comments

    During usage I noticed it would miss a few seconds every week. As the LPC1756 does not have the clock out pin. It made it very difficult to get the correct RTC frequency. To make it easier to set the time I created a menu to set the time and the RTC calibration values. (I also added a mouse jiggler as I was getting annoyed to unlock my work machine every time)

    Settings menu of the authenticator

    Time settings screen. Asks for year, month, day, hour, minute and seconds. (Currently it only works if you enter the time of the GMT+0 timezone)

    DateTime entry in the settings menu

    I also did a rework of the main screen. I added the name of the profile at the top and added a numeric value in the circle to see how many seconds are left until the next token is valid.

  • CSV profile editor

    itzandroidtab02/18/2024 at 15:50 0 comments

    To make it easier to add/delete profiles I create a option to make the authenticator show up as a USB drive.

    USB drive in Windows

    CSV file when opened (note it hides the key by only showing `***`, this is not the key of the test profile)

    To add a new profile a new line can be added before the `EOF` marker. To delete a profile the line can be removed and it will disapear from the menu. (it only updates when the file is saved)

  • More buttons / rechargeable RTC battery / simplified PCB / Case

    itzandroidtab02/18/2024 at 15:38 0 comments

    When I designed the first PCB, I didn't really consider the ease with which they could be assembled. This was quite annoying as I would have to hand solder one side (as I could not reflow the other side). This and the idea that I wanted a rechargeable RTC battery made me design a new version.

    In this version I reduced the amount of layers from 4 to 2, moved most of the components to a single side, I added a rechargable 5.5mAh RTC battery (should have a battery life of around 6 months without charging), circuit to charge the RTC battery and I added more buttons to allow switching between profiles. The Kicad design files can be found at:

    PCB back with components

    PCB front with components

    During this time I also created a case in Inventor. The case is held together using 4x M1.4 and is specificly designed to keep the movement of the PCB as low as possible. Exported STL files can be found at:

  • TOTP Software / RTC battery

    itzandroidtab02/18/2024 at 15:34 0 comments

    First support for current and next TOTP, countdown circle

    Tweaking the UI and adding screen refresh time in microseconds

    To keep the time I added a RTC battery using a battery holder

  • Framebuffer

    itzandroidtab02/18/2024 at 15:18 0 comments

    The 135x240 ST7789 display requires (135x240x2) 64800 bytes for a full framebuffer. The LPC1756 does not have that much contiguous memory. (2x 16Kb) To work around this issue I could do three things:

    * Directly writing pixel for pixel to the screen

    * Smaller framebuffers for the items that change

    * Divide the screen in sections and update the screen that way

    I passed on the first option as that was pretty slow, I passed on the second option as it would make it more difficult to create screens other than the main screen. (It would need a fallback to be able to write pixels outside the predetermined regions.) This made me chose the last option. 

    This last option works by splitting the screen in multiple sections and updating a framebuffer while sending a framebuffer to the display. The size of the sections I chose was 15 pixels in height. This option also needs DMA, this makes it that it can send the data to the display without any action of the CPU.

View all 13 project logs

  • 1
    Updating the authenticator

    To update the TOTP authenticator you need the following:

    * A authenticator with the dfu bootloader installed (prebuild bootloader can be found here.

    * Dfu util

    * New software

    To install the new firmware follow the following steps:

    1. Hold the "enter" (the center) button and plug the authenticator into your pc. The screen should stay blank and the light on the bottom side should light up.

    2. Open a terminal

    3. Run dfu-util with parameter "-D" with the file to download to the device.

    4. Unplug and plug the authenticator in your pc to start the new software.

View all instructions

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates