mirror of https://github.com/wolfSSL/wolfBoot.git
XMSS wolfBoot support.
parent
9b12acfed3
commit
79aadb5cc1
|
@ -0,0 +1,26 @@
|
||||||
|
# XMSS/XMSS^MT/HSS signature example, based on sim.config example.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
ARCH=sim
|
||||||
|
TARGET=sim
|
||||||
|
SIGN?=XMSS
|
||||||
|
HASH?=SHA256
|
||||||
|
XMSS_PARAMS='XMSS-SHA2_10_256'
|
||||||
|
WOLFBOOT_SMALL_STACK=0
|
||||||
|
SPI_FLASH=0
|
||||||
|
DEBUG=0
|
||||||
|
DELTA_UPDATES=0
|
||||||
|
IMAGE_SIGNATURE_SIZE=2500
|
||||||
|
IMAGE_HEADER_SIZE?=5000
|
||||||
|
|
||||||
|
# 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
|
91
docs/PQ.md
91
docs/PQ.md
|
@ -1,17 +1,27 @@
|
||||||
# Post-Quantum Signatures
|
# Post-Quantum Signatures
|
||||||
|
|
||||||
wolfBoot is adding support for post-quantum signatures. At present, support
|
wolfBoot is adding support for post-quantum signatures. At present, support
|
||||||
for LMS/HSS signatures has been added.
|
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.
|
||||||
|
|
||||||
## LMS/HSS
|
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
|
||||||
LMS/HSS is a post-quantum stateful hash-based signature scheme (HBS). It
|
signing and verifying operations, but larger signatures. Their signature sizes
|
||||||
is known for having small public and private keys, but larger signatures.
|
however are tunable via their different parameters, which affords a space-time
|
||||||
The signature size is tunable via the different LMS parameters.
|
tradeoff.
|
||||||
|
|
||||||
Stateful HBS schemes are based on the security of their underlying hash
|
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
|
functions and Merkle trees, which are not expected to be broken by the advent
|
||||||
of cryptographically relevant quantum computers.
|
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
|
||||||
|
|
||||||
|
|
||||||
|
## LMS/HSS
|
||||||
|
|
||||||
|
|
||||||
### Building with LMS Support
|
### Building with LMS Support
|
||||||
|
|
||||||
|
@ -44,7 +54,7 @@ keygen, signing, and verifying functionality. However wolfBoot
|
||||||
links directly with the subset of objects in the `hss_verify.a`
|
links directly with the subset of objects in the `hss_verify.a`
|
||||||
build rule, as it only requires verify functionality.
|
build rule, as it only requires verify functionality.
|
||||||
|
|
||||||
### Config
|
### LMS Config
|
||||||
|
|
||||||
A new LMS sim example has been added here:
|
A new LMS sim example has been added here:
|
||||||
```
|
```
|
||||||
|
@ -69,17 +79,66 @@ 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
|
script `tools/lms/lms_siglen.sh` to calculate your signature length given your
|
||||||
LMS parameters:
|
LMS parameters:
|
||||||
```
|
```
|
||||||
$./tools/lms/lms_siglen.sh
|
$ ./tools/lms/lms_siglen.sh 2 5 8
|
||||||
levels: 3
|
levels: 2
|
||||||
height: 5
|
height: 5
|
||||||
winternitz: 8
|
winternitz: 8
|
||||||
#
|
signature length: 2644
|
||||||
total_len: 3992
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### More Info
|
## XMSS/XMSS^MT
|
||||||
|
|
||||||
See these links for more info on LMS and wolfSSL/wolfCrypt:
|
### Building with XMSS Support
|
||||||
- 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
|
|
||||||
|
|
||||||
|
XMSS/XMSS^MT support in wolfCrypt requires a patched version of the
|
||||||
|
xmss-reference library ( https://github.com/XMSS/xmss-reference.git ).
|
||||||
|
Use the following procedure to prepare xmss-reference for building with
|
||||||
|
wolfBoot:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cd lib
|
||||||
|
$ git clone https://github.com/XMSS/xmss-reference.git xmss
|
||||||
|
$ ls
|
||||||
|
CMakeLists.txt wolfPKCS11 wolfTPM wolfssl xmss
|
||||||
|
$ cd xmss
|
||||||
|
$ git checkout 171ccbd26f098542a67eb5d2b128281c80bd71a6
|
||||||
|
$ git apply ../../../tools/xmss/0001-Patch-to-support-wolfSSL-xmss-reference-integration.patch
|
||||||
|
```
|
||||||
|
|
||||||
|
The patch creates an addendum readme, `patch_readme.md`, with further comments.
|
||||||
|
|
||||||
|
Nothing more is needed beyond the patch step, as wolfBoot will handle building
|
||||||
|
the xmss build artifacts it requires.
|
||||||
|
|
||||||
|
### XMSS 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
|
||||||
|
```
|
||||||
|
|
|
@ -67,6 +67,9 @@ extern "C" {
|
||||||
* options.mk from the .config file. */
|
* 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)
|
||||||
|
extern const unsigned char xmss_pub_key[];
|
||||||
|
extern unsigned int xmss_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 */
|
||||||
|
|
|
@ -85,6 +85,7 @@ extern "C" {
|
||||||
#define AUTH_KEY_ECC521 0x07
|
#define AUTH_KEY_ECC521 0x07
|
||||||
#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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -105,6 +106,7 @@ extern "C" {
|
||||||
#define HDR_IMG_TYPE_AUTH_ECC521 (AUTH_KEY_ECC521 << 8)
|
#define HDR_IMG_TYPE_AUTH_ECC521 (AUTH_KEY_ECC521 << 8)
|
||||||
#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_DIFF 0x00D0
|
#define HDR_IMG_TYPE_DIFF 0x00D0
|
||||||
|
|
||||||
|
@ -122,6 +124,7 @@ extern "C" {
|
||||||
#define KEYSTORE_PUBKEY_SIZE_RSA3072 448
|
#define KEYSTORE_PUBKEY_SIZE_RSA3072 448
|
||||||
#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
|
||||||
|
|
||||||
/* Mask for key permissions */
|
/* Mask for key permissions */
|
||||||
#define KEY_VERIFY_ALL (0xFFFFFFFFU)
|
#define KEY_VERIFY_ALL (0xFFFFFFFFU)
|
||||||
|
@ -222,6 +225,11 @@ extern "C" {
|
||||||
# ifndef WOLFBOOT_UNIVERSAL_KEYSTORE
|
# ifndef WOLFBOOT_UNIVERSAL_KEYSTORE
|
||||||
# define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_LMS
|
# define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_LMS
|
||||||
# endif
|
# endif
|
||||||
|
#elif defined(WOLFBOOT_SIGN_XMSS)
|
||||||
|
# define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_XMSS
|
||||||
|
# ifndef WOLFBOOT_UNIVERSAL_KEYSTORE
|
||||||
|
# define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_XMSS
|
||||||
|
# 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."
|
||||||
|
|
40
options.mk
40
options.mk
|
@ -381,6 +381,46 @@ ifeq ($(SIGN),LMS)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(SIGN),XMSS)
|
||||||
|
ifndef XMSS_PARAMS
|
||||||
|
$(error XMSS_PARAMS not set)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifndef IMAGE_SIGNATURE_SIZE
|
||||||
|
$(error IMAGE_SIGNATURE_SIZE not set)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifndef IMAGE_HEADER_SIZE
|
||||||
|
$(error IMAGE_HEADER_SIZE not set)
|
||||||
|
endif
|
||||||
|
|
||||||
|
XMSSDIR = lib/xmss
|
||||||
|
KEYGEN_OPTIONS+=--xmss
|
||||||
|
SIGN_OPTIONS+=--xmss
|
||||||
|
WOLFCRYPT_OBJS+= \
|
||||||
|
./$(XMSSDIR)/params.o \
|
||||||
|
./$(XMSSDIR)/thash.o \
|
||||||
|
./$(XMSSDIR)/hash_address.o \
|
||||||
|
./$(XMSSDIR)/wots.o \
|
||||||
|
./$(XMSSDIR)/xmss.o \
|
||||||
|
./$(XMSSDIR)/xmss_core_fast.o \
|
||||||
|
./$(XMSSDIR)/xmss_commons.o \
|
||||||
|
./$(XMSSDIR)/utils.o \
|
||||||
|
./lib/wolfssl/wolfcrypt/src/ext_xmss.o \
|
||||||
|
./lib/wolfssl/wolfcrypt/src/memory.o \
|
||||||
|
./lib/wolfssl/wolfcrypt/src/wc_port.o \
|
||||||
|
./lib/wolfssl/wolfcrypt/src/hash.o
|
||||||
|
CFLAGS+=-D"WOLFBOOT_SIGN_XMSS" -D"WOLFSSL_HAVE_XMSS" -D"HAVE_LIBXMSS" \
|
||||||
|
-DXMSS_PARAMS=\"$(XMSS_PARAMS)\" -I$(XMSSDIR) \
|
||||||
|
-D"IMAGE_SIGNATURE_SIZE"=$(IMAGE_SIGNATURE_SIZE) \
|
||||||
|
-D"WOLFSSL_XMSS_VERIFY_ONLY" -D"XMSS_VERIFY_ONLY"
|
||||||
|
ifeq ($(WOLFBOOT_SMALL_STACK),1)
|
||||||
|
$(error WOLFBOOT_SMALL_STACK with XMSS not supported)
|
||||||
|
else
|
||||||
|
STACK_USAGE=18064
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(RAM_CODE),1)
|
ifeq ($(RAM_CODE),1)
|
||||||
CFLAGS+= -D"RAM_CODE"
|
CFLAGS+= -D"RAM_CODE"
|
||||||
endif
|
endif
|
||||||
|
|
65
src/image.c
65
src/image.c
|
@ -382,6 +382,71 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
|
||||||
}
|
}
|
||||||
#endif /* WOLFBOOT_SIGN_LMS */
|
#endif /* WOLFBOOT_SIGN_LMS */
|
||||||
|
|
||||||
|
#ifdef WOLFBOOT_SIGN_XMSS
|
||||||
|
#include <wolfssl/wolfcrypt/xmss.h>
|
||||||
|
#ifdef HAVE_LIBXMSS
|
||||||
|
#include <wolfssl/wolfcrypt/ext_xmss.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void wolfBoot_verify_signature(uint8_t key_slot,
|
||||||
|
struct wolfBoot_image *img, uint8_t *sig)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
XmssKey xmss;
|
||||||
|
word32 pub_len = 0;
|
||||||
|
uint8_t * pubkey = NULL;
|
||||||
|
|
||||||
|
wolfBoot_printf("info: XMSS wolfBoot_verify_signature\n");
|
||||||
|
|
||||||
|
pubkey = keystore_get_buffer(key_slot);
|
||||||
|
if (pubkey == NULL) {
|
||||||
|
wolfBoot_printf("error: Xmss pubkey not found\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wc_XmssKey_Init(&xmss, NULL, INVALID_DEVID);
|
||||||
|
if (ret != 0) {
|
||||||
|
wolfBoot_printf("error: wc_XmssKey_Init returned %d\n", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wolfBoot_printf("info: using XMSS parameters: %s\n", XMSS_PARAMS);
|
||||||
|
|
||||||
|
/* Set the XMSS parameters. */
|
||||||
|
ret = wc_XmssKey_SetParamStr(&xmss, XMSS_PARAMS);
|
||||||
|
if (ret != 0) {
|
||||||
|
/* Something is wrong with the pub key or XMSS parameters. */
|
||||||
|
wolfBoot_printf("error: wc_XmssKey_SetParamStr(%s)" \
|
||||||
|
" returned %d\n", XMSS_PARAMS, ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wolfBoot_printf("info: using XMSS parameters: %s\n", XMSS_PARAMS);
|
||||||
|
|
||||||
|
/* Set the public key. */
|
||||||
|
ret = wc_XmssKey_ImportPubRaw(&xmss, pubkey, KEYSTORE_PUBKEY_SIZE);
|
||||||
|
if (ret != 0) {
|
||||||
|
/* Something is wrong with the pub key or LMS parameters. */
|
||||||
|
wolfBoot_printf("error: wc_XmssKey_ImportPubRaw" \
|
||||||
|
" returned %d\n", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wc_XmssKey_Verify(&xmss, sig, IMAGE_SIGNATURE_SIZE, img->sha_hash,
|
||||||
|
WOLFBOOT_SHA_DIGEST_SIZE);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
wolfBoot_printf("info: wc_XmssKey_Verify returned OK\n");
|
||||||
|
wolfBoot_image_confirm_signature_ok(img);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wolfBoot_printf("error: wc_XmssKey_Verify returned %d\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
wc_XmssKey_Free(&xmss);
|
||||||
|
}
|
||||||
|
#endif /* WOLFBOOT_SIGN_XMSS */
|
||||||
|
|
||||||
#endif /* WOLFBOOT_TPM && WOLFBOOT_TPM_VERIFY */
|
#endif /* WOLFBOOT_TPM && WOLFBOOT_TPM_VERIFY */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ ifeq ($(ARCH),)
|
||||||
LMS_LEVELS?=0
|
LMS_LEVELS?=0
|
||||||
LMS_HEIGHT?=0
|
LMS_HEIGHT?=0
|
||||||
LMS_WINTERNITZ?=0
|
LMS_WINTERNITZ?=0
|
||||||
|
XMSS_PARAMS?=XMSS-SHA2_10_256
|
||||||
NO_MPU?=0
|
NO_MPU?=0
|
||||||
ENCRYPT?=0
|
ENCRYPT?=0
|
||||||
ENCRYPT_WITH_CHACHA?=0
|
ENCRYPT_WITH_CHACHA?=0
|
||||||
|
@ -93,4 +94,5 @@ CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXSDK MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO
|
||||||
ENCRYPT_WITH_CHACHA ENCRYPT_WITH_AES128 ENCRYPT_WITH_AES256 ARMORED \
|
ENCRYPT_WITH_CHACHA ENCRYPT_WITH_AES128 ENCRYPT_WITH_AES256 ARMORED \
|
||||||
LMS_LEVELS LMS_HEIGHT LMS_WINTERNITZ \
|
LMS_LEVELS LMS_HEIGHT LMS_WINTERNITZ \
|
||||||
WOLFBOOT_UNIVERSAL_KEYSTORE \
|
WOLFBOOT_UNIVERSAL_KEYSTORE \
|
||||||
|
XMSS_PARAMS \
|
||||||
ELF
|
ELF
|
||||||
|
|
|
@ -25,6 +25,15 @@ ifeq ($(SIGN),LMS)
|
||||||
-D"LMS_WINTERNITZ=$(LMS_WINTERNITZ)"
|
-D"LMS_WINTERNITZ=$(LMS_WINTERNITZ)"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(SIGN),XMSS)
|
||||||
|
$(info xmss params: $(XMSS_PARAMS))
|
||||||
|
XMSSDIR = $(WOLFBOOTDIR)/lib/xmss
|
||||||
|
CFLAGS +=-DWOLFBOOT_SIGN_XMSS -DWOLFSSL_HAVE_XMSS -DHAVE_LIBXMSS -I$(XMSSDIR) \
|
||||||
|
-D"IMAGE_SIGNATURE_SIZE"=$(IMAGE_SIGNATURE_SIZE) \
|
||||||
|
-DXMSS_PARAMS=\"$(XMSS_PARAMS)\"
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
# option variables
|
# option variables
|
||||||
DEBUG_FLAGS = -g -DDEBUG -DDEBUG_SIGNTOOL -DDEBUG_WOLFSSL -DDEBUG_WOLFSSL_VERBOSE
|
DEBUG_FLAGS = -g -DDEBUG -DDEBUG_SIGNTOOL -DDEBUG_WOLFSSL -DDEBUG_WOLFSSL_VERBOSE
|
||||||
SANITIZE_FLAGS = -fsanitize=address
|
SANITIZE_FLAGS = -fsanitize=address
|
||||||
|
@ -75,16 +84,33 @@ OBJS_REAL=\
|
||||||
$(WOLFDIR)/wolfcrypt/src/tfm.o \
|
$(WOLFDIR)/wolfcrypt/src/tfm.o \
|
||||||
$(WOLFDIR)/wolfcrypt/src/wc_port.o \
|
$(WOLFDIR)/wolfcrypt/src/wc_port.o \
|
||||||
$(WOLFDIR)/wolfcrypt/src/wolfmath.o \
|
$(WOLFDIR)/wolfcrypt/src/wolfmath.o \
|
||||||
$(WOLFDIR)/wolfcrypt/src/ext_lms.o
|
$(WOLFDIR)/wolfcrypt/src/ext_lms.o \
|
||||||
|
$(WOLFDIR)/wolfcrypt/src/ext_xmss.o
|
||||||
|
|
||||||
OBJS_REAL+=\
|
OBJS_REAL+=\
|
||||||
$(WOLFBOOTDIR)/src/delta.o
|
$(WOLFBOOTDIR)/src/delta.o
|
||||||
|
|
||||||
|
ifeq ($(SIGN),XMSS)
|
||||||
|
OBJS_REAL+=\
|
||||||
|
$(XMSSDIR)/params.o \
|
||||||
|
$(XMSSDIR)/thash.o \
|
||||||
|
$(XMSSDIR)/hash_address.o \
|
||||||
|
$(XMSSDIR)/wots.o \
|
||||||
|
$(XMSSDIR)/xmss.o \
|
||||||
|
$(XMSSDIR)/xmss_core_fast.o \
|
||||||
|
$(XMSSDIR)/xmss_commons.o \
|
||||||
|
$(XMSSDIR)/utils.o
|
||||||
|
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/
|
||||||
vpath %.c ./
|
vpath %.c ./
|
||||||
|
|
||||||
|
ifeq ($(SIGN),XMSS)
|
||||||
|
vpath %.c $(XMSSDIR)/
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: clean all
|
.PHONY: clean all
|
||||||
|
|
||||||
all: $(WOLFBOOTDIR)/include/target.h sign keygen
|
all: $(WOLFBOOTDIR)/include/target.h sign keygen
|
||||||
|
@ -114,6 +140,9 @@ $(OBJDIR)/%.o: $(WOLFBOOTDIR)/src/%.c
|
||||||
$(OBJDIR)/%.o: $(WOLFDIR)/wolfcrypt/src/%.c
|
$(OBJDIR)/%.o: $(WOLFDIR)/wolfcrypt/src/%.c
|
||||||
$(Q)$(CC) $(CFLAGS) -c -o $@ $<
|
$(Q)$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$(XMSSDIR)/src/%.o: $(XMSSDIR)/src/%.c
|
||||||
|
$(Q)$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
# build templates
|
# build templates
|
||||||
sign: $(OBJS_VIRT) $(LIBS) sign.o
|
sign: $(OBJS_VIRT) $(LIBS) sign.o
|
||||||
@echo "Building signing tool"
|
@echo "Building signing tool"
|
||||||
|
|
|
@ -68,6 +68,13 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(WOLFSSL_HAVE_XMSS)
|
||||||
|
#include <wolfssl/wolfcrypt/xmss.h>
|
||||||
|
#ifdef HAVE_LIBXMSS
|
||||||
|
#include <wolfssl/wolfcrypt/ext_xmss.h>
|
||||||
|
#endif
|
||||||
|
#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
|
||||||
|
@ -91,6 +98,7 @@
|
||||||
#define KEYGEN_ECC521 7
|
#define KEYGEN_ECC521 7
|
||||||
#define KEYGEN_RSA3072 8
|
#define KEYGEN_RSA3072 8
|
||||||
#define KEYGEN_LMS 9
|
#define KEYGEN_LMS 9
|
||||||
|
#define KEYGEN_XMSS 10
|
||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
static FILE *fpub, *fpub_image;
|
static FILE *fpub, *fpub_image;
|
||||||
|
@ -236,7 +244,8 @@ const char KType[][17] = {
|
||||||
"AUTH_KEY_ECC384",
|
"AUTH_KEY_ECC384",
|
||||||
"AUTH_KEY_ECC521",
|
"AUTH_KEY_ECC521",
|
||||||
"AUTH_KEY_RSA3072",
|
"AUTH_KEY_RSA3072",
|
||||||
"AUTH_KEY_LMS"
|
"AUTH_KEY_LMS",
|
||||||
|
"AUTH_KEY_XMSS"
|
||||||
};
|
};
|
||||||
|
|
||||||
const char KSize[][29] = {
|
const char KSize[][29] = {
|
||||||
|
@ -249,7 +258,8 @@ const char KSize[][29] = {
|
||||||
"KEYSTORE_PUBKEY_SIZE_ECC384",
|
"KEYSTORE_PUBKEY_SIZE_ECC384",
|
||||||
"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"
|
||||||
};
|
};
|
||||||
|
|
||||||
const char KName[][8] = {
|
const char KName[][8] = {
|
||||||
|
@ -262,7 +272,8 @@ const char KName[][8] = {
|
||||||
"ECC384",
|
"ECC384",
|
||||||
"ECC521",
|
"ECC521",
|
||||||
"RSA3072",
|
"RSA3072",
|
||||||
"LMS"
|
"LMS",
|
||||||
|
"XMSS"
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_PUBKEYS 64
|
#define MAX_PUBKEYS 64
|
||||||
|
@ -306,6 +317,9 @@ static uint32_t get_pubkey_size(uint32_t keyType)
|
||||||
case KEYGEN_LMS:
|
case KEYGEN_LMS:
|
||||||
size = KEYSTORE_PUBKEY_SIZE_LMS;
|
size = KEYSTORE_PUBKEY_SIZE_LMS;
|
||||||
break;
|
break;
|
||||||
|
case KEYGEN_XMSS:
|
||||||
|
size = KEYSTORE_PUBKEY_SIZE_XMSS;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
@ -595,6 +609,97 @@ static void keygen_lms(const char *priv_fname, uint32_t id_mask)
|
||||||
}
|
}
|
||||||
#endif /* if defined(WOLFSSL_HAVE_LMS) */
|
#endif /* if defined(WOLFSSL_HAVE_LMS) */
|
||||||
|
|
||||||
|
#if defined(WOLFSSL_HAVE_XMSS)
|
||||||
|
#include "../xmss/xmss_common.h"
|
||||||
|
|
||||||
|
static void keygen_xmss(const char *priv_fname, uint32_t id_mask)
|
||||||
|
{
|
||||||
|
FILE * fpriv;
|
||||||
|
XmssKey key;
|
||||||
|
int ret;
|
||||||
|
word32 priv_sz = 0;
|
||||||
|
byte xmss_pub[XMSS_SHA256_PUBLEN];
|
||||||
|
word32 pub_len = sizeof(xmss_pub);
|
||||||
|
|
||||||
|
ret = wc_XmssKey_Init(&key, NULL, INVALID_DEVID);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_XmssKey_Init returned %d\n", ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wc_XmssKey_SetParamStr(&key, XMSS_PARAMS);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_XmssKey_SetParamStr(%s)" \
|
||||||
|
" returned %d\n", XMSS_PARAMS, ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("info: using XMSS parameters: %s\n", XMSS_PARAMS);
|
||||||
|
|
||||||
|
ret = wc_XmssKey_SetWriteCb(&key, xmss_write_key);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_XmssKey_SetWriteCb returned %d\n", ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wc_XmssKey_SetReadCb(&key, xmss_read_key);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_XmssKey_SetReadCb returned %d\n", ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wc_XmssKey_SetContext(&key, (void *) priv_fname);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_XmssKey_SetContext returned %d\n", ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make the key pair. */
|
||||||
|
ret = wc_XmssKey_MakeKey(&key, &rng);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_XmssKey_MakeKey returned %d\n", ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the XMSS/XMSS^MT secret key length. */
|
||||||
|
ret = wc_XmssKey_GetPrivLen(&key, &priv_sz);
|
||||||
|
if (ret != 0 || priv_sz <= 0) {
|
||||||
|
printf("error: wc_XmssKey_GetPrivLen returned %d\n",
|
||||||
|
ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wc_XmssKey_ExportPubRaw(&key, xmss_pub, &pub_len);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_XmssKey_ExportPubRaw returned %d\n", ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pub_len != sizeof(xmss_pub)) {
|
||||||
|
fprintf(stderr, "error: wc_XmssKey_ExportPubRaw returned pub_len=%d\n" \
|
||||||
|
", expected %zu\n", pub_len, sizeof(xmss_pub));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append the public key to the private keyfile. */
|
||||||
|
fpriv = fopen(priv_fname, "r+");
|
||||||
|
if (!fpriv) {
|
||||||
|
fprintf(stderr, "error: fopen(%s, \"r+\") returned %d\n", priv_fname,
|
||||||
|
ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(fpriv, priv_sz, SEEK_SET);
|
||||||
|
fwrite(xmss_pub, KEYSTORE_PUBKEY_SIZE_XMSS, 1, fpriv);
|
||||||
|
fclose(fpriv);
|
||||||
|
|
||||||
|
keystore_add(KEYGEN_XMSS, xmss_pub, KEYSTORE_PUBKEY_SIZE_XMSS, priv_fname, id_mask);
|
||||||
|
|
||||||
|
wc_XmssKey_Free(&key);
|
||||||
|
}
|
||||||
|
#endif /* if defined(WOLFSSL_HAVE_XMSS) */
|
||||||
|
|
||||||
|
|
||||||
static void key_gen_check(const char *kfilename)
|
static void key_gen_check(const char *kfilename)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
@ -663,6 +768,12 @@ static void key_generate(uint32_t ktype, const char *kfilename, uint32_t id_mask
|
||||||
keygen_lms(kfilename, id_mask);
|
keygen_lms(kfilename, id_mask);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_HAVE_XMSS
|
||||||
|
case KEYGEN_XMSS:
|
||||||
|
keygen_xmss(kfilename, id_mask);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
} /* end switch */
|
} /* end switch */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,6 +926,11 @@ int main(int argc, char** argv)
|
||||||
else if (strcmp(argv[i], "--lms") == 0) {
|
else if (strcmp(argv[i], "--lms") == 0) {
|
||||||
keytype = KEYGEN_LMS;
|
keytype = KEYGEN_LMS;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(WOLFSSL_HAVE_XMSS)
|
||||||
|
else if (strcmp(argv[i], "--xmss") == 0) {
|
||||||
|
keytype = KEYGEN_XMSS;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (strcmp(argv[i], "--force") == 0) {
|
else if (strcmp(argv[i], "--force") == 0) {
|
||||||
force = 1;
|
force = 1;
|
||||||
|
|
|
@ -108,6 +108,13 @@ static inline int fp_truncate(FILE *f, size_t len)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(WOLFSSL_HAVE_XMSS)
|
||||||
|
#include <wolfssl/wolfcrypt/xmss.h>
|
||||||
|
#ifdef HAVE_LIBXMSS
|
||||||
|
#include <wolfssl/wolfcrypt/ext_xmss.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_SIGNTOOL
|
#ifdef DEBUG_SIGNTOOL
|
||||||
#include <wolfssl/wolfcrypt/logging.h>
|
#include <wolfssl/wolfcrypt/logging.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -169,6 +176,7 @@ static inline int fp_truncate(FILE *f, size_t len)
|
||||||
#define SIGN_ECC384 HDR_IMG_TYPE_AUTH_ECC384
|
#define SIGN_ECC384 HDR_IMG_TYPE_AUTH_ECC384
|
||||||
#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 ENC_OFF 0
|
#define ENC_OFF 0
|
||||||
|
@ -203,6 +211,10 @@ static void header_append_tag(uint8_t* header, uint32_t* idx, uint16_t tag,
|
||||||
#include "../lms/lms_common.h"
|
#include "../lms/lms_common.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_HAVE_XMSS
|
||||||
|
#include "../xmss/xmss_common.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
static const char wolfboot_delta_file[] = "/tmp/wolfboot-delta.bin";
|
static const char wolfboot_delta_file[] = "/tmp/wolfboot-delta.bin";
|
||||||
|
|
||||||
|
@ -222,6 +234,9 @@ static union {
|
||||||
#ifdef WOLFSSL_HAVE_LMS
|
#ifdef WOLFSSL_HAVE_LMS
|
||||||
LmsKey lms;
|
LmsKey lms;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WOLFSSL_HAVE_XMSS
|
||||||
|
XmssKey xmss;
|
||||||
|
#endif
|
||||||
} key;
|
} key;
|
||||||
|
|
||||||
struct cmd_options {
|
struct cmd_options {
|
||||||
|
@ -736,6 +751,57 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WOLFSSL_HAVE_LMS */
|
#endif /* WOLFSSL_HAVE_LMS */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_HAVE_XMSS
|
||||||
|
FALL_THROUGH;
|
||||||
|
case SIGN_XMSS:
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
|
if (CMD.sign == SIGN_AUTO) {
|
||||||
|
/* XMSS is stateful and requires additional config, and is not
|
||||||
|
* compatible with SIGN_AUTO. */
|
||||||
|
printf("error: SIGN_AUTO with XMSS is not supported\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* The XMSS file callbacks will handle writing and reading the
|
||||||
|
* private key. We only need to set the public key here.
|
||||||
|
*
|
||||||
|
* If both priv/pub are present:
|
||||||
|
* - The first ?? bytes is the private key.
|
||||||
|
* - The next 60 bytes is the public key. */
|
||||||
|
word32 priv_sz = 0;
|
||||||
|
int xmss_ret = 0;
|
||||||
|
|
||||||
|
xmss_ret = wc_XmssKey_GetPrivLen(&key.xmss, &priv_sz);
|
||||||
|
if (xmss_ret != 0 || priv_sz <= 0) {
|
||||||
|
printf("error: wc_XmssKey_GetPrivLen returned %d\n",
|
||||||
|
xmss_ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("info: xmss sk len: %d\n", priv_sz);
|
||||||
|
printf("info: xmss pk len: %d\n", KEYSTORE_PUBKEY_SIZE_XMSS);
|
||||||
|
|
||||||
|
if (*key_buffer_sz == (priv_sz + KEYSTORE_PUBKEY_SIZE_XMSS)) {
|
||||||
|
/* priv + pub */
|
||||||
|
*pubkey = (*key_buffer) + priv_sz;
|
||||||
|
*pubkey_sz = (*key_buffer_sz) - priv_sz;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else if (*key_buffer_sz == KEYSTORE_PUBKEY_SIZE_XMSS) {
|
||||||
|
/* pub only. */
|
||||||
|
*pubkey = (*key_buffer);
|
||||||
|
*pubkey_sz = KEYSTORE_PUBKEY_SIZE_XMSS;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* We don't recognize this as an XMSS pub or private key. */
|
||||||
|
printf("error: unrecognized XMSS key size: %d\n",
|
||||||
|
*key_buffer_sz );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSL_HAVE_XMSS */
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} /* end switch (CMD.sign) */
|
} /* end switch (CMD.sign) */
|
||||||
|
|
||||||
|
@ -868,6 +934,35 @@ static int sign_digest(int sign, int hash_algo,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif /* WOLFSSL_HAVE_LMS */
|
#endif /* WOLFSSL_HAVE_LMS */
|
||||||
|
#ifdef WOLFSSL_HAVE_XMSS
|
||||||
|
if (sign == SIGN_XMSS) {
|
||||||
|
ret = wc_XmssKey_Init(&key.xmss, NULL, INVALID_DEVID);
|
||||||
|
/* Set the callbacks, so XMSS can update the private key while signing */
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = wc_XmssKey_SetWriteCb(&key.xmss, xmss_write_key);
|
||||||
|
}
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = wc_XmssKey_SetReadCb(&key.xmss, xmss_read_key);
|
||||||
|
}
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = wc_XmssKey_SetContext(&key.xmss, (void*)CMD.key_file);
|
||||||
|
}
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = wc_XmssKey_SetParamStr(&key.xmss, XMSS_PARAMS);
|
||||||
|
}
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = wc_XmssKey_Reload(&key.xmss);
|
||||||
|
}
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = wc_XmssKey_Sign(&key.xmss, signature, signature_sz, digest,
|
||||||
|
digest_sz);
|
||||||
|
}
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "error signing with XMSS: %d\n", ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* WOLFSSL_HAVE_XMSS */
|
||||||
{
|
{
|
||||||
ret = NOT_COMPILED_IN;
|
ret = NOT_COMPILED_IN;
|
||||||
}
|
}
|
||||||
|
@ -1769,6 +1864,12 @@ int main(int argc, char** argv)
|
||||||
CMD.sign = SIGN_LMS;
|
CMD.sign = SIGN_LMS;
|
||||||
sign_str = "LMS";
|
sign_str = "LMS";
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef WOLFSSL_HAVE_XMSS
|
||||||
|
else if (strcmp(argv[i], "--xmss") == 0) {
|
||||||
|
CMD.sign = SIGN_XMSS;
|
||||||
|
sign_str = "XMSS";
|
||||||
|
}
|
||||||
#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;
|
||||||
|
@ -1980,6 +2081,39 @@ int main(int argc, char** argv)
|
||||||
CMD.signature_sz = sig_sz;
|
CMD.signature_sz = sig_sz;
|
||||||
}
|
}
|
||||||
#endif /* WOLFSSL_HAVE_LMS */
|
#endif /* WOLFSSL_HAVE_LMS */
|
||||||
|
#ifdef WOLFSSL_HAVE_XMSS
|
||||||
|
else if (CMD.sign == SIGN_XMSS) {
|
||||||
|
int xmss_ret = 0;
|
||||||
|
word32 sig_sz = 0;
|
||||||
|
|
||||||
|
xmss_ret = wc_XmssKey_Init(&key.xmss, NULL, INVALID_DEVID);
|
||||||
|
if (xmss_ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_XmssKey_Init returned %d\n", xmss_ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmss_ret = wc_XmssKey_SetParamStr(&key.xmss, XMSS_PARAMS);
|
||||||
|
if (xmss_ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_XmssKey_SetParamStr(%s)" \
|
||||||
|
" returned %d\n", XMSS_PARAMS, ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("info: using XMSS parameters: %s\n", XMSS_PARAMS);
|
||||||
|
|
||||||
|
xmss_ret = wc_XmssKey_GetSigLen(&key.xmss, &sig_sz);
|
||||||
|
if (xmss_ret != 0) {
|
||||||
|
fprintf(stderr, "error: wc_XmssKey_GetSigLen returned %d\n",
|
||||||
|
xmss_ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("info: XMSS signature size: %d\n", sig_sz);
|
||||||
|
|
||||||
|
CMD.header_sz = 2 * sig_sz;
|
||||||
|
CMD.signature_sz = sig_sz;
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSL_HAVE_XMSS */
|
||||||
|
|
||||||
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) {
|
||||||
|
|
|
@ -53,6 +53,9 @@ endif
|
||||||
ifeq ($(SIGN),LMS)
|
ifeq ($(SIGN),LMS)
|
||||||
SIGN_ARGS+= --lms
|
SIGN_ARGS+= --lms
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(SIGN),XMSS)
|
||||||
|
SIGN_ARGS+= --xmss
|
||||||
|
endif
|
||||||
|
|
||||||
# Make sign hash argument
|
# Make sign hash argument
|
||||||
ifeq ($(HASH),SHA256)
|
ifeq ($(HASH),SHA256)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,146 @@
|
||||||
|
/* xmss_common.h
|
||||||
|
*
|
||||||
|
* Common callback functions used by XMSS to write/read the private
|
||||||
|
* key file.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 wolfSSL Inc.
|
||||||
|
*
|
||||||
|
* This file is part of wolfBoot.
|
||||||
|
*
|
||||||
|
* wolfBoot is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* wolfBoot is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XMSS_COMMON_H
|
||||||
|
#define XMSS_COMMON_H
|
||||||
|
static enum wc_XmssRc xmss_write_key(const byte * priv, word32 privSz, void * context)
|
||||||
|
{
|
||||||
|
FILE * file = NULL;
|
||||||
|
const char * filename = NULL;
|
||||||
|
int n_cmp = 0;
|
||||||
|
size_t n_read = 0;
|
||||||
|
size_t n_write = 0;
|
||||||
|
byte * buff = NULL;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (priv == NULL || context == NULL || privSz == 0) {
|
||||||
|
fprintf(stderr, "error: invalid write args\n");
|
||||||
|
return WC_XMSS_RC_BAD_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
filename = context;
|
||||||
|
|
||||||
|
/* Open file for read and write. */
|
||||||
|
file = fopen(filename, "r+");
|
||||||
|
if (!file) {
|
||||||
|
/* Create the file if it didn't exist. */
|
||||||
|
file = fopen(filename, "w+");
|
||||||
|
if (!file) {
|
||||||
|
fprintf(stderr, "error: fopen(%s, \"w+\") failed: %d\n", filename,
|
||||||
|
ferror(file));
|
||||||
|
return WC_XMSS_RC_WRITE_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n_write = fwrite(priv, 1, privSz, file);
|
||||||
|
|
||||||
|
if (n_write != privSz) {
|
||||||
|
fprintf(stderr, "error: wrote %zu, expected %d: %d\n", n_write, privSz,
|
||||||
|
ferror(file));
|
||||||
|
return WC_XMSS_RC_WRITE_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = fclose(file);
|
||||||
|
if (err) {
|
||||||
|
fprintf(stderr, "error: fclose returned %d\n", err);
|
||||||
|
return WC_XMSS_RC_WRITE_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify private key data has actually been written to persistent
|
||||||
|
* storage correctly. */
|
||||||
|
file = fopen(filename, "r+");
|
||||||
|
if (!file) {
|
||||||
|
fprintf(stderr, "error: fopen(%s, \"r+\") failed: %d\n", filename,
|
||||||
|
ferror(file));
|
||||||
|
return WC_XMSS_RC_WRITE_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buff = malloc(privSz);
|
||||||
|
if (buff == NULL) {
|
||||||
|
fprintf(stderr, "error: malloc(%d) failed\n", privSz);
|
||||||
|
return WC_XMSS_RC_WRITE_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMEMSET(buff, 0, n_write);
|
||||||
|
|
||||||
|
n_read = fread(buff, 1, n_write, file);
|
||||||
|
|
||||||
|
if (n_read != n_write) {
|
||||||
|
fprintf(stderr, "error: read %zu, expected %zu: %d\n", n_read, n_write,
|
||||||
|
ferror(file));
|
||||||
|
free(buff);
|
||||||
|
return WC_XMSS_RC_WRITE_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
n_cmp = XMEMCMP(buff, priv, n_write);
|
||||||
|
free(buff);
|
||||||
|
buff = NULL;
|
||||||
|
|
||||||
|
if (n_cmp != 0) {
|
||||||
|
fprintf(stderr, "error: write data was corrupted: %d\n", n_cmp);
|
||||||
|
return WC_XMSS_RC_WRITE_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = fclose(file);
|
||||||
|
if (err) {
|
||||||
|
fprintf(stderr, "error: fclose returned %d\n", err);
|
||||||
|
return WC_XMSS_RC_WRITE_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WC_XMSS_RC_SAVED_TO_NV_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum wc_XmssRc xmss_read_key(byte * priv, word32 privSz, void * context)
|
||||||
|
{
|
||||||
|
FILE * file = NULL;
|
||||||
|
const char * filename = NULL;
|
||||||
|
size_t n_read = 0;
|
||||||
|
|
||||||
|
if (priv == NULL || context == NULL || privSz == 0) {
|
||||||
|
fprintf(stderr, "error: invalid read args\n");
|
||||||
|
return WC_XMSS_RC_BAD_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
filename = context;
|
||||||
|
|
||||||
|
file = fopen(filename, "rb");
|
||||||
|
if (!file) {
|
||||||
|
fprintf(stderr, "error: fopen(%s, \"rb\") failed\n", filename);
|
||||||
|
return WC_XMSS_RC_READ_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
n_read = fread(priv, 1, privSz, file);
|
||||||
|
|
||||||
|
if (n_read != privSz) {
|
||||||
|
fprintf(stderr, "error: read %zu, expected %d: %d\n", n_read, privSz,
|
||||||
|
ferror(file));
|
||||||
|
return WC_XMSS_RC_READ_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return WC_XMSS_RC_READ_TO_MEMORY;
|
||||||
|
}
|
||||||
|
#endif /* XMSS_COMMON_H */
|
|
@ -0,0 +1,93 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Prints the XMSS/XMSS^MT signature length given a parameter set string.
|
||||||
|
#
|
||||||
|
# References:
|
||||||
|
# - https://www.rfc-editor.org/rfc/rfc8391.html
|
||||||
|
# - https://eprint.iacr.org/2017/349.pdf
|
||||||
|
|
||||||
|
print_usage_and_exit() {
|
||||||
|
echo "usage:"
|
||||||
|
echo " ./xmss_siglen.sh <parameter string>"
|
||||||
|
echo ""
|
||||||
|
echo "examples:"
|
||||||
|
echo " ./xmss_siglen.sh XMSS-SHA2_10_256"
|
||||||
|
echo " ./xmss_siglen.sh XMSS-SHA2_16_256"
|
||||||
|
echo " ./xmss_siglen.sh XMSS-SHA2_20_256"
|
||||||
|
echo " ./xmss_siglen.sh XMSSMT-SHA2_20/2_256"
|
||||||
|
echo " ./xmss_siglen.sh XMSSMT-SHA2_20/4_256"
|
||||||
|
echo " ./xmss_siglen.sh XMSSMT-SHA2_40/2_256"
|
||||||
|
echo " ./xmss_siglen.sh XMSSMT-SHA2_40/4_256"
|
||||||
|
echo " ./xmss_siglen.sh XMSSMT-SHA2_40/8_256"
|
||||||
|
echo " ./xmss_siglen.sh XMSSMT-SHA2_60/3_256"
|
||||||
|
echo " ./xmss_siglen.sh XMSSMT-SHA2_60/6_256"
|
||||||
|
echo " ./xmss_siglen.sh XMSSMT-SHA2_60/12_256"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
print_usage_and_exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
param=$1
|
||||||
|
len=${#param}
|
||||||
|
|
||||||
|
n=32
|
||||||
|
p=67
|
||||||
|
h=0
|
||||||
|
d=1
|
||||||
|
|
||||||
|
if [[ "$len" != @("16"|"20"|"21") ]]; then
|
||||||
|
echo "error: invalid len: $len"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $len == 16 ]]; then
|
||||||
|
# Must be one of these three:
|
||||||
|
# - "XMSS-SHA2_10_256"
|
||||||
|
# - "XMSS-SHA2_16_256"
|
||||||
|
# - "XMSS-SHA2_20_256"
|
||||||
|
if [[ $param =~ "XMSS-SHA2_" && $param =~ "_256" ]]; then
|
||||||
|
h=$(echo $param | cut -c 11-12)
|
||||||
|
else
|
||||||
|
echo "error: invalid param string: $param"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# In XMSS the signature length is:
|
||||||
|
# siglen = 4 + n(p + h + 1)
|
||||||
|
siglen=$((4 + n * (p + h + 1)))
|
||||||
|
else
|
||||||
|
# Must be one of these 8:
|
||||||
|
# - "XMSSMT-SHA2_20/2_256"
|
||||||
|
# - "XMSSMT-SHA2_20/4_256"
|
||||||
|
# - "XMSSMT-SHA2_40/2_256"
|
||||||
|
# - "XMSSMT-SHA2_40/4_256"
|
||||||
|
# - "XMSSMT-SHA2_40/8_256"
|
||||||
|
# - "XMSSMT-SHA2_60/3_256"
|
||||||
|
# - "XMSSMT-SHA2_60/6_256"
|
||||||
|
# - "XMSSMT-SHA2_60/12_256"
|
||||||
|
#
|
||||||
|
if [[ $param =~ "XMSSMT-SHA2_" && $param =~ "_256" ]]; then
|
||||||
|
h=$(echo $param | cut -c 13-14)
|
||||||
|
else
|
||||||
|
echo "error: invalid param string: $param"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $len == 20 ]]; then
|
||||||
|
d=$(echo $param | cut -c 16-16)
|
||||||
|
else
|
||||||
|
d=$(echo $param | cut -c 16-17)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# In XMSS^MT the signature length is:
|
||||||
|
# siglen = Sum[h]/8 + n (Sum[p] + Sum[h] + 1)
|
||||||
|
#
|
||||||
|
# Where Sum[h] means the total height of the hyper-tree.
|
||||||
|
# Note: The Sum[h]/8 must be rounded up.
|
||||||
|
siglen=$((((h + 7) / 8) + n * ((d * p) + h + 1)))
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "parameter set: $param"
|
||||||
|
echo "signature length: $siglen"
|
Loading…
Reference in New Issue