Skip to content

Commit de524e9

Browse files
de-nordicnvlsianpu
authored andcommitted
[nrf noup] bootutil: PureEdDSA using ED25519
The commit adds support for PureEdDSA, which validates signature of image rather than hash. This is most secure, available, ED25519 usage in MCUboot, but due to requirement of PureEdDSA to be able to calculate signature at whole message at once, here image, it only works on setups where entire image can be mapped to device address space, so that PSA functions calculating the signature can see the whole image at once. This option is enabled with Kconfig option: CONFIG_BOOT_SIGNATURE_TYPE_PURE when the ED25519 signature type is already selected. Note that the option will enable SHA512 for calculating public key hash. Signed-off-by: Dominik Ermel <[email protected]>
1 parent e1591c0 commit de524e9

File tree

6 files changed

+155
-8
lines changed

6 files changed

+155
-8
lines changed

boot/bootutil/include/bootutil/image.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ struct flash_area;
102102
#define IMAGE_TLV_ECDSA_SIG 0x22 /* ECDSA of hash output */
103103
#define IMAGE_TLV_RSA3072_PSS 0x23 /* RSA3072 of hash output */
104104
#define IMAGE_TLV_ED25519 0x24 /* ed25519 of hash output */
105+
#define IMAGE_TLV_SIG_PURE 0x25 /* Whatever signature has been selected, it will be used
106+
* as "pure" where signature is verified over entire
107+
* image rather than hash of an image */
105108
#define IMAGE_TLV_ENC_RSA2048 0x30 /* Key encrypted with RSA-OAEP-2048 */
106109
#define IMAGE_TLV_ENC_KW 0x31 /* Key encrypted with AES-KW 128 or 256*/
107110
#define IMAGE_TLV_ENC_EC256 0x32 /* Key encrypted with ECIES-EC256 */

boot/bootutil/src/bootutil_priv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,9 @@ struct boot_loader_state {
262262
fih_ret bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig,
263263
size_t slen, uint8_t key_id);
264264

265+
fih_ret bootutil_verify_img(const uint8_t *img, uint32_t size,
266+
uint8_t *sig, size_t slen, uint8_t key_id);
267+
265268
fih_ret boot_fih_memequal(const void *s1, const void *s2, size_t n);
266269

267270
int boot_find_status(int image_index, const struct flash_area **fap);

boot/bootutil/src/image_ed25519.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,41 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen,
111111
FIH_RET(fih_rc);
112112
}
113113

114+
fih_ret
115+
bootutil_verify_img(const uint8_t *img, uint32_t size,
116+
uint8_t *sig, size_t slen, uint8_t key_id)
117+
{
118+
int rc;
119+
FIH_DECLARE(fih_rc, FIH_FAILURE);
120+
uint8_t *pubkey;
121+
uint8_t *end;
122+
123+
if (slen != EDDSA_SIGNAGURE_LENGTH) {
124+
FIH_SET(fih_rc, FIH_FAILURE);
125+
goto out;
126+
}
127+
128+
pubkey = (uint8_t *)bootutil_keys[key_id].key;
129+
end = pubkey + *bootutil_keys[key_id].len;
130+
131+
rc = bootutil_import_key(&pubkey, end);
132+
if (rc) {
133+
FIH_SET(fih_rc, FIH_FAILURE);
134+
goto out;
135+
}
136+
137+
rc = ED25519_verify(img, size, sig, pubkey);
138+
139+
if (rc == 0) {
140+
/* if verify returns 0, there was an error. */
141+
FIH_SET(fih_rc, FIH_FAILURE);
142+
goto out;
143+
}
144+
145+
FIH_SET(fih_rc, FIH_SUCCESS);
146+
out:
147+
148+
FIH_RET(fih_rc);
149+
}
150+
114151
#endif /* MCUBOOT_SIGN_ED25519 */

boot/bootutil/src/image_validate.c

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ BOOT_LOG_MODULE_DECLARE(mcuboot);
6565

6666
#include "bootutil_priv.h"
6767

68+
#ifndef MCUBOOT_SIGN_PURE
6869
/*
6970
* Compute SHA hash over the image.
7071
* (SHA384 if ECDSA-P384 is being used,
@@ -184,6 +185,7 @@ bootutil_img_hash(struct enc_key_data *enc_state, int image_index,
184185

185186
return 0;
186187
}
188+
#endif
187189

188190
/*
189191
* Currently, we only support being able to verify one type of
@@ -370,6 +372,35 @@ bootutil_get_img_security_cnt(struct image_header *hdr,
370372
return 0;
371373
}
372374

375+
#if defined(MCUBOOT_SIGN_PURE)
376+
/* Returns:
377+
* 0 -- found
378+
* 1 -- not found
379+
* -1 -- failed for some reason
380+
*
381+
* Value of TLV does not matter, presence decides.
382+
*/
383+
static int bootutil_check_for_pure(const struct image_header *hdr,
384+
const struct flash_area *fap)
385+
{
386+
struct image_tlv_iter it;
387+
uint32_t off;
388+
uint16_t len;
389+
int32_t rc;
390+
391+
rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_SIG_PURE, false);
392+
if (rc) {
393+
return rc;
394+
}
395+
396+
/* Search for the TLV */
397+
rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
398+
399+
return rc;
400+
}
401+
#endif
402+
403+
373404
#ifndef ALLOW_ROGUE_TLVS
374405
/*
375406
* The following list of TLVs are the only entries allowed in the unprotected
@@ -386,6 +417,9 @@ static const uint16_t allowed_unprot_tlvs[] = {
386417
IMAGE_TLV_ECDSA_SIG,
387418
IMAGE_TLV_RSA3072_PSS,
388419
IMAGE_TLV_ED25519,
420+
#if defined(MCUBOOT_SIGN_PURE)
421+
IMAGE_TLV_SIG_PURE,
422+
#endif
389423
IMAGE_TLV_ENC_RSA2048,
390424
IMAGE_TLV_ENC_KW,
391425
IMAGE_TLV_ENC_EC256,
@@ -408,7 +442,6 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index,
408442
uint32_t off;
409443
uint16_t len;
410444
uint16_t type;
411-
int image_hash_valid = 0;
412445
#ifdef EXPECTED_SIG_TLV
413446
FIH_DECLARE(valid_signature, FIH_FAILURE);
414447
#ifndef MCUBOOT_BUILTIN_KEY
@@ -425,7 +458,10 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index,
425458
#endif /* EXPECTED_SIG_TLV */
426459
struct image_tlv_iter it;
427460
uint8_t buf[SIG_BUF_SIZE];
461+
#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE)
462+
int image_hash_valid = 0;
428463
uint8_t hash[IMAGE_HASH_SIZE];
464+
#endif
429465
int rc = 0;
430466
FIH_DECLARE(fih_rc, FIH_FAILURE);
431467
#ifdef MCUBOOT_HW_ROLLBACK_PROT
@@ -494,6 +530,7 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index,
494530
}
495531
#endif
496532

533+
#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE)
497534
rc = bootutil_img_hash(enc_state, image_index, hdr, fap, tmp_buf,
498535
tmp_buf_sz, hash, seed, seed_len);
499536
if (rc) {
@@ -503,6 +540,15 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index,
503540
if (out_hash) {
504541
memcpy(out_hash, hash, IMAGE_HASH_SIZE);
505542
}
543+
#endif
544+
545+
#if defined(MCUBOOT_SIGN_PURE)
546+
/* If Pure type signature is expected then it has to be there */
547+
rc = bootutil_check_for_pure(hdr, fap);
548+
if (rc != 0) {
549+
goto out;
550+
}
551+
#endif
506552

507553
rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false);
508554
if (rc) {
@@ -546,8 +592,10 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index,
546592
}
547593
}
548594
#endif
549-
550-
if (type == EXPECTED_HASH_TLV) {
595+
switch(type) {
596+
#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE)
597+
case EXPECTED_HASH_TLV:
598+
{
551599
/* Verify the image hash. This must always be present. */
552600
if (len != sizeof(hash)) {
553601
rc = -1;
@@ -565,8 +613,12 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index,
565613
}
566614

567615
image_hash_valid = 1;
616+
break;
617+
}
618+
#endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */
568619
#ifdef EXPECTED_KEY_TLV
569-
} else if (type == EXPECTED_KEY_TLV) {
620+
case EXPECTED_KEY_TLV:
621+
{
570622
/*
571623
* Determine which key we should be checking.
572624
*/
@@ -591,9 +643,12 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index,
591643
* The key may not be found, which is acceptable. There
592644
* can be multiple signatures, each preceded by a key.
593645
*/
646+
break;
647+
}
594648
#endif /* EXPECTED_KEY_TLV */
595649
#ifdef EXPECTED_SIG_TLV
596-
} else if (type == EXPECTED_SIG_TLV) {
650+
case EXPECTED_SIG_TLV:
651+
{
597652
/* Ignore this signature if it is out of bounds. */
598653
if (key_id < 0 || key_id >= bootutil_key_cnt) {
599654
key_id = -1;
@@ -607,12 +662,25 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index,
607662
if (rc) {
608663
goto out;
609664
}
665+
#ifndef MCUBOOT_SIGN_PURE
610666
FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash),
611667
buf, len, key_id);
668+
#else
669+
/* Directly check signature on the image, by using the mapping of
670+
* a device to memory. The pointer is beginning of image in flash,
671+
* so offset of area, the range is header + image + protected tlvs.
672+
*/
673+
FIH_CALL(bootutil_verify_img, valid_signature, (void *)flash_area_get_off(fap),
674+
hdr->ih_hdr_size + hdr->ih_img_size + hdr->ih_protect_tlv_size,
675+
buf, len, key_id);
676+
#endif
612677
key_id = -1;
678+
break;
679+
}
613680
#endif /* EXPECTED_SIG_TLV */
614681
#ifdef MCUBOOT_HW_ROLLBACK_PROT
615-
} else if (type == IMAGE_TLV_SEC_CNT) {
682+
case IMAGE_TLV_SEC_CNT:
683+
{
616684
/*
617685
* Verify the image's security counter.
618686
* This must always be present.
@@ -647,14 +715,21 @@ bootutil_img_validate(struct enc_key_data *enc_state, int image_index,
647715

648716
/* The image's security counter has been successfully verified. */
649717
security_counter_valid = fih_rc;
718+
break;
719+
}
650720
#endif /* MCUBOOT_HW_ROLLBACK_PROT */
651721
}
652722
}
653723

724+
#if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE)
654725
rc = !image_hash_valid;
655726
if (rc) {
656727
goto out;
657728
}
729+
#elif defined(MCUBOOT_SIGN_PURE)
730+
/* This returns true on EQ, rc is err on non-0 */
731+
rc = !FIH_EQ(valid_signature, FIH_SUCCESS);
732+
#endif
658733
#ifdef EXPECTED_SIG_TLV
659734
FIH_SET(fih_rc, valid_signature);
660735
#endif

boot/zephyr/Kconfig

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,14 @@ config BOOT_IMG_HASH_ALG_SHA512
192192

193193
endchoice # BOOT_IMG_HASH_ALG
194194

195+
config BOOT_SIGNATURE_TYPE_PURE_ALLOW
196+
bool
197+
help
198+
Hidden option set by configurations that allow Pure variant,
199+
for example ed25519. The pure variant means that image
200+
signature is calculated over entire image instead of hash
201+
of an image.
202+
195203
choice BOOT_SIGNATURE_TYPE
196204
prompt "Signature type"
197205
default BOOT_SIGNATURE_TYPE_ED25519 if BOARD_NRF54L15PDK_NRF54L15_CPUAPP
@@ -242,15 +250,32 @@ endif
242250

243251
config BOOT_SIGNATURE_TYPE_ED25519
244252
bool "Edwards curve digital signatures using ed25519"
245-
select BOOT_ENCRYPTION_SUPPORT
246-
select BOOT_IMG_HASH_ALG_SHA256_ALLOW
253+
select BOOT_ENCRYPTION_SUPPORT if !BOOT_SIGNATURE_TYPE_PURE
254+
select BOOT_IMG_HASH_ALG_SHA256_ALLOW if !BOOT_SIGNATURE_TYPE_PURE
255+
# The SHA is used only for key hashing, not for images.
247256
select BOOT_IMG_HASH_ALG_SHA512_ALLOW
257+
select BOOT_SIGNATURE_TYPE_PURE_ALLOW
248258
help
249259
This is ed25519 signature calculated over SHA512 of SHA256 of application
250260
image; that is not completely correct approach as the SHA512 should be
251261
rather directly calculated over an image.
262+
Select BOOT_SIGNATURE_TYPE_PURE to have a PureEdDSA calculating image
263+
signature directly on image, rather than hash of the image.
252264

253265
if BOOT_SIGNATURE_TYPE_ED25519
266+
267+
config BOOT_SIGNATURE_TYPE_PURE
268+
bool "Use Pure signature of image"
269+
depends on BOOT_SIGNATURE_TYPE_PURE_ALLOW
270+
help
271+
The Pure signature is calculated directly over image rather than
272+
hash of an image.
273+
This is more secure signature, specifically if hardware can do the
274+
verification without need to share key.
275+
Note that this requires that all slots for which signature is to be
276+
verified need to be accessible through memory address space that
277+
cryptography can access.
278+
254279
choice BOOT_ED25519_IMPLEMENTATION
255280
prompt "Ecdsa implementation"
256281
default BOOT_ED25519_TINYCRYPT

boot/zephyr/include/mcuboot_config/mcuboot_config.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@
147147
#define MCUBOOT_HASH_STORAGE_DIRECTLY
148148
#endif
149149

150+
#ifdef CONFIG_BOOT_SIGNATURE_TYPE_PURE
151+
#define MCUBOOT_SIGN_PURE
152+
#endif
153+
150154
#ifdef CONFIG_BOOT_BOOTSTRAP
151155
#define MCUBOOT_BOOTSTRAP 1
152156
#endif

0 commit comments

Comments
 (0)