pico-hsm: turning a Raspberry Pi Pico into a PKCS11 hardware security module
Hardware Security Module (HSM) for Raspberry Pico and ESP32
At a glance
- What is it?
- pico-hsm is firmware that turns a Raspberry Pi Pico or an ESP32 into a hardware security module, generating and storing private keys, doing AES operations and signing without ever exposing a key. It talks PKCS11 to the host over USB CCID, and the key hierarchy is anchored in one-time programmable flash and a PIN-derived master key.
- Who is it for?
- pico-hsm suits a maker or a small vendor who needs hardware-backed key storage and PKCS11 on a desk rather than in a data centre, and the fact that it runs on a Pico and an ESP32 puts the price of that guarantee in the tens of pounds.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 14 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The device holds the key, so the host never sees it
The project's aim is stated plainly: to transform a Raspberry Pi Pico or ESP32 microcontroller into a Hardware Security Module, with the modified board capable of generating and storing private keys, performing AES encryption or decryption, and signing data without exposing the private key. The private key remains on the board and cannot be retrieved because it is encrypted within the flash memory. The trust anchor is a master AES 256 key, the MKEK, and the MKEK itself is encrypted with a hashed and salted version of the PIN. The guarantee the README makes about that hierarchy is absolute in its wording: no private or secret keys, DKEK or PIN are stored in plain text ever, never. The second key in the chain is the Device Key Encryption Key, the DKEK, and there is an important structural consequence of the design, which is that a PIN is what gates private and secret key use, with alphanumeric PINs supported, and a separate transport PIN exists for provisioning so the device can be shown to have not been tampered with while in transit.
The algorithm surface is wide, and deliberately standard
The list of supported cryptography is long, and the pattern is that almost everything a modern host software stack expects is present. RSA key generation covers 1024, 2048, 3072 and 4096 bits, and the README notes that private keys never leave the device. ECDSA key generation supports curves from 192 to 521 bits, and the curve list includes secp192r1, secp256r1, secp384r1, secp521r1, brainpoolP256r1, brainpoolP384r1, brainpoolP512r1, secp192k1 with the note that it is insecure, secp256k1, Curve25519 and Curve448. Signatures combine with SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 digests, RSA signatures come as RSA-PSS, RSA-PKCS or raw, and ECDSA signatures can be raw or pre-hashed. On the symmetric side, AES key generation is supported at 128, 192 and 256 bits, and again at up to 512 bits for the concatenated keys AES XTS needs. AES itself is supported in ECB, CBC, CFB, OFB, XTS, CTR, GCM and CCM modes with a customisable IV or nonce and additional authenticated data, plus CMAC, HMAC with SHA digests, and ChaCha20-Poly1305. Key derivation covers ECDH for shared secrets, HKDF, PBKDF2 and X963-KDF, and X25519 and X448 for key agreement, with the note that those two cannot be used for signing.
PKCS11 to the host, and what the host can do with it
The interface is where the firmware becomes useful to existing software, and it is a standard one. Interfacing with the PKCS11 standard is supported, and there is full USB CCID stack support for communication with the host via OpenSC and PCSC, which allows the use of frontend applications like OpenSSL through the PKCS11 module. That combination is the important part: a host tool that already speaks PKCS11 can drive this device without knowing anything about microcontrollers. The protocol layer supports extended APDU packets, allowing up to 65535 bytes, and there is a built-in hardware random number generator designed for maximum entropy. The device also has a real-time clock with external date and time setting and retrieval, which matters for certificate validity and for anything that needs a trustworthy timestamp. So the practical usage pattern is: a PKCS11 module on a USB device, plugged into a machine that runs ordinary crypto tooling.
Provisioning, key domains and the ways keys leave or do not
Several features exist to control how keys enter the device and how they are used once inside. External private keys and certificates can be imported via WKY or PKCS#12 files. DKEK shares can be imported to wrap, unwrap and encrypt keys, and there is an n-of-m threshold scheme, so a DKEK can be reconstructed from shares held by several custodians, which the README says exists to prevent outages when a DKEK custodian is unavailable. There is also XKEK, an advanced key sharing scheme for securely wrapping and unwrapping keys within authorized domains. Multiple key domains are supported, each protected by an independent DKEK, so different keys live in different domains. A key usage counter tracks and limits the use of private or secret keys, disabling them once the counter reaches zero, which is the mechanism for a one-time or limited-use signing key. There is a public key authentication mode, PKA, which requires a secondary device and uses a challenge-response mechanism, and a secure lock that ties the device to a specific computer using a private key, plus a press-to-confirm button that uses the BOOTSEL button to give a 15 second window to approve any operation touching a private or secret key.
Firmware trust, recovery and the parts that are hardware guarantees
The lower layers of the trust story are where the hardware is doing work that software cannot. One-time programmable storage securely stores the MKEK and the device key permanently and makes them inaccessible from external interfaces, so a software bug on the host or a reflashed firmware cannot read the master key out. On top of that, secure boot ensures only authenticated firmware can run on the device by verifying each firmware's digital signature to block unauthorised code, and a second secure lock, this one aimed at the manufacturer, restricts the device to the manufacturer's firmware only, locking out debug access and preventing any further boot key installations. The counterweight is a built-in rescue interface, which allows recovery of the device if it becomes unresponsive or undetectable and restores it to operational status without compromising security. There is also CV certificate handling, which keeps internal certificate storage to a minimum, and a secure messaging mode, with encrypted channels between host and device to prevent man-in-the-middle attacks, secured by a certificate issued by an external PKI. Attestation is the closing piece: each generated key is attached to a certificate signed by an external PKI, so a relying party can tell that the key was generated by that specific device.
Building the firmware, and what the repository holds
The repository is a C project built with CMake, and the layout shows the pieces. There is a CMakeLists.txt at the root, a build_pico_hsm.sh script for the build, a pico_sdk_import.cmake for the Raspberry Pi Pico SDK, a pico-keys-sdk directory, an sdkconfig.defaults file for the build configuration, and then src/, tests/, tools/, doc/ and workflows/ directories. The .gitmodules file tells you the SDK is pulled in as a submodule, and the .uncrustify.cfg file is the C style configuration, so the project formats its own code rather than inheriting a style. The homepage is picokeys.com, and the licence is AGPL-3.0, with an ENTERPRISE.md file at the root alongside CONTRIBUTING.md and a LICENSE file. The AGPL choice is the one to think about if this firmware ever ships inside a product, since it is the copyleft licence with the network use clause, and the presence of a separate ENTERPRISE.md suggests the author has thought about commercial arrangements.
Where this is the wrong tool
Three limits are worth naming. The first is that this is not a certified HSM. A commercial FIPS or Common Criteria validated module comes with a third party evaluation of the whole design, the manufacturing process and the firmware supply chain, and a Pico running open firmware you flash yourself has none of that, whatever the strength of the key hierarchy. The second is the hardware platform. A Pico or an ESP32 is a microcontroller with a flash partition that the firmware claims for one-time programmable storage, and the project depends on the board's flash layout supporting that claim, which is a different proposition from a device designed for key storage. The third is the single device, single operator model. The PIN is the gate, the press-to-confirm button is the second gate, and the DKEK share scheme exists so that several custodians can reconstruct a wrapping key, but a device sitting on a desk that anyone can unplug is a device that can be stolen with its secrets still inside. A commercial HSM is built to be stolen from. This one is built to be cheap and open, and those are different goals.
Editorial conclusion
pico-hsm suits a maker or a small vendor who needs hardware-backed key storage and PKCS11 on a desk rather than in a data centre, and the fact that it runs on a Pico and an ESP32 puts the price of that guarantee in the tens of pounds. It is the wrong tool if you need the certification and attestation guarantees of a commercial HSM, since the attestation here means each generated key is attached to a certificate signed by an external PKI, which is a scheme you provide rather than one the vendor vouches for. It is also the wrong tool if you want a device that is a drop-in for a company PKCS11 module, since the key hierarchy here is built around a PIN, a master key encryption key and one-time programmable storage, which is a different provisioning model from most enterprise modules. Verify first which board you are flashing and which firmware build you are taking, since the releases list nightly tags alongside versioned ones, and note the AGPL-3.0 licence before you put it in a product.
Frequently asked questions
What does pico-hsm turn a Raspberry Pi Pico into?
It turns the board into a Hardware Security Module that generates and stores private keys, performs AES encryption and decryption, and signs data without exposing the private key, because the key stays on the board encrypted within the flash memory.
How are keys protected on the device?
Private and secret keys are secured using a master AES 256 key, the MKEK, and the MKEK is encrypted with a hashed and salted version of the PIN. The README states that no private or secret keys, DKEK or PIN are stored in plain text ever, and the MKEK and device key are held in one-time programmable storage inaccessible from external interfaces.
How does the host software talk to the Pico HSM?
Through a PKCS11 interface over a full USB CCID stack, so communication with the host works via OpenSC and PCSC and frontend applications like OpenSSL can use the device through the PKCS11 module. Extended APDU packets are supported, allowing up to 65535 bytes.
Which elliptic curves and signature algorithms are supported?
RSA key generation at 1024, 2048, 3072 and 4096 bits, and ECDSA from 192 to 521 bits across secp192r1, secp256r1, secp384r1, secp521r1, the brainpool curves, secp192k1 which is marked insecure, secp256k1, Curve25519 and Curve448. RSA signatures come as RSA-PSS, RSA-PKCS or raw, and ECDSA signatures can be raw or pre-hashed.
What extra hardware features does the firmware rely on?
A hardware random number generator designed for maximum entropy, a real-time clock with external date and time setting and retrieval, one-time programmable flash storage for the MKEK and device key, and the BOOTSEL button used as a press-to-confirm control that gives a 15 second window to approve operations involving private or secret keys.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/polhenarejos-pico-hsm)Was this useful?