Skip to content

Commit 47639ad

Browse files
committed
LMS wolfBoot support.
1 parent adce087 commit 47639ad

File tree

12 files changed

+590
-6
lines changed

12 files changed

+590
-6
lines changed

config/examples/sim-lms.config

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# LMS/HSS signature example, based on sim.config example.
2+
#
3+
# LMS/HSS is a post-quantum, stateful, hash-based signature scheme.
4+
#
5+
# The acceptable parameter values are those in RFC8554:
6+
# levels = {1..8}
7+
# height = {5, 10, 15, 20, 25}
8+
# winternitz = {1, 2, 4, 8}
9+
#
10+
# The number of available signatures is:
11+
# N = 2 ** (levels * height)
12+
#
13+
# LMS/HSS Signature sizes are directly proportional to the levels parm,
14+
# and inversely proportional to Winternitz. They grow only modestly with
15+
# the height.
16+
#
17+
# Key generation time is strongly determined by the height of the first
18+
# level tree.
19+
#
20+
# Use the helper script
21+
# tools/lms/lms_siglen
22+
# to calculate your signature length given the chosen levels, height,
23+
# Winternitz values.
24+
#
25+
26+
ARCH=sim
27+
TARGET=sim
28+
SIGN?=LMS
29+
HASH?=SHA256
30+
LMS_LEVELS=2
31+
LMS_HEIGHT=5
32+
LMS_WINTERNITZ=8
33+
WOLFBOOT_SMALL_STACK=0
34+
SPI_FLASH=0
35+
DEBUG=0
36+
DELTA_UPDATES=0
37+
IMAGE_SIGNATURE_SIZE=2644
38+
IMAGE_HEADER_SIZE?=5288
39+
40+
# it should be multiple of system page size
41+
WOLFBOOT_PARTITION_SIZE=0x40000
42+
WOLFBOOT_SECTOR_SIZE=0x1000
43+
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x20000
44+
45+
# if on external flash, it should be multiple of system page size
46+
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x60000
47+
WOLFBOOT_PARTITION_SWAP_ADDRESS=0xA0000
48+
49+
# required for keytools
50+
WOLFBOOT_FIXED_PARTITIONS=1

include/loader.h

+6
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ 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+
#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. */
68+
extern const unsigned char lms_pub_key[];
69+
extern unsigned int lms_pub_key_len;
6470
#elif !defined(WOLFBOOT_NO_SIGN)
6571
# error "No public key available for given signing algorithm."
6672
#endif /* Algorithm selection */

include/wolfboot/wolfboot.h

+6
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ extern "C" {
8080
#define AUTH_KEY_ECC384 0x06
8181
#define AUTH_KEY_ECC521 0x07
8282
#define AUTH_KEY_RSA3072 0x08
83+
#define AUTH_KEY_LMS 0x09
8384

8485

8586

@@ -99,6 +100,7 @@ extern "C" {
99100
#define HDR_IMG_TYPE_AUTH_ECC384 (AUTH_KEY_ECC384 << 8)
100101
#define HDR_IMG_TYPE_AUTH_ECC521 (AUTH_KEY_ECC521 << 8)
101102
#define HDR_IMG_TYPE_AUTH_RSA3072 (AUTH_KEY_RSA3072 << 8)
103+
#define HDR_IMG_TYPE_AUTH_LMS (AUTH_KEY_LMS << 8)
102104

103105
#define HDR_IMG_TYPE_DIFF 0x00D0
104106

@@ -115,6 +117,7 @@ extern "C" {
115117
#define KEYSTORE_PUBKEY_SIZE_RSA2048 320
116118
#define KEYSTORE_PUBKEY_SIZE_RSA3072 448
117119
#define KEYSTORE_PUBKEY_SIZE_RSA4096 576
120+
#define KEYSTORE_PUBKEY_SIZE_LMS 60
118121

119122
/* Mask for key permissions */
120123
#define KEY_VERIFY_ALL (0xFFFFFFFFU)
@@ -194,6 +197,9 @@ extern "C" {
194197
#elif defined(WOLFBOOT_SIGN_RSA4096)
195198
# define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_RSA4096
196199
# define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_RSA4096
200+
#elif defined(WOLFBOOT_SIGN_LMS)
201+
# define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_LMS
202+
# define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_LMS
197203
#else
198204
# error "No valid authentication mechanism selected. " \
199205
"Please select a valid SIGN= option."

options.mk

+47
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,53 @@ ifeq ($(SIGN),RSA4096)
286286
endif
287287
endif
288288

289+
ifeq ($(SIGN),LMS)
290+
# In LMS the signature size is a function of the LMS parameters.
291+
# All five of these parms must be set in the LMS .config file:
292+
# LMS_LEVELS, LMS_HEIGHT, LMS_WINTERNITZ, IMAGE_SIGNATURE_SIZE,
293+
# IMAGE_HEADER_SIZE
294+
295+
ifndef LMS_LEVELS
296+
$(error LMS_LEVELS not set)
297+
endif
298+
299+
ifndef LMS_HEIGHT
300+
$(error LMS_HEIGHT not set)
301+
endif
302+
303+
ifndef LMS_WINTERNITZ
304+
$(error LMS_WINTERNITZ not set)
305+
endif
306+
307+
ifndef IMAGE_SIGNATURE_SIZE
308+
$(error IMAGE_SIGNATURE_SIZE not set)
309+
endif
310+
311+
ifndef IMAGE_HEADER_SIZE
312+
$(error IMAGE_HEADER_SIZE not set)
313+
endif
314+
315+
LMSDIR = lib/hash-sigs
316+
KEYGEN_OPTIONS+=--lms
317+
SIGN_OPTIONS+=--lms
318+
WOLFCRYPT_OBJS+= \
319+
./lib/wolfssl/wolfcrypt/src/ext_lms.o \
320+
./lib/wolfssl/wolfcrypt/src/hash.o \
321+
./lib/wolfssl/wolfcrypt/src/memory.o \
322+
./lib/wolfssl/wolfcrypt/src/wc_port.o
323+
CFLAGS+=-D"WOLFBOOT_SIGN_LMS" -D"WOLFSSL_HAVE_LMS" -D"HAVE_LIBLMS" \
324+
-D"LMS_LEVELS=$(LMS_LEVELS)" -D"LMS_HEIGHT=$(LMS_HEIGHT)" \
325+
-D"LMS_WINTERNITZ=$(LMS_WINTERNITZ)" -I"$(LMSDIR)" \
326+
-D"IMAGE_SIGNATURE_SIZE"=$(IMAGE_SIGNATURE_SIZE) \
327+
-D"PRINTF_ENABLED"
328+
LD_END_GROUP+=-L./$(LMSDIR) -l:hss_lib.a
329+
ifeq ($(WOLFBOOT_SMALL_STACK),1)
330+
$(error WOLFBOOT_SMALL_STACK with LMS not supported)
331+
else
332+
STACK_USAGE=18064
333+
endif
334+
endif
335+
289336

290337
ifeq ($(USE_GCC_HEADLESS),1)
291338
CFLAGS+="-Wstack-usage=$(STACK_USAGE)"

src/image.c

+74
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,80 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
372372
#endif /* WOLFBOOT_SIGN_RSA2048 || WOLFBOOT_SIGN_3072 || \
373373
* WOLFBOOT_SIGN_RSA4096 */
374374

375+
#ifdef WOLFBOOT_SIGN_LMS
376+
#include <wolfssl/wolfcrypt/lms.h>
377+
#ifdef HAVE_LIBLMS
378+
#include <wolfssl/wolfcrypt/ext_lms.h>
379+
#endif
380+
381+
static void wolfBoot_verify_signature(uint8_t key_slot,
382+
struct wolfBoot_image *img, uint8_t *sig)
383+
{
384+
int ret = 0;
385+
LmsKey lms;
386+
word32 pub_len = 0;
387+
uint8_t * pubkey = NULL;
388+
389+
wolfBoot_printf("info: LMS wolfBoot_verify_signature\n");
390+
391+
pubkey = keystore_get_buffer(key_slot);
392+
if (pubkey == NULL) {
393+
wolfBoot_printf("error: Lms pubkey not found\n");
394+
return;
395+
}
396+
397+
ret = wc_LmsKey_Init(&lms, NULL, INVALID_DEVID);
398+
if (ret != 0) {
399+
wolfBoot_printf("error: wc_LmsKey_Init returned %d\n", ret);
400+
return;
401+
}
402+
403+
/* Set the LMS parameters. */
404+
ret = wc_LmsKey_SetParameters(&lms, LMS_LEVELS, LMS_HEIGHT,
405+
LMS_WINTERNITZ);
406+
if (ret != 0) {
407+
/* Something is wrong with the pub key or LMS parameters. */
408+
wolfBoot_printf("error: wc_LmsKey_SetParameters(%d, %d, %d)" \
409+
" returned %d\n", LMS_LEVELS, LMS_HEIGHT,
410+
LMS_WINTERNITZ, ret);
411+
return;
412+
}
413+
414+
wolfBoot_printf("info: using LMS parameters: L%d-H%d-W%d\n", LMS_LEVELS,
415+
LMS_HEIGHT, LMS_WINTERNITZ);
416+
417+
/* Set the public key. */
418+
XMEMCPY(lms.pub, pubkey, KEYSTORE_PUBKEY_SIZE);
419+
420+
ret = wc_LmsKey_GetPubLen(&lms, &pub_len);
421+
422+
if (ret != 0) {
423+
/* Something is wrong with the pub key or LMS parameters. */
424+
wolfBoot_printf("error: wc_LmsKey_GetPubLen %d\n", ret);
425+
return;
426+
}
427+
428+
if (pub_len != KEYSTORE_PUBKEY_SIZE) {
429+
/* Something is wrong with the pub key or LMS parameters. */
430+
wolfBoot_printf("error: wc_LmsKey_GetPubLen mismatch: "\
431+
" got %d, expected %d\n", pub_len,
432+
KEYSTORE_PUBKEY_SIZE);
433+
return;
434+
}
435+
436+
ret = wc_LmsKey_Verify(&lms, sig, IMAGE_SIGNATURE_SIZE, img->sha_hash,
437+
WOLFBOOT_SHA_DIGEST_SIZE);
438+
439+
if (ret == 0) {
440+
wolfBoot_printf("info: wc_LmsKey_Verify returned OK\n");
441+
wolfBoot_image_confirm_signature_ok(img);
442+
}
443+
else {
444+
wolfBoot_printf("error: wc_LmsKey_Verify returned %d\n", ret);
445+
}
446+
}
447+
#endif /* WOLFBOOT_SIGN_LMS */
448+
375449

376450
static uint16_t get_header_ext(struct wolfBoot_image *img, uint16_t type,
377451
uint8_t **ptr);

tools/config.mk

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ ifeq ($(ARCH),)
3030
DISABLE_BACKUP?=0
3131
WOLFBOOT_VERSION?=0
3232
V?=0
33+
LMS_LEVELS?=0
34+
LMS_HEIGHT?=0
35+
LMS_WINTERNITZ?=0
3336
NO_MPU?=0
3437
ENCRYPT?=0
3538
ENCRYPT_WITH_CHACHA?=0

tools/keytools/Makefile

+10-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ CFLAGS += -I. -DWOLFSSL_USER_SETTINGS -I$(WOLFDIR) -I$(WOLFBOOTDIR)/include -DW
1616
LDFLAGS =
1717
OBJDIR = ./
1818

19+
ifeq ($(SIGN),LMS)
20+
LMSDIR = $(WOLFBOOTDIR)/lib/hash-sigs/
21+
LDFLAGS+=-L$(LMSDIR) -l:hss_lib.a
22+
CFLAGS +=-DWOLFBOOT_SIGN_LMS -DWOLFSSL_HAVE_LMS -DHAVE_LIBLMS -I$(LMSDIR) \
23+
-D"LMS_LEVELS=$(LMS_LEVELS)" -D"LMS_HEIGHT=$(LMS_HEIGHT)" \
24+
-D"LMS_WINTERNITZ=$(LMS_WINTERNITZ)"
25+
endif
26+
1927
# option variables
2028
DEBUG_FLAGS = -g -DDEBUG -DDEBUG_SIGNTOOL -DDEBUG_WOLFSSL -DDEBUG_WOLFSSL_VERBOSE -fsanitize=address
2129
OPTIMIZE = -O2
@@ -63,7 +71,8 @@ OBJS_REAL=\
6371
$(WOLFDIR)/wolfcrypt/src/sha512.o \
6472
$(WOLFDIR)/wolfcrypt/src/tfm.o \
6573
$(WOLFDIR)/wolfcrypt/src/wc_port.o \
66-
$(WOLFDIR)/wolfcrypt/src/wolfmath.o
74+
$(WOLFDIR)/wolfcrypt/src/wolfmath.o \
75+
$(WOLFDIR)/wolfcrypt/src/ext_lms.o
6776

6877
OBJS_REAL+=\
6978
$(WOLFBOOTDIR)/src/delta.o

0 commit comments

Comments
 (0)