wolfBoot/docs/PQ.md

281 lines
8.9 KiB
Markdown

# Post-Quantum Signatures
wolfBoot is continuously adding support for post-quantum (PQ) signature
algorithms as they mature. At present, support has been added for three NIST
approved PQ signature algorithms:
- ML-DSA: https://csrc.nist.gov/pubs/fips/204/final
- LMS/HSS: https://csrc.nist.gov/projects/stateful-hash-based-signatures
- XMSS/XMSS^MT: https://csrc.nist.gov/projects/stateful-hash-based-signatures
ML-DSA is a PQ lattice-based algorithm standardized by NIST (FIPS 204).
LMS/HSS and XMSS/XMSS^MT are both PQ stateful hash-based signature (HBS)
schemes, recommended in NIST SP 800-208.
In terms of relative tradeoffs:
- All three methods have fast verifying operations.
- All three methods have variable length signature sizes.
- ML-DSA key generation is much faster than LMS/HSS and XMSS/XMSS^MT.
- ML-DSA public keys are larger than LMS/HSS and XMSS/XMSS^MT, and
variable sized.
- LMS/HSS and XMSS/XMSS^MT have stateful private keys, which requires
more care with key generation and signing operations.
See these config files for simulated target examples:
- `config/examples/sim-ml-dsa.config`
- `config/examples/sim-ml-dsa3.config`
- `config/examples/sim-ml-dsa5.config`
- `config/examples/sim-lms.config`
- `config/examples/sim-xmss.config`
## Lattice Based Signature Methods
### ML-DSA
ML-DSA (Module-Lattice Digital Signature Algorithm) was standardized in
FIPS 204 (https://csrc.nist.gov/pubs/fips/204/final), based on its
round 3 predecessor CRYSTALS-DILITHIUM.
ML-DSA has three standardized parameter sets:
- `ML-DSA-44`
- `ML-DSA-65`
- `ML-DSA-87`
The numerical suffix (44, 65, 87) denotes the dimension of the matrix used
in the underlying lattice construction.
The private key, public key, signature size, and overall security strength
all depend on the parameter set:
```
#
# Private Key Public Key Signature Size Security Strength
# ML-DSA-44 2560 1312 2420 Category 2
# ML-DSA-65 4032 1952 3309 Category 3
# ML-DSA-87 4896 2592 4627 Category 5
#
```
### ML-DSA Config
See ML-DSA sim examples here:
```
config/examples/sim-ml-dsa.config
config/examples/sim-ml-dsa3.config
config/examples/sim-ml-dsa5.config
```
The security category level is configured with `ML_DSA_LEVEL=<num>`, where
num = 2, 3, 5. Here is an example for level 2:
```
# ML-DSA config examples:
#
# Category 2:
ML_DSA_LEVEL=2
IMAGE_SIGNATURE_SIZE=2420
IMAGE_HEADER_SIZE?=4840
```
Note: The wolfcrypt implementation of ML-DSA builds to the FIPS 204 final
standard by default. If you wish to conform to the older FIPS 204 draft
standard, then build with `WOLFSSL_MLDSA_FIPS204_DRAFT`
instead.
## Stateful Hash-Based Signature Methods
LMS/HSS and XMSS/XMSS^MT are both post-quantum stateful hash-based signature
(HBS) schemes. They are known for having small public keys, relatively fast
signing and verifying operations, but larger signatures. Their signature sizes
however are tunable via their different parameters, which affords a space-time
tradeoff.
Stateful HBS schemes are based on the security of their underlying hash
functions and Merkle trees, which are not expected to be broken by the advent
of cryptographically relevant quantum computers. For this reason they have
been recommended by both NIST SP 800-208, and the NSA's CNSA 2.0 suite.
See these links for more info on stateful HBS support and wolfSSL/wolfCrypt:
- https://www.wolfssl.com/documentation/manuals/wolfssl/appendix07.html#post-quantum-stateful-hash-based-signatures
- https://github.com/wolfSSL/wolfssl-examples/tree/master/pq/stateful_hash_sig
### Supported PQ HBS Options
These two hash-based PQ signature options are supported:
- LMS: uses wolfcrypt implementation from `wc_lms.c`, and `wc_lms_impl.c`.
- XMSS: uses wolfcrypt implementation from `wc_xmss.c`, and `wc_xmss_impl.c`.
### LMS/HSS Config
A new LMS sim example has been added here:
```
config/examples/sim-lms.config
```
The `LMS_LEVELS`, `LMS_HEIGHT`, and `LMS_WINTERNITZ`, `IMAGE_SIGNATURE_SIZE`,
and (optionally) `IMAGE_HEADER_SIZE` must be set:
```
SIGN?=LMS
...
LMS_LEVELS=2
LMS_HEIGHT=5
LMS_WINTERNITZ=8
...
IMAGE_SIGNATURE_SIZE=2644
IMAGE_HEADER_SIZE?=5288
```
In LMS the signature size is a function of the parameters. Use the added helper
script `tools/lms/lms_siglen.sh` to calculate your signature length given your
LMS parameters:
```
$ ./tools/lms/lms_siglen.sh 2 5 8
levels: 2
height: 5
winternitz: 8
signature length: 2644
```
### XMSS/XMSS^MT Config
A new XMSS sim example has been added here:
```
config/examples/sim-xmss.config
```
The `XMSS_PARAMS`, `IMAGE_SIGNATURE_SIZE`, and (optionally) `IMAGE_HEADER_SIZE`
must be set:
```
SIGN?=XMSS
...
XMSS_PARAMS='XMSS-SHA2_10_256'
...
IMAGE_SIGNATURE_SIZE=2500
IMAGE_HEADER_SIZE?=5000
```
The `XMSS_PARAMS` may be any SHA256 parameter set string from Tables 10 and 11
from NIST SP 800-208. Use the helper script `tools/xmss/xmss_siglen.sh` to
calculate your signature length given your XMSS/XMSS^MT parameter string, e.g.:
```
$ ./tools/xmss/xmss_siglen.sh XMSS-SHA2_10_256
parameter set: XMSS-SHA2_10_256
signature length: 2500
```
```
$ ./tools/xmss/xmss_siglen.sh XMSSMT-SHA2_20/2_256
parameter set: XMSSMT-SHA2_20/2_256
signature length: 4963
```
## Hybrid mode (classic + PQ)
wolfBoot supports a hybrid mode where both classic and PQ signatures are verified,
sequentially. This allows for a gradual transition from classic to PQ signatures,
and protects the secure boot mechanism from potential vulnerabilities in either of
the two ciphers in use.
The hybrid mode is enabled by setting a `SECONDARY_SIGN` option in the config file,
which specifies the secondary signature algorithm to be used. The secondary signature
option requires the option `WOLFBOOT_UNIVERSAL_KEYSTORE=1`, to ensure that the
keystore can handle both classic and PQ keys.
The secondary signature option can be set to any of the supported PQ signature options.
The example configuration provided in `config/examples/sim-ml-dsa-ecc-hybrid.config`
demonstrates the use of hybrid mode with both ML-DSA-65 and ECC-384.
### Hybrid signature
The `sign` tool supports hybrid signatures. It is sufficient to specify two
ciphers argument from command line. When you do that, the tool expects two private
key files path passed as arguments, instead of one.
The two public keys must be added to the same keystore. For this reason, the two
keypairs must be generated either at the same time, or in two subsequent steps.
### Generating keypairs for hybrid signatures
#### Generate both keys at the same time:
```
./tools/keytools/keygen --ml_dsa -g wolfboot_signing_private_key.der --ecc384 -g wolfboot_signing_second_private_key.der
```
both keys are automatically added to the same keystore.
#### Generate the two keys in separate steps
If you want to generate the keys in two steps, you will have to import the first
key in the new keystore. The first public key is stored in `keystore.der` during
the keypair generation:
```
./tools/keytools/keygen --ml_dsa -g wolfboot_signing_private_key.der
```
The first 16 bytes contain the keystore header, and must be skipped:
```
dd if=keystore.der of=ml_dsa-pubkey.der bs=1 skip=16
```
The new keypair can be generated (`-g`) while importing (`-i`)the old public key:
```
./tools/keytools/keygen --ml_dsa -i ml_dsa-pubkey.der -g --ecc384 wolfboot_signing_second_private_key.der
```
The keystore generated is now ready to be used by wolfBoot for hybrid signature verification.
### Hybrid signature of the firmware
In both examples above, the two private keys are now available in separate .der files.
The `sign` tool can now be used to sign the firmware with both keys:
```
./tools/sign/sign --ml_dsa --ecc384 --sha256 test-app/image.elf wolfboot_signing_private_key.der wolfboot_signing_second_private_key.der 1
```
The command should confirm that both keys are loaded, and that the image is signed and includes the hybrid signature:
```
wolfBoot KeyTools (Compiled C version)
wolfBoot version 2020000
Parsing arguments in hybrid mode
Secondary private key: wolfboot_signing_second_private_key.der
Secondary cipher: ECC384
Version: 1
Update type: Firmware
Input image: test-app/image.elf
Selected cipher: ML-DSA
Selected hash : SHA256
Private key: wolfboot_signing_private_key.der
Secondary cipher: ECC384
Secondary private key: wolfboot_signing_second_private_key.der
Output image: test-app/image_v1_signed.bin
Target partition id : 1
info: using ML-DSA parameters: 3
info: ML-DSA signature size: 3309
Key buffer size: 5984
info: ml-dsa priv len: 4032
info: ml-dsa pub len: 1952
Found ml-dsa key
image header size overridden by config value (8192 bytes)
Loading secondary key
Key buffer size: 144
Secondary ECC key, size: 96
image header size overridden by config value (8192 bytes)
Creating hybrid signature
[...]
```
The resulting image `image_v1_signed.bin` contains both signatures, and can be verified using a wolfBoot with hybrid signature support.