From 7781148d97ee14ed22022baa356231264c983c10 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Mon, 25 Aug 2025 16:16:31 +0200 Subject: [PATCH] [nrf fromtree] boot: Enable Encryption with PSA + ECDSA This configuration was not supported until now. Signed-off-by: Artur Hadasz (cherry picked from commit e375252c3d98e8bb1f2e219c172b56f052ab9310) --- boot/bootutil/src/encrypted.c | 65 ++++++++++----------- boot/bootutil/src/encrypted_psa.c | 96 +++++++++++++++++++++++++++++-- boot/zephyr/CMakeLists.txt | 9 +-- 3 files changed, 130 insertions(+), 40 deletions(-) diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index cf6f380e2..9792a9038 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -22,11 +22,11 @@ #include "bootutil/crypto/aes_kw.h" #endif +#if !defined(MCUBOOT_USE_PSA_CRYPTO) #if defined(MCUBOOT_ENCRYPT_EC256) #include "bootutil/crypto/ecdh_p256.h" #endif -#if !defined(MCUBOOT_USE_PSA_CRYPTO) #if defined(MCUBOOT_ENCRYPT_X25519) #include "bootutil/crypto/ecdh_x25519.h" #endif @@ -50,7 +50,7 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #include "bootutil_priv.h" /* NOUP Fixme: */ -#if !defined(CONFIG_BOOT_ED25519_PSA) +#if !defined(CONFIG_BOOT_ED25519_PSA) && !defined(CONFIG_BOOT_ECDSA_PSA) #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) #if defined(_compare) static inline int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size) @@ -105,65 +105,64 @@ static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1; * curve keypair. See RFC5208 and RFC5915. */ static int -parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) +parse_priv_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) { - int rc; size_t len; int version; mbedtls_asn1_buf alg; mbedtls_asn1_buf param; - if ((rc = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + if (mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { return -1; } if (*p + len != end) { - return -2; + return -1; } version = 0; if (mbedtls_asn1_get_int(p, end, &version) || version != 0) { - return -3; + return -1; } - if ((rc = mbedtls_asn1_get_alg(p, end, &alg, ¶m)) != 0) { - return -5; + if (mbedtls_asn1_get_alg(p, end, &alg, ¶m) != 0) { + return -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 -6; + return -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 -7; + return -1; } - if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { - return -8; + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return -1; } /* RFC5915 - ECPrivateKey */ - if ((rc = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return -9; + if (mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return -1; } version = 0; if (mbedtls_asn1_get_int(p, end, &version) || version != 1) { - return -10; + return -1; } /* privateKey */ - if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { - return -11; + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return -1; } if (len != NUM_ECC_BYTES) { - return -12; + return -1; } memcpy(private_key, *p, len); @@ -180,7 +179,7 @@ static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_GOV X25519_OID; static int -parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) +parse_priv_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) { size_t len; int version; @@ -193,33 +192,33 @@ parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) } if (*p + len != end) { - return -2; + return -1; } version = 0; if (mbedtls_asn1_get_int(p, end, &version) || version != 0) { - return -3; + return -1; } if (mbedtls_asn1_get_alg(p, end, &alg, ¶m) != 0) { - return -4; + return -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 -5; + return -1; } if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { - return -6; + return -1; } if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { - return -7; + return -1; } if (len != EC_PRIVK_LEN) { - return -8; + return -1; } memcpy(private_key, *p, EC_PRIVK_LEN); @@ -455,8 +454,9 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) * Load the stored EC256 decryption private key */ - rc = parse_ec256_enckey(&cp, cpend, private_key); + rc = parse_priv_enckey(&cp, cpend, private_key); if (rc) { + BOOT_LOG_ERR("Failed to parse ASN1 private key"); return rc; } @@ -482,8 +482,9 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) * Load the stored X25519 decryption private key */ - rc = parse_x25519_enckey(&cp, cpend, private_key); + rc = parse_priv_enckey(&cp, cpend, private_key); if (rc) { + BOOT_LOG_ERR("Failed to parse ASN1 private key"); return rc; } @@ -580,7 +581,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) return rc; } -#endif /* CONFIG_BOOT_ED25519_PSA */ +#endif /* CONFIG_BOOT_ED25519_PSA && CONFIG_BOOT_ECDSA_PSA */ /* * Load encryption key. diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c index 7e53ed4a7..55f7f6f2d 100644 --- a/boot/bootutil/src/encrypted_psa.c +++ b/boot/bootutil/src/encrypted_psa.c @@ -33,9 +33,18 @@ BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc); #define PSA_HMAC_HKDF_SHA PSA_ALG_SHA_256 #endif +#if defined(MCUBOOT_ENCRYPT_EC256) +#define NUM_ECC_BYTES (256 / 8) +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 ECC_FAMILY PSA_ECC_FAMILY_SECP_R1 +#endif /* defined(MCUBOOT_ENCRYPT_EC256) */ +#if defined(MCUBOOT_ENCRYPT_X25519) #define X25519_OID "\x6e" static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_GOV X25519_OID; +#define ECC_FAMILY PSA_ECC_FAMILY_MONTGOMERY +#endif /* defined(MCUBOOT_ENCRYPT_X25519) */ /* Partitioning of HKDF derived material, from the exchange derived key */ /* AES key encryption key */ @@ -51,9 +60,86 @@ static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ /* Total size */ #define HKDF_SIZE (HKDF_AES_KEY_SIZE + HKDF_MAC_FEED_SIZE) +#if defined(MCUBOOT_ENCRYPT_EC256) +/* Fixme: This duplicates code from encrypted.c and depends on mbedtls */ + +/* + * Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic + * curve keypair. See RFC5208 and RFC5915. + */ +static int +parse_priv_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) +{ + size_t len; + int version; + mbedtls_asn1_buf alg; + mbedtls_asn1_buf param; + + if (mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return -1; + } + + if (*p + len != end) { + return -1; + } + + version = 0; + if (mbedtls_asn1_get_int(p, end, &version) || version != 0) { + return -1; + } + + if (mbedtls_asn1_get_alg(p, end, &alg, ¶m) != 0) { + return -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 -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 -1; + } + + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return -1; + } + + /* RFC5915 - ECPrivateKey */ + + if (mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return -1; + } + + version = 0; + if (mbedtls_asn1_get_int(p, end, &version) || version != 1) { + return -1; + } + + /* privateKey */ + + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return -1; + } + + if (len != NUM_ECC_BYTES) { + return -1; + } + + memcpy(private_key, *p, len); + + /* publicKey usually follows but is not parsed here */ + + return 0; +} +#endif /* defined(MCUBOOT_ENCRYPT_EC256) */ + +#if defined(MCUBOOT_ENCRYPT_X25519) /* Fixme: This duplicates code from encrypted.c and depends on mbedtls */ static int -parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) +parse_priv_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) { size_t len; int version; @@ -98,6 +184,7 @@ parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) memcpy(private_key, *p, EC_PRIVK_LEN); return 0; } +#endif /* defined(MCUBOOT_ENCRYPT_X25519) */ void bootutil_aes_ctr_init(bootutil_aes_ctr_context *ctx) { @@ -153,14 +240,15 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) } /* - * Load the stored X25519 decryption private key + * * Load the stored decryption private key */ - rc = parse_x25519_enckey(&cp, cpend, private_key); + rc = parse_priv_enckey(&cp, cpend, private_key); if (rc) { + BOOT_LOG_ERR("Failed to parse ASN1 private key"); return rc; } - psa_set_key_type(&kattr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY)); + psa_set_key_type(&kattr, PSA_KEY_TYPE_ECC_KEY_PAIR(ECC_FAMILY)); psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&kattr, PSA_ALG_ECDH); diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index e8d79af7d..f9e0e70bc 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -123,11 +123,12 @@ zephyr_library_sources( ${BOOT_DIR}/bootutil/src/fault_injection_hardening.c ) -if(DEFINED CONFIG_BOOT_ENCRYPT_X25519 AND DEFINED CONFIG_BOOT_ED25519_PSA) +if((CONFIG_BOOT_ENCRYPT_X25519 AND CONFIG_BOOT_ED25519_PSA) + OR (CONFIG_BOOT_ENCRYPT_EC256 AND CONFIG_BOOT_ECDSA_PSA)) zephyr_library_sources(${BOOT_DIR}/bootutil/src/encrypted_psa.c) endif() -if(DEFINED CONFIG_MEASURED_BOOT OR DEFINED CONFIG_BOOT_SHARE_DATA) +if(CONFIG_MEASURED_BOOT OR CONFIG_BOOT_SHARE_DATA) zephyr_library_sources( ${BOOT_DIR}/bootutil/src/boot_record.c ) @@ -321,7 +322,7 @@ elseif(CONFIG_BOOT_SIGNATURE_TYPE_ED25519 OR CONFIG_BOOT_ENCRYPT_X25519) endif() endif() -if(NOT CONFIG_BOOT_ED25519_PSA) +if(NOT CONFIG_BOOT_ED25519_PSA AND NOT CONFIG_BOOT_ECDSA_PSA) if(CONFIG_BOOT_ENCRYPT_EC256 OR CONFIG_BOOT_ENCRYPT_X25519) zephyr_library_sources( ${TINYCRYPT_DIR}/source/aes_encrypt.c @@ -333,7 +334,7 @@ if(NOT CONFIG_BOOT_ED25519_PSA) endif() endif() -if(CONFIG_BOOT_ENCRYPT_EC256) +if(CONFIG_BOOT_ENCRYPT_EC256 AND NOT CONFIG_BOOT_ECDSA_PSA) zephyr_library_sources( ${TINYCRYPT_DIR}/source/ecc_dh.c )