Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PSA implementation of ed25519 image verification and x25519 random key encryption/decryption #323

Merged
merged 14 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 6 additions & 13 deletions boot/boot_serial/src/boot_serial_encryption.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,7 @@ boot_image_validate_encrypted(const struct flash_area *fa_p,
memset(&boot_data, 0, sizeof(struct boot_loader_state));
image_index = BOOT_CURR_IMG(state);
if(IS_ENCRYPTED(hdr)) {
rc = boot_enc_load(BOOT_CURR_ENC(state), image_index, hdr, fa_p, bs);
if (rc < 0) {
FIH_RET(fih_rc);
}
rc = flash_area_id_to_multi_image_slot(image_index, flash_area_get_id(fa_p));
rc = boot_enc_load(BOOT_CURR_ENC(state), 1, hdr, fa_p, bs);
if (rc < 0) {
FIH_RET(fih_rc);
}
Expand Down Expand Up @@ -129,10 +125,11 @@ decrypt_region_inplace(struct boot_loader_state *state,
size_t blk_off;
uint16_t idx;
uint32_t blk_sz;
uint8_t image_index;

int slot = flash_area_id_to_multi_image_slot(BOOT_CURR_IMG(state),
flash_area_get_id(fap));
uint8_t buf[sz] __attribute__((aligned));
assert(sz <= sizeof buf);
assert(slot >= 0);

bytes_copied = 0;
while (bytes_copied < sz) {
Expand All @@ -147,7 +144,6 @@ decrypt_region_inplace(struct boot_loader_state *state,
return BOOT_EFLASH;
}

image_index = BOOT_CURR_IMG(state);
if (IS_ENCRYPTED(hdr)) {
blk_sz = chunk_sz;
idx = 0;
Expand Down Expand Up @@ -175,7 +171,7 @@ decrypt_region_inplace(struct boot_loader_state *state,
blk_sz = tlv_off - (off + bytes_copied);
}
}
boot_encrypt(BOOT_CURR_ENC(state), image_index, fap,
boot_enc_decrypt(BOOT_CURR_ENC(state), slot,
(off + bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
blk_off, &buf[idx]);
}
Expand Down Expand Up @@ -222,7 +218,6 @@ decrypt_image_inplace(const struct flash_area *fa_p,
size_t sect_size;
size_t sect_count;
size_t sect;
uint8_t image_index;
struct flash_sector sector;

memset(&boot_data, 0, sizeof(struct boot_loader_state));
Expand All @@ -232,8 +227,6 @@ decrypt_image_inplace(const struct flash_area *fa_p,
rc = flash_area_get_sector(fa_p, boot_status_off(fa_p), &sector);


image_index = BOOT_CURR_IMG(state);

if(IS_ENCRYPTED(hdr)) {
#if 0 //Skip this step?, the image will just not boot if it's not decrypted properly
static uint8_t tmpbuf[BOOT_TMPBUF_SZ];
Expand All @@ -245,7 +238,7 @@ decrypt_image_inplace(const struct flash_area *fa_p,
#endif
memset(&boot_data, 0, sizeof(struct boot_loader_state));
/* Load the encryption keys into cache */
rc = boot_enc_load(BOOT_CURR_ENC(state), image_index, hdr, fa_p, bs);
rc = boot_enc_load(BOOT_CURR_ENC(state), 0, hdr, fa_p, bs);
if (rc < 0) {
FIH_RET(fih_rc);
}
Expand Down
38 changes: 36 additions & 2 deletions boot/bootutil/include/bootutil/crypto/aes_ctr.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
#include "mcuboot_config/mcuboot_config.h"

#if (defined(MCUBOOT_USE_MBED_TLS) + \
defined(MCUBOOT_USE_TINYCRYPT)) != 1
#error "One crypto backend must be defined: either MBED_TLS or TINYCRYPT"
defined(MCUBOOT_USE_TINYCRYPT) + defined(MCUBOOT_USE_PSA_CRYPTO)) != 1
#error "One crypto backend must be defined: either MBED_TLS or TINYCRYPT or PSA"
#endif

#if defined(MCUBOOT_USE_MBED_TLS)
Expand All @@ -38,12 +38,46 @@
#define BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE TC_AES_BLOCK_SIZE
#endif /* MCUBOOT_USE_TINYCRYPT */


#if defined(MCUBOOT_USE_PSA_CRYPTO)
#include <psa/crypto.h>
#include "bootutil/enc_key_public.h"
#define BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE BOOT_ENC_KEY_SIZE
#define BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE (16)
#endif

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

#if defined(MCUBOOT_USE_PSA_CRYPTO)
typedef struct {
/* Fixme: This should not be, here, psa_key_id should be passed */
uint8_t key[BOOT_ENC_KEY_SIZE];
} bootutil_aes_ctr_context;

void bootutil_aes_ctr_init(bootutil_aes_ctr_context *ctx);

static inline void bootutil_aes_ctr_drop(bootutil_aes_ctr_context *ctx)
{
memset(ctx, 0, sizeof(ctx));
}

static inline int bootutil_aes_ctr_set_key(bootutil_aes_ctr_context *ctx, const uint8_t *k)
{
memcpy(ctx->key, k, sizeof(ctx->key));

return 0;
}

int bootutil_aes_ctr_encrypt(bootutil_aes_ctr_context *ctx, uint8_t *counter,
const uint8_t *m, uint32_t mlen, size_t blk_off, uint8_t *c);
int bootutil_aes_ctr_decrypt(bootutil_aes_ctr_context *ctx, uint8_t *counter,
const uint8_t *c, uint32_t clen, size_t blk_off, uint8_t *m);
#endif

#if defined(MCUBOOT_USE_MBED_TLS)
typedef mbedtls_aes_context bootutil_aes_ctr_context;
static inline void bootutil_aes_ctr_init(bootutil_aes_ctr_context *ctx)
Expand Down
9 changes: 9 additions & 0 deletions boot/bootutil/include/bootutil/crypto/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,13 @@
#define MBEDTLS_CONTEXT_MEMBER(X) X
#endif

/* Newer versions of Mbed TLS have removed the private accessor requirement for
* the ASN1 fields.
*/
#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) && (MBEDTLS_VERSION_NUMBER < 0x03010000)
#define ASN1_CONTEXT_MEMBER(X) MBEDTLS_PRIVATE(X)
#else
#define ASN1_CONTEXT_MEMBER(X) X
#endif

#endif /* __BOOTUTIL_CRYPTO_COMMON_H__ */
16 changes: 8 additions & 8 deletions boot/bootutil/include/bootutil/crypto/ecdsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,13 @@ static int bootutil_import_key(uint8_t **cp, uint8_t *end)
return -2;
}
/* id-ecPublicKey (RFC5480) */
if (alg.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
memcmp(alg.MBEDTLS_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
if (alg.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
memcmp(alg.ASN1_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
return -3;
}
/* namedCurve (RFC5480) */
if (param.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_secp256r1_oid) - 1 ||
memcmp(param.MBEDTLS_CONTEXT_MEMBER(p), ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) {
if (param.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_secp256r1_oid) - 1 ||
memcmp(param.ASN1_CONTEXT_MEMBER(p), ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) {
return -4;
}
/* ECPoint (RFC5480) */
Expand Down Expand Up @@ -521,12 +521,12 @@ static int bootutil_parse_eckey(bootutil_ecdsa_context *ctx, uint8_t **p, uint8_
if (mbedtls_asn1_get_alg(p, end, &alg, &param)) {
return -2;
}
if (alg.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
memcmp(alg.MBEDTLS_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
if (alg.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
memcmp(alg.ASN1_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
return -3;
}
if (param.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_secp256r1_oid) - 1||
memcmp(param.MBEDTLS_CONTEXT_MEMBER(p), ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) {
if (param.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_secp256r1_oid) - 1||
memcmp(param.ASN1_CONTEXT_MEMBER(p), ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) {
return -4;
}

Expand Down
16 changes: 9 additions & 7 deletions boot/bootutil/include/bootutil/enc_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,21 @@ struct enc_key_data {
extern const struct bootutil_key bootutil_enc_key;
struct boot_status;

/* Decrypt random, symmetric encryption key */
int boot_decrypt_key(const uint8_t *buf, uint8_t *enckey);

int boot_enc_init(struct enc_key_data *enc_state, uint8_t slot);
int boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot);
int boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot,
const struct boot_status *bs);
int boot_enc_load(struct enc_key_data *enc_state, int image_index,
int boot_enc_load(struct enc_key_data *enc_state, int slot,
const struct image_header *hdr, const struct flash_area *fap,
struct boot_status *bs);
int boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey);
bool boot_enc_valid(struct enc_key_data *enc_state, int image_index,
const struct flash_area *fap);
void boot_encrypt(struct enc_key_data *enc_state, int image_index,
const struct flash_area *fap, uint32_t off, uint32_t sz,
uint32_t blk_off, uint8_t *buf);
bool boot_enc_valid(struct enc_key_data *enc_state, int slot);
void boot_enc_encrypt(struct enc_key_data *enc_state, int slot,
uint32_t off, uint32_t sz, uint32_t blk_off, uint8_t *buf);
void boot_enc_decrypt(struct enc_key_data *enc_state, int slot,
uint32_t off, uint32_t sz, uint32_t blk_off, uint8_t *buf);
void boot_enc_zeroize(struct enc_key_data *enc_state);

#ifdef __cplusplus
Expand Down
2 changes: 1 addition & 1 deletion boot/bootutil/src/bootutil_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ boot_read_enc_key(const struct flash_area *fap, uint8_t slot, struct boot_status
}
/* Only try to decrypt non-erased TLV metadata */
if (i != BOOT_ENC_TLV_ALIGN_SIZE) {
rc = boot_enc_decrypt(bs->enctlv[slot], bs->enckey[slot]);
rc = boot_decrypt_key(bs->enctlv[slot], bs->enckey[slot]);
}
}
#else
Expand Down
71 changes: 71 additions & 0 deletions boot/bootutil/src/ed25519_psa.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
#include <assert.h>
#include <string.h>
#include <stdint.h>

#include <mcuboot_config/mcuboot_config.h>
#include "bootutil/bootutil_log.h"

#include <psa/crypto.h>
#include <psa/crypto_types.h>

BOOT_LOG_MODULE_DECLARE(ed25519_psa);

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

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])
{
/* Set to any error */
psa_status_t status = PSA_ERROR_BAD_STATE;
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t kid;
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\n", status);
return 0;
}

status = PSA_ERROR_BAD_STATE;

psa_set_key_type(&key_attr,
PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS));
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&key_attr, PSA_ALG_PURE_EDDSA);

status = psa_import_key(&key_attr, public_key, EDDSA_KEY_LENGTH, &kid);
if (status != PSA_SUCCESS) {
BOOT_LOG_ERR("ED25519 key import failed %d", status);
return 0;
}

status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, message_len,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the place where psa_verify_hash() will be used instead for full sha512 based signature check?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Exactly. In the following PR 33a7ec4 there is already that part done.

The difference is that instead of the sha256, which is the messge here, we will get sha512, and therefore we do not rely on the internal sha512 calculation of psa_verify_message, but rather just verify the hash.

signature, EDDSA_SIGNAGURE_LENGTH);
if (status != PSA_SUCCESS) {
BOOT_LOG_ERR("ED25519 signature verification failed %d", status);
ret = 0;
/* Pass through to destroy key */
} else {
ret = 1;
/* Pass through to destroy key */
}

status = psa_destroy_key(kid);

if (status != PSA_SUCCESS) {
/* Just for logging */
BOOT_LOG_WRN("Failed to destroy key %d", status);
}

return ret;
}
Loading
Loading