diff --git a/.gitignore b/.gitignore index 45ad705fb4..8aa6f25b24 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ target.sh *.pyc tags rusty-tags.* +.vscode # mynewt /repos/ @@ -34,3 +35,9 @@ compile_commands.json # The target directory from Rust development /target/ + +build* +_build* + +west.yml +module.yml \ No newline at end of file diff --git a/boot/bootutil/include/bootutil/bootutil_hwrng.h b/boot/bootutil/include/bootutil/bootutil_hwrng.h new file mode 100644 index 0000000000..236b5dea25 --- /dev/null +++ b/boot/bootutil/include/bootutil/bootutil_hwrng.h @@ -0,0 +1,27 @@ +#ifndef H_BOOTUTIL_HWRNG_H_ +#define H_BOOTUTIL_HWRNG_H_ + +#include "ignore.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef MCUBOOT_HAVE_HWRNG +#include + +#define BOOT_RNG(...) MCUBOOT_RNG(__VA_ARGS__) + +#else + +#define BOOT_RNG(...) IGNORE(__VA_ARGS__) + +#endif /* MCUBOOT_HAVE_RNG */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/boot/bootutil/include/bootutil/generate_key_pair.h b/boot/bootutil/include/bootutil/generate_key_pair.h new file mode 100644 index 0000000000..7b22af1e86 --- /dev/null +++ b/boot/bootutil/include/bootutil/generate_key_pair.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 WIKA Alexander Wiegand SE & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef __GENERATE_KEY_PAIR_H__ +#define __GENERATE_KEY_PAIR_H__ + +#ifdef __cplusplus +extern "C" { +#endif +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/pk.h" +#include "mbedtls/ecp.h" + +void generate_enc_key_pair(); +int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen); +int gen_p256_keypair(mbedtls_pk_context *pk); +void dump_p256(const mbedtls_pk_context *pk); +int export_privkey_der(mbedtls_pk_context *pk); +int export_pub_pem(mbedtls_pk_context *pk); + +#ifdef __cplusplus +} +#endif + +#endif /* __GENERATE_KEY_PAIR_H__ */ \ No newline at end of file diff --git a/boot/bootutil/src/generate_key_pair.c b/boot/bootutil/src/generate_key_pair.c new file mode 100644 index 0000000000..ab05336869 --- /dev/null +++ b/boot/bootutil/src/generate_key_pair.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2025 WIKA Alexander Wiegand SE & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "mcuboot_config/mcuboot_config.h" + +#if defined(MCUBOOT_GEN_ENC_KEY) +#include +#include +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/pk.h" +#include "mbedtls/ecp.h" +#include "bootutil/generate_key_pair.h" +#include "bootutil/bootutil_log.h" +#include "bootutil/bootutil_hwrng.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +/** + * @brief Generate random data using the hardware random number generator. + * + * @param data Not used. + * @param output Buffer to fill with random data. + * @param len Number of random bytes to generate. + * @param olen Number of random bytes actually generated. + * + * @return 0 on success or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED on RNG failure. + */ +#if !defined(CONFIG_MBEDTLS_ENTROPY_POLL_ZEPHYR) +#define NBR_WARM_UP 8 +int +mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen) +{ + (void)data; + uint32_t val; + size_t produced = 0; + + for (int i = 0; i < NBR_WARM_UP; i++) { + BOOT_RNG(&val); + } + BOOT_LOG_INF("RNG value: %u\r\n", val); + + BOOT_LOG_INF("mbedtls_hardware_poll: ask %lu bytes", (unsigned long)len); + + while (produced < len) { + if (BOOT_RNG(&val) != 0) { + BOOT_LOG_ERR("RNG reads fails at %lu/%lu bytes", + (unsigned long)produced, (unsigned long)len); + *olen = produced; + return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + } + + size_t copy_len = (len - produced >= 4) ? 4 : (len - produced); + memcpy(output + produced, &val, copy_len); + produced += copy_len; + BOOT_LOG_INF("val=0x%lX producted=%lu len=%lu", (unsigned long)val, + (unsigned long)produced, (unsigned long)len); + } + *olen = produced; + BOOT_LOG_INF("mbedtls_hardware_poll: total generated = %lu bytes", + (unsigned long)*olen); + return 0; +} +#endif + +/** + * @brief Wrap mbedtls_hardware_poll + * + * @return Function to generate random data using the hardware random number generator + */ +int +mbedtls_hardware_polll_full(void *data, unsigned char *output, size_t len) +{ + + size_t dummy; + return mbedtls_hardware_poll(data, output, len, &dummy); +} + +/** + * @brief Generate public and private key and contain in mbedtls_pk_context. + * + * @param pk Initialize mbedtls_pk_context and contains the generate key pair. + * + * @return 0 for Success. + * @return Not equal to zero, therefore failure. + */ +int +gen_p256_keypair(mbedtls_pk_context *pk) +{ + int ret; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + const unsigned char pers[] = "keyge-p256-keygenkeyge-p256-keygen"; + + mbedtls_pk_init(pk); + mbedtls_entropy_init(&entropy); + mbedtls_ctr_drbg_init(&ctr_drbg); + + ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_hardware_polll_full, NULL, + pers, sizeof(pers) - 1); + if (ret != 0) { + BOOT_LOG_ERR("SEED FAIL ret=%d", ret); + goto cleanup; + } + + ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)); + if (ret != 0) { + BOOT_LOG_ERR("PK_SETUP FAIL ret=%d", ret); + goto cleanup; + } + + ret = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, mbedtls_pk_ec(*pk), + mbedtls_ctr_drbg_random, &ctr_drbg); + if (ret != 0) { + BOOT_LOG_ERR("GEN_KEY FAIL ret=%d", ret); + goto cleanup; + } + +cleanup: + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + return ret; +} + +/** + * @brief Export private key in PKCS8 format. + * + * @param pk Initialize mbedtls_pk_context and contains the generate key pair. + * + * @return 0 for Success. + * @return Not equal to zero, therefore failure. + */ +int +export_privkey_der(mbedtls_pk_context *pk) +{ + unsigned char buf[800]; + unsigned char *der_ptr; + size_t der_len; + char line[160]; + int pos = 0; + + int len = mbedtls_pk_write_keypkcs8_der(pk, buf, sizeof(buf)); + if (len < 0) { + BOOT_LOG_ERR("fails write pkcs8 der"); + return len; + } + + der_ptr = buf + sizeof(buf) - len; + der_len = (size_t)len; + + BOOT_LOG_INF("Private key DER length = %u\n", (unsigned int)der_len); + + for (size_t i = 0; i < der_len; i++) { + unsigned int val = (unsigned int)der_ptr[i]; + if (val < 0x10) { + pos += snprintk(&line[pos], sizeof(line) - pos, "0x0%X", val); + } else { + pos += snprintk(&line[pos], sizeof(line) - pos, "0x%X", val); + } + + if (i < der_len - 1) { + pos += snprintk(&line[pos], sizeof(line) - pos, ","); + } + + if (pos > sizeof(line) - 8 || i == der_len - 1) { + BOOT_LOG_INF("%s", line); + pos = 0; + } + } + + return 0; +} + +/** + * @brief Export private and public key in PEM format. + * + * @param pk Initialize mbedtls_pk_context and contains the generate key pair. + * + * @return 0 for Success. + * @return Not equal to zero, therefore failure. + */ +int +export_pub_pem(mbedtls_pk_context *pk) +{ + unsigned char buf_pub[800]; + unsigned char buf_priv[800]; + int ret; + + ret = mbedtls_pk_write_pubkey_pem(pk, buf_pub, sizeof(buf_pub)); + if (ret != 0) { + + return ret; + } + + ret = mbedtls_pk_write_key_pem(pk, buf_priv, sizeof(buf_priv)); + if (ret != 0) { + + return ret; + } + + BOOT_LOG_INF("\n%s", buf_pub); + BOOT_LOG_INF("\n%s", buf_priv); + return 0; +} + +/** + * @brief Print private and public key + * + * @param pk Initialize mbedtls_pk_context and contains the generate key pair. + * + */ +void +dump_p256(const mbedtls_pk_context *pk) +{ + const mbedtls_ecp_keypair *eckey = mbedtls_pk_ec(*pk); + unsigned char buf[32]; + memset(buf, 0, sizeof buf); + mbedtls_mpi_write_binary(&eckey->private_d, buf, 32); + BOOT_LOG_INF("Private key d = "); + for (int i = 0; i < 32; i++) { + BOOT_LOG_INF("%02X", buf[i]); + } + BOOT_LOG_INF("\n"); + + mbedtls_mpi_write_binary(&eckey->private_Q.private_X, buf, 32); + BOOT_LOG_INF("Public key Q.X = "); + for (int i = 0; i < 32; i++) { + BOOT_LOG_INF("%02X", buf[i]); + } + BOOT_LOG_INF("\n"); + + mbedtls_mpi_write_binary(&eckey->private_Q.private_Y, buf, 32); + BOOT_LOG_INF("Public key Q.Y = "); + for (int i = 0; i < 32; i++) { + BOOT_LOG_INF("%02X", buf[i]); + } + BOOT_LOG_INF("\n"); +} + +/** + * @brief Generate public and private key for encryption in (PKCS8 and PEM format). + * + * @param pk Initialize mbedtls_pk_context and contains the generate key pair. + * + * @note On failure, print error message. + * @note On success, print success message. + */ +void +generate_enc_key_pair() +{ + mbedtls_pk_context pk; + int rc = -1; + BOOT_LOG_INF("Generate enc key pair starting..."); + rc = gen_p256_keypair(&pk); + rc = export_privkey_der(&pk); + rc = export_pub_pem(&pk); + dump_p256(&pk); + + if (rc != 0) { + BOOT_LOG_ERR("Error during the generation enc key pair\n"); + } else { + BOOT_LOG_INF("Success key is generated"); + } +} + +#endif /* MCUBOOT_GEN_ENC_KEY */ diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 1813ea3217..85b39c2579 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -61,6 +61,11 @@ zephyr_library_include_directories( if(DEFINED CONFIG_MBEDTLS) zephyr_library_include_directories( ${ZEPHYR_MBEDTLS_MODULE_DIR}/include + ${ZEPHYR_MBEDTLS_MODULE_DIR}/library + ) + zephyr_library_sources( + ${ZEPHYR_MBEDTLS_MODULE_DIR}/library + ) endif() @@ -185,6 +190,17 @@ else() endif() endif() +if(CONFIG_BOOT_HAVE_HWRNG) + zephyr_library_sources( + boot_rng.c + ) +endif() +if(CONFIG_BOOT_GEN_ENC_KEY) + zephyr_library_sources( + ${BOOT_DIR}/bootutil/src/generate_key_pair.c + ${MCUBOOT_DIR}/ext/mbedtls-pkcs8/pkcs8secp256write.c + ) +endif() if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) # When ECDSA PSA is used, do not pull in additional ASN.1 include # directories or sources, as it would cause incorrect header files diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 2f7e25da05..995e74632e 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -135,6 +135,14 @@ endif # BOOT_USE_PSA_CRYPTO menu "MCUBoot settings" +config BOOT_HAVE_HWRNG + bool "have hwrng" + help + Dependencies RNG drivers + +config BOOT_GEN_ENC_KEY + bool "generate encryption key" + config SINGLE_APPLICATION_SLOT bool "Single slot bootloader" help @@ -300,6 +308,17 @@ config BOOT_ECDSA_PSA select BOOT_IMG_HASH_ALG_SHA512_ALLOW select BOOT_ECDSA_PSA_DEPENDENCIES +config BOOT_ECDSA_MBEDTLS + bool "Use mbedTLS" + select BOOT_USE_MBEDTLS + # select BOOT_IMG_HASH_ALG_SHA256_ALLOW + # select BOOT_IMG_HASH_ALG_SHA512_ALLOW + # select MBEDTLS + # select MBEDTLS_ECDSA_C + # select MBEDTLS_ECP_DP_SECP256R1_ENABLED + # select MBEDTLS_ECP_DP_SECP521R1_ENABLED + # select MBEDTLS_ECDH_C + endchoice # Ecdsa implementation endif diff --git a/boot/zephyr/app.overlay b/boot/zephyr/app.overlay index 74d3dfbfd2..0d1cd902cd 100644 --- a/boot/zephyr/app.overlay +++ b/boot/zephyr/app.overlay @@ -2,4 +2,4 @@ chosen { zephyr,code-partition = &boot_partition; }; -}; +}; \ No newline at end of file diff --git a/boot/zephyr/boot_rng.c b/boot/zephyr/boot_rng.c new file mode 100644 index 0000000000..6a9d7c8f1d --- /dev/null +++ b/boot/zephyr/boot_rng.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2025 WIKA Alexander Wiegand SE & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "boot_rng.h" + +int +generator_hw_rng(uint32_t *val) +{ + *val = sys_rand32_get(); + + return 0; +} diff --git a/boot/zephyr/include/boot_rng.h b/boot/zephyr/include/boot_rng.h new file mode 100644 index 0000000000..c97a773dad --- /dev/null +++ b/boot/zephyr/include/boot_rng.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2025 WIKA Alexander Wiegand SE & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _BOOT_RNG_H_ +#define _BOOT_RNG_H_ + +#include +#include +#include + +int generator_hw_rng(uint32_t *val); + +#endif /*_BOOT_RNG_H_*/ diff --git a/boot/zephyr/include/config-ec.h b/boot/zephyr/include/config-ec.h index f6c690b8c5..8b04278511 100644 --- a/boot/zephyr/include/config-ec.h +++ b/boot/zephyr/include/config-ec.h @@ -91,4 +91,14 @@ #define MBEDTLS_NIST_KW_C #endif /* MCUBOOT_ENC_IMAGES */ +#if defined(CONFIG_BOOT_HAVE_HWRNG) +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_PEM_WRITE_C +#define MBEDTLS_BASE64_C +#define MBEDTLS_PEM_PARSE_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_ERROR_C +#define MBEDTLS_PK_WRITE_C +#endif /*CONFIG_BOOT_HAVE_HWRNG*/ + #endif /* MCUBOOT_MBEDTLS_CONFIG_ECDSA */ diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 5dec8a2577..c579949ba5 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -161,6 +161,14 @@ #define MCUBOOT_ENCRYPT_EC256 #endif +#ifdef CONFIG_BOOT_HAVE_HWRNG +#define MCUBOOT_HAVE_HWRNG +#endif + +#ifdef CONFIG_BOOT_GEN_ENC_KEY +#define MCUBOOT_GEN_ENC_KEY +#endif + #ifdef CONFIG_BOOT_ENCRYPT_X25519 #define MCUBOOT_ENC_IMAGES #define MCUBOOT_ENCRYPT_X25519 diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_rng.h b/boot/zephyr/include/mcuboot_config/mcuboot_rng.h new file mode 100644 index 0000000000..7cfee393a6 --- /dev/null +++ b/boot/zephyr/include/mcuboot_config/mcuboot_rng.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2025 WIKA Alexander Wiegand SE & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef __MCUBOOT_RNG_H__ +#define __MCUBOOT_RNG_H__ + +#include "boot_rng.h" + +#define MCUBOOT_RNG(...) generator_hw_rng(__VA_ARGS__) + +#endif /* __MCUBOOT_RNG_H__ */ \ No newline at end of file diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 1494002e7e..b04189c89b 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#include "bootutil/bootutil_hwrng.h" #include #include #include @@ -28,6 +28,7 @@ #include #include #include +#include "bootutil/generate_key_pair.h" #if defined(CONFIG_BOOT_DISABLE_CACHES) #include @@ -58,21 +59,21 @@ #include #include -#define IMAGE_INDEX_0 0 -#define IMAGE_INDEX_1 1 +#define IMAGE_INDEX_0 0 +#define IMAGE_INDEX_1 1 -#define PRIMARY_SLOT 0 -#define SECONDARY_SLOT 1 +#define PRIMARY_SLOT 0 +#define SECONDARY_SLOT 1 -#define IMAGE0_PRIMARY_START_ADDRESS \ - DT_PROP_BY_IDX(DT_NODE_BY_FIXED_PARTITION_LABEL(image_0), reg, 0) -#define IMAGE0_PRIMARY_SIZE \ - DT_PROP_BY_IDX(DT_NODE_BY_FIXED_PARTITION_LABEL(image_0), reg, 1) +#define IMAGE0_PRIMARY_START_ADDRESS \ + DT_PROP_BY_IDX(DT_NODE_BY_FIXED_PARTITION_LABEL(image_0), reg, 0) +#define IMAGE0_PRIMARY_SIZE \ + DT_PROP_BY_IDX(DT_NODE_BY_FIXED_PARTITION_LABEL(image_0), reg, 1) -#define IMAGE1_PRIMARY_START_ADDRESS \ - DT_PROP_BY_IDX(DT_NODE_BY_FIXED_PARTITION_LABEL(image_1), reg, 0) -#define IMAGE1_PRIMARY_SIZE \ - DT_PROP_BY_IDX(DT_NODE_BY_FIXED_PARTITION_LABEL(image_1), reg, 1) +#define IMAGE1_PRIMARY_START_ADDRESS \ + DT_PROP_BY_IDX(DT_NODE_BY_FIXED_PARTITION_LABEL(image_1), reg, 0) +#define IMAGE1_PRIMARY_SIZE \ + DT_PROP_BY_IDX(DT_NODE_BY_FIXED_PARTITION_LABEL(image_1), reg, 1) #endif /* CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 */ @@ -80,10 +81,8 @@ #include "boot_serial/boot_serial.h" #include "serial_adapter/serial_adapter.h" -const struct boot_uart_funcs boot_funcs = { - .read = console_read, - .write = console_write -}; +const struct boot_uart_funcs boot_funcs = { .read = console_read, + .write = console_write }; #endif #if defined(CONFIG_BOOT_USB_DFU_WAIT) || defined(CONFIG_BOOT_USB_DFU_GPIO) @@ -94,7 +93,7 @@ const struct boot_uart_funcs boot_funcs = { #include #endif -#if defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_IMMEDIATE) && \ +#if defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_IMMEDIATE) && \ !defined(CONFIG_LOG_MODE_MINIMAL) #ifdef CONFIG_LOG_PROCESS_THREAD #warning "The log internal thread for log processing can't transfer the log"\ @@ -111,16 +110,20 @@ volatile bool boot_log_stop = false; K_SEM_DEFINE(boot_log_sem, 1, 1); /* log processing need to be initalized by the application */ -#define ZEPHYR_BOOT_LOG_START() zephyr_boot_log_start() -#define ZEPHYR_BOOT_LOG_STOP() zephyr_boot_log_stop() +#define ZEPHYR_BOOT_LOG_START() zephyr_boot_log_start() +#define ZEPHYR_BOOT_LOG_STOP() zephyr_boot_log_stop() #endif /* CONFIG_LOG_PROCESS_THREAD */ #else /* synchronous log mode doesn't need to be initalized by the application */ -#define ZEPHYR_BOOT_LOG_START() do { } while (false) -#define ZEPHYR_BOOT_LOG_STOP() do { } while (false) -#endif /* defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_IMMEDIATE) && \ - * !defined(CONFIG_LOG_MODE_MINIMAL) - */ +#define ZEPHYR_BOOT_LOG_START() \ + do { \ + } while (false) +#define ZEPHYR_BOOT_LOG_STOP() \ + do { \ + } while (false) +#endif /* defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_IMMEDIATE) && \ + * !defined(CONFIG_LOG_MODE_MINIMAL) \ + */ BOOT_LOG_MODULE_REGISTER(mcuboot); @@ -148,7 +151,8 @@ struct arm_vector_table { #endif }; -static void do_boot(struct boot_rsp *rsp) +static void +do_boot(struct boot_rsp *rsp) { /* vt is static as it shall not land on the stack, * as this procedure modifies stack pointer before usage of *vt @@ -171,8 +175,7 @@ static void do_boot(struct boot_rsp *rsp) rc = flash_device_base(rsp->br_flash_dev_id, &flash_base); assert(rc == 0); - vt = (struct arm_vector_table *)(flash_base + - rsp->br_image_off + + vt = (struct arm_vector_table *)(flash_base + rsp->br_image_off + rsp->br_hdr->ih_hdr_size); #endif @@ -199,8 +202,7 @@ static void do_boot(struct boot_rsp *rsp) z_arm_clear_arm_mpu_config(); #endif -#if defined(CONFIG_BUILTIN_STACK_GUARD) && \ - defined(CONFIG_CPU_CORTEX_M_HAS_SPLIM) +#if defined(CONFIG_BUILTIN_STACK_GUARD) && defined(CONFIG_CPU_CORTEX_M_HAS_SPLIM) /* Reset limit registers to avoid inflicting stack overflow on image * being booted. */ @@ -221,7 +223,7 @@ static void do_boot(struct boot_rsp *rsp) #elif defined(CONFIG_CPU_CORTEX_M_HAS_VTOR) SCB->VTOR = (uint32_t)vt; #endif /* CONFIG_SW_VECTOR_RELAY */ -#else /* CONFIG_BOOT_INTR_VEC_RELOC */ +#else /* CONFIG_BOOT_INTR_VEC_RELOC */ #if defined(CONFIG_CPU_CORTEX_M_HAS_VTOR) && defined(CONFIG_SW_VECTOR_RELAY) _vector_table_pointer = _vector_start; SCB->VTOR = (uint32_t)__vector_relay_table; @@ -239,23 +241,22 @@ static void do_boot(struct boot_rsp *rsp) #else /* Set mode to supervisor and A, I and F bit as described in the * Cortex R5 TRM */ - __asm__ volatile( - " mrs r0, CPSR\n" - /* change mode bits to supervisor */ - " bic r0, #0x1f\n" - " orr r0, #0x13\n" - /* set the A, I and F bit */ - " mov r1, #0b111\n" - " lsl r1, #0x6\n" - " orr r0, r1\n" - - " msr CPSR, r0\n" - ::: "r0", "r1"); + __asm__ volatile(" mrs r0, CPSR\n" + /* change mode bits to supervisor */ + " bic r0, #0x1f\n" + " orr r0, #0x13\n" + /* set the A, I and F bit */ + " mov r1, #0b111\n" + " lsl r1, #0x6\n" + " orr r0, r1\n" + + " msr CPSR, r0\n" :: + : "r0", "r1"); #endif /* CONFIG_CPU_CORTEX_M */ #endif #if CONFIG_MCUBOOT_CLEANUP_RAM - __asm__ volatile ( + __asm__ volatile( /* vt->reset -> r0 */ " mov r0, %0\n" /* base to write -> r1 */ @@ -278,21 +279,20 @@ static void do_boot(struct boot_rsp *rsp) /* jump to reset vector of an app */ " bx r0\n" : - : "r" (vt->reset), "i" (CONFIG_SRAM_BASE_ADDRESS), - "i" (CONFIG_SRAM_SIZE * 1024), "i" (0) - : "r0", "r1", "r2", "r3", "memory" - ); + : "r"(vt->reset), "i"(CONFIG_SRAM_BASE_ADDRESS), + "i"(CONFIG_SRAM_SIZE * 1024), "i"(0) + : "r0", "r1", "r2", "r3", "memory"); #else #ifdef CONFIG_CPU_CORTEX_M ((void (*)(void))vt->reset)(); #else - /* Some ARM CPUs like the Cortex-R5 can run in thumb mode but reset into ARM - * mode (depending on a CPU signal configurations). To do the switch into ARM - * mode, if needed, an explicit branch with exchange instruction set - * instruction is needed + /* Some ARM CPUs like the Cortex-R5 can run in thumb mode but reset into + * ARM mode (depending on a CPU signal configurations). To do the switch + * into ARM mode, if needed, an explicit branch with exchange instruction + * set instruction is needed */ - __asm__("bx %0\n" : : "r" (&vt->reset)); + __asm__("bx %0\n" : : "r"(&vt->reset)); #endif #endif @@ -302,9 +302,10 @@ static void do_boot(struct boot_rsp *rsp) #ifndef CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 -#define SRAM_BASE_ADDRESS 0xBE030000 +#define SRAM_BASE_ADDRESS 0xBE030000 -static void copy_img_to_SRAM(int slot, unsigned int hdr_offset) +static void +copy_img_to_SRAM(int slot, unsigned int hdr_offset) { const struct flash_area *fap; int area_id; @@ -334,7 +335,8 @@ static void copy_img_to_SRAM(int slot, unsigned int hdr_offset) /* Entry point (.ResetVector) is at the very beginning of the image. * Simply copy the image to a suitable location and jump there. */ -static void do_boot(struct boot_rsp *rsp) +static void +do_boot(struct boot_rsp *rsp) { #ifndef CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 void *start; @@ -344,8 +346,8 @@ static void do_boot(struct boot_rsp *rsp) BOOT_LOG_INF("ih_hdr_size = 0x%x\n", rsp->br_hdr->ih_hdr_size); #ifdef CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 - int slot = (rsp->br_image_off == IMAGE0_PRIMARY_START_ADDRESS) ? - PRIMARY_SLOT : SECONDARY_SLOT; + int slot = (rsp->br_image_off == IMAGE0_PRIMARY_START_ADDRESS) ? PRIMARY_SLOT + : SECONDARY_SLOT; /* Load memory segments and start from entry point */ start_cpu0_image(IMAGE_INDEX_0, slot, rsp->br_hdr->ih_hdr_size); #else @@ -365,7 +367,8 @@ static void do_boot(struct boot_rsp *rsp) * in the vector table. Assume the vector table is at the start of the image, * and jump to reset */ -static void do_boot(struct boot_rsp *rsp) +static void +do_boot(struct boot_rsp *rsp) { struct arc_vector_table { void (*reset)(void); /* Reset vector */ @@ -381,7 +384,7 @@ static void do_boot(struct boot_rsp *rsp) assert(rc == 0); vt = (struct arc_vector_table *)(flash_base + rsp->br_image_off + - rsp->br_hdr->ih_hdr_size); + rsp->br_hdr->ih_hdr_size); #endif /* Lock interrupts and dive into the entry point */ @@ -394,7 +397,8 @@ static void do_boot(struct boot_rsp *rsp) * lock interrupts and jump there. This is the right thing to do for X86 and * possibly other platforms. */ -static void do_boot(struct boot_rsp *rsp) +static void +do_boot(struct boot_rsp *rsp) { void *start; @@ -407,8 +411,7 @@ static void do_boot(struct boot_rsp *rsp) rc = flash_device_base(rsp->br_flash_dev_id, &flash_base); assert(rc == 0); - start = (void *)(flash_base + rsp->br_image_off + - rsp->br_hdr->ih_hdr_size); + start = (void *)(flash_base + rsp->br_image_off + rsp->br_hdr->ih_hdr_size); #endif /* Lock interrupts and dive into the entry point */ @@ -417,17 +420,17 @@ static void do_boot(struct boot_rsp *rsp) } #endif -#if defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_IMMEDIATE) && \ +#if defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_IMMEDIATE) && \ !defined(CONFIG_LOG_PROCESS_THREAD) && !defined(CONFIG_LOG_MODE_MINIMAL) -/* The log internal thread for log processing can't transfer log well as has too - * low priority. - * Dedicated thread for log processing below uses highest application - * priority. This allows to transmit all logs without adding k_sleep/k_yield - * anywhere else int the code. +/* The log internal thread for log processing can't transfer log well as has + * too low priority. Dedicated thread for log processing below uses highest + * application priority. This allows to transmit all logs without adding + * k_sleep/k_yield anywhere else int the code. */ /* most simple log processing theread */ -void boot_log_thread_func(void *dummy1, void *dummy2, void *dummy3) +void +boot_log_thread_func(void *dummy1, void *dummy2, void *dummy3) { (void)dummy1; (void)dummy2; @@ -447,19 +450,20 @@ void boot_log_thread_func(void *dummy1, void *dummy2, void *dummy3) k_sem_give(&boot_log_sem); } -void zephyr_boot_log_start(void) +void +zephyr_boot_log_start(void) { /* start logging thread */ k_thread_create(&boot_log_thread, boot_log_stack, - K_THREAD_STACK_SIZEOF(boot_log_stack), - boot_log_thread_func, NULL, NULL, NULL, - K_HIGHEST_APPLICATION_THREAD_PRIO, 0, + K_THREAD_STACK_SIZEOF(boot_log_stack), boot_log_thread_func, + NULL, NULL, NULL, K_HIGHEST_APPLICATION_THREAD_PRIO, 0, BOOT_LOG_PROCESSING_INTERVAL); k_thread_name_set(&boot_log_thread, "logging"); } -void zephyr_boot_log_stop(void) +void +zephyr_boot_log_stop(void) { boot_log_stop = true; @@ -470,13 +474,16 @@ void zephyr_boot_log_stop(void) */ (void)k_sem_take(&boot_log_sem, K_FOREVER); } -#endif /* defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_IMMEDIATE) && \ - * !defined(CONFIG_LOG_PROCESS_THREAD) && !defined(CONFIG_LOG_MODE_MINIMAL) +#endif /* defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_IMMEDIATE) && \ + * !defined(CONFIG_LOG_PROCESS_THREAD) && !defined(CONFIG_LOG_MODE_MINIMAL) \ */ -#if defined(CONFIG_BOOT_SERIAL_ENTRANCE_GPIO) || defined(CONFIG_BOOT_SERIAL_PIN_RESET) \ - || defined(CONFIG_BOOT_SERIAL_BOOT_MODE) || defined(CONFIG_BOOT_SERIAL_NO_APPLICATION) -static void boot_serial_enter() +#if defined(CONFIG_BOOT_SERIAL_ENTRANCE_GPIO) || \ + defined(CONFIG_BOOT_SERIAL_PIN_RESET) || \ + defined(CONFIG_BOOT_SERIAL_BOOT_MODE) || \ + defined(CONFIG_BOOT_SERIAL_NO_APPLICATION) +static void +boot_serial_enter() { int rc; @@ -494,7 +501,8 @@ static void boot_serial_enter() } #endif -int main(void) +int +main(void) { struct boot_rsp rsp; int rc; @@ -535,8 +543,7 @@ int main(void) #ifdef CONFIG_BOOT_SERIAL_ENTRANCE_GPIO BOOT_LOG_DBG("Checking GPIO for serial recovery"); - if (io_detect_pin() && - !io_boot_skip_serial_recovery()) { + if (io_detect_pin() && !io_boot_skip_serial_recovery()) { boot_serial_enter(); } #endif @@ -574,7 +581,8 @@ int main(void) BOOT_LOG_INF("Waiting for USB DFU"); #if defined(CONFIG_BOOT_USB_DFU_WAIT) - BOOT_LOG_DBG("Waiting for USB DFU for %dms", CONFIG_BOOT_USB_DFU_WAIT_DELAY_MS); + BOOT_LOG_DBG("Waiting for USB DFU for %dms", + CONFIG_BOOT_USB_DFU_WAIT_DELAY_MS); mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_WAITING); wait_for_usb_dfu(K_MSEC(CONFIG_BOOT_USB_DFU_WAIT_DELAY_MS)); BOOT_LOG_INF("USB DFU wait time elapsed"); @@ -594,6 +602,7 @@ int main(void) * initial mcumgr command(s) into our buffers */ rc = boot_console_init(); + int timeout_in_ms = CONFIG_BOOT_SERIAL_WAIT_FOR_DFU_TIMEOUT; uint32_t start = k_uptime_get_32(); @@ -606,7 +615,8 @@ int main(void) if (FIH_EQ(fih_rc, FIH_BOOT_HOOK_REGULAR)) { FIH_CALL(boot_go, fih_rc, &rsp); } - BOOT_LOG_DBG("Left boot_go with success == %d", FIH_EQ(fih_rc, FIH_SUCCESS) ? 1 : 0); + BOOT_LOG_DBG("Left boot_go with success == %d", + FIH_EQ(fih_rc, FIH_SUCCESS) ? 1 : 0); #ifdef CONFIG_BOOT_SERIAL_BOOT_MODE if (io_detect_boot_mode()) { @@ -620,11 +630,11 @@ int main(void) #ifdef CONFIG_BOOT_SERIAL_WAIT_FOR_DFU timeout_in_ms -= (k_uptime_get_32() - start); - if( timeout_in_ms <= 0 ) { + if (timeout_in_ms <= 0) { /* at least one check if time was expired */ timeout_in_ms = 1; } - boot_serial_check_start(&boot_funcs,timeout_in_ms); + boot_serial_check_start(&boot_funcs, timeout_in_ms); #ifdef CONFIG_MCUBOOT_INDICATION_LED io_led_set(0); @@ -633,6 +643,9 @@ int main(void) if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { BOOT_LOG_ERR("Unable to find bootable image"); +#if defined(MCUBOOT_GEN_ENC_KEY) && defined(MCUBOOT_HAVE_HWRNG) + generate_enc_key_pair(); +#endif mcuboot_status_change(MCUBOOT_STATUS_NO_BOOTABLE_IMAGE_FOUND); @@ -655,21 +668,19 @@ int main(void) } #ifdef MCUBOOT_RAM_LOAD - BOOT_LOG_INF("Bootloader chainload address offset: 0x%x", - rsp.br_hdr->ih_load_addr); + BOOT_LOG_INF("Bootloader chainload address offset: 0x%x", rsp.br_hdr->ih_load_addr); #else - BOOT_LOG_INF("Bootloader chainload address offset: 0x%x", - rsp.br_image_off); + BOOT_LOG_INF("Bootloader chainload address offset: 0x%x", rsp.br_image_off); #endif BOOT_LOG_INF("Image version: v%d.%d.%d", rsp.br_hdr->ih_ver.iv_major, - rsp.br_hdr->ih_ver.iv_minor, - rsp.br_hdr->ih_ver.iv_revision); + rsp.br_hdr->ih_ver.iv_minor, rsp.br_hdr->ih_ver.iv_revision); #if defined(MCUBOOT_DIRECT_XIP) BOOT_LOG_INF("Jumping to the image slot"); #else BOOT_LOG_INF("Jumping to the first image slot"); + #endif mcuboot_status_change(MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND); diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index b824ca1b1a..13610806fa 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -29,3 +29,17 @@ CONFIG_CBPRINTF_NANO=y CONFIG_PICOLIBC=y ### Disable malloc arena because we don't need it CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 + +CONFIG_BOOT_VALIDATE_SLOT0=y +CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y + +CONFIG_BOOT_SIGNATURE_KEY_FILE="root-ec-p256.pem" +# generated key enc +CONFIG_MBEDTLS=y +CONFIG_CUSTOM_MBEDTLS_CFG_FILE=y +CONFIG_MBEDTLS_CFG_FILE="config-ec.h" +CONFIG_BOOT_ECDSA_MBEDTLS=y +CONFIG_BOOT_GEN_ENC_KEY=y +CONFIG_BOOT_HAVE_HWRNG=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_TIMER_RANDOM_GENERATOR=y \ No newline at end of file diff --git a/docs/key_generation.md b/docs/key_generation.md new file mode 100644 index 0000000000..d434475afc --- /dev/null +++ b/docs/key_generation.md @@ -0,0 +1,53 @@ +# Key Generation for Firmware Encryption with Mcuboot + +## Context + +Mcuboot supports firmware encryption using the Elliptic Curve Integrated Encryption Scheme (ECIES). This mechanism requires a key pair based on the SECP256R1 elliptic curve. + +- The private key is securely generated and stored within the microcontroller. +- The public key is used to encrypt firmware updates before transmission. + +## Current Implementation + +In the default Mcuboot implementation, the private key used for firmware decryption is compiled directly into the bootloader binary. + +- The key pair is generated externally (e.g, on a production machine). +- The public is used to encrypt the firmware image. +- The private key is embedded in the bootloader and used to decrypt and verify the firmware during boot. + + +## Implemented Functionality + +During the first boot, the microcontroller automatically generates a key pair. The process includes: + +1. Secure random number generation using STM32 hardware TRNG (True Random Generator). +2. ECC key pair creation (SECP256R1) using the mbedTLS library. +3. Conversion of the private key to DER format following the PKCS#8 standard. +4. Conversion of the public key to PEM format for export. + +The private key remains stored in a secure area of the microcontroller and is never exposed. The public key can be retrived during the update. + +## Process Steps + +1. Verify the integrity of the current firmware. +2. Generate a secure random number. +3. Create ECC key pair (SECP256R1). +4. Convert the private key to DER format (PKCS#8). +5. Convert the public key to PEM format. + +## PKCS#8 standard + +PrivateKeyInfo ::= SEQUENCE { + version Version, + privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + privateKey PrivateKey, + attributes [0] IMPLICIT Attributes OPTIONAL } + +## SEC1 standard + +ECPrivateKey ::= SEQUENCE { + version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + privateKey OCTET STRING, + parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + publicKey [1] BIT STRING OPTIONAL +} diff --git a/ext/mbedtls-asn1/include/mbedtls/mbedtls_config.h b/ext/mbedtls-asn1/include/mbedtls/mbedtls_config.h index 2fa14ebc36..cf60f4df61 100644 --- a/ext/mbedtls-asn1/include/mbedtls/mbedtls_config.h +++ b/ext/mbedtls-asn1/include/mbedtls/mbedtls_config.h @@ -92,5 +92,4 @@ #endif #include "check_config.h" - -#endif /* MBEDTLS_CONFIG_H */ +#endif /* MBEDTLS_CONFIG_H */ \ No newline at end of file diff --git a/ext/mbedtls-pkcs8/pkcs8secp256write.c b/ext/mbedtls-pkcs8/pkcs8secp256write.c new file mode 100644 index 0000000000..d37301e023 --- /dev/null +++ b/ext/mbedtls-pkcs8/pkcs8secp256write.c @@ -0,0 +1,256 @@ +#include "common.h" + +#if defined(MBEDTLS_PK_WRITE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "pk_internal.h" + +#endif +#include + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/bignum.h" +#include "mbedtls/ecp.h" +#include "mbedtls/platform_util.h" +#endif +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +#include "pk_internal.h" +#endif +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS) +#include "pkwrite.h" +#endif +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +#define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE +#define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH +#elif defined(MBEDTLS_USE_PSA_CRYPTO) +#define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE +#define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH +#else +#define PK_MAX_EC_PUBLIC_KEY_SIZE MBEDTLS_ECP_MAX_PT_LEN +#define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_ECP_MAX_BYTES +#endif + +static mbedtls_pk_type_t pk_get_type_ext(const mbedtls_pk_context *pk) +{ + mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (pk_type == MBEDTLS_PK_OPAQUE) { + psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t opaque_key_type; + + if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) { + return MBEDTLS_PK_NONE; + } + opaque_key_type = psa_get_key_type(&opaque_attrs); + psa_reset_key_attributes(&opaque_attrs); + + if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) { + return MBEDTLS_PK_ECKEY; + } else if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) { + return MBEDTLS_PK_RSA; + } else { + return MBEDTLS_PK_NONE; + } + } else +#endif + return pk_type; +} + +static int pk_write_ec_private(unsigned char **p, unsigned char *start, + const mbedtls_pk_context *pk) +{ + size_t byte_length; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE]; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status; + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { + status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); + if (status != PSA_SUCCESS) { + ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + return ret; + } + } else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + { + mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk); + byte_length = (ec->grp.pbits + 7) / 8; + + ret = mbedtls_ecp_write_key_ext(ec, &byte_length, tmp, sizeof(tmp)); + if (ret != 0) { + goto exit; + } + } + ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); +exit: + mbedtls_platform_zeroize(tmp, sizeof(tmp)); + return ret; +} + +static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, + const mbedtls_pk_context *pk) +{ + size_t len = 0; + unsigned char buf[PK_MAX_EC_PUBLIC_KEY_SIZE]; + mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { + if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + *p -= len; + memcpy(*p, buf, len); + return (int) len; + } else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + { + if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &len, buf, sizeof(buf))) != 0) { + return ret; + } + } + + if (*p < start || (size_t) (*p - start) < len) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + + *p -= len; + memcpy(*p, buf, len); + + return (int) len; +} + + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +/*=====Encodes an EC private key into PKCS#8 DER format.=====*/ +static int pk_write_ecpkcs8_der(unsigned char **p, unsigned char *buf, + const mbedtls_pk_context *pk) +{ + + + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + size_t pubkey_raw_len = 0; + size_t pubkey_bitstring_len = 0; + size_t pubkey_block_len = 0; + size_t ec_privkey_len = 0; + size_t alg_id_len = 0; + + /* ========publicKey========= */ + MBEDTLS_ASN1_CHK_ADD(pubkey_raw_len, pk_write_ec_pubkey(p, buf, pk)); + + if (*p - buf < 1) + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + + (*p)--; + **p = 0; + pubkey_raw_len += 1; + + /*bit string publicKey*/ + MBEDTLS_ASN1_CHK_ADD(pubkey_bitstring_len, mbedtls_asn1_write_len(p, buf, pubkey_raw_len)); + MBEDTLS_ASN1_CHK_ADD(pubkey_bitstring_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING)); + + pubkey_block_len = pubkey_raw_len + pubkey_bitstring_len; + + /*bit string publicKey in a specific tag 1 */ + MBEDTLS_ASN1_CHK_ADD(pubkey_block_len, mbedtls_asn1_write_len(p, buf, pubkey_block_len)); + MBEDTLS_ASN1_CHK_ADD(pubkey_block_len, mbedtls_asn1_write_tag(p, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1)); + + len += pubkey_block_len; + + /* ======privateKey====== */ + MBEDTLS_ASN1_CHK_ADD(ec_privkey_len, pk_write_ec_private(p, buf, pk)); + + /* version privateKey */ + MBEDTLS_ASN1_CHK_ADD(ec_privkey_len, mbedtls_asn1_write_int(p, buf, 1)); + + ec_privkey_len += pubkey_block_len; + + /* sequence privateKey */ + MBEDTLS_ASN1_CHK_ADD(ec_privkey_len, mbedtls_asn1_write_len(p, buf, ec_privkey_len)); + MBEDTLS_ASN1_CHK_ADD(ec_privkey_len, mbedtls_asn1_write_tag(p, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + + /* octet string privateKey */ + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, ec_privkey_len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING)); + + + len += ec_privkey_len - pubkey_block_len; + + /*======AlgotithmIdentifier=====*/ + MBEDTLS_ASN1_CHK_ADD(alg_id_len, mbedtls_asn1_write_oid(p, buf, + MBEDTLS_OID_EC_GRP_SECP256R1, + MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP256R1))); + + /*id-ecPublicKey*/ + const char oid_ec_public_key[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED; + MBEDTLS_ASN1_CHK_ADD(alg_id_len, mbedtls_asn1_write_oid(p, buf, + oid_ec_public_key, strlen(oid_ec_public_key))); + + /*oid sequence*/ + MBEDTLS_ASN1_CHK_ADD(alg_id_len, mbedtls_asn1_write_len(p, buf, alg_id_len)); + MBEDTLS_ASN1_CHK_ADD(alg_id_len, mbedtls_asn1_write_tag(p, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + /* version */ + size_t version_len = 0; + MBEDTLS_ASN1_CHK_ADD(version_len, mbedtls_asn1_write_int(p, buf, 0)); + + /*SEQUENCE*/ + size_t total_len = version_len + alg_id_len + len; + + MBEDTLS_ASN1_CHK_ADD(total_len, mbedtls_asn1_write_len(p, buf, total_len)); + MBEDTLS_ASN1_CHK_ADD(total_len, mbedtls_asn1_write_tag(p, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + + len += total_len - len; + + + return (int) len; +} +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + + +int mbedtls_pk_write_keypkcs8_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size) +{ + unsigned char *c; + + if (size == 0) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + + c = buf + size; + +#if defined(MBEDTLS_RSA_C) + if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) { + return pk_write_rsa_der(&c, buf, key); + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) { +#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) + if (mbedtls_pk_is_rfc8410(key)) { + return pk_write_ec_rfc8410_der(&c, buf, key); + } +#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ + return pk_write_ecpkcs8_der(&c, buf, key); + } else +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; +} + + diff --git a/zephyr/module.yml b/zephyr/module.yml index d2af55384c..2148831dd7 100644 --- a/zephyr/module.yml +++ b/zephyr/module.yml @@ -6,4 +6,4 @@ build: package-managers: pip: requirement-files: - - zephyr/requirements.txt + - zephyr/requirements.txt \ No newline at end of file