subsys/crypto/ provides the hashes and ciphers the firmware uses. It is
built with CONFIG_CRYPTO, which the code that uses it selects:
Header |
Functions |
Algorithm |
|---|---|---|
|
|
SHA-256 (FIPS 180-4) |
|
|
AES-128/192/256 (FIPS 197), single blocks or ECB |
Other AES modes of operation are left to their users.
The public functions own the software implementations, which are always built, and decide when to hand work to hardware:
flowchart TD
api["pbl_sha256_update() / pbl_aes_ecb_encrypt()<br/>subsys/crypto"]
hw["pbl_crypto_hw_*()<br/>driver, optional"]
sw["mbedTLS"]
api -- "len ≥ CONFIG_CRYPTO_*_HW_MIN_LEN" --> hw
api -- "remainder" --> sw
hw -. "what it did not process" .-> sw
classDef app fill:#fa4a36,stroke:#fa4a36,color:#ffffff
classDef system fill:#fd8a7c,stroke:#fd8a7c,color:#171717
classDef base fill:#525252,stroke:#525252,color:#ffffff
class api app
class sw system
class hw base
The subsystem keeps its own state: struct pbl_sha256_ctx holds the chaining
value, the length and a partial block, and struct pbl_aes_ctx the encryption
and decryption round keys, whose first words are the key itself. The subsystem
buffers and pads SHA-256 itself and hands runs of whole blocks, or runs of AES
blocks, to the hardware above a threshold and to mbedTLS otherwise. mbedTLS
only runs block functions, on a temporary context loaded with that state, so
its types never reach the public headers. Bluetooth already links all of
mbedTLS’s AES, and SHA-256 is built with MBEDTLS_SHA256_SMALLER.
Hardware acceleration comes from a crypto driver, which may process any number of the blocks it is given: the subsystem always finishes in software, so callers never see a failure.
CONFIG_CRYPTO_SELFTEST (off by default) checks the accelerators with known
answers fed through the hardware hooks, independently of any driver: the FIPS
180-4 one-block and two-block SHA-256 examples, the latter in one request and
resumed across two, and the FIPS 197 examples for every AES key size, both
ways. Each algorithm is checked before its first hardware use; one whose
accelerator returns a wrong result logs an error and stays in software from
then on.
It also provides pbl_crypto_selftest() (include/pbl/crypto/selftest.h), to
run the check on demand. It returns 0, -EIO on a wrong result or -ENODEV
without a ready accelerator.
The crypto shell command (CONFIG_CRYPTO_SHELL, on with
CONFIG_SUBSYS_SHELL where an accelerator is present) compares the
accelerators against software on random buffers, aligned and unaligned
(crypto check [len]), times both (crypto bench [len]) and, with
CONFIG_CRYPTO_SELFTEST, runs the self-test (crypto selftest).
Programming an accelerator costs a fixed setup, so short runs stay in
software. CONFIG_CRYPTO_SHA256_HW_MIN_LEN and CONFIG_CRYPTO_AES_HW_MIN_LEN
set the shortest run handed to the hardware; the
driver pages give the measurements behind
their defaults.
Generated from PebbleOS f4926c952. This page is maintained in the pebbleos repository: docs/subsystems/crypto.md.