Specification and proposal for keypad entry to the hackerspace.
At a recent members meeting it was agreed entry to the space via a keypad would be useful. Therefore the aim of this project is to add a secure way for access codes to be set, which can be entered via an external keypad in order to get in.
This will benefit:
- Users who forget their fobs or prefer using a code
- Contractors who aren’t members but are doing work at the space
- Admin team, who can set codes for the landlord or other “one off” situations. These codes can eventually become “single use” or “gift vouchers” should the desire arise.
- New members, who won’t have to wait to set up a fob
Brief overview of current setup
An RFID reader is connected to an FTDI board, which communicates with a Pi over serial. The Pi also has an input from the big exit button and an output to the lock circuitry which releases the door. The Pi fetches a list of valid fob IDs regularly, and when a fob is presented it checks if there’s a match.
The only visible change will be the addition of a keypad.
In the new system, a “code” is some user input from outside the space, and can either be a “key code” (from a keypad) or a “fob code” (from an RFID reader).
code = entered code
fdbk = feedback (for a green light, for example)
A code is set in the member system in the same way as a fob is set. This means we can treat entry codes as just that and won’t need to distinguish between fob codes or key codes. We can also add some nice UI bits to help users differentiate between key codes and fob codes as well as a “wizard” for setting key codes.
Each code entry device will be connected to its own Arduino which will handle the many input wires and present a unified interface to the master controller which is the Rapsberry Pi. I2C will be used for communication between the master and input boards. A program will run on the Pi and will be written in Python.
The separate Arduino boards aim to separate concerns (and code), and will interpret data from their connected input device, provide any feedback to the user such as beeps to indicate a key press, and, if a valid input is received (which will also act as a degree of sanitisation), send it to the Pi. The Pi, reading from the input boards, checks the information against a list of valid codes. Voltage shifters will be used between the Pi and Arduinos. All components are generic and modular allowing easy replacement, reprogramming, or removal when an updated and custom access system is implemented.
The only valid data from the fob reader will be a-f and 0-9, and the only valid data from the keypad will be 0-9, clear(*) and enter(#). The keypad will only send key codes to the Pi once the enter key has been pressed - this allows codes of many lengths to be used. There will be a reasonable (say, 50) maximum length to prevent anyone being overly smart trying to crash the system.
To prevent brute forcing of codes, which is more likely to happen from the keypad, the keypad will “lock out” for some time after three incorrect codes are entered (proposing 30s increasing to 120s). If this proves problematic from misuse, we can enforce a “code entry mode”, where two zeros must be entered first to enable the keypad. This reduces the chance dramatically of someone entering invalid codes and causing lockouts.
The main security risks we face are:
- Insecure codes set by users that are easy to guess
- Forced entry
- Damage to equipment
Each of these is considered in turn.
Insecure codes that are easy to guess
To prevent users setting easy to guess codes which would undo any other security measures, there will be both encouragement to set secure codes and enforcement against insecure codes.
When setting codes, users are encouraged to set a date, such as their birthday, and then two random characters, e.g. ddmmyyyyab - this 10 character code will offer good security. This can be done by a “wizard” which asks for a memorable date and then generates random numbers as a suggested code.
When codes are set and entered, a check will be done to deny insecure codes. This prevents insecure codes from being set and in the event that fails, prevents an insecure code from being accepted.
This will forbid codes that are:
- too short (1234)
- too many proceeding occurances of the same number (11111111)
- too many incrementing or decrementing numbers (123456, 987654)
- obvious codes (80085)
- codes with repeating patterns (1010101010).
- codes that match the keypad layout (741 852 963)
For physical security, the only thing on the insecure (outside) side will be the RFID reader, and keypad. Everything else will be on the secure side. They keypad will be placed such that it will not weaken the door - so no holes will be made in the door itself. The keypad will be mounted by the door on the brick, with no large holes into the space to prevent someone using tools to get in. Additionally, security screws could be used to deter someone from unscrewing the keypad.
Additionally delays are added for incorrect codes. These won’t hinder correct code entries but will delay someone outside trying random codes. The aim is to slow, frustrate and bore them. The fob reader doesn’t have any delay built in, the age old joke being “if they’re using spoofed IDs to get in, then they probably belong inside anyway”.
Damage to equipment
If someone forces off the fob reader or keypad, it should just expose low voltage wires that do not activate the lock directly. A tamper switch could be implemented to isolated the keypad until reset inside.
The code mustn’t:
- store any secrets in the code (which will be managed via environment variables.)
- have any “testing codes” in it when in production
The code must:
- be able to handle unreasonable inputs
- Maintain a list of logs that go back a reasonable number of days
- be resilient to power downs
- fail secure
- be super simple and understandable so as many people can understand it (and improve/critique it)
The code should:
- Indicate to users the state of the system
- Push activity to the membership system API
- Be extendable such as allowing “One Time Access” codes