Skip to content

Commit

Permalink
Add ML-DSA support.
Browse files Browse the repository at this point in the history
  • Loading branch information
philljj committed Oct 5, 2024
1 parent b6b77f0 commit 8a9a7f0
Show file tree
Hide file tree
Showing 15 changed files with 644 additions and 13 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/test-renode-nrf52.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ jobs:
- name: Renode Tests ext_XMSS-SHA2_10_256
run: ./tools/renode/docker-test.sh "SIGN=ext_XMSS XMSS_PARAMS='XMSS-SHA2_10_256' WOLFBOOT_SMALL_STACK=0 IMAGE_SIGNATURE_SIZE=2500 IMAGE_HEADER_SIZE=5000"

# ML-DSA TEST
- name: Renode Tests ML-DSA-44
run: ./tools/renode/docker-test.sh "SIGN=ML_DSA ML_DSA_LEVEL=2 WOLFBOOT_SMALL_STACK=0 IMAGE_SIGNATURE_SIZE=2420 IMAGE_HEADER_SIZE=4840"


- name: Upload Output Dir
uses: actions/upload-artifact@v3
Expand Down
63 changes: 63 additions & 0 deletions config/examples/sim-ml-dsa.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# ML-DSA signature example, based on sim.config example.
#
# The acceptable parameter values are those in FIPS 204:
#
# ML_DSA_LEVEL = {2, 3, 5}
#
# This corresponds to these security levels (from FIPS 204, Table 1.):
#
# Claimed Security Strength
# ML-DSA-44 Category 2
# ML-DSA-65 Category 3
# ML-DSA-87 Category 5
#
# The signature, pub key, and priv key lengths are all a function
# of this parameter. Refer to this table (from FIPS 204, Table 2.)
# to configure your IMAGE_SIGNATURE_SIZE:
#
# Table 2. Sizes (in bytes) of keys and signatures of ML-DSA
#
# Private Key Public Key Signature Size
# ML-DSA-44 2560 1312 2420
# ML-DSA-65 4032 1952 3309
# ML-DSA-87 4896 2592 4627
#

ARCH=sim
TARGET=sim
SIGN?=ML_DSA
HASH?=SHA256
WOLFBOOT_SMALL_STACK=0
SPI_FLASH=0
DEBUG=0
DELTA_UPDATES=0

#
# ML-DSA config examples:
#
# Category 2:
ML_DSA_LEVEL=2
IMAGE_SIGNATURE_SIZE=2420
IMAGE_HEADER_SIZE?=4840
#
# Category 3:
# ML_DSA_LEVEL=3
# IMAGE_SIGNATURE_SIZE=3309
# IMAGE_HEADER_SIZE?=6618
#
# Category 5:
# ML_DSA_LEVEL=5
# IMAGE_SIGNATURE_SIZE=4627
# IMAGE_HEADER_SIZE?=9254
#

# sizes should be multiple of system page size
WOLFBOOT_PARTITION_SIZE=0x40000
WOLFBOOT_SECTOR_SIZE=0x1000
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x20000
# if on external flash, it should be multiple of system page size
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x60000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0xA0000

# required for keytools
WOLFBOOT_FIXED_PARTITIONS=1
90 changes: 86 additions & 4 deletions docs/PQ.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,90 @@
# Post-Quantum Signatures

wolfBoot is adding support for post-quantum signatures. At present, support
for LMS/HSS (https://www.rfc-editor.org/rfc/rfc8554.html), and XMSS/XMSS^MT
(https://www.rfc-editor.org/rfc/rfc8391.html) has been added.
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, derived from
CRYSTALS-DILITHIUM (a round three NIST finalist).

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-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

A new ML-DSA sim example has been added here:

```
config/examples/sim-ml-dsa.config
```

The security category level is configured with `ML_DSA_LEVEL=<num>`, where
num = 2, 3, 5. Here is an example from the `sim-ml-dsa.config` for category
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 (dilithium) 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_DILITHIUM_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
Expand All @@ -19,7 +101,7 @@ 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 Signature Methods
### Supported PQ HBS Options

These four PQ signature options are supported:
- LMS: uses wolfcrypt implementation from `wc_lms.c`, and `wc_lms_impl.c`.
Expand Down
9 changes: 6 additions & 3 deletions include/loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,18 @@ extern "C" {
extern const unsigned char rsa4096_pub_key[];
extern unsigned int rsa4096_pub_key_len;
# define IMAGE_SIGNATURE_SIZE (512)
/* In PQC methods the signature size is a function of
* the parameters. Therefore IMAGE_SIGNATURE_SIZE is
* set in options.mk from the .config file. */
#elif defined(WOLFBOOT_SIGN_LMS)
/* Because signature size in LMS is function of
* LMS variables, IMAGE_SIGNATURE_SIZE is set in
* options.mk from the .config file. */
extern const unsigned char lms_pub_key[];
extern unsigned int lms_pub_key_len;
#elif defined(WOLFBOOT_SIGN_XMSS)
extern const unsigned char xmss_pub_key[];
extern unsigned int xmss_pub_key_len;
#elif defined(WOLFBOOT_SIGN_ML_DSA)
extern const unsigned char ml_dsa_pub_key[];
extern unsigned int ml_dsa_pub_key_len;
#elif !defined(WOLFBOOT_NO_SIGN)
# error "No public key available for given signing algorithm."
#endif /* Algorithm selection */
Expand Down
23 changes: 23 additions & 0 deletions include/user_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,29 @@ extern int tolower(int c);
# define NO_RSA
#endif /* RSA */

/* ML-DSA (dilithium) */
#if defined(WOLFBOOT_SIGN_ML_DSA)
# define HAVE_DILITHIUM
# define WOLFSSL_WC_DILITHIUM
# define WOLFSSL_EXPERIMENTAL_SETTINGS
/* Wolfcrypt builds ML-DSA (dilithium) to the FIPS 204 final
* standard by default. Uncomment this if you want the draft
* version instead. */
#if 0
#define WOLFSSL_DILITHIUM_FIPS204_DRAFT
#endif
# define WOLFSSL_DILITHIUM_VERIFY_ONLY
# define WOLFSSL_DILITHIUM_NO_LARGE_CODE
# define WOLFSSL_DILITHIUM_SMALL
# define WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM
# define WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC
# define WOLFSSL_DILITHIUM_NO_ASN1
/* dilithium needs these sha functions. */
# define WOLFSSL_SHA3
# define WOLFSSL_SHAKE256
# define WOLFSSL_SHAKE128
#endif /* WOLFBOOT_SIGN_ML_DSA */

#ifdef WOLFBOOT_HASH_SHA3_384
# define WOLFSSL_SHA3
# if defined(NO_RSA) && !defined(WOLFBOOT_TPM) && \
Expand Down
23 changes: 23 additions & 0 deletions include/wolfboot/wolfboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ extern "C" {
#define AUTH_KEY_RSA3072 0x08
#define AUTH_KEY_LMS 0x09
#define AUTH_KEY_XMSS 0x10
#define AUTH_KEY_ML_DSA 0x11



Expand All @@ -107,6 +108,7 @@ extern "C" {
#define HDR_IMG_TYPE_AUTH_RSA3072 (AUTH_KEY_RSA3072 << 8)
#define HDR_IMG_TYPE_AUTH_LMS (AUTH_KEY_LMS << 8)
#define HDR_IMG_TYPE_AUTH_XMSS (AUTH_KEY_XMSS << 8)
#define HDR_IMG_TYPE_AUTH_ML_DSA (AUTH_KEY_ML_DSA << 8)

#define HDR_IMG_TYPE_DIFF 0x00D0

Expand All @@ -125,6 +127,22 @@ extern "C" {
#define KEYSTORE_PUBKEY_SIZE_RSA4096 576
#define KEYSTORE_PUBKEY_SIZE_LMS 60
#define KEYSTORE_PUBKEY_SIZE_XMSS 68
/* ML-DSA pub key size is a function of parameters.
* This needs to be configurable. Default to security
* category 2. */
#ifdef ML_DSA_LEVEL
#if ML_DSA_LEVEL == 2
#define KEYSTORE_PUBKEY_SIZE_ML_DSA 1312
#elif ML_DSA_LEVEL == 3
#define KEYSTORE_PUBKEY_SIZE_ML_DSA 1952
#elif ML_DSA_LEVEL == 5
#define KEYSTORE_PUBKEY_SIZE_ML_DSA 2592
#else
#error "Invalid ML_DSA_LEVEL!"
#endif
#else
#define KEYSTORE_PUBKEY_SIZE_ML_DSA 1312
#endif /* ML_DSA_LEVEL */

/* Mask for key permissions */
#define KEY_VERIFY_ALL (0xFFFFFFFFU)
Expand Down Expand Up @@ -235,6 +253,11 @@ extern "C" {
# ifndef WOLFBOOT_UNIVERSAL_KEYSTORE
# define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_XMSS
# endif
#elif defined(WOLFBOOT_SIGN_ML_DSA)
# define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_ML_DSA
# ifndef WOLFBOOT_UNIVERSAL_KEYSTORE
# define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_ML_DSA
# endif
#else
# error "No valid authentication mechanism selected. " \
"Please select a valid SIGN= option."
Expand Down
20 changes: 20 additions & 0 deletions options.mk
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,26 @@ ifneq (,$(filter $(SIGN), ext_LMS ext_XMSS))
CFLAGS +=-DWOLFSSL_EXPERIMENTAL_SETTINGS
endif

ifeq ($(SIGN),ML_DSA)
# Use wolfcrypt ML-DSA dilithium implementation.
KEYGEN_OPTIONS+=--ml_dsa
SIGN_OPTIONS+=--ml_dsa
WOLFCRYPT_OBJS+= \
./lib/wolfssl/wolfcrypt/src/dilithium.o \
./lib/wolfssl/wolfcrypt/src/memory.o \
./lib/wolfssl/wolfcrypt/src/sha3.o \
./lib/wolfssl/wolfcrypt/src/wc_port.o \
./lib/wolfssl/wolfcrypt/src/hash.o
CFLAGS+=-D"WOLFBOOT_SIGN_ML_DSA" \
-D"IMAGE_SIGNATURE_SIZE"=$(IMAGE_SIGNATURE_SIZE) \
-D"ML_DSA_LEVEL"=$(ML_DSA_LEVEL)
ifeq ($(WOLFBOOT_SMALL_STACK),1)
$(error WOLFBOOT_SMALL_STACK with ML-DSA not supported yet)
else
STACK_USAGE=19544
endif
endif

ifeq ($(RAM_CODE),1)
CFLAGS+= -D"RAM_CODE"
endif
Expand Down
Loading

0 comments on commit 8a9a7f0

Please sign in to comment.