Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

rpifwcrypto

The Raspberry Pi Firmware Cryptography service is a mailbox based API that allows a limited set of cryptographic operations to be performed by the firmware without exposing private keys to userspace.

The initial implementation is designed to support PiConnect and provides an ECDSA P-256 SHA256 signature API.

A SHA256 HMAC API is provided to provide basic support for derived keys instead of using the raw device unique private key e.g. HMAC(serial-number + EMMC CID) could be used for a LUKS passphrase.

Although this service can be used via raw vcmailbox commands the recommended API is either the command line rpi-fw-crypto application or the librpifwcrypto.so shared library.

Build Instructions

Install prerequisites with sudo apt install cmake libgnutls28-dev - you need at least version 3.10.

mkdir build
cd build
cmake ..
make
sudo make install

If overwriting the system (APT) installed rpi-fw-crypto set the CMake install prefix to /usr. Otherwise, there will be a library mismatch because the default install prefix is /usr/local:

cmake -DCMAKE_INSTALL_PREFIX=/usr ..

Usage

Display usage instructions for all operations:

rpi-fw-crypto -h

Return the number of OTP key slots:

rpi-fw-crypto get-num-otp-keys

Sign message.bin with the device unique OTP key (id 1):

rpi-fw-crypto sign --in message.bin --key-id 1 --alg ec --out sig.bin

Get the status of key-id 1:

rpi-fw-crypto get-key-status 1

Block the raw OTP read API on key-id 1 until the device is rebooted:

rpi-fw-crypto set-key-status 1 READ_LOCKED

All locks persist until the device is rebooted:

Flag Description
READ_LOCKED Blocks the raw OTP read API (privkey)
GEN_LOCKED Blocks key generation (genkey)
SIGN_LOCKED Blocks signing (sign)
HMAC_LOCKED Blocks HMAC (hmac)
USAGE_LOCKED Blocks setting the key usage (set-key-usage)

Get the usage of key-id 1:

rpi-fw-crypto get-key-usage 1

Set the usage of key-id 1 to RPI_CONNECT in OTP:

rpi-fw-crypto set-key-usage 1 0x1

The key usage is stored in OTP and records what the key is used for (RPI_FW_CRYPTO_KEY_USAGE in rpifwcrypto.h):

Value Usage Description
0x0 UNDEFINED Key usage has not been set
0x1 RPI_CONNECT Raspberry Pi Connect device key
0x2 - 0x7 RPI_RESERVED_0 - RPI_RESERVED_5 Reserved for use by Raspberry Pi
0x8 - 0xE USER_DEFINED_0 - USER_DEFINED_6 Available for user-defined purposes
0xF INVALID Invalid / not usable

Generate the SHA256 HMAC of message.bin and OTP key id 1:

rpi-fw-crypto hmac --in message.bin --key-id 1 --out hmac.bin

Derive and retrieve the corresponding public key for the specified device private ECDSA P256 key:

rpi-fw-crypto pubkey --key-id 1 --out device-pub.der

Retrieve the device private key in DER form - will error if key status is locked:

rpi-fw-crypto privkey --key-id 1 --out device-priv.der

Generate an ECDSA P256 key-pair and write the private key to the OTP:

rpi-fw-crypto genkey --key-id 1 --alg ec

Locking at boot via config.txt

Locks can be applied to every key by default at boot via config.txt and persist until the device is rebooted.

lock_device_private_key=1 blocks the raw OTP read API (rpi-fw-crypto privkey) for all keys, whilst still allowing the sign, hmac and pubkey operations.

lock_device_key_write=1 blocks both generating a key (rpi-fw-crypto genkey) and setting its usage (rpi-fw-crypto set-key-usage). This is equivalent to applying GEN_LOCKED and USAGE_LOCKED to every key.

The contents of config.txt (within boot.img) is authenticated by the firmware if secure-boot is enabled and lock_device_private_key=1 should always be specified if secure-boot is enabled.

OpenSSL equivalents

The firmware uses MbedTLS to implement the cryptographic operations. For reference / test, here are the OpenSSL equivalents. In these examples private_key.pem is a local copy of the device private key. If the key status is not LOCKED it can be extracted and converted to PEM with:

rpi-fw-crypto privkey --key-id 1 --out device-priv.der
openssl ec -inform DER -in device-priv.der -outform PEM -out private_key.pem

sign - SHA256 hash of the input, ECDSA P-256 signature in DER form:

openssl pkeyutl -sign -inkey private_key.pem -rawin -in message.bin -out sig.bin

verify - check a signature with the device public key:

openssl pkeyutl -verify -pubin -inkey device-pub.der -sigfile sig.bin -rawin -in message.bin

hmac - HMAC-SHA256 keyed with the raw 32-byte OTP key value:

openssl dgst -sha256 -mac HMAC -macopt hexkey:"$(rpi-otp-private-key)" message.bin

pubkey - DER (SubjectPublicKeyInfo) public key derived from the private key:

openssl ec -in private_key.pem -pubout -outform DER -out device-pub.der

genkey - ECDSA P-256 (prime256v1) key-pair generation:

openssl ecparam -name prime256v1 -genkey -noout -out private_key.pem

Error handling and debug

If the firmware reports an error then rpi-fw-crypto prints the error e.g. Last crypto error: 4 (Key locked) and sets the exit code to the negated firmware error code (RPI_FW_CRYPTO_STATUS in rpifwcrypto.h). Since shells report exit codes as an unsigned byte this appears as 256 - N e.g. KEY_LOCKED (4) gives an exit code of 252.

The firmware logs can be viewed with sudo vclog -m for additional debug.

Code Status Description
0 RPI_FW_CRYPTO_SUCCESS Success
1 RPI_FW_CRYPTO_ERROR_UNKNOWN Unknown error
2 RPI_FW_CRYPTO_EINVAL Invalid argument errors e.g. zero length etc
3 RPI_FW_CRYPTO_KEY_NOT_FOUND No key for the given key-id
4 RPI_FW_CRYPTO_KEY_LOCKED Requested operation for that key is locked
5 RPI_FW_CRYPTO_KEY_OTP_ERROR OTP read error
6 RPI_FW_CRYPTO_KEY_NOT_SET Key is all zeros
7 RPI_FW_CRYPTO_KEY_INVALID Invalid key type/format
8 RPI_FW_CRYPTO_NOT_SUPPORTED Requested operation is not supported
9 RPI_FW_CRYPTO_OPERATION_FAILED Crypto algorithm error
10 RPI_FW_CRYPTO_KEY_NOT_BLANK Key slot is not blank

Notes

The device unique private key can also be provisioned with the rpi-otp-private-key utility. This MUST be a raw ECDSA P-256 key and not just a random number.

This service is not a hardware security module and the current implementation does not protect the key and/or OTP from being accessed directly with root level privileges. It just removes the need to expose the key to userspace (e.g. initramfs) scripts.