Background
I have too many passwords to keep them in mind, so one day I have decided to develop my own hardware secured password storage. It should have met the following requirements to satisfy my needs:
- Usability: hardware and software should be simple in usage and maintenance.
- Security: it should have basic internal pseudo-encryption (it is enough for the first version) and it should not store master password.
- Storage: device should be able to store about a hundred passwords at a minimum.
- Performance: password retrieve time should not exceed 1 second.
- Sizes: device with enclosing should have typical size of USB stick.
- Price: should not exceed $30.00.
I believe there are many analogues presented at the market and you may find many varieties of encrypted storage, here are couple of examples:
But the idea is to focus on passwords and descriptions for them (addresses, URLs, devices, etc.), current, full and, I hope, final name of the project is OWLSAN Keyring.
Architecture
The next step was to define architecture. Omitting the details and reasons of my choice, I have finally decided on implementing basic client-server architecture, where the client is user's PC and the server is Keyring device.
On the client side there is a small program in Python, which sends requests to Keyring device via USB, retrieves replies and fetches data. Server side receives requests, performs required actions and sends back replies.
Refer to the table 1 for Keyring Interaction Protocol (KIP) commands, to the table 2 for KIP statuses and to the table 3 for KIP variable sizes.
Command
|
Value
|
Description
|
| ACCESS |
0
|
Accesses Keyring
using master password. Authentication should be done using this
command prior to performing any other actions, otherwise FAIL
status will be returned for every action.
Session is
initially set by this command and should be used for further
interaction by UI.
Request:
[Command][Session][Master
password]
Reply:
[Command][Status] |
| LIST |
1
|
Returns the list
of record statuses chunk-by-chunk – returns the specified chunk
of statuses.
Request:
[Command][Session][Chunk
number]
Reply:
[Command][Status][Chunk
list] |
| READ |
2
|
Reads record data.
Full reading should be done in two steps: first reply contains
description, the second one contains password.
Request:
[Command][Session][Number]
Reply:
[Command][Status][Description]
– after the first request
[Command][Status][Password]
– after the second request |
| WRITE |
3
|
Writes data to the
specified record.
Request:
[Command][Session][Number][Description][Password]
Reply:
[Command][Status] |
| DELETE |
4
|
Deletes specified
record.
Request:
[Command][Session][Number]
Reply:
[Command][Status] |
| MASTER |
5
|
Changes master
password. Device should not be disconnected/powered off during
this operation, otherwise data integrity is not guaranteed.
Request:
[Command][Session][New
master password]
Reply:
[Command][Status] |
| FORMAT |
6
|
Formats Keyring –
clears data and resets master password to default –
“OWLSANKEYRING”.
Request:
[Command][Session]
Reply:
[Command][Status] |
| FLUSH |
7
|
Flushes number
flag for READ command – service command.
Request:
[Command][Session]
Reply:
[Command][Status] |
| RESET |
8
|
Resets Keyring –
clears access flag and session (sign out analogue).
Request:
[Command][Session]
Reply:
[Command][Status] |
| PROGRAM |
9
|
Sets programming
flag, device enters DFU bootloader after the next reset.
Request:
[Command][Session]
Reply:
[Command][Status] |
Table 1
Status
|
Value
|
Description
|
| FAIL |
0
|
Command execution
has failed |
| DONE |
1
|
Command performed
successfully |
Table 2
Variable
|
Size,
bytes
|
Description
|
| Command |
1 |
Refer to table 1
for the list of available commands. |
| Session |
4 |
Unique ID that
should be assigned to the connection on every ACCESS command
invocation. |
| Status |
1 |
Refer to table 2
for the list of available statuses. |
| Number |
4 |
Record number –
number of pair description + password. |
| Description |
32 |
Description (hint)
for the password. |
| Password/Master
password |
16 |
– |
| Chunk number |
4 |
Number of record
list status chunk. |
| Chunk list |
32 |
List of record
statuses. Refer to table 4 for KIP record statuses details. |
Table 3
Record
status
|
Value
|
Description
|
| FREE |
0
|
Record space is
free |
| DATA |
1
|
Record space
contains data |
| CORRUPTED |
2
|
Corrupted record
space – cannot be verified |
Table 4
Notes:
- Master password is not stored anywhere, only its hash in order to authenticate user.
- Default master password is equal to signature – “OWLSANKEYRING” (uppercase, without quotes).
- USB data packet size is 64 bytes.
Internal and external EEPROM structure is presented in the table 5.
Location
|
Offset,
bytes
|
Item
|
| Internal |
0 |
Signature –
“OWLSANKEYRING” (w/o quotes) |
| Internal |
128 |
Master password
CRC32 hash |
| Internal |
256 |
Programming flag |
| External |
0 |
CRC32 hash table –
used in CRC32 calculations |
| External |
1024 |
Records statuses
list |
| External |
2048 |
Records data |
Table 5
Hardware
Hardware core of the Keyring is Atmel AT90USB162 MCU (image 1), it has several important features which meet my initial requirements:
- Size – 7x7x1 mm in TQFP32 package.
- Price – $5 per unit.
- Performance – up to 16 MIPS at 16 MHz.
- Interface – USB 2.0.
- Storage – 16 kbytes of flash, 512 bytes of internal EEPROM.
Also it has DFU bootloader which will make your life easier with programming FLIP software – you don't need to use serial programmer anymore.
As a storage unit I have utilized Microchip 24LC512 I2C EEPROM (image 2), which has 512 kbits (64 kbytes) of memory – quite enough to store a hundred of passwords with their short descriptions (hints):
- Size – 6x4.9x1.25 mm in SOIC8 package.
- Price – $3 per unit.
- Performance – page (128 bytes) write time is 5 ms max.
- Interface – TWI/I2C.
- Storage – 65536 bytes.
 |
| Image 1 |
 |
| Image 2 |
The other required components are:
- 22 Ohm resistors for MCU USB data lines
- 4.7 uF bypass capacitor for MCU USB
- 16 MHz quarz for MCU
- 22 pF load capacitors for quartz
- 100 nF ceramic (fast) and 4.7 uF bypass capacitors
- 4.7 kOhm pull-up resistors for EEPROM
- USB-A SMD connector
- Material for PCB
- Enclosure
Refer to table 6 for bill of material.
Type
|
Component
|
Count
|
Price
per unit, $
|
Total
price, $
|
MCU
|
AT90USB162
|
1
|
5.04
|
5.04
|
EEPROM
|
24LC512
|
1
|
2.94
|
2.94
|
Quartz
|
HC-49/SMD
16 MHz
|
1
|
2.58
|
2.58
|
Capacitor
|
22 pF
|
2
|
0.02
|
0.04
|
Capacitor
|
100 nF
|
2
|
0.05
|
0.10
|
Capacitor
|
4.7 uF
|
2
|
0.05
|
0.10
|
Resistor
|
22 Ohm
|
2
|
0.01
|
0.02
|
Resistor
|
4.7
kOhm
|
2
|
0.01
|
0.02
|
Connector
|
USB-A
SMD
|
1
|
1.83
|
1.83
|
PCB
material
|
Glass
textolite
|
–
|
1.00
|
1.00
|
Enclosure
|
Plastic
box
|
1
|
2.00
|
2.00
|
|
15.67
|
Table 6
For enabling DFU programmer you will also need to implement HWB (hardware boot) and RST (reset) buttons. Take a look at image 3 for complete circuit – moreover, it shows connections to FT232RL board for serial programming. Image 4 depicts circuit after assembling components on the breadboard.
 |
| Image 3 |
 |
| Image 4 |
Firmware
Keyring Firmware utilizes LUFA library for interaction via USB interface. AT90USB162 MCU does not have “native” TWI/I2C interface for interaction with 24LC512 EEPROM chip, so the corresponding library is implemented to emulate it.
Keyring Firmware consists of the following modules:
- LUFA
- TWI/I2C firmware library
- Core firmware
Core initializes hardware, checks signature integrity and starts “listening”: when USB data buffer is filled, it is parsed by core and processing cycle is done, after that core awaits when the buffer will be filled again.
TWI/I2C library pins are mapped to hardware pins the following way:
- SCL – pin 15 (PB1)
- SDA – pin 16 (PB2)
Software
Keyring Software is simple and written in Python, it utilizes PyUSB library and PyQt and consists of the following components:
- PyQt
- PyUSB library
- Core library
- Core software
Keyring Software implements the following functionality:
- Connect – authenticate at the Keyring (image 5).
- Reset – sign out and disconnect.
- Browse records (image 6).
- View password (image 7).
- Edit record (images 8-9).
- Delete record (image 8).
- Add record (image 10).
- Set master password (image 11).
- Format device.
 |
| Image 5 |
 |
| Image 6 |
 |
| Image 7 |
 |
| Image 8 |
 |
| Image 9 |
 |
| Image 10 |
 |
| Image 11 |
Schematics
I have designed two variants of PCB schematics:
- Debug (images 12-20): includes pins for serial programming and required elements for hardware boot and reset buttons on the board
 |
| Image 12 |
 |
| Image 13 |
 |
| Image 14 |
 |
| Image 15 |
 |
| Image 16 |
 |
| Image 17 |
 |
| Image 18 |
 |
| Image 19 |
 |
| Image 20 |
- Release (images 21-27): has only serial programming (with external Vcc/Vss) and HWB/RST pins and is much smaller than debug version
 |
| Image 21 |
 |
| Image 22 |
 |
| Image 23 |
 |
| Image 24 |
 |
| Image 25 |
 |
| Image 26 |
 |
| Image 27 |
Both are two-sided PCBs with minimum amount of vias and maximum wire thickness (0.4 mm).
Sizes (w/o pins, enclosure and USB connector):
- Debug: 60x30x8 mm.
- Release: 40x25x8 mm.
Enclosure for release version is not ready yet, but I'm working on it, also as soon as possible I will present another – more compact – PCB design.
Programming
Programming should be performed in a several steps:
- Connect Keyring to FT232RL serial programmer.
- Upload new bootloader which supports 16 MHz quartz using avrdude to Keyring.
- Upload new fuses values to enable 16MHz support.
- Disconnect serial programmer.
- Connect Keyring to PC via USB.
- Enter DFU bootloader: Press RST and HWB buttons, then release RST button and finally release HWB button.
- Upload Keyring Firmware (Firmware/Keyring.hex) using FLIP software.
- Reset device (plug out and plug in it again or press RST button).
Steps 2-3 can be easily performed by executing Hardware/Fuses/Fuses.sh bash script, required bootloader is already there.
After first upload device will auto-format itself and will not be visible for a few seconds.
Its USB vendor ID and device ID are 0x03eb:0x204f, which corresponds to “LUFA Generic HID Demo Application”.
Installation
Currently Keyring Software has been tested only under Linux (Ubuntu/Mint), the next version will support Microsoft Windows.
To use Keyring Software you should prepare appropriate environment:
- Install Python.
- Install Qt and PyQt.
- Install PyUSB library.
- Copy rules.d/81-owlsan-keyring.rules permissions file to /etc/udev/rules.d/ in order to have non-root access to Keyring.
To run Keyring Software just execute Software/Keyring.py with Python. Keep in mind that default master password is “OWLSANKEYRING” (uppercase, w/o quotes).
Also please be notified that Keyring software is rather raw yet.
License
- OWLSAN Keyring Hardware is licensed under Creative Commons Attribution-ShareAlike 3.0 Unported License, refer to corresponding LICENSE.txt file or proceed via the link for more information: http://creativecommons.org/licenses/by-sa/3.0/
- OWLSAN Keyring Firmware is licensed under GNU GPLv3, refer to corresponding LICENSE.txt file or proceed via the link for more information: https://gnu.org/licenses/gpl.html
- OWLSAN Keyring Software is licensed under GNU GPLv3, refer to corresponding LICENSE.txt file or proceed via the link for more information: https://gnu.org/licenses/gpl.html
Downloads
The packages below contain all data related to this project: circuits, PCB schematics, bills of materials, firmware and software source codes and some required software.
And here you may get AVRDUDE (Linux 32/64) with FT232RL serial bitbang programming mode support:
Specifications:
Links
- Atmel AT90USB162 product page
- Microchip 24LC512 product page
- Atmel AT90USB162 DFU bootloader
- Atmel AT90USB162 DFU bootloader discuss on AVR Freaks
- FLIP utility page
- AVRDUDE home
- Adafruit Eagle Library (very useful!) at github
- PyQt page
- PyUSB page