Skip to content
A hardware password manager, built around a Paspberry Pi Zero and
Branch: master
Clone or download
Latest commit b6fdf08 Sep 18, 2018
Type Name Latest commit message Commit time
Failed to load latest commit information.
LICENSE removed instructions from license (was github template) Feb 21, 2016
Makefile initial code import Feb 11, 2016 Update Sep 18, 2018 addded copyright notice to files Feb 21, 2016
main.c remove unecessary files, add tab and return key, more documentation Apr 23, 2017
scancodes.c fix #6 Sep 18, 2018


A hardware password manager, built around a Raspberry Pi Zero and pass, the UNIX password manager.

This project is now maintained at this repository.


sendHID is a tool to simulate typing using the Linux USB Gadget mode.

Use a Raspberry Pi Zero (or A) to send keystrokes to a host computer.

using the driver

There are two drivers available: the legacy g_hid driver, which has windows support, and the new libcomposite, which makes emulation of multiple devices at the same time very easy. Setup instructions on the latter are below.

The neccessary drivers are available only in the Raspbian 4.4 Kernel, which you can install using sudo BRANCH=next rpi-update, if you haven't updated you Pi in a long time.

You also need to activate the device tree overlay dwc2 and load the corresponding kernel module:

echo "dtoverlay=dwc2" | sudo tee -a /boot/config.txt
echo "dwc2" | sudo tee -a /etc/modules

To use this program, you have to enable the libcomposite driver on the Raspberry Pi and create a USB HID gadget. You can use this bash script:

# this is a stripped down version of - I don't claim any rights

modprobe libcomposite
cd /sys/kernel/config/usb_gadget/
mkdir -p g1
cd g1
echo 0x1d6b > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB2
mkdir -p strings/0x409
echo "fedcba9876543210" > strings/0x409/serialnumber
echo "girst" > strings/0x409/manufacturer 
echo "Hardpass" > strings/0x409/product
mkdir -p functions/hid.$N
echo 1 > functions/hid.usb0/protocol
echo 1 > functions/hid.usb0/subclass
echo 8 > functions/hid.usb0/report_length
echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > functions/hid.usb0/report_desc
mkdir -p configs/c.$C/strings/0x409
echo "Config $C: ECM network" > configs/c.$C/strings/0x409/configuration 
echo 250 > configs/c.$C/MaxPower 
ln -s functions/hid.$N configs/c.$C/
ls /sys/class/udc > UDC

internals of this code

whenever you need to add (or remove) a new keyboard layout, the following changes have to be made:

adding a new key to existing layouts

  1. if the key is on the keyboard, just add a new line, and use the keycode ("Usage ID (Hex)") from the table 12 on page 53pp of the USB HID Usage Tables document.

Following the keycode comes the modifier bit mask. 0x02 is Shift, 0x40 AltGraph.

Now an example adding the letter A:

{"A",  //character to translate
	{ //english layout
		0x04, //keycode
		0x02  //shift
	}, { //german layout
		0x04, //keycode
		0x02  //shift
	}, { //german-nodeadkeys
		0x04, //keycode
		0x02  //shift
  1. if it isn't on the keyboard, fill keyocde and modifier bit mask with 0x00 for the layout and use the .unicode=0xXXXX (See point 3 in the 'adding a new layout' section below).

adding a new keyboard layout (example)

  1. in scancodes.h add the layout to keysym-struct: this identifier does not need to be used outside of scancodes.{h,c}.
struct keysym {
	// ...
	struct layout de_dv; //dvorak layout
	// ...
  1. the enum kbd1 has to be ammended:
enum kbdl {  //keyboard layouts:
	// ...
        de_DV //de_AT-Dvorak
  1. in scancodes.c you need to add a new column (containing more columns) to the big keysyms[] table: It is suggested to explicitly name .is_dead and .unicode to avoid confusion. Also notice that .is_dead is part of the layout (and goes within the inner braces), while .unicode resides in the keysym-struct. if you want to add new keys, the following must be kept in mind: toscan() will use the nth line of the table, if n is larger than 32 (aka. will use the ascii code to look up chars). symbols not in the 7-bit ascii standard can be put on the first 32 positions as utf-8 encoded strings, although keeping [0] to the release all chars is recommended. (some text editors will convert files to older encodings - this might break things)
struct keysym keysyms[] = {
	{"#", {0x20, 0x02}, {0x31, 0x00}, {0x31, 0x00}, {KEY, MODIFIER}},
	{"^", {0x23, 0x02}, {0x35, 0x00}, {0x35, 0x00}, {KEY, MODIFIER, .is_dead = 1}},
	{"&", {0x24, 0x02}, {0x23, 0x02}, {0x23, 0x02}, {KEY, MODIFIER}, .unicode=OxHEX},
  1. tolay() needs a new case to its switch statement: This is the only place where the layout-idenitfier from keysym needs to be used.
struct layout* tolay (struct keysym* s, enum kbdl layout) {
        switch (layout) {
	// ...
        case de_DV: return &(s->de_dv);
        default: return NULL;
  1. finally, your code must understand the new layout, represented by the enum kbd1-entry, de_DV in this example.
You can’t perform that action at this time.