mirror of https://github.com/wolfSSL/wolfBoot.git
Add ML-DSA support.
parent
8bdb0507c0
commit
b97abd4ace
|
@ -80,6 +80,10 @@ jobs:
|
||||||
- name: Renode Tests ext_XMSS-SHA2_10_256
|
- 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"
|
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
|
- name: Upload Output Dir
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
|
|
|
@ -546,3 +546,15 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
tools/scripts/sim-sunnyday-update.sh
|
tools/scripts/sim-sunnyday-update.sh
|
||||||
|
|
||||||
|
- name: Run sunny day LMS update test
|
||||||
|
run: |
|
||||||
|
tools/scripts/sim-pq-sunnyday-update.sh config/examples/sim-lms.config
|
||||||
|
|
||||||
|
- name: Run sunny day XMSS update test
|
||||||
|
run: |
|
||||||
|
tools/scripts/sim-pq-sunnyday-update.sh config/examples/sim-xmss.config
|
||||||
|
|
||||||
|
- name: Run sunny day ML-DSA update test
|
||||||
|
run: |
|
||||||
|
tools/scripts/sim-pq-sunnyday-update.sh config/examples/sim-ml-dsa.config
|
||||||
|
|
||||||
|
|
|
@ -27,15 +27,15 @@ ARCH=sim
|
||||||
TARGET=sim
|
TARGET=sim
|
||||||
SIGN?=LMS
|
SIGN?=LMS
|
||||||
HASH?=SHA256
|
HASH?=SHA256
|
||||||
LMS_LEVELS=2
|
LMS_LEVELS=1
|
||||||
LMS_HEIGHT=5
|
LMS_HEIGHT=10
|
||||||
LMS_WINTERNITZ=8
|
LMS_WINTERNITZ=8
|
||||||
|
IMAGE_SIGNATURE_SIZE=1456
|
||||||
|
IMAGE_HEADER_SIZE=4096
|
||||||
WOLFBOOT_SMALL_STACK=0
|
WOLFBOOT_SMALL_STACK=0
|
||||||
SPI_FLASH=0
|
SPI_FLASH=0
|
||||||
DEBUG=0
|
DEBUG=0
|
||||||
DELTA_UPDATES=0
|
DELTA_UPDATES=0
|
||||||
IMAGE_SIGNATURE_SIZE=2644
|
|
||||||
IMAGE_HEADER_SIZE?=5288
|
|
||||||
|
|
||||||
# sizes should be multiple of system page size
|
# sizes should be multiple of system page size
|
||||||
WOLFBOOT_PARTITION_SIZE=0x40000
|
WOLFBOOT_PARTITION_SIZE=0x40000
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
# 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?=8192
|
||||||
|
#
|
||||||
|
# Category 3:
|
||||||
|
# ML_DSA_LEVEL=3
|
||||||
|
# IMAGE_SIGNATURE_SIZE=3309
|
||||||
|
# IMAGE_HEADER_SIZE?=8192
|
||||||
|
#
|
||||||
|
# Category 5:
|
||||||
|
# ML_DSA_LEVEL=5
|
||||||
|
# IMAGE_SIGNATURE_SIZE=4627
|
||||||
|
# IMAGE_HEADER_SIZE?=12288
|
||||||
|
# This example needsd larger sector size.
|
||||||
|
# WOLFBOOT_SECTOR_SIZE=0x3000
|
||||||
|
#
|
||||||
|
|
||||||
|
# sizes should be multiple of system page size
|
||||||
|
WOLFBOOT_PARTITION_SIZE=0x40000
|
||||||
|
WOLFBOOT_SECTOR_SIZE=0x2000
|
||||||
|
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
|
|
@ -17,11 +17,11 @@ SPI_FLASH=0
|
||||||
DEBUG=0
|
DEBUG=0
|
||||||
DELTA_UPDATES=0
|
DELTA_UPDATES=0
|
||||||
IMAGE_SIGNATURE_SIZE=2500
|
IMAGE_SIGNATURE_SIZE=2500
|
||||||
IMAGE_HEADER_SIZE?=5000
|
IMAGE_HEADER_SIZE?=8192
|
||||||
|
|
||||||
# sizes should be multiple of system page size
|
# sizes should be multiple of system page size
|
||||||
WOLFBOOT_PARTITION_SIZE=0x40000
|
WOLFBOOT_PARTITION_SIZE=0x40000
|
||||||
WOLFBOOT_SECTOR_SIZE=0x1000
|
WOLFBOOT_SECTOR_SIZE=0x2000
|
||||||
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x20000
|
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x20000
|
||||||
# if on external flash, it should be multiple of system page size
|
# if on external flash, it should be multiple of system page size
|
||||||
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x60000
|
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x60000
|
||||||
|
|
90
docs/PQ.md
90
docs/PQ.md
|
@ -1,8 +1,90 @@
|
||||||
# Post-Quantum Signatures
|
# Post-Quantum Signatures
|
||||||
|
|
||||||
wolfBoot is adding support for post-quantum signatures. At present, support
|
wolfBoot is continuously adding support for post-quantum (PQ) signature
|
||||||
for LMS/HSS (https://www.rfc-editor.org/rfc/rfc8554.html), and XMSS/XMSS^MT
|
algorithms as they mature. At present, support has been added for three NIST
|
||||||
(https://www.rfc-editor.org/rfc/rfc8391.html) has been added.
|
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
|
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
|
(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:
|
||||||
- https://www.wolfssl.com/documentation/manuals/wolfssl/appendix07.html#post-quantum-stateful-hash-based-signatures
|
- 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
|
- 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:
|
These four PQ signature options are supported:
|
||||||
- LMS: uses wolfcrypt implementation from `wc_lms.c`, and `wc_lms_impl.c`.
|
- LMS: uses wolfcrypt implementation from `wc_lms.c`, and `wc_lms_impl.c`.
|
||||||
|
|
|
@ -61,15 +61,18 @@ extern "C" {
|
||||||
extern const unsigned char rsa4096_pub_key[];
|
extern const unsigned char rsa4096_pub_key[];
|
||||||
extern unsigned int rsa4096_pub_key_len;
|
extern unsigned int rsa4096_pub_key_len;
|
||||||
# define IMAGE_SIGNATURE_SIZE (512)
|
# 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)
|
#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 const unsigned char lms_pub_key[];
|
||||||
extern unsigned int lms_pub_key_len;
|
extern unsigned int lms_pub_key_len;
|
||||||
#elif defined(WOLFBOOT_SIGN_XMSS)
|
#elif defined(WOLFBOOT_SIGN_XMSS)
|
||||||
extern const unsigned char xmss_pub_key[];
|
extern const unsigned char xmss_pub_key[];
|
||||||
extern unsigned int xmss_pub_key_len;
|
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)
|
#elif !defined(WOLFBOOT_NO_SIGN)
|
||||||
# error "No public key available for given signing algorithm."
|
# error "No public key available for given signing algorithm."
|
||||||
#endif /* Algorithm selection */
|
#endif /* Algorithm selection */
|
||||||
|
|
|
@ -227,6 +227,29 @@ extern int tolower(int c);
|
||||||
# define NO_RSA
|
# define NO_RSA
|
||||||
#endif /* 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
|
#ifdef WOLFBOOT_HASH_SHA3_384
|
||||||
# define WOLFSSL_SHA3
|
# define WOLFSSL_SHA3
|
||||||
# if defined(NO_RSA) && !defined(WOLFBOOT_TPM) && \
|
# if defined(NO_RSA) && !defined(WOLFBOOT_TPM) && \
|
||||||
|
|
|
@ -86,6 +86,7 @@ extern "C" {
|
||||||
#define AUTH_KEY_RSA3072 0x08
|
#define AUTH_KEY_RSA3072 0x08
|
||||||
#define AUTH_KEY_LMS 0x09
|
#define AUTH_KEY_LMS 0x09
|
||||||
#define AUTH_KEY_XMSS 0x10
|
#define AUTH_KEY_XMSS 0x10
|
||||||
|
#define AUTH_KEY_ML_DSA 0x11
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,6 +108,7 @@ extern "C" {
|
||||||
#define HDR_IMG_TYPE_AUTH_RSA3072 (AUTH_KEY_RSA3072 << 8)
|
#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_LMS (AUTH_KEY_LMS << 8)
|
||||||
#define HDR_IMG_TYPE_AUTH_XMSS (AUTH_KEY_XMSS << 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
|
#define HDR_IMG_TYPE_DIFF 0x00D0
|
||||||
|
|
||||||
|
@ -127,6 +129,22 @@ extern "C" {
|
||||||
#define KEYSTORE_PUBKEY_SIZE_RSA4096 576
|
#define KEYSTORE_PUBKEY_SIZE_RSA4096 576
|
||||||
#define KEYSTORE_PUBKEY_SIZE_LMS 60
|
#define KEYSTORE_PUBKEY_SIZE_LMS 60
|
||||||
#define KEYSTORE_PUBKEY_SIZE_XMSS 68
|
#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 */
|
/* Mask for key permissions */
|
||||||
#define KEY_VERIFY_ALL (0xFFFFFFFFU)
|
#define KEY_VERIFY_ALL (0xFFFFFFFFU)
|
||||||
|
@ -237,6 +255,11 @@ extern "C" {
|
||||||
# ifndef WOLFBOOT_UNIVERSAL_KEYSTORE
|
# ifndef WOLFBOOT_UNIVERSAL_KEYSTORE
|
||||||
# define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_XMSS
|
# define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_XMSS
|
||||||
# endif
|
# 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
|
#else
|
||||||
# error "No valid authentication mechanism selected. " \
|
# error "No valid authentication mechanism selected. " \
|
||||||
"Please select a valid SIGN= option."
|
"Please select a valid SIGN= option."
|
||||||
|
|
20
options.mk
20
options.mk
|
@ -487,6 +487,26 @@ ifneq (,$(filter $(SIGN), ext_LMS ext_XMSS))
|
||||||
CFLAGS +=-DWOLFSSL_EXPERIMENTAL_SETTINGS
|
CFLAGS +=-DWOLFSSL_EXPERIMENTAL_SETTINGS
|
||||||
endif
|
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)
|
ifeq ($(RAM_CODE),1)
|
||||||
CFLAGS+= -D"RAM_CODE"
|
CFLAGS+= -D"RAM_CODE"
|
||||||
endif
|
endif
|
||||||
|
|
100
src/image.c
100
src/image.c
|
@ -472,6 +472,106 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
|
||||||
}
|
}
|
||||||
#endif /* WOLFBOOT_SIGN_XMSS */
|
#endif /* WOLFBOOT_SIGN_XMSS */
|
||||||
|
|
||||||
|
#ifdef WOLFBOOT_SIGN_ML_DSA
|
||||||
|
#include <wolfssl/wolfcrypt/dilithium.h>
|
||||||
|
static void wolfBoot_verify_signature(uint8_t key_slot,
|
||||||
|
struct wolfBoot_image *img, uint8_t *sig)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
MlDsaKey ml_dsa;
|
||||||
|
uint8_t * pubkey = NULL;
|
||||||
|
int pub_len = 0;
|
||||||
|
int sig_len = 0;
|
||||||
|
int verify_res = 0;
|
||||||
|
|
||||||
|
wolfBoot_printf("info: ML-DSA wolfBoot_verify_signature\n");
|
||||||
|
|
||||||
|
pubkey = keystore_get_buffer(key_slot);
|
||||||
|
|
||||||
|
if (pubkey == NULL) {
|
||||||
|
wolfBoot_printf("error: ML-DSA pubkey not found\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wc_MlDsaKey_Init(&ml_dsa, NULL, INVALID_DEVID);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
wolfBoot_printf("error: wc_MlDsaKey_Init returned %d\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
/* Set the ML-DSA security level. */
|
||||||
|
ret = wc_MlDsaKey_SetParams(&ml_dsa, ML_DSA_LEVEL);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
wolfBoot_printf("error: wc_MlDsaKey_SetParams(%d)" \
|
||||||
|
" returned %d\n", ML_DSA_LEVEL, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure pub key matches parameters. */
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = wc_MlDsaKey_GetPubLen(&ml_dsa, &pub_len);
|
||||||
|
|
||||||
|
if (ret != 0 || pub_len <= 0) {
|
||||||
|
wolfBoot_printf("error: wc_MlDsaKey_GetPubLen returned %d\n", ret);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
else if (pub_len != KEYSTORE_PUBKEY_SIZE_ML_DSA) {
|
||||||
|
wolfBoot_printf("error: ML-DSA pub key mismatch: got %d bytes " \
|
||||||
|
"expected %d\n", pub_len, KEYSTORE_PUBKEY_SIZE_ML_DSA);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure sig len matches parameters. */
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = wc_MlDsaKey_GetSigLen(&ml_dsa, &sig_len);
|
||||||
|
|
||||||
|
if (ret != 0 || sig_len <= 0) {
|
||||||
|
wolfBoot_printf("error: wc_MlDsaKey_GetPubLen returned %d\n", ret);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
else if (sig_len != IMAGE_SIGNATURE_SIZE) {
|
||||||
|
wolfBoot_printf("error: ML-DSA sig len mismatch: got %d bytes " \
|
||||||
|
"expected %d\n", sig_len, IMAGE_SIGNATURE_SIZE);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
/* Now import pub key. */
|
||||||
|
ret = wc_MlDsaKey_ImportPubRaw(&ml_dsa, pubkey, pub_len);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
wolfBoot_printf("error: wc_MlDsaKey_ImportPubRaw returned: %d\n",
|
||||||
|
ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
wolfBoot_printf("info: using ML-DSA security level: %d\n",
|
||||||
|
ML_DSA_LEVEL);
|
||||||
|
|
||||||
|
/* Finally verify signagure. */
|
||||||
|
ret = wc_MlDsaKey_Verify(&ml_dsa, sig, IMAGE_SIGNATURE_SIZE,
|
||||||
|
img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE,
|
||||||
|
&verify_res);
|
||||||
|
|
||||||
|
if (ret == 0 && verify_res == 1) {
|
||||||
|
wolfBoot_printf("info: wc_MlDsaKey_Verify returned OK\n");
|
||||||
|
wolfBoot_image_confirm_signature_ok(img);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wolfBoot_printf("error: wc_MlDsaKey_Verify returned: ret=%d, "
|
||||||
|
"res=%d\n", ret, verify_res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wc_MlDsaKey_Free(&ml_dsa);
|
||||||
|
}
|
||||||
|
#endif /* WOLFBOOT_SIGN_ML_DSA */
|
||||||
|
|
||||||
#endif /* WOLFBOOT_TPM && WOLFBOOT_TPM_VERIFY */
|
#endif /* WOLFBOOT_TPM && WOLFBOOT_TPM_VERIFY */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -162,6 +162,15 @@ OBJS_REAL+=\
|
||||||
$(XMSSDIR)/utils.o
|
$(XMSSDIR)/utils.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Add wolfcrypt ML-DSA (dilithium) implementation.
|
||||||
|
ifeq ($(SIGN),ML_DSA)
|
||||||
|
OBJS_REAL+=$(WOLFDIR)/wolfcrypt/src/dilithium.o
|
||||||
|
|
||||||
|
CFLAGS += -D"WOLFBOOT_SIGN_ML_DSA" \
|
||||||
|
-D"IMAGE_SIGNATURE_SIZE"=$(IMAGE_SIGNATURE_SIZE) \
|
||||||
|
-D"ML_DSA_LEVEL"=$(ML_DSA_LEVEL)
|
||||||
|
endif
|
||||||
|
|
||||||
OBJS_VIRT=$(addprefix $(OBJDIR), $(notdir $(OBJS_REAL)))
|
OBJS_VIRT=$(addprefix $(OBJDIR), $(notdir $(OBJS_REAL)))
|
||||||
vpath %.c $(WOLFDIR)/wolfcrypt/src/
|
vpath %.c $(WOLFDIR)/wolfcrypt/src/
|
||||||
vpath %.c $(WOLFBOOTDIR)/src/
|
vpath %.c $(WOLFBOOTDIR)/src/
|
||||||
|
|
|
@ -79,6 +79,10 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_WC_DILITHIUM
|
||||||
|
#include <wolfssl/wolfcrypt/dilithium.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/random.h>
|
#include <wolfssl/wolfcrypt/random.h>
|
||||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||||
#ifdef DEBUG_SIGNTOOL
|
#ifdef DEBUG_SIGNTOOL
|
||||||
|
@ -103,6 +107,7 @@
|
||||||
#define KEYGEN_RSA3072 8
|
#define KEYGEN_RSA3072 8
|
||||||
#define KEYGEN_LMS 9
|
#define KEYGEN_LMS 9
|
||||||
#define KEYGEN_XMSS 10
|
#define KEYGEN_XMSS 10
|
||||||
|
#define KEYGEN_ML_DSA 11
|
||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
static FILE *fpub, *fpub_image;
|
static FILE *fpub, *fpub_image;
|
||||||
|
@ -117,7 +122,12 @@ static int saveAsDer = 0;
|
||||||
static WC_RNG rng;
|
static WC_RNG rng;
|
||||||
|
|
||||||
#ifndef KEYSLOT_MAX_PUBKEY_SIZE
|
#ifndef KEYSLOT_MAX_PUBKEY_SIZE
|
||||||
|
#if defined(WOLFSSL_WC_DILITHIUM)
|
||||||
|
/* ML-DSA pub keys are big. */
|
||||||
|
#define KEYSLOT_MAX_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_ML_DSA
|
||||||
|
#else
|
||||||
#define KEYSLOT_MAX_PUBKEY_SIZE 576
|
#define KEYSLOT_MAX_PUBKEY_SIZE 576
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct keystore_slot {
|
struct keystore_slot {
|
||||||
|
@ -300,7 +310,8 @@ const char KType[][17] = {
|
||||||
"AUTH_KEY_ECC521",
|
"AUTH_KEY_ECC521",
|
||||||
"AUTH_KEY_RSA3072",
|
"AUTH_KEY_RSA3072",
|
||||||
"AUTH_KEY_LMS",
|
"AUTH_KEY_LMS",
|
||||||
"AUTH_KEY_XMSS"
|
"AUTH_KEY_XMSS",
|
||||||
|
"AUTH_KEY_ML_DSA"
|
||||||
};
|
};
|
||||||
|
|
||||||
const char KSize[][29] = {
|
const char KSize[][29] = {
|
||||||
|
@ -314,7 +325,8 @@ const char KSize[][29] = {
|
||||||
"KEYSTORE_PUBKEY_SIZE_ECC521",
|
"KEYSTORE_PUBKEY_SIZE_ECC521",
|
||||||
"KEYSTORE_PUBKEY_SIZE_RSA3072",
|
"KEYSTORE_PUBKEY_SIZE_RSA3072",
|
||||||
"KEYSTORE_PUBKEY_SIZE_LMS",
|
"KEYSTORE_PUBKEY_SIZE_LMS",
|
||||||
"KEYSTORE_PUBKEY_SIZE_XMSS"
|
"KEYSTORE_PUBKEY_SIZE_XMSS",
|
||||||
|
"KEYSTORE_PUBKEY_SIZE_ML_DSA"
|
||||||
};
|
};
|
||||||
|
|
||||||
const char KName[][8] = {
|
const char KName[][8] = {
|
||||||
|
@ -328,7 +340,8 @@ const char KName[][8] = {
|
||||||
"ECC521",
|
"ECC521",
|
||||||
"RSA3072",
|
"RSA3072",
|
||||||
"LMS",
|
"LMS",
|
||||||
"XMSS"
|
"XMSS",
|
||||||
|
"ML_DSA"
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_PUBKEYS 64
|
#define MAX_PUBKEYS 64
|
||||||
|
@ -375,6 +388,9 @@ static uint32_t get_pubkey_size(uint32_t keyType)
|
||||||
case KEYGEN_XMSS:
|
case KEYGEN_XMSS:
|
||||||
size = KEYSTORE_PUBKEY_SIZE_XMSS;
|
size = KEYSTORE_PUBKEY_SIZE_XMSS;
|
||||||
break;
|
break;
|
||||||
|
case KEYGEN_ML_DSA:
|
||||||
|
size = KEYSTORE_PUBKEY_SIZE_ML_DSA;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
@ -404,6 +420,13 @@ void keystore_add(uint32_t ktype, uint8_t *key, uint32_t sz, const char *keyfile
|
||||||
sl.part_id_mask = id_mask;
|
sl.part_id_mask = id_mask;
|
||||||
|
|
||||||
sl.pubkey_size = get_pubkey_size(ktype);
|
sl.pubkey_size = get_pubkey_size(ktype);
|
||||||
|
|
||||||
|
if (sl.pubkey_size > sizeof(sl.pubkey)){
|
||||||
|
printf("error: %s pubkey larger than keystore: %d > %zu\n",
|
||||||
|
KName[ktype], sl.pubkey_size, sizeof(sl.pubkey));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(sl.pubkey, key, sl.pubkey_size);
|
memcpy(sl.pubkey, key, sl.pubkey_size);
|
||||||
#ifdef WOLFBOOT_UNIVERSAL_KEYSTORE
|
#ifdef WOLFBOOT_UNIVERSAL_KEYSTORE
|
||||||
slot_size = sizeof(struct keystore_slot);
|
slot_size = sizeof(struct keystore_slot);
|
||||||
|
@ -773,6 +796,120 @@ static void keygen_xmss(const char *priv_fname, uint32_t id_mask)
|
||||||
}
|
}
|
||||||
#endif /* if defined(WOLFSSL_HAVE_XMSS) */
|
#endif /* if defined(WOLFSSL_HAVE_XMSS) */
|
||||||
|
|
||||||
|
#if defined(WOLFSSL_WC_DILITHIUM)
|
||||||
|
|
||||||
|
static void keygen_ml_dsa(const char *priv_fname, uint32_t id_mask)
|
||||||
|
{
|
||||||
|
FILE * fpriv = NULL;
|
||||||
|
MlDsaKey key;
|
||||||
|
int ret;
|
||||||
|
byte * priv = NULL;
|
||||||
|
byte pub[KEYSTORE_PUBKEY_SIZE_ML_DSA];
|
||||||
|
word32 priv_len = 0;
|
||||||
|
word32 pub_len = 0;
|
||||||
|
int ml_dsa_priv_len = 0;
|
||||||
|
int ml_dsa_pub_len = 0;
|
||||||
|
|
||||||
|
ret = wc_MlDsaKey_Init(&key, NULL, INVALID_DEVID);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_MlDsaKey_Init returned %d\n", ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wc_MlDsaKey_SetParams(&key, ML_DSA_LEVEL);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_MlDsaKey_SetParams(%d) returned %d\n",
|
||||||
|
ML_DSA_LEVEL, ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make the key pair. */
|
||||||
|
ret = wc_MlDsaKey_MakeKey(&key, &rng);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_MlDsaKey_MakeKey returned %d\n", ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the ML-DSA public key length. */
|
||||||
|
ret = wc_MlDsaKey_GetPubLen(&key, &ml_dsa_pub_len);
|
||||||
|
if (ret != 0 || ml_dsa_pub_len <= 0) {
|
||||||
|
printf("error: wc_MlDsaKey_GetPrivLen returned %d\n",
|
||||||
|
ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the ML-DSA private key length. This API returns
|
||||||
|
* the public + private length. */
|
||||||
|
ret = wc_MlDsaKey_GetPrivLen(&key, &ml_dsa_priv_len);
|
||||||
|
if (ret != 0 || ml_dsa_priv_len <= 0) {
|
||||||
|
printf("error: wc_MlDsaKey_GetPrivLen returned %d\n",
|
||||||
|
ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ml_dsa_priv_len <= ml_dsa_pub_len) {
|
||||||
|
printf("error: ml-dsa: unexpected key lengths: %d, %d",
|
||||||
|
ml_dsa_priv_len, ml_dsa_pub_len);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ml_dsa_priv_len -= ml_dsa_pub_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv = malloc(ml_dsa_priv_len);
|
||||||
|
if (priv == NULL) {
|
||||||
|
fprintf(stderr, "error: malloc(%d) failed\n", ml_dsa_priv_len);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the expected key lengths. */
|
||||||
|
pub_len = (word32) ml_dsa_pub_len;
|
||||||
|
priv_len = (word32) ml_dsa_priv_len;
|
||||||
|
|
||||||
|
ret = wc_MlDsaKey_ExportPubRaw(&key, pub, &pub_len);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_MlDsaKey_ExportPubRaw returned %d\n", ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wc_MlDsaKey_ExportPrivRaw(&key, priv, &priv_len);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_MlDsaKey_ExportPrivRaw returned %d\n", ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pub_len != sizeof(pub)) {
|
||||||
|
fprintf(stderr, "error: wc_MlDsaKey_ExportPubRaw returned pub_len=%d, " \
|
||||||
|
"expected %zu\n", pub_len, sizeof(pub));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((int) priv_len != ml_dsa_priv_len) {
|
||||||
|
fprintf(stderr, "error: ml_dsa priv key mismatch: got %d " \
|
||||||
|
"bytes, expected %d\n", priv_len, ml_dsa_priv_len);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fpriv = fopen(priv_fname, "wb");
|
||||||
|
|
||||||
|
if (fpriv == NULL) {
|
||||||
|
fprintf(stderr, "error: fopen(%s) failed: %s",
|
||||||
|
priv_fname, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(priv, priv_len, 1, fpriv);
|
||||||
|
fwrite(pub, pub_len, 1, fpriv);
|
||||||
|
fclose(fpriv);
|
||||||
|
|
||||||
|
keystore_add(KEYGEN_ML_DSA, pub, KEYSTORE_PUBKEY_SIZE_ML_DSA,
|
||||||
|
priv_fname, id_mask);
|
||||||
|
|
||||||
|
wc_MlDsaKey_Free(&key);
|
||||||
|
free(priv);
|
||||||
|
priv = NULL;
|
||||||
|
}
|
||||||
|
#endif /* if defined(WOLFSSL_WC_DILITHIUM) */
|
||||||
|
|
||||||
static void key_gen_check(const char *kfilename)
|
static void key_gen_check(const char *kfilename)
|
||||||
{
|
{
|
||||||
|
@ -848,6 +985,13 @@ static void key_generate(uint32_t ktype, const char *kfilename, uint32_t id_mask
|
||||||
keygen_xmss(kfilename, id_mask);
|
keygen_xmss(kfilename, id_mask);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_WC_DILITHIUM
|
||||||
|
case KEYGEN_ML_DSA:
|
||||||
|
keygen_ml_dsa(kfilename, id_mask);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
} /* end switch */
|
} /* end switch */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1009,6 +1153,11 @@ int main(int argc, char** argv)
|
||||||
else if (strcmp(argv[i], "--xmss") == 0) {
|
else if (strcmp(argv[i], "--xmss") == 0) {
|
||||||
keytype = KEYGEN_XMSS;
|
keytype = KEYGEN_XMSS;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(WOLFSSL_WC_DILITHIUM)
|
||||||
|
else if (strcmp(argv[i], "--ml_dsa") == 0) {
|
||||||
|
keytype = KEYGEN_ML_DSA;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (strcmp(argv[i], "--force") == 0) {
|
else if (strcmp(argv[i], "--force") == 0) {
|
||||||
force = 1;
|
force = 1;
|
||||||
|
|
|
@ -124,6 +124,10 @@ static inline int fp_truncate(FILE *f, size_t len)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_WC_DILITHIUM
|
||||||
|
#include <wolfssl/wolfcrypt/dilithium.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_SIGNTOOL
|
#ifdef DEBUG_SIGNTOOL
|
||||||
#include <wolfssl/wolfcrypt/logging.h>
|
#include <wolfssl/wolfcrypt/logging.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -186,6 +190,7 @@ static inline int fp_truncate(FILE *f, size_t len)
|
||||||
#define SIGN_ECC521 HDR_IMG_TYPE_AUTH_ECC521
|
#define SIGN_ECC521 HDR_IMG_TYPE_AUTH_ECC521
|
||||||
#define SIGN_LMS HDR_IMG_TYPE_AUTH_LMS
|
#define SIGN_LMS HDR_IMG_TYPE_AUTH_LMS
|
||||||
#define SIGN_XMSS HDR_IMG_TYPE_AUTH_XMSS
|
#define SIGN_XMSS HDR_IMG_TYPE_AUTH_XMSS
|
||||||
|
#define SIGN_ML_DSA HDR_IMG_TYPE_AUTH_ML_DSA
|
||||||
|
|
||||||
|
|
||||||
#define ENC_OFF 0
|
#define ENC_OFF 0
|
||||||
|
@ -246,6 +251,9 @@ static union {
|
||||||
#ifdef WOLFSSL_HAVE_XMSS
|
#ifdef WOLFSSL_HAVE_XMSS
|
||||||
XmssKey xmss;
|
XmssKey xmss;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WOLFSSL_WC_DILITHIUM
|
||||||
|
MlDsaKey ml_dsa;
|
||||||
|
#endif
|
||||||
} key;
|
} key;
|
||||||
|
|
||||||
struct cmd_options {
|
struct cmd_options {
|
||||||
|
@ -467,9 +475,13 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz,
|
||||||
uint32_t idx = 0;
|
uint32_t idx = 0;
|
||||||
int io_sz;
|
int io_sz;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
#ifdef WOLFSSL_HAVE_XMSS
|
#if defined(WOLFSSL_HAVE_XMSS)
|
||||||
word32 priv_sz = 0;
|
word32 priv_sz = 0;
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(WOLFSSL_WC_DILITHIUM)
|
||||||
|
int priv_sz = 0;
|
||||||
|
int pub_sz = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* open and load key buffer */
|
/* open and load key buffer */
|
||||||
*key_buffer = NULL;
|
*key_buffer = NULL;
|
||||||
|
@ -746,6 +758,63 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz,
|
||||||
}
|
}
|
||||||
#endif /* WOLFSSL_HAVE_XMSS */
|
#endif /* WOLFSSL_HAVE_XMSS */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_WC_DILITHIUM
|
||||||
|
FALL_THROUGH; /* we didn't solve the key, keep trying */
|
||||||
|
case SIGN_ML_DSA:
|
||||||
|
ret = wc_MlDsaKey_GetPubLen(&key.ml_dsa, &pub_sz);
|
||||||
|
|
||||||
|
if (ret != 0 || pub_sz <= 0) {
|
||||||
|
printf("error: wc_MlDsaKey_GetPubLen returned %d\n", ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the ML-DSA private key length. This API returns
|
||||||
|
* the public + private length. */
|
||||||
|
ret = wc_MlDsaKey_GetPrivLen(&key.ml_dsa, &priv_sz);
|
||||||
|
|
||||||
|
if (ret != 0 || priv_sz <= 0) {
|
||||||
|
printf("error: wc_MlDsaKey_GetPrivLen returned %d\n", ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv_sz <= pub_sz) {
|
||||||
|
printf("error: ml-dsa: unexpected key lengths: %d, %d",
|
||||||
|
priv_sz, pub_sz);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
priv_sz -= pub_sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("info: ml-dsa priv len: %d\n", priv_sz);
|
||||||
|
printf("info: ml-dsa pub len: %d\n", pub_sz);
|
||||||
|
|
||||||
|
if ((int)*key_buffer_sz == (priv_sz + pub_sz)) {
|
||||||
|
/* priv + pub */
|
||||||
|
ret = wc_MlDsaKey_ImportPrivRaw(&key.ml_dsa, *key_buffer,
|
||||||
|
priv_sz);
|
||||||
|
*pubkey = (*key_buffer) + priv_sz;
|
||||||
|
*pubkey_sz = (*key_buffer_sz) - priv_sz;
|
||||||
|
ret = 0;
|
||||||
|
printf("Found ml-dsa key\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if ((int)*key_buffer_sz == pub_sz) {
|
||||||
|
/* pub only */
|
||||||
|
*pubkey = (*key_buffer);
|
||||||
|
*pubkey_sz = pub_sz;
|
||||||
|
ret = 0;
|
||||||
|
printf("Found ml-dsa public only key\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* We don't recognize this as an ML-DSA pub or private key. */
|
||||||
|
printf("error: unrecognized ml-dsa key size: %d\n",
|
||||||
|
*key_buffer_sz);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSL_WC_DILITHIUM */
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} /* end switch (CMD.sign) */
|
} /* end switch (CMD.sign) */
|
||||||
|
|
||||||
|
@ -915,6 +984,19 @@ static int sign_digest(int sign, int hash_algo,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif /* WOLFSSL_HAVE_XMSS */
|
#endif /* WOLFSSL_HAVE_XMSS */
|
||||||
|
#ifdef WOLFSSL_WC_DILITHIUM
|
||||||
|
if (sign == SIGN_ML_DSA) {
|
||||||
|
/* Nothing else to do, ready to sign. */
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = wc_MlDsaKey_Sign(&key.ml_dsa, signature, signature_sz,
|
||||||
|
digest, digest_sz, &rng);
|
||||||
|
}
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "error signing with XMSS: %d\n", ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* WOLFSSL_WC_DILITHIUM */
|
||||||
{
|
{
|
||||||
ret = NOT_COMPILED_IN;
|
ret = NOT_COMPILED_IN;
|
||||||
}
|
}
|
||||||
|
@ -1871,6 +1953,12 @@ int main(int argc, char** argv)
|
||||||
CMD.sign = SIGN_XMSS;
|
CMD.sign = SIGN_XMSS;
|
||||||
sign_str = "XMSS";
|
sign_str = "XMSS";
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_DILITHIUM
|
||||||
|
else if (strcmp(argv[i], "--ml_dsa") == 0) {
|
||||||
|
CMD.sign = SIGN_ML_DSA;
|
||||||
|
sign_str = "ML-DSA";
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (strcmp(argv[i], "--sha256") == 0) {
|
else if (strcmp(argv[i], "--sha256") == 0) {
|
||||||
CMD.hash_algo = HASH_SHA256;
|
CMD.hash_algo = HASH_SHA256;
|
||||||
|
@ -2250,10 +2338,44 @@ int main(int argc, char** argv)
|
||||||
CMD.signature_sz = sig_sz;
|
CMD.signature_sz = sig_sz;
|
||||||
}
|
}
|
||||||
#endif /* WOLFSSL_HAVE_XMSS */
|
#endif /* WOLFSSL_HAVE_XMSS */
|
||||||
|
#ifdef WOLFSSL_WC_DILITHIUM
|
||||||
|
else if (CMD.sign == SIGN_ML_DSA) {
|
||||||
|
int ml_dsa_ret = 0;
|
||||||
|
int sig_sz = 0;
|
||||||
|
|
||||||
|
ml_dsa_ret = wc_MlDsaKey_Init(&key.ml_dsa, NULL, INVALID_DEVID);
|
||||||
|
if (ml_dsa_ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_MlDsaKey_Init returned %d\n", ml_dsa_ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ml_dsa_ret = wc_MlDsaKey_SetParams(&key.ml_dsa, ML_DSA_LEVEL);
|
||||||
|
if (ml_dsa_ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_MlDsaKey_SetParamStr(%d)" \
|
||||||
|
" returned %d\n", ML_DSA_LEVEL, ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("info: using ML-DSA parameters: %d\n", ML_DSA_LEVEL);
|
||||||
|
|
||||||
|
ml_dsa_ret = wc_MlDsaKey_GetSigLen(&key.ml_dsa, &sig_sz);
|
||||||
|
if (ml_dsa_ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_MlDsaKey_GetSigLen returned %d\n",
|
||||||
|
ml_dsa_ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("info: ML-DSA signature size: %d\n", sig_sz);
|
||||||
|
|
||||||
|
CMD.header_sz = 2 * sig_sz;
|
||||||
|
CMD.signature_sz = sig_sz;
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSL_WC_DILITHIUM */
|
||||||
|
|
||||||
if (((CMD.sign != NO_SIGN) && (CMD.signature_sz == 0)) ||
|
if (((CMD.sign != NO_SIGN) && (CMD.signature_sz == 0)) ||
|
||||||
CMD.header_sz == 0) {
|
CMD.header_sz == 0) {
|
||||||
printf("Invalid hash or signature type! %d\n", CMD.sign);
|
printf("Invalid hash or signature type! %d, %d, %d\n", CMD.sign,
|
||||||
|
CMD.signature_sz, CMD.header_sz);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2311,6 +2433,11 @@ int main(int argc, char** argv)
|
||||||
else if (CMD.sign == SIGN_XMSS) {
|
else if (CMD.sign == SIGN_XMSS) {
|
||||||
#ifdef WOLFSSL_HAVE_XMSS
|
#ifdef WOLFSSL_HAVE_XMSS
|
||||||
wc_XmssKey_Free(&key.xmss);
|
wc_XmssKey_Free(&key.xmss);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (CMD.sign == SIGN_ML_DSA) {
|
||||||
|
#ifdef WOLFSSL_WC_DILITHIUM
|
||||||
|
wc_MlDsaKey_Free(&key.ml_dsa);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -73,6 +73,21 @@
|
||||||
#define WOLFSSL_SHA3
|
#define WOLFSSL_SHA3
|
||||||
#undef NO_SHA256
|
#undef NO_SHA256
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
/* dilithium needs these sha functions. */
|
||||||
|
# define WOLFSSL_SHAKE128
|
||||||
|
#endif /* WOLFBOOT_SIGN_ML_DSA */
|
||||||
|
|
||||||
/* ASN */
|
/* ASN */
|
||||||
#define WOLFSSL_ASN_TEMPLATE
|
#define WOLFSSL_ASN_TEMPLATE
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# For PQ methods the keytools must be built to match the alg.
|
||||||
|
#
|
||||||
|
|
||||||
|
print_usage_and_die() {
|
||||||
|
echo "usage:"
|
||||||
|
echo " ./tools/scripts/sim-pq-sunnyday-update.sh <path to sim-pq dot config>"
|
||||||
|
echo ""
|
||||||
|
echo "example:"
|
||||||
|
echo " ./tools/scripts/sim-pq-sunnyday-update.sh config/examples/sim-ml-dsa.config"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
err_and_die() {
|
||||||
|
echo "error: $1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
print_usage_and_die
|
||||||
|
fi
|
||||||
|
|
||||||
|
sim_pq=$1
|
||||||
|
|
||||||
|
if [ ! -f $sim_pq ]; then
|
||||||
|
err_and_die "file not found: $sim_pq"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp $sim_pq .config || err_and_die "cp $sim_pq"
|
||||||
|
|
||||||
|
make distclean; make clean;
|
||||||
|
|
||||||
|
make keytools || err_and_die "keytools build failed"
|
||||||
|
|
||||||
|
make test-sim-internal-flash-with-update || err_and_die "make sim failed"
|
||||||
|
|
||||||
|
V=`./wolfboot.elf update_trigger get_version 2>/dev/null`
|
||||||
|
if [ "x$V" != "x1" ]; then
|
||||||
|
echo "Failed first boot with update_trigger"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
V=`./wolfboot.elf success get_version 2>/dev/null`
|
||||||
|
if [ "x$V" != "x2" ]; then
|
||||||
|
echo "Failed update (V: $V)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo Test successful.
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,10 @@ ifeq ($(SIGN),XMSS)
|
||||||
SIGN_ARGS+= --xmss
|
SIGN_ARGS+= --xmss
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(SIGN),ML_DSA)
|
||||||
|
SIGN_ARGS+= --ml_dsa
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(HASH),SHA256)
|
ifeq ($(HASH),SHA256)
|
||||||
SIGN_ARGS+= --sha256
|
SIGN_ARGS+= --sha256
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -57,6 +57,9 @@ endif
|
||||||
ifneq (,$(filter $(SIGN), XMSS ext_XMSS))
|
ifneq (,$(filter $(SIGN), XMSS ext_XMSS))
|
||||||
SIGN_ARGS+= --xmss
|
SIGN_ARGS+= --xmss
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(SIGN),ML_DSA)
|
||||||
|
SIGN_ARGS+= --ml_dsa
|
||||||
|
endif
|
||||||
|
|
||||||
# Make sign hash argument
|
# Make sign hash argument
|
||||||
ifeq ($(HASH),SHA256)
|
ifeq ($(HASH),SHA256)
|
||||||
|
|
Loading…
Reference in New Issue