Skip to content

Commit

Permalink
[nrf noup] bootutil: Add support for KMU stored ED25519 signature key
Browse files Browse the repository at this point in the history
The commit adds verification of image using keys stored in KMU.

Signed-off-by: Dominik Ermel <dominik.ermel@nordicsemi.no>
  • Loading branch information
de-nordic committed Oct 22, 2024
1 parent 720fa02 commit 32f0a27
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 5 deletions.
51 changes: 51 additions & 0 deletions boot/bootutil/src/ed25519_psa.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,28 @@

#include <psa/crypto.h>
#include <psa/crypto_types.h>
#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU)
#include <cracen_psa_kmu.h>
#endif

BOOT_LOG_MODULE_DECLARE(ed25519_psa);

#define SHA512_DIGEST_LENGTH 64
#define EDDSA_KEY_LENGTH 32
#define EDDSA_SIGNAGURE_LENGTH 64

#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU)
/* List of KMU stored key ids available for MCUboot */
#define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id)
static psa_key_id_t kmu_key_ids[3] = {
MAKE_PSA_KMU_KEY_ID(226),
MAKE_PSA_KMU_KEY_ID(228),
MAKE_PSA_KMU_KEY_ID(230)
};
#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0]))
#endif

#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU)
int ED25519_verify(const uint8_t *message, size_t message_len,
const uint8_t signature[EDDSA_SIGNAGURE_LENGTH],
const uint8_t public_key[EDDSA_KEY_LENGTH])
Expand Down Expand Up @@ -69,3 +84,39 @@ int ED25519_verify(const uint8_t *message, size_t message_len,

return ret;
}
#else
int ED25519_verify(const uint8_t *message, size_t message_len,
const uint8_t signature[EDDSA_SIGNAGURE_LENGTH],
const uint8_t public_key[EDDSA_KEY_LENGTH])
{
ARG_UNUSED(public_key);
/* Set to any error */
psa_status_t status = PSA_ERROR_BAD_STATE;
int ret = 0; /* Fail by default */

/* Initialize PSA Crypto */
status = psa_crypto_init();
if (status != PSA_SUCCESS) {
BOOT_LOG_ERR("PSA crypto init failed %d", status);
return 0;
}

status = PSA_ERROR_BAD_STATE;

for (int i = 0; i < KMU_KEY_COUNT; ++i) {
psa_key_id_t kid = kmu_key_ids[i];

status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message,
message_len, signature,
EDDSA_SIGNAGURE_LENGTH);
if (status == PSA_SUCCESS) {
ret = 1;
break;
}

BOOT_LOG_ERR("ED25519 signature verification failed %d", status);
}

return ret;
}
#endif
19 changes: 15 additions & 4 deletions boot/bootutil/src/image_ed25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@
#include "bootutil/crypto/sha.h"

#define EDDSA_SIGNATURE_LENGTH 64

static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70";
#define NUM_ED25519_BYTES 32

extern int ED25519_verify(const uint8_t *message, size_t message_len,
const uint8_t signature[EDDSA_SIGNATURE_LENGTH],
const uint8_t public_key[NUM_ED25519_BYTES]);

#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU)

static const uint8_t ed25519_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x65\x70";

/*
* Parse the public key used for signing.
*/
Expand Down Expand Up @@ -71,21 +73,25 @@ bootutil_import_key(uint8_t **cp, uint8_t *end)

return 0;
}
#endif

fih_ret
bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen,
uint8_t key_id)
{
int rc;
FIH_DECLARE(fih_rc, FIH_FAILURE);
uint8_t *pubkey;
uint8_t *pubkey = NULL;
#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU)
uint8_t *end;
#endif

if (hlen != IMAGE_HASH_SIZE || slen != EDDSA_SIGNATURE_LENGTH) {
FIH_SET(fih_rc, FIH_FAILURE);
goto out;
}

#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU)
pubkey = (uint8_t *)bootutil_keys[key_id].key;
end = pubkey + *bootutil_keys[key_id].len;

Expand All @@ -94,6 +100,7 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen,
FIH_SET(fih_rc, FIH_FAILURE);
goto out;
}
#endif

rc = ED25519_verify(hash, IMAGE_HASH_SIZE, sig, pubkey);

Expand All @@ -115,14 +122,17 @@ bootutil_verify_img(const uint8_t *img, uint32_t size,
{
int rc;
FIH_DECLARE(fih_rc, FIH_FAILURE);
uint8_t *pubkey;
uint8_t *pubkey = NULL;
#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU)
uint8_t *end;
#endif

if (slen != EDDSA_SIGNATURE_LENGTH) {
FIH_SET(fih_rc, FIH_FAILURE);
goto out;
}

#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU)
pubkey = (uint8_t *)bootutil_keys[key_id].key;
end = pubkey + *bootutil_keys[key_id].len;

Expand All @@ -131,6 +141,7 @@ bootutil_verify_img(const uint8_t *img, uint32_t size,
FIH_SET(fih_rc, FIH_FAILURE);
goto out;
}
#endif

rc = ED25519_verify(img, size, sig, pubkey);

Expand Down
2 changes: 1 addition & 1 deletion boot/zephyr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ if(CONFIG_MCUBOOT_SERIAL)
endif()
endif()

if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "")
if(NOT CONFIG_BOOT_SIGNATURE_USING_KMU OR NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "")
# CONF_FILE points to the KConfig configuration files of the bootloader.
foreach (filepath ${CONF_FILE})
file(READ ${filepath} temp_text)
Expand Down
16 changes: 16 additions & 0 deletions boot/zephyr/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,20 @@ endif

endchoice

config BOOT_SIGNATURE_USING_KMU
bool "Use KMU stored keys for signature verification"
help
The MCUboot will use keys provisioned to board for signature verification
instead of compiling in a key data.
select PSA_WANT_ALG_GCM
select PSA_WANT_KEY_TYPE_AES
select PSA_WANT_AES_KEY_SIZE_256
select PSA_WANT_ALG_SP800_108_COUNTER_CMAC
select PSA_WANT_ALG_CMAC
select PSA_WANT_ALG_ECB_NO_PADDING

if !BOOT_SIGNATURE_USING_KMU

config BOOT_SIGNATURE_KEY_FILE
string "PEM key file"
default "root-ec-p256.pem" if BOOT_SIGNATURE_TYPE_ECDSA_P256
Expand All @@ -319,6 +333,8 @@ config BOOT_SIGNATURE_KEY_FILE
with the public key information will be written in a format expected by
MCUboot.

endif

config MCUBOOT_CLEANUP_ARM_CORE
bool "Perform core cleanup before chain-load the application"
depends on CPU_CORTEX_M
Expand Down

0 comments on commit 32f0a27

Please sign in to comment.