Skip to content

Commit b97abd4

Browse files
philljjdanielinux
authored andcommitted
Add ML-DSA support.
1 parent 8bdb050 commit b97abd4

File tree

18 files changed

+711
-19
lines changed

18 files changed

+711
-19
lines changed

.github/workflows/test-renode-nrf52.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ jobs:
8080
- name: Renode Tests ext_XMSS-SHA2_10_256
8181
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"
8282

83+
# ML-DSA TEST
84+
- name: Renode Tests ML-DSA-44
85+
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"
86+
8387

8488
- name: Upload Output Dir
8589
uses: actions/upload-artifact@v3

.github/workflows/test-sunnyday-simulator.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,3 +546,15 @@ jobs:
546546
run: |
547547
tools/scripts/sim-sunnyday-update.sh
548548
549+
- name: Run sunny day LMS update test
550+
run: |
551+
tools/scripts/sim-pq-sunnyday-update.sh config/examples/sim-lms.config
552+
553+
- name: Run sunny day XMSS update test
554+
run: |
555+
tools/scripts/sim-pq-sunnyday-update.sh config/examples/sim-xmss.config
556+
557+
- name: Run sunny day ML-DSA update test
558+
run: |
559+
tools/scripts/sim-pq-sunnyday-update.sh config/examples/sim-ml-dsa.config
560+

config/examples/sim-lms.config

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ ARCH=sim
2727
TARGET=sim
2828
SIGN?=LMS
2929
HASH?=SHA256
30-
LMS_LEVELS=2
31-
LMS_HEIGHT=5
30+
LMS_LEVELS=1
31+
LMS_HEIGHT=10
3232
LMS_WINTERNITZ=8
33+
IMAGE_SIGNATURE_SIZE=1456
34+
IMAGE_HEADER_SIZE=4096
3335
WOLFBOOT_SMALL_STACK=0
3436
SPI_FLASH=0
3537
DEBUG=0
3638
DELTA_UPDATES=0
37-
IMAGE_SIGNATURE_SIZE=2644
38-
IMAGE_HEADER_SIZE?=5288
3939

4040
# sizes should be multiple of system page size
4141
WOLFBOOT_PARTITION_SIZE=0x40000

config/examples/sim-ml-dsa.config

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# ML-DSA signature example, based on sim.config example.
2+
#
3+
# The acceptable parameter values are those in FIPS 204:
4+
#
5+
# ML_DSA_LEVEL = {2, 3, 5}
6+
#
7+
# This corresponds to these security levels (from FIPS 204, Table 1.):
8+
#
9+
# Claimed Security Strength
10+
# ML-DSA-44 Category 2
11+
# ML-DSA-65 Category 3
12+
# ML-DSA-87 Category 5
13+
#
14+
# The signature, pub key, and priv key lengths are all a function
15+
# of this parameter. Refer to this table (from FIPS 204, Table 2.)
16+
# to configure your IMAGE_SIGNATURE_SIZE:
17+
#
18+
# Table 2. Sizes (in bytes) of keys and signatures of ML-DSA
19+
#
20+
# Private Key Public Key Signature Size
21+
# ML-DSA-44 2560 1312 2420
22+
# ML-DSA-65 4032 1952 3309
23+
# ML-DSA-87 4896 2592 4627
24+
#
25+
26+
ARCH=sim
27+
TARGET=sim
28+
SIGN?=ML_DSA
29+
HASH?=SHA256
30+
WOLFBOOT_SMALL_STACK=0
31+
SPI_FLASH=0
32+
DEBUG=0
33+
DELTA_UPDATES=0
34+
35+
#
36+
# ML-DSA config examples:
37+
#
38+
# Category 2:
39+
ML_DSA_LEVEL=2
40+
IMAGE_SIGNATURE_SIZE=2420
41+
IMAGE_HEADER_SIZE?=8192
42+
#
43+
# Category 3:
44+
# ML_DSA_LEVEL=3
45+
# IMAGE_SIGNATURE_SIZE=3309
46+
# IMAGE_HEADER_SIZE?=8192
47+
#
48+
# Category 5:
49+
# ML_DSA_LEVEL=5
50+
# IMAGE_SIGNATURE_SIZE=4627
51+
# IMAGE_HEADER_SIZE?=12288
52+
# This example needsd larger sector size.
53+
# WOLFBOOT_SECTOR_SIZE=0x3000
54+
#
55+
56+
# sizes should be multiple of system page size
57+
WOLFBOOT_PARTITION_SIZE=0x40000
58+
WOLFBOOT_SECTOR_SIZE=0x2000
59+
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x20000
60+
# if on external flash, it should be multiple of system page size
61+
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x60000
62+
WOLFBOOT_PARTITION_SWAP_ADDRESS=0xA0000
63+
64+
# required for keytools
65+
WOLFBOOT_FIXED_PARTITIONS=1

config/examples/sim-xmss.config

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ SPI_FLASH=0
1717
DEBUG=0
1818
DELTA_UPDATES=0
1919
IMAGE_SIGNATURE_SIZE=2500
20-
IMAGE_HEADER_SIZE?=5000
20+
IMAGE_HEADER_SIZE?=8192
2121

2222
# sizes should be multiple of system page size
2323
WOLFBOOT_PARTITION_SIZE=0x40000
24-
WOLFBOOT_SECTOR_SIZE=0x1000
24+
WOLFBOOT_SECTOR_SIZE=0x2000
2525
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x20000
2626
# if on external flash, it should be multiple of system page size
2727
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x60000

docs/PQ.md

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,90 @@
11
# Post-Quantum Signatures
22

3-
wolfBoot is adding support for post-quantum signatures. At present, support
4-
for LMS/HSS (https://www.rfc-editor.org/rfc/rfc8554.html), and XMSS/XMSS^MT
5-
(https://www.rfc-editor.org/rfc/rfc8391.html) has been added.
3+
wolfBoot is continuously adding support for post-quantum (PQ) signature
4+
algorithms as they mature. At present, support has been added for three NIST
5+
approved PQ signature algorithms:
6+
7+
- ML-DSA: https://csrc.nist.gov/pubs/fips/204/final
8+
- LMS/HSS: https://csrc.nist.gov/projects/stateful-hash-based-signatures
9+
- XMSS/XMSS^MT: https://csrc.nist.gov/projects/stateful-hash-based-signatures
10+
11+
ML-DSA is a PQ lattice-based algorithm, derived from
12+
CRYSTALS-DILITHIUM (a round three NIST finalist).
13+
14+
LMS/HSS and XMSS/XMSS^MT are both PQ stateful hash-based signature (HBS)
15+
schemes, recommended in NIST SP 800-208.
16+
17+
In terms of relative tradeoffs:
18+
- All three methods have fast verifying operations.
19+
- All three methods have variable length signature sizes.
20+
- ML-DSA key generation is much faster than LMS/HSS and XMSS/XMSS^MT.
21+
- ML-DSA public keys are larger than LMS/HSS and XMSS/XMSS^MT, and
22+
variable sized.
23+
- LMS/HSS and XMSS/XMSS^MT have stateful private keys, which requires
24+
more care with key generation and signing operations.
25+
26+
See these config files for simulated target examples:
27+
28+
- `config/examples/sim-ml-dsa.config`
29+
- `config/examples/sim-lms.config`
30+
- `config/examples/sim-xmss.config`
31+
32+
## Lattice Based Signature Methods
33+
34+
### ML-DSA
35+
36+
ML-DSA (Module-Lattice Digital Signature Algorithm) was standardized in
37+
FIPS 204 (https://csrc.nist.gov/pubs/fips/204/final), based on its
38+
round 3 predecessor CRYSTALS-DILITHIUM.
39+
40+
ML-DSA has three standardized parameter sets:
41+
42+
- `ML-DSA-44`
43+
- `ML-DSA-65`
44+
- `ML-DSA-87`
45+
46+
The numerical suffix (44, 65, 87) denotes the dimension of the matrix used
47+
in the underlying lattice construction.
48+
49+
The private key, public key, signature size, and overall security strength
50+
all depend on the parameter set:
51+
52+
```
53+
#
54+
# Private Key Public Key Signature Size Security Strength
55+
# ML-DSA-44 2560 1312 2420 Category 2
56+
# ML-DSA-65 4032 1952 3309 Category 3
57+
# ML-DSA-87 4896 2592 4627 Category 5
58+
#
59+
```
60+
61+
### ML-DSA Config
62+
63+
A new ML-DSA sim example has been added here:
64+
65+
```
66+
config/examples/sim-ml-dsa.config
67+
```
68+
69+
The security category level is configured with `ML_DSA_LEVEL=<num>`, where
70+
num = 2, 3, 5. Here is an example from the `sim-ml-dsa.config` for category
71+
2:
72+
73+
```
74+
# ML-DSA config examples:
75+
#
76+
# Category 2:
77+
ML_DSA_LEVEL=2
78+
IMAGE_SIGNATURE_SIZE=2420
79+
IMAGE_HEADER_SIZE?=4840
80+
```
81+
82+
Note: The wolfcrypt implementation of ML-DSA (dilithium) builds to the
83+
FIPS 204 final standard by default. If you wish to conform to the older
84+
FIPS 204 draft standard, then build with `WOLFSSL_DILITHIUM_FIPS204_DRAFT`
85+
instead.
86+
87+
## Stateful Hash-Based Signature Methods
688

789
LMS/HSS and XMSS/XMSS^MT are both post-quantum stateful hash-based signature
890
(HBS) schemes. They are known for having small public keys, relatively fast
@@ -19,7 +101,7 @@ See these links for more info on stateful HBS support and wolfSSL/wolfCrypt:
19101
- https://www.wolfssl.com/documentation/manuals/wolfssl/appendix07.html#post-quantum-stateful-hash-based-signatures
20102
- https://github.com/wolfSSL/wolfssl-examples/tree/master/pq/stateful_hash_sig
21103

22-
## Supported PQ Signature Methods
104+
### Supported PQ HBS Options
23105

24106
These four PQ signature options are supported:
25107
- LMS: uses wolfcrypt implementation from `wc_lms.c`, and `wc_lms_impl.c`.

include/loader.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,18 @@ extern "C" {
6161
extern const unsigned char rsa4096_pub_key[];
6262
extern unsigned int rsa4096_pub_key_len;
6363
# define IMAGE_SIGNATURE_SIZE (512)
64+
/* In PQC methods the signature size is a function of
65+
* the parameters. Therefore IMAGE_SIGNATURE_SIZE is
66+
* set in options.mk from the .config file. */
6467
#elif defined(WOLFBOOT_SIGN_LMS)
65-
/* Because signature size in LMS is function of
66-
* LMS variables, IMAGE_SIGNATURE_SIZE is set in
67-
* options.mk from the .config file. */
6868
extern const unsigned char lms_pub_key[];
6969
extern unsigned int lms_pub_key_len;
7070
#elif defined(WOLFBOOT_SIGN_XMSS)
7171
extern const unsigned char xmss_pub_key[];
7272
extern unsigned int xmss_pub_key_len;
73+
#elif defined(WOLFBOOT_SIGN_ML_DSA)
74+
extern const unsigned char ml_dsa_pub_key[];
75+
extern unsigned int ml_dsa_pub_key_len;
7376
#elif !defined(WOLFBOOT_NO_SIGN)
7477
# error "No public key available for given signing algorithm."
7578
#endif /* Algorithm selection */

include/user_settings.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,29 @@ extern int tolower(int c);
227227
# define NO_RSA
228228
#endif /* RSA */
229229

230+
/* ML-DSA (dilithium) */
231+
#if defined(WOLFBOOT_SIGN_ML_DSA)
232+
# define HAVE_DILITHIUM
233+
# define WOLFSSL_WC_DILITHIUM
234+
# define WOLFSSL_EXPERIMENTAL_SETTINGS
235+
/* Wolfcrypt builds ML-DSA (dilithium) to the FIPS 204 final
236+
* standard by default. Uncomment this if you want the draft
237+
* version instead. */
238+
#if 0
239+
#define WOLFSSL_DILITHIUM_FIPS204_DRAFT
240+
#endif
241+
# define WOLFSSL_DILITHIUM_VERIFY_ONLY
242+
# define WOLFSSL_DILITHIUM_NO_LARGE_CODE
243+
# define WOLFSSL_DILITHIUM_SMALL
244+
# define WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM
245+
# define WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC
246+
# define WOLFSSL_DILITHIUM_NO_ASN1
247+
/* dilithium needs these sha functions. */
248+
# define WOLFSSL_SHA3
249+
# define WOLFSSL_SHAKE256
250+
# define WOLFSSL_SHAKE128
251+
#endif /* WOLFBOOT_SIGN_ML_DSA */
252+
230253
#ifdef WOLFBOOT_HASH_SHA3_384
231254
# define WOLFSSL_SHA3
232255
# if defined(NO_RSA) && !defined(WOLFBOOT_TPM) && \

include/wolfboot/wolfboot.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ extern "C" {
8686
#define AUTH_KEY_RSA3072 0x08
8787
#define AUTH_KEY_LMS 0x09
8888
#define AUTH_KEY_XMSS 0x10
89+
#define AUTH_KEY_ML_DSA 0x11
8990

9091

9192

@@ -107,6 +108,7 @@ extern "C" {
107108
#define HDR_IMG_TYPE_AUTH_RSA3072 (AUTH_KEY_RSA3072 << 8)
108109
#define HDR_IMG_TYPE_AUTH_LMS (AUTH_KEY_LMS << 8)
109110
#define HDR_IMG_TYPE_AUTH_XMSS (AUTH_KEY_XMSS << 8)
111+
#define HDR_IMG_TYPE_AUTH_ML_DSA (AUTH_KEY_ML_DSA << 8)
110112

111113
#define HDR_IMG_TYPE_DIFF 0x00D0
112114

@@ -127,6 +129,22 @@ extern "C" {
127129
#define KEYSTORE_PUBKEY_SIZE_RSA4096 576
128130
#define KEYSTORE_PUBKEY_SIZE_LMS 60
129131
#define KEYSTORE_PUBKEY_SIZE_XMSS 68
132+
/* ML-DSA pub key size is a function of parameters.
133+
* This needs to be configurable. Default to security
134+
* category 2. */
135+
#ifdef ML_DSA_LEVEL
136+
#if ML_DSA_LEVEL == 2
137+
#define KEYSTORE_PUBKEY_SIZE_ML_DSA 1312
138+
#elif ML_DSA_LEVEL == 3
139+
#define KEYSTORE_PUBKEY_SIZE_ML_DSA 1952
140+
#elif ML_DSA_LEVEL == 5
141+
#define KEYSTORE_PUBKEY_SIZE_ML_DSA 2592
142+
#else
143+
#error "Invalid ML_DSA_LEVEL!"
144+
#endif
145+
#else
146+
#define KEYSTORE_PUBKEY_SIZE_ML_DSA 1312
147+
#endif /* ML_DSA_LEVEL */
130148

131149
/* Mask for key permissions */
132150
#define KEY_VERIFY_ALL (0xFFFFFFFFU)
@@ -237,6 +255,11 @@ extern "C" {
237255
# ifndef WOLFBOOT_UNIVERSAL_KEYSTORE
238256
# define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_XMSS
239257
# endif
258+
#elif defined(WOLFBOOT_SIGN_ML_DSA)
259+
# define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_ML_DSA
260+
# ifndef WOLFBOOT_UNIVERSAL_KEYSTORE
261+
# define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_ML_DSA
262+
# endif
240263
#else
241264
# error "No valid authentication mechanism selected. " \
242265
"Please select a valid SIGN= option."

options.mk

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,26 @@ ifneq (,$(filter $(SIGN), ext_LMS ext_XMSS))
487487
CFLAGS +=-DWOLFSSL_EXPERIMENTAL_SETTINGS
488488
endif
489489

490+
ifeq ($(SIGN),ML_DSA)
491+
# Use wolfcrypt ML-DSA dilithium implementation.
492+
KEYGEN_OPTIONS+=--ml_dsa
493+
SIGN_OPTIONS+=--ml_dsa
494+
WOLFCRYPT_OBJS+= \
495+
./lib/wolfssl/wolfcrypt/src/dilithium.o \
496+
./lib/wolfssl/wolfcrypt/src/memory.o \
497+
./lib/wolfssl/wolfcrypt/src/sha3.o \
498+
./lib/wolfssl/wolfcrypt/src/wc_port.o \
499+
./lib/wolfssl/wolfcrypt/src/hash.o
500+
CFLAGS+=-D"WOLFBOOT_SIGN_ML_DSA" \
501+
-D"IMAGE_SIGNATURE_SIZE"=$(IMAGE_SIGNATURE_SIZE) \
502+
-D"ML_DSA_LEVEL"=$(ML_DSA_LEVEL)
503+
ifeq ($(WOLFBOOT_SMALL_STACK),1)
504+
$(error WOLFBOOT_SMALL_STACK with ML-DSA not supported yet)
505+
else
506+
STACK_USAGE=19544
507+
endif
508+
endif
509+
490510
ifeq ($(RAM_CODE),1)
491511
CFLAGS+= -D"RAM_CODE"
492512
endif

0 commit comments

Comments
 (0)