diff --git a/.github/workflows/test-renode-nrf52.yml b/.github/workflows/test-renode-nrf52.yml index 6f50f4f9..09b2ce0c 100644 --- a/.github/workflows/test-renode-nrf52.yml +++ b/.github/workflows/test-renode-nrf52.yml @@ -30,18 +30,26 @@ jobs: run: | make -C tools/test-expect-version - # ECC256 TEST - name: make clean run: | make clean && make -C tools/keytools clean && rm -f include/target.h - name: Select config run: | - cp config/examples/nrf52840.config .config && make include/target.h SIGN=ECC256 + cp config/examples/nrf52840.config .config && make include/target.h - name: Build key tools run: | - make -C tools/keytools SIGN=ECC256 + make -C tools/keytools + + # ECC256 TEST + - name: make clean + run: | + make clean && rm -f include/target.h + + - name: Select config + run: | + cp config/examples/nrf52840.config .config && make include/target.h SIGN=ECC256 - name: Build wolfboot and test app image v1, SIGN=ECC256 run: | @@ -54,19 +62,35 @@ jobs: - name: Renode Tests ECC256 run: ./tools/renode/docker-test.sh +# ECC384 TEST + - name: make clean + run: | + make clean && rm -f include/target.h + + - name: Select config + run: | + cp config/examples/nrf52840.config .config && make include/target.h SIGN=ECC384 + + - name: Build wolfboot and test app image v1, SIGN=ECC384 + run: | + make SIGN=ECC384 + + - name: Build update image v2 + run: | + make /tmp/renode-test-update.bin SIGN=ECC384 && cp /tmp/renode-test-update.bin test-app/ + + - name: Renode Tests ECC384 + run: ./tools/renode/docker-test.sh + # ED25519 TEST - name: make clean run: | - make clean && make -C tools/keytools clean && rm -f include/target.h + make clean && rm -f include/target.h - name: Select config run: | cp config/examples/nrf52840.config .config && make include/target.h SIGN=ED25519 - - name: Build key tools - run: | - make -C tools/keytools SIGN=ED25519 - - name: Build wolfboot and test app image v1, SIGN=ED25519 run: | make SIGN=ED25519 @@ -81,16 +105,12 @@ jobs: # ED448 TEST - name: make clean run: | - make clean && make -C tools/keytools clean && rm -f include/target.h + make clean && rm -f include/target.h - name: Select config run: | cp config/examples/nrf52840.config .config && make include/target.h SIGN=ED448 - - name: Build key tools - run: | - make -C tools/keytools SIGN=ED448 - - name: Build wolfboot and test app image v1, SIGN=ED448 run: | make SIGN=ED448 @@ -105,16 +125,12 @@ jobs: # RSA2048 TEST - name: make clean run: | - make clean && make -C tools/keytools clean && rm -f include/target.h + make clean && rm -f include/target.h - name: Select config run: | cp config/examples/nrf52840.config .config && make include/target.h SIGN=RSA2048 - - name: Build key tools - run: | - make -C tools/keytools SIGN=RSA2048 - - name: Build wolfboot and test app image v1, SIGN=RSA2048 run: | make SIGN=RSA2048 @@ -129,16 +145,12 @@ jobs: # RSA4096 TEST - name: make clean run: | - make clean && make -C tools/keytools clean && rm -f include/target.h + make clean && rm -f include/target.h - name: Select config run: | cp config/examples/nrf52840.config .config && make include/target.h SIGN=RSA4096 - - name: Build key tools - run: | - make -C tools/keytools SIGN=RSA4096 - - name: Build wolfboot and test app image v1, SIGN=RSA4096 run: | make SIGN=RSA4096 @@ -150,8 +162,6 @@ jobs: - name: Renode Tests RSA4096 run: ./tools/renode/docker-test.sh - - - name: Upload Output Dir uses: actions/upload-artifact@v2 with: diff --git a/.gitignore b/.gitignore index 259d2ffb..2e3f17d1 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,8 @@ src/ed25519_pub_key.c src/ed448_pub_key.c src/ecc256_pub_key.c +src/ecc384_pub_key.c +src/ecc512_pub_key.c src/rsa2048_pub_key.c src/rsa4096_pub_key.c diff --git a/Makefile b/Makefile index 4a696305..891fe0a4 100644 --- a/Makefile +++ b/Makefile @@ -112,6 +112,10 @@ ed448.der: $(Q)$(KEYGEN_TOOL) $(KEYGEN_OPTIONS) src/ed448_pub_key.c ecc256.der: $(Q)$(KEYGEN_TOOL) $(KEYGEN_OPTIONS) src/ecc256_pub_key.c +ecc384.der: + $(Q)$(KEYGEN_TOOL) $(KEYGEN_OPTIONS) src/ecc384_pub_key.c +ecc521.der: + $(Q)$(KEYGEN_TOOL) $(KEYGEN_OPTIONS) src/ecc521_pub_key.c rsa2048.der: $(Q)$(KEYGEN_TOOL) $(KEYGEN_OPTIONS) src/rsa2048_pub_key.c rsa4096.der: @@ -153,6 +157,10 @@ src/ed448_pub_key.c: ed448.der src/ecc256_pub_key.c: ecc256.der +src/ecc384_pub_key.c: ecc384.der + +src/ecc521_pub_key.c: ecc521.der + src/rsa2048_pub_key.c: rsa2048.der src/rsa4096_pub_key.c: rsa4096.der diff --git a/include/loader.h b/include/loader.h index 7efac269..090c564c 100644 --- a/include/loader.h +++ b/include/loader.h @@ -43,6 +43,18 @@ # define KEY_BUFFER ecc256_pub_key # define KEY_LEN ecc256_pub_key_len # define IMAGE_SIGNATURE_SIZE (64) +#elif defined(WOLFBOOT_SIGN_ECC384) + extern const unsigned char ecc384_pub_key[]; + extern unsigned int ecc384_pub_key_len; +# define KEY_BUFFER ecc384_pub_key +# define KEY_LEN ecc384_pub_key_len +# define IMAGE_SIGNATURE_SIZE (96) +#elif defined(WOLFBOOT_SIGN_ECC521) + extern const unsigned char ecc521_pub_key[]; + extern unsigned int ecc521_pub_key_len; +# define KEY_BUFFER ecc521_pub_key +# define KEY_LEN ecc521_pub_key_len +# define IMAGE_SIGNATURE_SIZE (132) #elif defined(WOLFBOOT_SIGN_RSA2048) extern const unsigned char rsa2048_pub_key[]; extern unsigned int rsa2048_pub_key_len; diff --git a/include/user_settings.h b/include/user_settings.h index 6673250d..f7e86717 100644 --- a/include/user_settings.h +++ b/include/user_settings.h @@ -64,10 +64,13 @@ #endif /* ECC and SHA256 */ -#ifdef WOLFBOOT_SIGN_ECC256 +#if defined (WOLFBOOT_SIGN_ECC256) ||\ + defined (WOLFBOOT_SIGN_ECC384) ||\ + defined (WOLFBOOT_SIGN_ECC521) # define HAVE_ECC # define ECC_TIMING_RESISTANT -# define FP_MAX_BITS (256 + 32) + + /* Kinetis LTC support */ # ifdef FREESCALE_USE_LTC @@ -96,8 +99,25 @@ /* Curve */ # define NO_ECC192 # define NO_ECC224 +#ifdef WOLFBOOT_SIGN_ECC256 # define HAVE_ECC256 +# define FP_MAX_BITS (256 + 32) # define NO_ECC384 +# define NO_ECC521 +#elif defined WOLFBOOT_SIGN_ECC384 +# define HAVE_ECC384 +# define FP_MAX_BITS (1024 + 32) +# define WOLFSSL_SP_384 +# define WOLFSSL_SP_NO_256 +# define NO_ECC256 +# define NO_ECC521 +#elif defined WOLFBOOT_SIGN_ECC521 +# define HAVE_ECC521 +# define FP_MAX_BITS (544 + 32) +# define NO_ECC256 +# define NO_ECC384 +#endif + # define NO_RSA # define NO_ASN #endif diff --git a/include/wolfboot/wolfboot.h b/include/wolfboot/wolfboot.h index 5f7f487d..8eb0ef1d 100644 --- a/include/wolfboot/wolfboot.h +++ b/include/wolfboot/wolfboot.h @@ -71,6 +71,8 @@ #define HDR_IMG_TYPE_AUTH_RSA2048 0x0300 #define HDR_IMG_TYPE_AUTH_RSA4096 0x0400 #define HDR_IMG_TYPE_AUTH_ED448 0x0500 +#define HDR_IMG_TYPE_AUTH_ECC384 0x0600 +#define HDR_IMG_TYPE_AUTH_ECC521 0x0700 #define HDR_IMG_TYPE_WOLFBOOT 0x0000 #define HDR_IMG_TYPE_APP 0x0001 #define HDR_IMG_TYPE_DIFF 0x00D0 @@ -85,12 +87,17 @@ # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_ED448 #elif defined(WOLFBOOT_SIGN_ECC256) # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_ECC256 + #elif defined(WOLFBOOT_SIGN_ECC384) + # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_ECC384 + #elif defined(WOLFBOOT_SIGN_ECC521) + # define HDR_IMG_TYPE_AUTH HDR_IMG_TYPE_AUTH_ECC521 + # error "ECC521 curves not yet supported in this version of wolfBoot. Please select a valid SIGN= option." #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" + # error "no valid authentication mechanism selected. Please select a valid SIGN= option." #endif /* defined WOLFBOOT_SIGN_ECC256 || WOLFBOOT_SIGN_ED25519 */ #endif /* defined WOLFBOOT */ diff --git a/options.mk b/options.mk index 8a47d888..ee953179 100644 --- a/options.mk +++ b/options.mk @@ -51,6 +51,60 @@ ifeq ($(SIGN),ECC256) endif endif +ifeq ($(SIGN),ECC384) + KEYGEN_OPTIONS+=--ecc384 + SIGN_OPTIONS+=--ecc384 + PRIVATE_KEY=ecc384.der + WOLFCRYPT_OBJS+= \ + $(MATH_OBJS) \ + ./lib/wolfssl/wolfcrypt/src/ecc.o \ + ./lib/wolfssl/wolfcrypt/src/memory.o \ + ./lib/wolfssl/wolfcrypt/src/wc_port.o \ + ./lib/wolfssl/wolfcrypt/src/wolfmath.o \ + ./lib/wolfssl/wolfcrypt/src/hash.o + CFLAGS+=-D"WOLFBOOT_SIGN_ECC384" + ifeq ($(WOLFBOOT_SMALL_STACK),1) + STACK_USAGE=5880 + else ifeq ($(WOLFTPM),1) + STACK_USAGE=6680 + else ifneq ($(SPMATH),1) + STACK_USAGE=6056 + else + STACK_USAGE=5880 + endif + PUBLIC_KEY_OBJS=./src/ecc384_pub_key.o + ifeq ($(shell test $(IMAGE_HEADER_SIZE) -lt 512; echo $$?),0) + IMAGE_HEADER_SIZE=512 + endif +endif + +ifeq ($(SIGN),ECC521) + KEYGEN_OPTIONS+=--ecc521 + SIGN_OPTIONS+=--ecc521 + PRIVATE_KEY=ecc521.der + WOLFCRYPT_OBJS+= \ + $(MATH_OBJS) \ + ./lib/wolfssl/wolfcrypt/src/ecc.o \ + ./lib/wolfssl/wolfcrypt/src/memory.o \ + ./lib/wolfssl/wolfcrypt/src/wc_port.o \ + ./lib/wolfssl/wolfcrypt/src/wolfmath.o \ + ./lib/wolfssl/wolfcrypt/src/hash.o + CFLAGS+=-D"WOLFBOOT_SIGN_ECC521" + ifeq ($(WOLFBOOT_SMALL_STACK),1) + STACK_USAGE=4096 + else ifeq ($(WOLFTPM),1) + STACK_USAGE=6680 + else ifneq ($(SPMATH),1) + STACK_USAGE=7352 + else + STACK_USAGE=3896 + endif + PUBLIC_KEY_OBJS=./src/ecc521_pub_key.o + ifeq ($(shell test $(IMAGE_HEADER_SIZE) -lt 512; echo $$?),0) + IMAGE_HEADER_SIZE=512 + endif +endif + ifeq ($(SIGN),ED25519) KEYGEN_OPTIONS+=--ed25519 SIGN_OPTIONS+=--ed25519 diff --git a/src/image.c b/src/image.c index e4ea66a8..3477db88 100644 --- a/src/image.c +++ b/src/image.c @@ -82,9 +82,25 @@ static void wolfBoot_verify_signature(struct wolfBoot_image *img, uint8_t *sig) #endif -#ifdef WOLFBOOT_SIGN_ECC256 + +#if defined(WOLFBOOT_SIGN_ECC256) || defined(WOLFBOOT_SIGN_ECC384) \ + || defined(WOLFBOOT_SIGN_ECC521) + #include -#define ECC_KEY_SIZE 32 + +#ifdef WOLFBOOT_SIGN_ECC256 + #define ECC_KEY_SIZE 32 + #define ECC_KEY_TYPE ECC_SECP256R1 +#endif +#ifdef WOLFBOOT_SIGN_ECC384 + #define ECC_KEY_SIZE 48 + #define ECC_KEY_TYPE ECC_SECP384R1 +#endif +#ifdef WOLFBOOT_SIGN_ECC521 + #define ECC_KEY_SIZE 66 + #define ECC_KEY_TYPE ECC_SECP521R1 +#endif + static void wolfBoot_verify_signature(struct wolfBoot_image *img, uint8_t *sig) { int ret, verify_res = 0; @@ -131,7 +147,7 @@ static void wolfBoot_verify_signature(struct wolfBoot_image *img, uint8_t *sig) /* Import public key */ ret = wc_ecc_import_unsigned(&ecc, (byte*)KEY_BUFFER, - (byte*)(KEY_BUFFER + ECC_KEY_SIZE), NULL, ECC_SECP256R1); + (byte*)(KEY_BUFFER + ECC_KEY_SIZE), NULL, ECC_KEY_TYPE); if ((ret < 0) || ecc.type != ECC_PUBLICKEY) { /* Failed to import ecc key */ return; diff --git a/src/xmalloc.c b/src/xmalloc.c index 3f11cab3..b8d173ca 100644 --- a/src/xmalloc.c +++ b/src/xmalloc.c @@ -54,20 +54,38 @@ struct xmalloc_slot { # error "No hash mechanism selected." #endif -#ifdef WOLFBOOT_SIGN_ECC256 +#if defined(WOLFBOOT_SIGN_ECC256) || defined(WOLFBOOT_SIGN_ECC384) #ifndef USE_FAST_MATH - #define MP_CURVE_SPECS_SIZE (80) - #ifdef WOLFSSL_SP_ARM_CORTEX_M_ASM - #define MP_POINT_SIZE (196) - #define MP_DIGITS_BUFFER_SIZE_0 (MP_DIGIT_SIZE * 16 * 8) - #define MP_DIGITS_BUFFER_SIZE_1 (MP_DIGIT_SIZE * 2 * 8 * 5) - #else - #define MP_POINT_SIZE (220) - #define MP_DIGITS_BUFFER_SIZE_0 (MP_DIGIT_SIZE * 16 * 9) - #define MP_DIGITS_BUFFER_SIZE_1 (MP_DIGIT_SIZE * (4 * 9 + 3)) - #define MP_DIGITS_BUFFER_SIZE_2 (MP_DIGIT_SIZE * (2 * 9 * 5)) - #endif + /* SP MATH */ + #ifdef WOLFBOOT_SIGN_ECC256 + #define MP_CURVE_SPECS_SIZE (80) + #ifdef WOLFSSL_SP_ARM_CORTEX_M_ASM + #define MP_POINT_SIZE (196) + #define MP_DIGITS_BUFFER_SIZE_0 (MP_DIGIT_SIZE * 16 * 8) + #define MP_DIGITS_BUFFER_SIZE_1 (MP_DIGIT_SIZE * 2 * 8 * 5) + #else + #define MP_POINT_SIZE (220) + #define MP_DIGITS_BUFFER_SIZE_0 (MP_DIGIT_SIZE * 16 * 9) + #define MP_DIGITS_BUFFER_SIZE_1 (MP_DIGIT_SIZE * (4 * 9 + 3)) + #define MP_DIGITS_BUFFER_SIZE_2 (MP_DIGIT_SIZE * (2 * 9 * 5)) + #define MP_MONTGOMERY_SIZE (sizeof(int64_t) * 2 * 8) + #endif + #endif /* WOLFBOOT_SIGN_ECC256 */ + #ifdef WOLFBOOT_SIGN_ECC384 + #define MP_CURVE_SPECS_SIZE (112) + #ifdef WOLFSSL_SP_ARM_CORTEX_M_ASM + #define MP_POINT_SIZE (292) + #define MP_DIGITS_BUFFER_SIZE_0 (MP_DIGIT_SIZE * 16 * 12) + #define MP_DIGITS_BUFFER_SIZE_1 (MP_DIGIT_SIZE * 2 * 12 * 6) + #define MP_MONTGOMERY_SIZE (sizeof(int64_t) * 12) + #else + #define MP_POINT_SIZE (220) + #define MP_DIGITS_BUFFER_SIZE_0 (MP_DIGIT_SIZE * 16 * 9) + #define MP_DIGITS_BUFFER_SIZE_1 (MP_DIGIT_SIZE * (4 * 9 + 3)) + #define MP_DIGITS_BUFFER_SIZE_2 (MP_DIGIT_SIZE * (2 * 9 * 5)) + #endif + #endif /* WOLFBOOT_SIGN_ECC384 */ #ifndef WC_NO_CACHE_RESISTANT static uint8_t mp_points_3[MP_POINT_SIZE]; #endif @@ -76,17 +94,31 @@ struct xmalloc_slot { static uint8_t mp_points_2[MP_POINT_SIZE * (16 + 1)]; static uint8_t mp_digits_buffer_0[MP_DIGITS_BUFFER_SIZE_0]; static uint8_t mp_digits_buffer_1[MP_DIGITS_BUFFER_SIZE_1]; - #ifndef WOLFSSL_SP_ARM_CORTEX_M_ASM + #if !defined(WOLFSSL_SP_ARM_CORTEX_M_ASM) && defined(WOLFBOOT_SIGN_ECC256) static uint8_t mp_digits_buffer_2[MP_DIGITS_BUFFER_SIZE_2]; - static uint8_t mp_montgomery[sizeof(int64_t) * 2 * 8]; + static uint8_t mp_montgomery[MP_MONTGOMERY_SIZE]; + #elif defined(WOLFBOOT_SIGN_ECC384) + static uint8_t mp_montgomery[MP_MONTGOMERY_SIZE]; #endif #else + /* TFM */ #define MP_INT_SIZE ((sizeof (fp_int))) - #define MP_CURVE_SPECS_SIZE (MP_INT_SIZE) - #define MP_CURVE_FIELD_COUNT_SIZE (380) - #define ECC_POINT_SIZE (228) - #define MP_INT_BUFFER_SIZE (MP_INT_SIZE * 6) - #define MP_DIGIT_BUFFER_MONT_SIZE (sizeof(fp_digit)*(FP_SIZE + 1)) + #ifdef WOLFBOOT_SIGN_ECC256 + #define MP_CURVE_SPECS_SIZE (MP_INT_SIZE) + #define MP_CURVE_FIELD_COUNT_SIZE (380) + #define ECC_POINT_SIZE (228) + #define MP_INT_BUFFER_SIZE (MP_INT_SIZE * 6) + #define MP_DIGIT_BUFFER_MONT_SIZE (sizeof(fp_digit)*(FP_SIZE + 1)) + #endif + #ifdef WOLFBOOT_SIGN_ECC384 + #define MP_CURVE_SPECS_SIZE (MP_INT_SIZE) + #define MP_CURVE_FIELD_COUNT_SIZE (380) + #define ECC_POINT_SIZE (516) + #define MP_INT_BUFFER_SIZE (MP_INT_SIZE * 5) + #define MP_INT_BUFFER_SIZE_1 (MP_INT_SIZE * 6) + #define MP_DIGIT_BUFFER_MONT_SIZE (sizeof(fp_digit)*(FP_SIZE + 1)) + #endif + static uint8_t mp_curve_field_count[MP_CURVE_FIELD_COUNT_SIZE]; static uint8_t mp_int_v[MP_INT_SIZE]; static uint8_t mp_int_w[MP_INT_SIZE]; @@ -103,6 +135,9 @@ struct xmalloc_slot { static uint8_t ecc_point4[ECC_POINT_SIZE]; static uint8_t ecc_point5[ECC_POINT_SIZE]; static uint8_t mp_buffer0[MP_INT_BUFFER_SIZE]; + #ifdef WOLFBOOT_SIGN_ECC384 + static uint8_t mp_buffer1[MP_INT_BUFFER_SIZE_1]; + #endif static uint8_t mp_digits_buffer[MP_DIGIT_BUFFER_MONT_SIZE]; #endif @@ -121,6 +156,9 @@ static struct xmalloc_slot xmalloc_pool[] = { { (uint8_t *)mp_points_0, MP_POINT_SIZE * 2, 0 }, #ifdef WOLFSSL_SP_ARM_CORTEX_M_ASM { (uint8_t *)mp_points_1, MP_POINT_SIZE * 2, 0 }, + #ifdef WOLFBOOT_SIGN_ECC384 + { (uint8_t *)mp_montgomery, MP_MONTGOMERY_SIZE, 0 }, + #endif #else { (uint8_t *)mp_points_1, MP_POINT_SIZE * 3, 0 }, { (uint8_t *)mp_digits_buffer_2, MP_DIGITS_BUFFER_SIZE_2, 0 }, @@ -149,6 +187,9 @@ static struct xmalloc_slot xmalloc_pool[] = { { ecc_point4, ECC_POINT_SIZE, 0}, { ecc_point5, ECC_POINT_SIZE, 0}, { mp_buffer0, MP_INT_BUFFER_SIZE, 0}, + #ifdef WOLFBOOT_SIGN_ECC384 + { mp_buffer1, MP_INT_BUFFER_SIZE_1, 0}, + #endif { mp_digits_buffer, MP_DIGIT_BUFFER_MONT_SIZE, 0}, #endif { NULL, 0, 0} diff --git a/tools/keytools/keygen.c b/tools/keytools/keygen.c index 72295535..2b06deff 100644 --- a/tools/keytools/keygen.c +++ b/tools/keytools/keygen.c @@ -67,10 +67,14 @@ #define KEYGEN_RSA2048 2 #define KEYGEN_RSA4096 3 #define KEYGEN_ED448 4 +#define KEYGEN_ECC384 5 +#define KEYGEN_ECC521 6 const char Ed25519_pub_key_define[] = "const uint8_t ed25519_pub_key[32] = {"; const char Ed448_pub_key_define[] = "const uint8_t ed448_pub_key[57] = {"; const char Ecc256_pub_key_define[] = "const uint8_t ecc256_pub_key[64] = {"; +const char Ecc384_pub_key_define[] = "const uint8_t ecc384_pub_key[96] = {"; +const char Ecc521_pub_key_define[] = "const uint8_t ecc521_pub_key[132] = {"; const char Rsa_2048_pub_key_define[] = "const uint8_t rsa2048_pub_key[%d] = {"; const char Rsa_4096_pub_key_define[] = "const uint8_t rsa4096_pub_key[%d] = {"; @@ -85,7 +89,8 @@ const char Cfile_Banner[] = "/* Public-key file for wolfBoot, automatically gene static void usage(const char *pname) /* implies exit */ { - printf("Usage: %s [--ed25519 | --ed448 | --ecc256 | --rsa2048 | --rsa4096 ] pub_key_file.c\n", pname); + printf("Usage: %s [--ed25519 | --ed448 | --ecc256 | --ecc384 " + "| --ecc521 | --rsa2048 | --rsa4096 ] pub_key_file.c\n", pname); exit(125); } @@ -158,20 +163,21 @@ static void keygen_rsa(WC_RNG *rng, char *pubkeyfile, int size) #endif #ifdef HAVE_ECC -#define ECC256_KEY_SIZE 32 -static void keygen_ecc256(WC_RNG *rng, char *pubkfile) +#define MAX_ECC_KEY_SIZE 66 + +static void keygen_ecc(WC_RNG *rng, char *pubkfile, uint16_t ecc_key_size) { ecc_key k; - uint8_t Qx[ECC256_KEY_SIZE], Qy[ECC256_KEY_SIZE], d[ECC256_KEY_SIZE]; - uint32_t qxsize = ECC256_KEY_SIZE, - qysize = ECC256_KEY_SIZE, - dsize = ECC256_KEY_SIZE; + uint8_t Qx[MAX_ECC_KEY_SIZE], Qy[MAX_ECC_KEY_SIZE], d[MAX_ECC_KEY_SIZE]; + uint32_t qxsize = ecc_key_size, + qysize = ecc_key_size, + dsize = ecc_key_size; FILE *fpriv, *fpub; char priv_fname[20] = ""; - if (wc_ecc_make_key(rng, ECC256_KEY_SIZE, &k) != 0) { - fprintf(stderr, "Unable to create ecc%d key\n", ECC256_KEY_SIZE << 3); + if (wc_ecc_make_key(rng, ecc_key_size, &k) != 0) { + fprintf(stderr, "Unable to create ecc key\n"); exit(1); } @@ -185,7 +191,7 @@ static void keygen_ecc256(WC_RNG *rng, char *pubkfile) exit(3); } - sprintf(priv_fname, "ecc%d.der", (ECC256_KEY_SIZE << 3)); + sprintf(priv_fname, "ecc%d.der", (ecc_key_size < 66)?(ecc_key_size << 3):521); fpriv = fopen(priv_fname, "wb"); if (fpriv == NULL) { @@ -203,12 +209,25 @@ static void keygen_ecc256(WC_RNG *rng, char *pubkfile) exit(4); } fprintf(fpub, "%s", Cfile_Banner); - fprintf(fpub, "%s", Ecc256_pub_key_define); + if (ecc_key_size == 32) + fprintf(fpub, "%s", Ecc256_pub_key_define); + else if (ecc_key_size == 48) + fprintf(fpub, "%s", Ecc384_pub_key_define); + else if (ecc_key_size == 66) + fprintf(fpub, "%s", Ecc521_pub_key_define); + else + fprintf(fpub, "#error Unknown ecc key size"); + fwritekey(Qx, qxsize, fpub); fprintf(fpub, ","); fwritekey(Qy, qysize, fpub); fprintf(fpub, "\n};\n"); - fprintf(fpub, "const uint32_t ecc256_pub_key_len = 64;\n"); + if (ecc_key_size == 32) + fprintf(fpub, "const uint32_t ecc256_pub_key_len = 64;\n"); + else if (ecc_key_size == 48) + fprintf(fpub, "const uint32_t ecc384_pub_key_len = 96;\n"); + else if (ecc_key_size == 66) + fprintf(fpub, "const uint32_t ecc521_pub_key_len = 132;\n"); fclose(fpub); } #endif @@ -328,6 +347,14 @@ int main(int argc, char** argv) keytype = KEYGEN_ECC256; kfilename = strdup("ecc256.der"); } + else if (strcmp(argv[i], "--ecc384") == 0) { + keytype = KEYGEN_ECC384; + kfilename = strdup("ecc384.der"); + } + else if (strcmp(argv[i], "--ecc521") == 0) { + keytype = KEYGEN_ECC521; + kfilename = strdup("ecc521.der"); + } else if (strcmp(argv[i], "--rsa2048") == 0) { keytype = KEYGEN_RSA2048; kfilename = strdup("rsa2048.der"); @@ -387,7 +414,17 @@ int main(int argc, char** argv) #ifdef HAVE_ECC case KEYGEN_ECC256: { - keygen_ecc256(&rng, output_pubkey_file); + keygen_ecc(&rng, output_pubkey_file, 32); + break; + } + case KEYGEN_ECC384: + { + keygen_ecc(&rng, output_pubkey_file, 48); + break; + } + case KEYGEN_ECC521: + { + keygen_ecc(&rng, output_pubkey_file, 66); break; } #endif diff --git a/tools/keytools/keygen.py b/tools/keytools/keygen.py index fbbb6994..3cea7c70 100755 --- a/tools/keytools/keygen.py +++ b/tools/keytools/keygen.py @@ -45,6 +45,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" Ed448_pub_key_define= "const uint8_t ed448_pub_key[57] = {\n\t" Ecc256_pub_key_define = "const uint8_t ecc256_pub_key[64] = {\n\t" +Ecc384_pub_key_define = "const uint8_t ecc384_pub_key[96] = {\n\t" +Ecc521_pub_key_define = "const uint8_t ecc521_pub_key[132] = {\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" @@ -56,6 +58,8 @@ parser = ap.ArgumentParser(prog='keygen.py', description='wolfBoot key generatio parser.add_argument('--ed25519', dest='ed25519', action='store_true') parser.add_argument('--ed448', dest='ed448', action='store_true') parser.add_argument('--ecc256', dest='ecc256', action='store_true') +parser.add_argument('--ecc384', dest='ecc384', action='store_true') +parser.add_argument('--ecc521', dest='ecc521', action='store_true') parser.add_argument('--rsa2048', dest='rsa2048', action='store_true') parser.add_argument('--rsa4096', dest='rsa4096', action='store_true') parser.add_argument('--force', dest='force', action='store_true') @@ -79,6 +83,14 @@ if (args.ecc256): if sign is not None: dupsign() sign='ecc256' +if (args.ecc384): + if sign is not None: + dupsign() + sign='ecc384' +if (args.ecc521): + if sign is not None: + dupsign() + sign='ecc521' if (args.rsa2048): if sign is not None: dupsign() @@ -165,16 +177,42 @@ if (sign == "ed448"): f.write("\n};\n") f.write("const uint32_t ed448_pub_key_len = 57;\n") f.close() +if (sign[0:3] == 'ecc'): + if (sign == "ecc256"): + ec = ciphers.EccPrivate.make_key(32) + banner = Ecc256_pub_key_define + ecc_pub_key_len = 64 + qx,qy,d = ec.encode_key_raw() + if os.path.exists(key_file) and not force: + 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) -if (sign == "ecc256"): - ec = ciphers.EccPrivate.make_key(32) - qx,qy,d = ec.encode_key_raw() - if os.path.exists(key_file) and not force: - 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) + if (sign == "ecc384"): + ec = ciphers.EccPrivate.make_key(48) + banner = Ecc384_pub_key_define + ecc_pub_key_len = 96 + qx,qy,d = ec.encode_key_raw() + if os.path.exists(key_file) and not force: + 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) + + if (sign == "ecc521"): + ec = ciphers.EccPrivate.make_key(66) + banner = Ecc521_pub_key_define + ecc_pub_key_len = 132 + qx,qy,d = ec.encode_key_raw() + if os.path.exists(key_file) and not force: + 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) print() print("Creating file " + key_file) @@ -186,7 +224,7 @@ if (sign == "ecc256"): print("Creating file " + pubkey_cfile) with open(pubkey_cfile, "w") as f: f.write(Cfile_Banner) - f.write(Ecc256_pub_key_define) + f.write(banner) i = 0 for c in bytes(qx): f.write("0x%02X, " % c) @@ -200,7 +238,7 @@ if (sign == "ecc256"): f.write('\n') f.write("0x%02X" % qy[-1]) f.write("\n};\n") - f.write("const uint32_t ecc256_pub_key_len = 64;\n") + f.write("const uint32_t %s_pub_key_len = %d;\n" % (sign, ecc_pub_key_len)) f.close() if (sign == "rsa2048"): diff --git a/tools/keytools/sign.c b/tools/keytools/sign.c index 713f2f56..40e7b45f 100755 --- a/tools/keytools/sign.c +++ b/tools/keytools/sign.c @@ -123,6 +123,8 @@ #define HDR_IMG_TYPE_AUTH_RSA2048 0x0300 #define HDR_IMG_TYPE_AUTH_RSA4096 0x0400 #define HDR_IMG_TYPE_AUTH_ED448 0x0500 +#define HDR_IMG_TYPE_AUTH_ECC384 0x0600 +#define HDR_IMG_TYPE_AUTH_ECC521 0x0700 #define HDR_IMG_TYPE_WOLFBOOT 0x0000 #define HDR_IMG_TYPE_APP 0x0001 #define HDR_IMG_TYPE_DIFF 0x00D0 @@ -137,6 +139,8 @@ #define SIGN_RSA2048 HDR_IMG_TYPE_AUTH_RSA2048 #define SIGN_RSA4096 HDR_IMG_TYPE_AUTH_RSA4096 #define SIGN_ED448 HDR_IMG_TYPE_AUTH_ED448 +#define SIGN_ECC384 HDR_IMG_TYPE_AUTH_ECC384 +#define SIGN_ECC521 HDR_IMG_TYPE_AUTH_ECC521 #define ENC_OFF 0 @@ -295,8 +299,8 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, goto failure; } if (CMD.sign == SIGN_AUTO) { - CMD.sign = SIGN_ECC256; - printf("ecc256 key autodetected\n"); + CMD.sign = SIGN_ECC384; + printf("ecc384 key autodetected\n"); } } else if (*key_buffer_sz > 512) { @@ -310,13 +314,15 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, CMD.sign = SIGN_RSA2048; printf("rsa2048 key autodetected\n"); } - if (CMD.sign != SIGN_RSA2048) { + if ((CMD.sign != SIGN_RSA2048) && (CMD.sign != SIGN_ECC384) && + (CMD.sign != SIGN_ECC521)) { printf("Error: key size too large for the selected cipher\n"); goto failure; } } else { - printf("Error: key size '%d' does not match any cipher\n", *key_buffer_sz); + printf("Error: key size '%d' does not match any cipher\n", + *key_buffer_sz); goto failure; } @@ -330,7 +336,8 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, if (ret == 0) { *pubkey = *key_buffer + ED25519_KEY_SIZE; *pubkey_sz = ED25519_PUB_KEY_SIZE; - ret = wc_ed25519_import_private_key(*key_buffer, ED25519_KEY_SIZE, *pubkey, *pubkey_sz, &key.ed); + ret = wc_ed25519_import_private_key(*key_buffer, + ED25519_KEY_SIZE, *pubkey, *pubkey_sz, &key.ed); } #endif } else if (CMD.sign == SIGN_ED448) { @@ -339,29 +346,53 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, if (ret == 0) { *pubkey = *key_buffer + ED448_KEY_SIZE; *pubkey_sz = ED448_PUB_KEY_SIZE; - ret = wc_ed448_import_private_key(*key_buffer, ED448_KEY_SIZE, *pubkey, *pubkey_sz, &key.ed4); + ret = wc_ed448_import_private_key(*key_buffer, ED448_KEY_SIZE, + *pubkey, *pubkey_sz, &key.ed4); } #endif - } else if (CMD.sign == SIGN_ECC256) { #ifdef HAVE_ECC + } else if (CMD.sign == SIGN_ECC256) { ret = wc_ecc_init(&key.ecc); if (ret == 0) { - ret = wc_ecc_import_unsigned(&key.ecc, *key_buffer, (*key_buffer) + 32, - (*key_buffer) + 64, ECC_SECP256R1); + ret = wc_ecc_import_unsigned(&key.ecc, *key_buffer, + (*key_buffer) + 32, (*key_buffer) + 64, ECC_SECP256R1); if (ret == 0) { *pubkey = *key_buffer; /* first 64 bytes is public portion */ *pubkey_sz = 64; } } + } else if (CMD.sign == SIGN_ECC384) { + ret = wc_ecc_init(&key.ecc); + if (ret == 0) { + ret = wc_ecc_import_unsigned(&key.ecc, *key_buffer, + (*key_buffer) + 48, (*key_buffer) + 96, ECC_SECP384R1); + if (ret == 0) { + *pubkey = *key_buffer; /* first 96 bytes is public portion */ + *pubkey_sz = 96; + } + } + } else if (CMD.sign == SIGN_ECC521) { + ret = wc_ecc_init(&key.ecc); + if (ret == 0) { + ret = wc_ecc_import_unsigned(&key.ecc, *key_buffer, + (*key_buffer) + 66, (*key_buffer) + 132, ECC_SECP521R1); + if (ret == 0) { + *pubkey = *key_buffer; /* first 132 bytes is public portion */ + *pubkey_sz = 132; + } + } + } #endif - } else if (CMD.sign == SIGN_RSA2048 || CMD.sign == SIGN_RSA4096) { #ifndef NO_RSA + else if (CMD.sign == SIGN_RSA2048 || CMD.sign == SIGN_RSA4096) { idx = 0; ret = wc_InitRsaKey(&key.rsa, NULL); if (ret == 0) { - ret = wc_RsaPrivateKeyDecode(*key_buffer, &idx, &key.rsa, *key_buffer_sz); + ret = wc_RsaPrivateKeyDecode(*key_buffer, &idx, &key.rsa, + *key_buffer_sz); if (ret == 0) { - ret = wc_RsaKeyToPublicDer(&key.rsa, *key_buffer, *key_buffer_sz); + ret = wc_RsaKeyToPublicDer(&key.rsa, *key_buffer, + *key_buffer_sz); if (ret > 0) { *pubkey = *key_buffer; *pubkey_sz = ret; @@ -369,8 +400,8 @@ static uint8_t *load_key(uint8_t **key_buffer, uint32_t *key_buffer_sz, } } } -#endif } +#endif if (ret != 0) { printf("Error %d loading key\n", ret); goto failure; @@ -395,7 +426,8 @@ failure: return NULL; } -static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, const char *image_file, const char *outfile, +static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, + const char *image_file, const char *outfile, uint32_t delta_base_version, uint16_t patch_len, uint32_t patch_inv_off, uint16_t patch_inv_len) { @@ -624,24 +656,45 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, cons wc_InitRng(&rng); if (CMD.sign == SIGN_ED25519) { #ifdef HAVE_ED25519 - ret = wc_ed25519_sign_msg(digest, digest_sz, signature, &CMD.signature_sz, &key.ed); + ret = wc_ed25519_sign_msg(digest, digest_sz, signature, + &CMD.signature_sz, &key.ed); #endif } else if (CMD.sign == SIGN_ED448) { #ifdef HAVE_ED448 - ret = wc_ed448_sign_msg(digest, digest_sz, signature, &CMD.signature_sz, &key.ed4, NULL, 0); + ret = wc_ed448_sign_msg(digest, digest_sz, signature, + &CMD.signature_sz, &key.ed4, NULL, 0); #endif } - else if (CMD.sign == SIGN_ECC256) { #ifdef HAVE_ECC + else if (CMD.sign == SIGN_ECC256) { mp_int r, s; mp_init(&r); mp_init(&s); - ret = wc_ecc_sign_hash_ex(digest, digest_sz, &rng, &key.ecc, &r, &s); + ret = wc_ecc_sign_hash_ex(digest, digest_sz, &rng, &key.ecc, + &r, &s); mp_to_unsigned_bin(&r, &signature[0]); mp_to_unsigned_bin(&s, &signature[32]); mp_clear(&r); mp_clear(&s); -#endif } + else if (CMD.sign == SIGN_ECC384) { + mp_int r, s; + mp_init(&r); mp_init(&s); + ret = wc_ecc_sign_hash_ex(digest, digest_sz, &rng, &key.ecc, + &r, &s); + mp_to_unsigned_bin(&r, &signature[0]); + mp_to_unsigned_bin(&s, &signature[48]); + mp_clear(&r); mp_clear(&s); + } + else if (CMD.sign == SIGN_ECC521) { + mp_int r, s; + mp_init(&r); mp_init(&s); + ret = wc_ecc_sign_hash_ex(digest, digest_sz, &rng, &key.ecc, + &r, &s); + mp_to_unsigned_bin(&r, &signature[0]); + mp_to_unsigned_bin(&s, &signature[66]); + mp_clear(&r); mp_clear(&s); + } +#endif else if (CMD.sign == SIGN_RSA2048 || CMD.sign == SIGN_RSA4096) { #ifndef NO_RSA uint32_t enchash_sz = digest_sz; @@ -653,10 +706,12 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, cons hashOID = SHA256h; else if (CMD.hash_algo == HASH_SHA3) hashOID = SHA3_384h; - enchash_sz = wc_EncodeSignature(buf, digest, digest_sz, hashOID); + enchash_sz = wc_EncodeSignature(buf, digest, digest_sz, + hashOID); enchash = buf; } - ret = wc_RsaSSL_Sign(enchash, enchash_sz, signature, CMD.signature_sz, + ret = wc_RsaSSL_Sign(enchash, enchash_sz, signature, + CMD.signature_sz, &key.rsa, &rng); if (ret > 0) { CMD.signature_sz = ret; @@ -692,7 +747,8 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, cons #endif /* Add signature to header */ - header_append_tag(header, &header_idx, HDR_SIGNATURE, CMD.signature_sz, signature); + header_append_tag(header, &header_idx, HDR_SIGNATURE, CMD.signature_sz, + signature); } /* end if(sign != NO_SIGN) */ /* Add padded header at end */ @@ -746,7 +802,8 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, cons } fek = fopen(CMD.encrypt_key_file, "rb"); if (fek == NULL) { - fprintf(stderr, "Open encryption key file %s: %s\n", CMD.encrypt_key_file, strerror(errno)); + fprintf(stderr, "Open encryption key file %s: %s\n", + CMD.encrypt_key_file, strerror(errno)); exit(1); } ret = fread(key, 1, keySz, fek); @@ -763,7 +820,8 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, cons fef = fopen(CMD.output_encrypted_image_file, "wb"); if (!fef) { - fprintf(stderr, "Open encrypted output file %s: %s\n", CMD.encrypt_key_file, strerror(errno)); + fprintf(stderr, "Open encrypted output file %s: %s\n", + CMD.encrypt_key_file, strerror(errno)); } fsize = ftell(f); fseek(f, 0, SEEK_SET); /* restart the _signed file from 0 */ @@ -771,7 +829,8 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, cons if (CMD.encrypt == ENC_CHACHA) { ChaCha cha; #ifndef HAVE_CHACHA - fprintf(stderr, "Encryption not supported: chacha support not found in wolfssl configuration.\n"); + fprintf(stderr, "Encryption not supported: chacha support not found" + "in wolfssl configuration.\n"); exit(100); #endif wc_Chacha_SetKey(&cha, key, sizeof(key)); @@ -815,16 +874,19 @@ failure: return ret; } -static int make_header(uint8_t *pubkey, uint32_t pubkey_sz, const char *image_file, const char *outfile) +static int make_header(uint8_t *pubkey, uint32_t pubkey_sz, + const char *image_file, const char *outfile) { return make_header_ex(0, pubkey, pubkey_sz, image_file, outfile, 0, 0, 0, 0); } -static int make_header_delta(uint8_t *pubkey, uint32_t pubkey_sz, const char *image_file, const char *outfile, +static int make_header_delta(uint8_t *pubkey, uint32_t pubkey_sz, + const char *image_file, const char *outfile, uint32_t delta_base_version, uint16_t patch_len, uint32_t patch_inv_off, uint16_t patch_inv_len) { - return make_header_ex(1, pubkey, pubkey_sz, image_file, outfile, delta_base_version, patch_len, + return make_header_ex(1, pubkey, pubkey_sz, image_file, outfile, + delta_base_version, patch_len, patch_inv_off, patch_inv_len); } @@ -1063,11 +1125,11 @@ int main(int argc, char** argv) /* Check arguments and print usage */ if (argc < 4 || argc > 10) { - printf("Usage: %s [--ed25519 | --ed447 | --ecc256 | --rsa2048 | --rsa2048enc | --rsa4096 | --rsa4096enc | --no-CMD.sign] [--sha256 | --sha3] [--wolfboot-update] [--encrypt enc_key.bin] [--chacha | --aes128 | --aes256] [--delta image_vX_signed.bin] image key.der fw_version\n", argv[0]); + printf("Usage: %s [--ed25519 | --ed447 | --ecc256 | --ecc384 | --ecc521 | --rsa2048 | --rsa2048enc | --rsa4096 | --rsa4096enc | --no-CMD.sign] [--sha256 | --sha3] [--wolfboot-update] [--encrypt enc_key.bin] [--chacha | --aes128 | --aes256] [--delta image_vX_signed.bin] image key.der fw_version\n", argv[0]); printf(" - or - "); printf(" %s [--sha256 | --sha3] [--sha-only] [--wolfboot-update] image pub_key.der fw_version\n", argv[0]); printf(" - or - "); - printf(" %s [--ed25519 | --ed448 | --ecc256 | --rsa2048 | --rsa4096 ] [--sha256 | --sha3] [--manual-CMD.sign] image pub_key.der fw_version signature.sig\n", argv[0]); + printf(" %s [--ed25519 | --ed448 | --ecc256 | --ecc384 | --ecc521 | --rsa2048 | --rsa4096 ] [--sha256 | --sha3] [--manual-CMD.sign] image pub_key.der fw_version signature.sig\n", argv[0]); return 0; } @@ -1087,6 +1149,14 @@ int main(int argc, char** argv) CMD.sign = SIGN_ECC256; sign_str = "ECC256"; } + else if (strcmp(argv[i], "--ecc384") == 0) { + CMD.sign = SIGN_ECC384; + sign_str = "ECC384"; + } + else if (strcmp(argv[i], "--ecc521") == 0) { + CMD.sign = SIGN_ECC521; + sign_str = "ECC521"; + } else if (strcmp(argv[i], "--rsa2048enc") == 0) { CMD.sign = SIGN_RSA2048; sign_str = "RSA2048ENC"; @@ -1164,14 +1234,17 @@ int main(int argc, char** argv) if (tmpstr) { *tmpstr = '\0'; /* null terminate at last "." */ } - snprintf(CMD.output_image_file, sizeof(CMD.output_image_file), "%s_v%s_%s.bin", - (char*)buf, CMD.fw_version, CMD.sha_only ? "digest" : "signed"); + snprintf(CMD.output_image_file, sizeof(CMD.output_image_file), + "%s_v%s_%s.bin", (char*)buf, CMD.fw_version, + CMD.sha_only ? "digest" : "signed"); - snprintf(CMD.output_encrypted_image_file, sizeof(CMD.output_encrypted_image_file), + snprintf(CMD.output_encrypted_image_file, + sizeof(CMD.output_encrypted_image_file), "%s_v%s_signed_and_encrypted.bin", (char*)buf, CMD.fw_version); - printf("Update type: %s\n", CMD.self_update ? "wolfBoot" : "Firmware"); + printf("Update type: %s\n", + CMD.self_update ? "wolfBoot" : "Firmware"); printf("Input image: %s\n", CMD.image_file); printf("Selected cipher: %s\n", sign_str); printf("Selected hash : %s\n", hash_str); @@ -1180,7 +1253,8 @@ int main(int argc, char** argv) } if (CMD.delta) { printf("Delta Base file: %s\n", CMD.delta_base_file); - snprintf(CMD.output_diff_file, sizeof(CMD.output_image_file), "%s_v%s_signed_diff.bin", + snprintf(CMD.output_diff_file, sizeof(CMD.output_image_file), + "%s_v%s_signed_diff.bin", (char*)buf, CMD.fw_version); } @@ -1206,6 +1280,16 @@ int main(int argc, char** argv) CMD.header_sz = 256; CMD.signature_sz = 64; } + else if (CMD.sign == SIGN_ECC384) { + if (CMD.header_sz < 512) + CMD.header_sz = 512; + CMD.signature_sz = 96; + } + else if (CMD.sign == SIGN_ECC521) { + if (CMD.header_sz < 512) + CMD.header_sz = 512; + CMD.signature_sz = 132; + } else if (CMD.sign == SIGN_RSA2048) { if (CMD.header_sz < 512) CMD.header_sz = 512; diff --git a/tools/keytools/sign.py b/tools/keytools/sign.py index 5abda7ca..41d0f3c5 100755 --- a/tools/keytools/sign.py +++ b/tools/keytools/sign.py @@ -54,6 +54,8 @@ HDR_IMG_TYPE_AUTH_ECC256 = 0x0200 HDR_IMG_TYPE_AUTH_RSA2048 = 0x0300 HDR_IMG_TYPE_AUTH_RSA4096 = 0x0400 HDR_IMG_TYPE_AUTH_ED448 = 0x0500 +HDR_IMG_TYPE_AUTH_ECC384 = 0x0600 +HDR_IMG_TYPE_AUTH_ECC521 = 0x0700 HDR_IMG_TYPE_DIFF = 0x00D0 HDR_IMG_TYPE_WOLFBOOT = 0x0000 @@ -110,6 +112,10 @@ def make_header(image_file, fw_version, extra_fields=[]): img_type = HDR_IMG_TYPE_AUTH_ED448 if (sign == 'ecc256'): img_type = HDR_IMG_TYPE_AUTH_ECC256 + if (sign == 'ecc384'): + img_type = HDR_IMG_TYPE_AUTH_ECC384 + if (sign == 'ecc521'): + img_type = HDR_IMG_TYPE_AUTH_ECC521 if (sign == 'rsa2048'): img_type = HDR_IMG_TYPE_AUTH_RSA2048 if (sign == 'rsa4096'): @@ -219,7 +225,7 @@ def make_header(image_file, fw_version, extra_fields=[]): signature = ed.sign(digest) elif (sign == 'ed448'): signature = ed.sign(digest) - elif (sign == 'ecc256'): + elif (sign[0:3] == 'ecc'): r, s = ecc.sign_raw(digest) signature = r + s elif (sign == 'rsa2048') or (sign == 'rsa4096'): @@ -265,6 +271,10 @@ while (i < len(argv)): sign='ed448' elif (argv[i] == '--ecc256'): sign='ecc256' + elif (argv[i] == '--ecc384'): + sign='ecc384' + elif (argv[i] == '--ecc521'): + sign='ecc521' elif (argv[i] == '--rsa2048'): sign='rsa2048' elif (argv[i] == '--rsa4096'): @@ -438,6 +448,20 @@ elif wolfboot_key_buffer_len == 96: if sign == 'auto': sign = 'ecc256' print("'ecc256' key autodetected.") +elif wolfboot_key_buffer_len == 144: + if (sign != 'auto' and sign != 'ecc384'): + print("Error: key size does not match the cipher selected") + sys.exit(1) + if sign == 'auto': + sign = 'ecc384' + print("'ecc384' key autodetected.") +elif wolfboot_key_buffer_len == 198: + if (sign != 'auto' and sign != 'ecc521'): + print("Error: key size does not match the cipher selected") + sys.exit(1) + if sign == 'auto': + sign = 'ecc521' + print("'ecc521' key autodetected.") elif (wolfboot_key_buffer_len > 512): if (sign == 'auto'): print("'rsa4096' key autodetected.") @@ -445,7 +469,7 @@ elif (wolfboot_key_buffer_len > 128): if (sign == 'auto'): print("'rsa2048' key autodetected.") elif (sign != 'rsa2048'): - print ("Error: key size too large for the selected cipher") + print ("Error: key size %d too large for the selected cipher" % wolfboot_key_buffer_len) else: print ("Error: key size does not match any cipher") sys.exit(2) @@ -462,6 +486,7 @@ elif not sha_only and not manual_sign: if sign == 'ed448': HDR_SIGNATURE_LEN = 114 if WOLFBOOT_HEADER_SIZE < 512: + print("Ed448: header size increased to 512") WOLFBOOT_HEADER_SIZE = 512 ed = ciphers.Ed448Private(key = wolfboot_key_buffer) privkey, pubkey = ed.encode_key() @@ -471,8 +496,29 @@ elif not sha_only and not manual_sign: ecc.decode_key_raw(wolfboot_key_buffer[0:32], wolfboot_key_buffer[32:64], wolfboot_key_buffer[64:]) pubkey = wolfboot_key_buffer[0:64] + if sign == 'ecc384': + HDR_SIGNATURE_LEN = 96 + if WOLFBOOT_HEADER_SIZE < 512: + print("Ecc384: header size increased to 512") + WOLFBOOT_HEADER_SIZE = 512 + ecc = ciphers.EccPrivate() + ecc.decode_key_raw(wolfboot_key_buffer[0:48], wolfboot_key_buffer[48:96], wolfboot_key_buffer[96:], + curve_id = ciphers.ECC_SECP384R1) + pubkey = wolfboot_key_buffer[0:96] + + if sign == 'ecc521': + HDR_SIGNATURE_LEN = 132 + ecc = ciphers.EccPrivate() + ecc.decode_key_raw(wolfboot_key_buffer[0:66], wolfboot_key_buffer[66:132], wolfboot_key_buffer[132:], + curve_id = ciphers.ECC_SECP521R1) + pubkey = wolfboot_key_buffer[0:132] + if WOLFBOOT_HEADER_SIZE < 512: + print("Ecc521: header size increased to 512") + WOLFBOOT_HEADER_SIZE = 512 + if sign == 'rsa2048': if WOLFBOOT_HEADER_SIZE < 512: + print("Rsa2048: header size increased to 512") WOLFBOOT_HEADER_SIZE = 512 HDR_SIGNATURE_LEN = 256 rsa = ciphers.RsaPrivate(wolfboot_key_buffer) @@ -480,6 +526,7 @@ elif not sha_only and not manual_sign: if sign == 'rsa4096': if WOLFBOOT_HEADER_SIZE < 1024: + print("Rsa4096: header size increased to 1024") WOLFBOOT_HEADER_SIZE = 1024 HDR_SIGNATURE_LEN = 512 rsa = ciphers.RsaPrivate(wolfboot_key_buffer) diff --git a/tools/keytools/user_settings.h b/tools/keytools/user_settings.h index 921dc1b8..4e1e32e2 100755 --- a/tools/keytools/user_settings.h +++ b/tools/keytools/user_settings.h @@ -45,6 +45,9 @@ #define HAVE_ECC #define WOLFSSL_HAVE_SP_ECC #define ECC_TIMING_RESISTANT +#define HAVE_ECC256 +#define HAVE_ECC384 +#define HAVE_ECC521 /* ED25519 */ #define HAVE_ED25519 diff --git a/tools/test-renode.mk b/tools/test-renode.mk index 554975f5..6d9075a0 100644 --- a/tools/test-renode.mk +++ b/tools/test-renode.mk @@ -68,6 +68,16 @@ ifeq ($(SIGN),ECC256) SIGN_ARGS+= --ecc256 endif +ifeq ($(SIGN),ECC384) + SIGN_ARGS+= --ecc384 +endif + +# Already supported in sign tools, not yet in wolfBoot. +# Currently, a compile-time error is produced if selected. +ifeq ($(SIGN),ECC521) + SIGN_ARGS+= --ecc521 +endif + ifeq ($(SIGN),RSA2048) SIGN_ARGS+= --rsa2048 endif @@ -208,6 +218,9 @@ renode-factory-ed448: FORCE renode-factory-ecc256: FORCE make renode-factory SIGN=ECC256 +renode-factory-ecc384: FORCE + make renode-factory SIGN=ECC384 + renode-factory-rsa2048: FORCE make renode-factory SIGN=RSA2048 @@ -222,9 +235,11 @@ renode-factory-all: FORCE ${Q}make clean ${Q}make renode-factory-ecc256 RENODE_PORT=55157 ${Q}make clean - ${Q}make renode-factory-rsa2048 RENODE_PORT=55158 + ${Q}make renode-factory-ecc384 RENODE_PORT=55158 ${Q}make clean - ${Q}make renode-factory-rsa4096 RENODE_PORT=55159 + ${Q}make renode-factory-rsa2048 RENODE_PORT=55160 + ${Q}make clean + ${Q}make renode-factory-rsa4096 RENODE_PORT=55161 ${Q}echo All tests in $@ OK! renode-update-ed25519: FORCE @@ -236,6 +251,9 @@ renode-update-ed448: FORCE renode-update-ecc256: FORCE make renode-update SIGN=ECC256 +renode-update-ecc384: FORCE + make renode-update SIGN=ECC384 + renode-update-rsa2048: FORCE make renode-update SIGN=RSA2048 @@ -251,6 +269,9 @@ renode-no-downgrade-ed448: FORCE renode-no-downgrade-ecc256: FORCE make renode-no-downgrade SIGN=ECC256 +renode-no-downgrade-ecc384: FORCE + make renode-no-downgrade SIGN=ECC384 + renode-no-downgrade-rsa2048: FORCE make renode-no-downgrade SIGN=RSA2048 @@ -266,6 +287,9 @@ renode-corrupted-ed448: FORCE renode-corrupted-ecc256: FORCE make renode-corrupted SIGN=ECC256 +renode-corrupted-ecc384: FORCE + make renode-corrupted SIGN=ECC384 + renode-corrupted-rsa2048: FORCE make renode-corrupted SIGN=RSA2048 @@ -280,9 +304,11 @@ renode-update-all: FORCE ${Q}make clean ${Q}make renode-update-ecc256 RENODE_PORT=55157 ${Q}make clean - ${Q}make renode-update-rsa2048 RENODE_PORT=55158 + ${Q}make renode-update-ecc384 RENODE_PORT=55158 ${Q}make clean - ${Q}make renode-update-rsa4096 RENODE_PORT=55159 + ${Q}make renode-update-rsa2048 RENODE_PORT=55160 + ${Q}make clean + ${Q}make renode-update-rsa4096 RENODE_PORT=55161 ${Q}echo All tests in $@ OK! renode-no-downgrade-all: FORCE @@ -293,9 +319,11 @@ renode-no-downgrade-all: FORCE ${Q}make clean ${Q}make renode-no-downgrade-ecc256 RENODE_PORT=55157 ${Q}make clean - ${Q}make renode-no-downgrade-rsa2048 RENODE_PORT=55158 + ${Q}make renode-no-downgrade-ecc384 RENODE_PORT=55158 ${Q}make clean - ${Q}make renode-no-downgrade-rsa4096 RENODE_PORT=55159 + ${Q}make renode-no-downgrade-rsa2048 RENODE_PORT=55160 + ${Q}make clean + ${Q}make renode-no-downgrade-rsa4096 RENODE_PORT=55161 ${Q}echo All tests in $@ OK! renode-corrupted-all: FORCE @@ -306,10 +334,24 @@ renode-corrupted-all: FORCE ${Q}make clean ${Q}make renode-corrupted-ecc256 RENODE_PORT=55157 ${Q}make clean - ${Q}make renode-corrupted-rsa2048 RENODE_PORT=55158 + ${Q}make renode-corrupted-ecc384 RENODE_PORT=55158 ${Q}make clean - ${Q}make renode-corrupted-rsa4096 RENODE_PORT=55159 + ${Q}make renode-corrupted-rsa2048 RENODE_PORT=55160 + ${Q}make clean + ${Q}make renode-corrupted-rsa4096 RENODE_PORT=55161 ${Q}echo All tests in $@ OK! renode-update-all-armored: FORCE ${Q}make renode-update-all ARMORED=1 + +renode-update-all-smallstack: FORCE + ${Q}make renode-update-all WOLFBOOT_SMALL_STACK=1 + +renode-update-all-smallstack-noasm: FORCE + ${Q}make renode-update-all WOLFBOOT_SMALL_STACK=1 NO_ASM=1 + +renode-update-all-fastmath: FORCE + ${Q}make renode-update-all SPMATH=0 + +renode-update-all-smallstack-fastmath: FORCE + ${Q}make renode-update-all SPMATH=0 WOLFBOOT_SMALL_STACK=1