From c847529698e94ddfe26e417fcabeab14fcae3f22 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Tue, 7 Jan 2020 11:32:09 +0100 Subject: [PATCH] Added RSA-4096 bit support --- .gitignore | 1 + Makefile | 27 +++++++++++++++++++++++++ arch.mk | 2 +- include/loader.h | 6 ++++++ include/user_settings.h | 11 ++++++++++ include/wolfboot/wolfboot.h | 3 +++ src/image.c | 12 ++++++++--- test-app/Makefile | 4 ++++ tools/keytools/keygen.py | 40 +++++++++++++++++++++++++++++++------ tools/keytools/sign.py | 22 ++++++++++++++++---- 10 files changed, 114 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 8974b214..2aaee003 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,7 @@ src/ed25519_pub_key.c src/ecc256_pub_key.c src/rsa2048_pub_key.c +src/rsa4096_pub_key.c # keygen binaries tools/ed25519/ed25519_sign diff --git a/Makefile b/Makefile index bb3a78eb..a110752b 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,9 @@ OBJS:= \ WOLFCRYPT_OBJS:= PUBLIC_KEY_OBJS:= +ifeq ($(SIGN),RSA4096) + SPMATH=0 +endif ## Architecture/CPU configuration include arch.mk @@ -77,6 +80,25 @@ ifeq ($(SIGN),RSA2048) -Wstack-usage=12288 -DIMAGE_HEADER_SIZE=512 endif +ifeq ($(SIGN),RSA4096) + KEYGEN_OPTIONS=--rsa4096 + SIGN_OPTIONS=--rsa4096 + PRIVATE_KEY=rsa4096.der + IMAGE_HEADER_SIZE=1024 + WOLFCRYPT_OBJS+= \ + $(RSA_EXTRA_OBJS) \ + $(MATH_OBJS) \ + ./lib/wolfssl/wolfcrypt/src/rsa.o \ + ./lib/wolfssl/wolfcrypt/src/sha256.o \ + ./lib/wolfssl/wolfcrypt/src/asn.o \ + ./lib/wolfssl/wolfcrypt/src/hash.o \ + ./lib/wolfssl/wolfcrypt/src/wolfmath.o \ + ./src/xmalloc_rsa.o + PUBLIC_KEY_OBJS=./src/rsa4096_pub_key.o + CFLAGS+=-DWOLFBOOT_SIGN_RSA4096 -DXMALLOC_USER $(RSA_EXTRA_CFLAGS) \ + -Wstack-usage=12288 -DIMAGE_HEADER_SIZE=1024 +endif + CFLAGS+=-Wall -Wextra -Wno-main -ffreestanding -Wno-unused \ -I. -Iinclude/ -Ilib/wolfssl -nostartfiles \ @@ -201,6 +223,9 @@ ecc256.der: rsa2048.der: @python3 tools/keytools/keygen.py $(KEYGEN_OPTIONS) src/rsa2048_pub_key.c +rsa4096.der: + @python3 tools/keytools/keygen.py $(KEYGEN_OPTIONS) src/rsa4096_pub_key.c + factory.bin: $(BOOT_IMG) wolfboot-align.bin $(PRIVATE_KEY) @echo "\t[SIGN] $(BOOT_IMG)" $(Q)python3 tools/keytools/sign.py $(SIGN_OPTIONS) $(BOOT_IMG) $(PRIVATE_KEY) 1 @@ -222,6 +247,8 @@ src/ecc256_pub_key.c: ecc256.der src/rsa2048_pub_key.c: rsa2048.der +src/rsa4096_pub_key.c: rsa4096.der + keys: $(PRIVATE_KEY) clean: diff --git a/arch.mk b/arch.mk index 6568927d..beb5132c 100644 --- a/arch.mk +++ b/arch.mk @@ -4,7 +4,7 @@ ifeq ($(SPMATH),1) MATH_OBJS:=./lib/wolfssl/wolfcrypt/src/sp_int.o else - MATH_OBJS:=./lib/wolfssl/wolfcrypt/src/integer.o + MATH_OBJS:=./lib/wolfssl/wolfcrypt/src/integer.o ./lib/wolfssl/wolfcrypt/src/tfm.o endif # Default flash offset diff --git a/include/loader.h b/include/loader.h index 56e4da94..e6e0ca50 100644 --- a/include/loader.h +++ b/include/loader.h @@ -43,6 +43,12 @@ # define KEY_BUFFER rsa2048_pub_key # define KEY_LEN rsa2048_pub_key_len # define IMAGE_SIGNATURE_SIZE (256) +#elif defined(WOLFBOOT_SIGN_RSA4096) + extern const unsigned char rsa4096_pub_key[]; + extern unsigned int rsa4096_pub_key_len; +# define KEY_BUFFER rsa4096_pub_key +# define KEY_LEN rsa4096_pub_key_len +# define IMAGE_SIGNATURE_SIZE (512) #else # error "No public key available for given signing algorithm." #endif /* Algorithm selection */ diff --git a/include/user_settings.h b/include/user_settings.h index aed0f429..fdb0e6c8 100644 --- a/include/user_settings.h +++ b/include/user_settings.h @@ -34,6 +34,7 @@ //#define TFM_TIMING_RESISTANT #define SIZEOF_LONG_LONG 8 + /* ED25519 and SHA512 */ #ifdef WOLFBOOT_SIGN_ED25519 # define HAVE_ED25519 @@ -97,6 +98,16 @@ # define WOLFSSL_SP_NO_3072 #endif +#ifdef WOLFBOOT_SIGN_RSA4096 +# define HAVE_RSA +# define RSA_LOW_MEM +# define WOLFSSL_RSA_VERIFY_INLINE +# define FP_MAX_BITS (4096 * 2) +# define WC_RSA_BLINDING +# define USE_FAST_MATH +# define TFM_TIMING_RESISTANT +#endif + /* Disables - For minimum wolfCrypt build */ #define NO_AES #define NO_CMAC diff --git a/include/wolfboot/wolfboot.h b/include/wolfboot/wolfboot.h index 173e8980..f83c444c 100644 --- a/include/wolfboot/wolfboot.h +++ b/include/wolfboot/wolfboot.h @@ -49,6 +49,7 @@ #define HDR_IMG_TYPE_AUTH_ED25519 0x0100 #define HDR_IMG_TYPE_AUTH_ECC256 0x0200 #define HDR_IMG_TYPE_AUTH_RSA2048 0x0300 +#define HDR_IMG_TYPE_AUTH_RSA4096 0x0400 #define HDR_IMG_TYPE_WOLFBOOT 0x0000 #define HDR_IMG_TYPE_APP 0x0001 @@ -60,6 +61,8 @@ # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_ECC256 #elif defined(WOLFBOOT_SIGN_RSA2048) # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_RSA2048 + #elif defined(WOLFBOOT_SIGN_RSA4096) + # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_RSA4096 #else # error "no valid authentication mechanism selected. Please define WOLFBOOT_SIGN_ED25519 or WOLFBOOT_SIGN_ECC256 or WOLFBOOT_SIGN_RSA2048" #endif /* defined WOLFBOOT_SIGN_ECC256 || WOLFBOOT_SIGN_ED25519 */ diff --git a/src/image.c b/src/image.c index 5940275e..4a37d121 100644 --- a/src/image.c +++ b/src/image.c @@ -90,11 +90,17 @@ static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig) } #endif /* WOLFBOOT_SIGN_ECC256 */ -#ifdef WOLFBOOT_SIGN_RSA2048 +#if defined(WOLFBOOT_SIGN_RSA2048) || defined (WOLFBOOT_SIGN_RSA4096) #include #include -#define RSA_MAX_KEY_SIZE 256 -#define RSA_SIG_SIZE 256 + +#ifdef WOLFBOOT_SIGN_RSA4096 +# define RSA_MAX_KEY_SIZE 512 +# define RSA_SIG_SIZE 512 +#else +# define RSA_MAX_KEY_SIZE 256 +# define RSA_SIG_SIZE 256 +#endif static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig) { diff --git a/test-app/Makefile b/test-app/Makefile index da9c7b74..c91655d2 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -8,6 +8,10 @@ ifeq ($(SIGN),RSA2048) IMAGE_HEADER_SIZE:=512 endif +ifeq ($(SIGN),RSA4096) + IMAGE_HEADER_SIZE:=1024 +endif + CFLAGS:=-g -ggdb -Wall -Wstack-usage=1024 -ffreestanding -Wno-unused -DPLATFORM_$(TARGET) -I../include -nostartfiles APP_OBJS:=app_$(TARGET).o led.o system.o timer.o ../hal/$(TARGET).o ../src/libwolfboot.o diff --git a/tools/keytools/keygen.py b/tools/keytools/keygen.py index e33234f4..63199e14 100755 --- a/tools/keytools/keygen.py +++ b/tools/keytools/keygen.py @@ -33,7 +33,8 @@ Cfile_Banner="/* Public-key file for wolfBoot, automatically generated. Do not e Ed25519_pub_key_define = "const uint8_t ed25519_pub_key[32] = {\n\t" Ecc256_pub_key_define = "const uint8_t ecc256_pub_key[64] = {\n\t" -Rsa_pub_key_define = "const uint8_t rsa2048_pub_key[%d] = {\n\t" +Rsa_2048_pub_key_define = "const uint8_t rsa2048_pub_key[%d] = {\n\t" +Rsa_4096_pub_key_define = "const uint8_t rsa4096_pub_key[%d] = {\n\t" sign="ed25519" @@ -41,12 +42,12 @@ argc = len(sys.argv) argv = sys.argv if (argc < 2) or (argc > 3): - print("Usage: %s [--ed25519 | --ecc256 | --rsa2048 ] pub_key_file.c\n" % sys.argv[0]) + print("Usage: %s [--ed25519 | --ecc256 | --rsa2048 | --rsa4096 ] pub_key_file.c\n" % sys.argv[0]) sys.exit(1) if argc == 3: - if argv[1] != '--ed25519' and argv[1] != '--ecc256' and argv[1] != '--rsa2048': - print("Usage: %s [--ed25519 | --ecc256 | --rsa2048] pub_key_file.c\n" % sys.argv[0]) + if argv[1] != '--ed25519' and argv[1] != '--ecc256' and argv[1] != '--rsa2048' and argv[1] != '--rsa4096': + print("Usage: %s [--ed25519 | --ecc256 | --rsa2048 | --rsa4096] pub_key_file.c\n" % sys.argv[0]) sys.exit(1) sign=argv[1][2:] pubkey_cfile = argv[2] @@ -130,7 +131,6 @@ if (sign == "ecc256"): f.write("const uint32_t ecc256_pub_key_len = 64;\n") f.close() - if (sign == "rsa2048"): rsa = ciphers.RsaPrivate.make_key(2048) if os.path.exists(key_file): @@ -148,7 +148,7 @@ if (sign == "rsa2048"): print("Creating file " + pubkey_cfile) with open(pubkey_cfile, "w") as f: f.write(Cfile_Banner) - f.write(Rsa_pub_key_define % len(pub)) + f.write(Rsa_2048_pub_key_define % len(pub)) i = 0 for c in bytes(pub): f.write("0x%02X, " % c) @@ -158,3 +158,31 @@ if (sign == "rsa2048"): f.write("\n};\n") f.write("const uint32_t rsa2048_pub_key_len = %d;\n" % len(pub)) f.close() + +if (sign == "rsa4096"): + rsa = ciphers.RsaPrivate.make_key(4096) + if os.path.exists(key_file): + choice = input("** Warning: key file already exist! Are you sure you want to "+ + "generate a new key and overwrite the existing key? [Type 'Yes, I am sure!']: ") + if (choice != "Yes, I am sure!"): + print("Operation canceled.") + sys.exit(2) + priv,pub = rsa.encode_key() + print() + print("Creating file " + key_file) + with open(key_file, "wb") as f: + f.write(priv) + f.close() + print("Creating file " + pubkey_cfile) + with open(pubkey_cfile, "w") as f: + f.write(Cfile_Banner) + f.write(Rsa_4096_pub_key_define % len(pub)) + i = 0 + for c in bytes(pub): + f.write("0x%02X, " % c) + i += 1 + if (i % 8 == 0): + f.write('\n') + f.write("\n};\n") + f.write("const uint32_t rsa4096_pub_key_len = %d;\n" % len(pub)) + f.close() diff --git a/tools/keytools/sign.py b/tools/keytools/sign.py index 41ea1c8a..d599692e 100755 --- a/tools/keytools/sign.py +++ b/tools/keytools/sign.py @@ -46,6 +46,7 @@ HDR_SIGNATURE_LEN = 64 HDR_IMG_TYPE_AUTH_ED25519 = 0x0100 HDR_IMG_TYPE_AUTH_ECC256 = 0x0200 HDR_IMG_TYPE_AUTH_RSA2048 = 0x0300 +HDR_IMG_TYPE_AUTH_RSA4096 = 0x0400 HDR_IMG_TYPE_WOLFBOOT = 0x0000 HDR_IMG_TYPE_APP = 0x0001 @@ -59,7 +60,7 @@ argc = len(sys.argv) argv = sys.argv if (argc < 4) or (argc > 6): - print("Usage: %s [--ed25519 | --ecc256 | --rsa2048 ] [--wolfboot-update] image key.der fw_version\n" % sys.argv[0]) + print("Usage: %s [--ed25519 | --ecc256 | --rsa2048 | --rsa4096 ] [--wolfboot-update] image key.der fw_version\n" % sys.argv[0]) sys.exit(1) for i in range(1, len(argv)): if (argv[i] == '--ed25519'): @@ -68,6 +69,8 @@ for i in range(1, len(argv)): sign='ecc256' elif (argv[i] == '--rsa2048'): sign='rsa2048' + elif (argv[i] == '--rsa4096'): + sign='rsa4096' elif (argv[i] == '--wolfboot-update'): self_update = True else: @@ -114,6 +117,9 @@ elif wolfboot_private_key_len == 96: if sign == 'auto': sign = 'ecc256' print("'ecc256' key autodetected.") +elif (wolfboot_private_key_len > 512): + if (sign == 'auto'): + print("'rsa4096' key autodetected.") elif (wolfboot_private_key_len > 128): if (sign == 'auto'): print("'rsa2048' key autodetected.") @@ -134,16 +140,22 @@ if sign == 'ecc256': pubkey = wolfboot_private_key[0:64] if sign == 'rsa2048': - WOLFBOOT_HEADER_SIZE = 512 + WOLFBOOT_HEADER_SIZE = 512 HDR_SIGNATURE_LEN = 256 rsa = ciphers.RsaPrivate(wolfboot_private_key) privkey,pubkey = rsa.encode_key() +if sign == 'rsa4096': + WOLFBOOT_HEADER_SIZE = 1024 + HDR_SIGNATURE_LEN = 512 + rsa = ciphers.RsaPrivate(wolfboot_private_key) + privkey,pubkey = rsa.encode_key() + img_size = os.path.getsize(image_file) # Magic header (spells 'WOLF') header = struct.pack('