Small USB 2FA authenticator for up to 32 profiles
To make the experience fit your profile, pick a username and tell us what interests you.
We found and based on your interests.
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.
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):
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
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
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
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.
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)
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: https://github.com/itzandroidtab/totp/tree/master/hardware/kicad
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: https://github.com/itzandroidtab/totp/tree/master/hardware/case
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
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.
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.
Create an account to leave a comment. Already have an account? Log In.
Become a member to follow this project and never miss any updates