Skip to content

Improvements in ENC definitions around TLV formats #2327

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

Merged
merged 3 commits into from
Jun 24, 2025
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: 19 additions & 0 deletions boot/bootutil/include/bootutil/bootutil_macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2025 Nordic Semiconductor ASA
*
*/

#ifndef H_BOOTUTIL_MACROS
#define H_BOOTUTIL_MACROS

#ifndef ALIGN_UP
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
#endif

#ifndef ALIGN_DOWN
#define ALIGN_DOWN(num, align) ((num) & ~((align) - 1))
#endif

#endif
9 changes: 1 addition & 8 deletions boot/bootutil/include/bootutil/bootutil_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,13 @@
#include <string.h>
#include <flash_map_backend/flash_map_backend.h>
#include <mcuboot_config/mcuboot_config.h>
#include <bootutil/bootutil_macros.h>
#include <bootutil/image.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifndef ALIGN_UP
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
#endif

#ifndef ALIGN_DOWN
#define ALIGN_DOWN(num, align) ((num) & ~((align) - 1))
#endif

/** Attempt to boot the contents of the primary slot. */
#define BOOT_SWAP_TYPE_NONE 1

Expand Down
4 changes: 2 additions & 2 deletions boot/bootutil/include/bootutil/crypto/rsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,12 @@ static int bootutil_rsa_oaep_decrypt(
return -1;
}
size_t input_size = PSA_BITS_TO_BYTES(psa_get_key_bits(&key_attr));
if (input_size != TLV_ENC_RSA_SZ) {
if (input_size != BOOT_ENC_TLV_SIZE) {
return -1;
}

status = psa_asymmetric_decrypt(ctx->key_id, PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256),
input, TLV_ENC_RSA_SZ, NULL, 0,
input, BOOT_ENC_TLV_SIZE, NULL, 0,
output, output_max_len, olen);
return (int)status;
}
Expand Down
2 changes: 0 additions & 2 deletions boot/bootutil/include/bootutil/enc_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@
extern "C" {
#endif

#define BOOT_ENC_TLV_ALIGN_SIZE ALIGN_UP(BOOT_ENC_TLV_SIZE, BOOT_MAX_ALIGN)

struct enc_key_data {
uint8_t valid;
bootutil_aes_ctr_context aes_ctr;
Expand Down
77 changes: 60 additions & 17 deletions boot/bootutil/include/bootutil/enc_key_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,37 +28,80 @@
#ifndef BOOTUTIL_ENC_KEY_PUBLIC_H
#define BOOTUTIL_ENC_KEY_PUBLIC_H
#include <mcuboot_config/mcuboot_config.h>
#include <bootutil/bootutil_macros.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifndef ALIGN_UP
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
#endif
/* The unit provides following system wide definitions:
* BOOT_ENC_TLV_SIZE -- is the complete size of TLV with encryption data.
* BOOT_ENC_TLV -- is the encryption TLV type, should be given value
* of one of IMAGE_TVL_ENC_ identifiers.
* BOOT_ENC_KEY_SIZE -- is the encryption key size; this includes portion
* of TLV data stream taken by key.
*
* For ECIES based key exchange there is additionally provided:
* EC_PUBK_LEN -- is the length, in bytes, of a public key; depends
* selected key exchange.
* EC_PRIVK_LEN -- is the length, in bytes, of a private key; depends
* on selected key exchange.
* EC_SHARED_LEN -- is the length, in bytes, of a shared key resulting
* from processing of private and public key; depends
* on selected key exchange parameters.
*
* ECIES TLV processing uses following TLVs, from this header:
* EC_TAG_INDEX -- is the HMAC tag of encryption key index within TLV data
* stream.
* EC_TAG_LEN -- is the HMAC tag length.
* EC_PUBK_INDEX -- is the index of shared public key within TLV data stream;
* EC_PUBK_LEN represents length in bytes.
* EC_CIPHERKEY_INDEX -- is the encryption key index within TLV data stream.
* EC_CIPHERKEY_LEN -- is the length of an encryption key; depends on selected
* encryption.
*
* Note that in case of ECIES, the BOOT_ENC_TLV_SIZE will be defined as
* a sum of EC_*_LEN TLV components, defined for selected key exchange.
*/

#ifdef MCUBOOT_AES_256
#define BOOT_ENC_KEY_SIZE 32
# define BOOT_ENC_KEY_SIZE 32
#else
#define BOOT_ENC_KEY_SIZE 16
# define BOOT_ENC_KEY_SIZE 16
#endif

#define BOOT_ENC_KEY_ALIGN_SIZE ALIGN_UP(BOOT_ENC_KEY_SIZE, BOOT_MAX_ALIGN)

#define TLV_ENC_RSA_SZ 256
#define TLV_ENC_KW_SZ (BOOT_ENC_KEY_SIZE + 8)
#define TLV_ENC_EC256_SZ (65 + 32 + BOOT_ENC_KEY_SIZE)
#define TLV_ENC_X25519_SZ (32 + 32 + BOOT_ENC_KEY_SIZE)

#if defined(MCUBOOT_ENCRYPT_RSA)
#define BOOT_ENC_TLV_SIZE TLV_ENC_RSA_SZ
# define BOOT_ENC_TLV_SIZE (256)
# define BOOT_ENC_TLV IMAGE_TLV_ENC_RSA2048
#elif defined(MCUBOOT_ENCRYPT_EC256)
#define BOOT_ENC_TLV_SIZE TLV_ENC_EC256_SZ
# define EC_PUBK_LEN (65)
# define EC_PRIVK_LEN (32)
# define EC_SHARED_LEN (32)
# define BOOT_ENC_TLV IMAGE_TLV_ENC_EC256
#elif defined(MCUBOOT_ENCRYPT_X25519)
#define BOOT_ENC_TLV_SIZE TLV_ENC_X25519_SZ
#else
#define BOOT_ENC_TLV_SIZE TLV_ENC_KW_SZ
# define EC_PUBK_LEN (32)
# define EC_PRIVK_LEN (32)
# define EC_SHARED_LEN (32)
# define BOOT_ENC_TLV IMAGE_TLV_ENC_X25519
#elif defined(MCUBOOT_ENCRYPT_KW)
# define BOOT_ENC_TLV_SIZE (BOOT_ENC_KEY_SIZE + 8)
# define BOOT_ENC_TLV IMAGE_TLV_ENC_KW
#endif

/* Common ECIES definitions */
#if defined(EC_PUBK_LEN)
# define EC_PUBK_INDEX (0)
# define EC_TAG_LEN (32)
# define EC_TAG_INDEX (EC_PUBK_INDEX + EC_PUBK_LEN)
# define EC_CIPHERKEY_INDEX (EC_TAG_INDEX + EC_TAG_LEN)
# define EC_CIPHERKEY_LEN BOOT_ENC_KEY_SIZE
# define EC_SHARED_KEY_LEN (32)
# define BOOT_ENC_TLV_SIZE (EC_PUBK_LEN + EC_TAG_LEN + EC_CIPHERKEY_LEN)
#endif

#define BOOT_ENC_KEY_ALIGN_SIZE ALIGN_UP(BOOT_ENC_KEY_SIZE, BOOT_MAX_ALIGN)
#define BOOT_ENC_TLV_ALIGN_SIZE ALIGN_UP(BOOT_ENC_TLV_SIZE, BOOT_MAX_ALIGN)

#ifdef __cplusplus
}
#endif
Expand Down
53 changes: 14 additions & 39 deletions boot/bootutil/src/encrypted.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,28 +46,6 @@

#include "bootutil_priv.h"

#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE

#if defined(MCUBOOT_ENCRYPT_RSA)
# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048
#elif defined(MCUBOOT_ENCRYPT_KW)
# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW
#elif defined(MCUBOOT_ENCRYPT_EC256)
# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256
# define EC_PUBK_INDEX (0)
# define EC_TAG_INDEX (65)
# define EC_CIPHERKEY_INDEX (65 + 32)
_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN,
"Please fix ECIES-P256 component indexes");
#elif defined(MCUBOOT_ENCRYPT_X25519)
# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519
# define EC_PUBK_INDEX (0)
# define EC_TAG_INDEX (32)
# define EC_CIPHERKEY_INDEX (32 + 32)
_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN,
"Please fix ECIES-X25519 component indexes");
#endif

/* NOUP Fixme: */
#if !defined(CONFIG_BOOT_ED25519_PSA)
#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Expand Down Expand Up @@ -104,7 +82,7 @@ key_unwrap(const uint8_t *wrapped, uint8_t *enckey, struct bootutil_key *bootuti
if (rc != 0) {
goto done;
}
rc = bootutil_aes_kw_unwrap(&aes_kw, wrapped, TLV_ENC_KW_SZ, enckey, BOOT_ENC_KEY_SIZE);
rc = bootutil_aes_kw_unwrap(&aes_kw, wrapped, BOOT_ENC_TLV_SIZE, enckey, BOOT_ENC_KEY_SIZE);
if (rc != 0) {
goto done;
}
Expand All @@ -119,9 +97,6 @@ key_unwrap(const uint8_t *wrapped, uint8_t *enckey, struct bootutil_key *bootuti
static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED;
static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1;

#define SHARED_KEY_LEN NUM_ECC_BYTES
#define PRIV_KEY_LEN NUM_ECC_BYTES

/*
* Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic
* curve keypair. See RFC5208 and RFC5915.
Expand Down Expand Up @@ -201,9 +176,6 @@ parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \
MBEDTLS_OID_ORG_GOV X25519_OID;

#define SHARED_KEY_LEN 32
#define PRIV_KEY_LEN 32

static int
parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
{
Expand Down Expand Up @@ -243,11 +215,11 @@ parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
return -7;
}

if (len != PRIV_KEY_LEN) {
if (len != EC_PRIVK_LEN) {
return -8;
}

memcpy(private_key, *p, PRIV_KEY_LEN);
memcpy(private_key, *p, EC_PRIVK_LEN);
return 0;
}
#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
Expand Down Expand Up @@ -421,11 +393,11 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey)
bootutil_hmac_sha256_context hmac;
bootutil_aes_ctr_context aes_ctr;
uint8_t tag[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
uint8_t shared[SHARED_KEY_LEN];
uint8_t shared[EC_SHARED_LEN];
uint8_t derived_key[BOOT_ENC_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
uint8_t *cp;
uint8_t *cpend;
uint8_t private_key[PRIV_KEY_LEN];
uint8_t private_key[EC_PRIVK_LEN];
uint8_t counter[BOOT_ENC_BLOCK_SIZE];
uint16_t len;
#endif
Expand Down Expand Up @@ -531,7 +503,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey)
*/

len = BOOT_ENC_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
rc = hkdf(shared, SHARED_KEY_LEN, (uint8_t *)"MCUBoot_ECIES_v1", 16,
rc = hkdf(shared, EC_SHARED_LEN, (uint8_t *)"MCUBoot_ECIES_v1", 16,
derived_key, &len);
if (rc != 0 || len != (BOOT_ENC_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE)) {
return -1;
Expand All @@ -543,6 +515,9 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey)

bootutil_hmac_sha256_init(&hmac);

/* First BOOT_ENC_KEY_SIZE are used for decryption, remaining 32 bytes are used
* for MAC tag key
*/
rc = bootutil_hmac_sha256_set_key(&hmac, &derived_key[BOOT_ENC_KEY_SIZE], 32);
if (rc != 0) {
(void)bootutil_hmac_sha256_drop(&hmac);
Expand All @@ -562,7 +537,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey)
return -1;
}

if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], 32) != 0) {
if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], EC_TAG_LEN) != 0) {
return -1;
}

Expand Down Expand Up @@ -618,7 +593,7 @@ boot_enc_load(struct boot_loader_state *state, int slot,
#if MCUBOOT_SWAP_SAVE_ENCTLV
uint8_t *buf;
#else
uint8_t buf[EXPECTED_ENC_LEN];
uint8_t buf[BOOT_ENC_TLV_SIZE];
#endif
int rc;

Expand All @@ -638,7 +613,7 @@ boot_enc_load(struct boot_loader_state *state, int slot,
#endif
#endif

rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_ENC_TLV, false);
rc = bootutil_tlv_iter_begin(&it, hdr, fap, BOOT_ENC_TLV, false);
if (rc) {
return -1;
}
Expand All @@ -648,7 +623,7 @@ boot_enc_load(struct boot_loader_state *state, int slot,
return rc;
}

if (len != EXPECTED_ENC_LEN) {
if (len != BOOT_ENC_TLV_SIZE) {
return -1;
}

Expand All @@ -657,7 +632,7 @@ boot_enc_load(struct boot_loader_state *state, int slot,
memset(buf, 0xff, BOOT_ENC_TLV_ALIGN_SIZE);
#endif

rc = flash_area_read(fap, off, buf, EXPECTED_ENC_LEN);
rc = flash_area_read(fap, off, buf, BOOT_ENC_TLV_SIZE);
if (rc) {
return -1;
}
Expand Down
18 changes: 3 additions & 15 deletions boot/bootutil/src/encrypted_psa.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,10 @@

BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc);

#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE
#define EC_PUBK_INDEX (0)
#define EC_PUBK_LEN (32)
#define EC_TAG_INDEX (EC_PUBK_INDEX + EC_PUBK_LEN)
#define EC_TAG_LEN (32)
#define EC_CIPHERKEY_INDEX (EC_TAG_INDEX + EC_TAG_LEN)
#define EC_CIPHERKEY_LEN BOOT_ENC_KEY_SIZE
_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN,
"Please fix ECIES-X25519 component indexes");

#define X25519_OID "\x6e"
static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \
MBEDTLS_OID_ORG_GOV X25519_OID;

#define PRIV_KEY_LEN 32

/* Partitioning of HKDF derived material, from the exchange derived key */
/* AES key encryption key */
#define HKDF_AES_KEY_INDEX 0
Expand Down Expand Up @@ -93,11 +81,11 @@ parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
return -7;
}

if (len != PRIV_KEY_LEN) {
if (len != EC_PRIVK_LEN) {
return -8;
}

memcpy(private_key, *p, PRIV_KEY_LEN);
memcpy(private_key, *p, EC_PRIVK_LEN);
return 0;
}

Expand Down Expand Up @@ -127,7 +115,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey)
uint8_t derived_key[HKDF_SIZE];
uint8_t *cp;
uint8_t *cpend;
uint8_t private_key[PRIV_KEY_LEN];
uint8_t private_key[EC_PRIVK_LEN];
size_t len;
psa_status_t psa_ret = PSA_ERROR_BAD_STATE;
psa_status_t psa_cleanup_ret = PSA_ERROR_BAD_STATE;
Expand Down
Loading