diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 99d6d5c9d..9c007547b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,6 +7,12 @@ variables: IDF_PATH: "$CI_PROJECT_DIR" + # Versioned esp-idf-doc env image to use for all document building jobs + ESP_IDF_DOC_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-idf-doc-env:v8" + + GIT_SUBMODULE_STRATEGY: recursive + ESPCI_TOKEN: $GITLAB_KEY + # before each job, we need to check if this job is filtered by bot stage/job filter .apply_bot_filter: &apply_bot_filter python $APPLY_BOT_FILTER_SCRIPT || exit 0 @@ -45,7 +51,7 @@ build_ssc: - git clone $GITLAB_SSH_SERVER/yinling/SSC.git - cd SSC # try checkout same branch - - git checkout "${CI_BUILD_REF_NAME}_8266" || echo "Using default branch..." + - git checkout "release/v3.4_8266" || echo "Using default branch..." - ./gen_misc_rtos.sh push_master_to_github: @@ -79,7 +85,7 @@ push_master_to_github: build_docs: stage: build - image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG + image: $ESP_IDF_DOC_ENV_IMAGE tags: - build_docs artifacts: diff --git a/.gitmodules b/.gitmodules index d36acbfe5..a4f43d7d3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,8 +2,12 @@ path = components/json/cJSON url = ../../DaveGamble/cJSON.git -[submodule "components/mbedtls/mbedtls"] - path = components/mbedtls/mbedtls +[submodule "components/mbedtls/mbedtls_v2/mbedtls"] + path = components/mbedtls/mbedtls_v2/mbedtls + url = ../../espressif/mbedtls.git + +[submodule "components/mbedtls/mbedtls_v3/mbedtls"] + path = components/mbedtls/mbedtls_v3/mbedtls url = ../../espressif/mbedtls.git [submodule "components/lwip/lwip"] @@ -16,4 +20,4 @@ [submodule "components/coap/libcoap"] path = components/coap/libcoap - url = ../../obgm/libcoap.git + url = https://jihulab.com/esp-mirror/obgm/libcoap.git diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index 50c7633cf..2e108b512 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -174,6 +174,15 @@ config BOOTLOADER_STORE_OFFSET bootloader of the SDK's bootloader, you can set the option to store SDK's bootloader to other space in the flash instead of "0x0". +config BOOTLOADER_FLASH_XMC_SUPPORT + bool "Enable the support for flash chips of XMC (READ HELP FIRST)" + default y + help + Perform the startup flow recommended by XMC. Please consult XMC for the details of this flow. + XMC chips will be forbidden to be used, when this option is disabled. + + DON'T DISABLE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. + endmenu # Bootloader diff --git a/components/bootloader/subproject/main/bootloader_start.c b/components/bootloader/subproject/main/bootloader_start.c index 3ba0addee..d79496db8 100644 --- a/components/bootloader/subproject/main/bootloader_start.c +++ b/components/bootloader/subproject/main/bootloader_start.c @@ -22,6 +22,7 @@ #include "esp_image_format.h" #include "esp_spi_flash.h" #include "esp_log.h" +#include "driver/soc.h" static const char* TAG = "boot"; @@ -30,6 +31,11 @@ static int selected_boot_partition(const bootloader_state_t *bs); void call_start_cpu(void) { + esp_irqflag_t irq; + + irq = soc_save_local_irq(); + ESP_LOGD(TAG, "CPU local irq: 0x%x", irq); + #ifdef CONFIG_BOOTLOADER_FAST_BOOT REG_SET_BIT(DPORT_CTL_REG, DPORT_CTL_DOUBLE_CLK); #endif diff --git a/components/bootloader/subproject/main/esp8266.bootloader.rom.ld b/components/bootloader/subproject/main/esp8266.bootloader.rom.ld index 3ff8f2710..27d35bbee 100644 --- a/components/bootloader/subproject/main/esp8266.bootloader.rom.ld +++ b/components/bootloader/subproject/main/esp8266.bootloader.rom.ld @@ -8,4 +8,5 @@ PROVIDE ( gpio_input_get = 0x40004cf0 ); PROVIDE ( xthal_get_ccount = 0x4000dd38 ); PROVIDE ( uart_div_modify = 0x400039d8 ); -PROVIDE ( ets_io_vprintf = 0x40001f00 ); \ No newline at end of file +PROVIDE ( ets_io_vprintf = 0x40001f00 ); +PROVIDE ( ets_rom_delay_us = 0x40002ecc ); \ No newline at end of file diff --git a/components/bootloader_support/include_priv/bootloader_flash.h b/components/bootloader_support/include_priv/bootloader_flash.h index 763136e03..101a32752 100644 --- a/components/bootloader_support/include_priv/bootloader_flash.h +++ b/components/bootloader_support/include_priv/bootloader_flash.h @@ -22,6 +22,11 @@ #define FLASH_SECTOR_SIZE 0x1000 +#define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */ +#define CMD_RDJEDECID 0x9F /* Read the JEDEC ID of the flash */ + +#define XMC_VENDOR_ID 0x20 + /* Provide a Flash API for bootloader_support code, that can be used from bootloader or app code. @@ -100,4 +105,20 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool */ esp_err_t bootloader_flash_erase_sector(size_t sector); +/** + * @brief Read the SFDP of the flash + * + * @param sfdp_addr Address of the parameter to read + * @param miso_byte_num Bytes to read + * @return The read SFDP, little endian, 4 bytes at most + */ +uint32_t bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num); + +/** + * @brief Startup flow recommended by XMC. Call at startup before any erase/write operation. + * + * @return ESP_OK When startup successfully, otherwise ESP_FAIL (indiciating you should reboot before erase/write). + */ +esp_err_t bootloader_flash_xmc_startup(void); + #endif diff --git a/components/bootloader_support/src/bootloader_flash.c b/components/bootloader_support/src/bootloader_flash.c index f93226b3a..47edf2126 100644 --- a/components/bootloader_support/src/bootloader_flash.c +++ b/components/bootloader_support/src/bootloader_flash.c @@ -263,9 +263,13 @@ esp_err_t bootloader_flash_erase_sector(size_t sector) #include "esp_err.h" #include "esp_log.h" +#include "esp8266/rom_functions.h" #ifndef BOOTLOADER_BUILD #include "esp_spi_flash.h" +#else +#include "bootloader_flash.h" +#include "priv/esp_spi_flash_raw.h" #endif #ifdef CONFIG_SOC_FULL_ICACHE @@ -274,18 +278,11 @@ esp_err_t bootloader_flash_erase_sector(size_t sector) #define SOC_CACHE_SIZE 0 // 16KB #endif -extern void Cache_Read_Disable(); -extern void Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t v); - -static const char *TAG = "bootloader_flash"; +#define XMC_SUPPORT CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT -typedef enum { SPI_FLASH_RESULT_OK = 0, - SPI_FLASH_RESULT_ERR = 1, - SPI_FLASH_RESULT_TIMEOUT = 2 } SpiFlashOpResult; +#define BYTESHIFT(VAR, IDX) (((VAR) >> ((IDX) * 8)) & 0xFF) -SpiFlashOpResult SPIRead(uint32_t addr, void *dst, uint32_t size); -SpiFlashOpResult SPIWrite(uint32_t addr, const uint8_t *src, uint32_t size); -SpiFlashOpResult SPIEraseSector(uint32_t sector_num); +static const char *TAG = "bootloader_flash"; static bool mapped; @@ -406,4 +403,150 @@ esp_err_t bootloader_flash_erase_sector(size_t sector) return ESP_OK; } +#ifdef BOOTLOADER_BUILD +uint32_t bootloader_read_flash_id(void) +{ + uint32_t id = spi_flash_get_id_raw(&g_rom_flashchip); + id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00); + return id; +} + +#if XMC_SUPPORT +static bool is_xmc_chip_strict(uint32_t rdid) +{ + uint32_t vendor_id = BYTESHIFT(rdid, 2); + uint32_t mfid = BYTESHIFT(rdid, 1); + uint32_t cpid = BYTESHIFT(rdid, 0); + + if (vendor_id != XMC_VENDOR_ID) { + return false; + } + + bool matched = false; + if (mfid == 0x40) { + if (cpid >= 0x13 && cpid <= 0x20) { + matched = true; + } + } else if (mfid == 0x41) { + if (cpid >= 0x17 && cpid <= 0x20) { + matched = true; + } + } else if (mfid == 0x50) { + if (cpid >= 0x15 && cpid <= 0x16) { + matched = true; + } + } + return matched; +} + +bool bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len) +{ + bool ret; + spi_cmd_t cmd; + + cmd.cmd = command; + cmd.cmd_len = 1; + cmd.addr = NULL; + cmd.addr_len = 0; + cmd.dummy_bits = 0; + cmd.data = NULL; + cmd.data_len = 0; + + ret = spi_user_cmd_raw(&g_rom_flashchip, SPI_TX, &cmd); + if (!ret) { + ESP_LOGE(TAG, "failed to write cmd=%02x", command); + } + + return ret; +} + +uint32_t bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num) +{ + bool ret; + spi_cmd_t cmd; + uint32_t data = 0; + uint32_t addr = sfdp_addr << 8; + + cmd.cmd = CMD_RDSFDP; + cmd.cmd_len = 1; + cmd.addr = &addr; + cmd.addr_len = 3; + cmd.dummy_bits = 8; + cmd.data = &data; + cmd.data_len = miso_byte_num; + + ret = spi_user_cmd_raw(&g_rom_flashchip, SPI_RX, &cmd); + if (!ret) { + ESP_LOGE(TAG, "failed to read sfdp"); + } + + return data; +} + +esp_err_t bootloader_flash_xmc_startup(void) +{ + extern void ets_rom_delay_us(uint16_t us); + + uint32_t id = bootloader_read_flash_id(); + + // If the RDID value is a valid XMC one, may skip the flow + const bool fast_check = true; + if (fast_check && is_xmc_chip_strict(id)) { + ESP_LOGD(TAG, "XMC chip detected by RDID (%08X), skip.", id); + return ESP_OK; + } + + // Check the Manufacturer ID in SFDP registers (JEDEC standard). If not XMC chip, no need to run the flow + const int sfdp_mfid_addr = 0x10; + uint8_t mf_id = (bootloader_flash_read_sfdp(sfdp_mfid_addr, 1) & 0xff); + if (mf_id != XMC_VENDOR_ID) { + ESP_LOGD(TAG, "non-XMC chip detected by SFDP Read (%02X), skip.", mf_id); + return ESP_OK; + } + + ESP_LOGI(TAG, "XM25QHxxC startup flow"); + // Enter DPD + bootloader_execute_flash_command(0xB9, 0, 0, 0); + // Enter UDPD + bootloader_execute_flash_command(0x79, 0, 0, 0); + // Exit UDPD + bootloader_execute_flash_command(0xFF, 0, 0, 0); + // Delay tXUDPD + ets_rom_delay_us(2000); + // Release Power-down + bootloader_execute_flash_command(0xAB, 0, 0, 0); + ets_rom_delay_us(20); + // Read flash ID and check again + id = bootloader_read_flash_id(); + if (!is_xmc_chip_strict(id)) { + ESP_LOGE(TAG, "XMC flash startup fail"); + return ESP_FAIL; + } + + return ESP_OK; +} +#else +static bool is_xmc_chip(uint32_t rdid) +{ + uint32_t vendor_id = (rdid >> 16) &0xff; + + return vendor_id == XMC_VENDOR_ID; +} + +esp_err_t bootloader_flash_xmc_startup(void) +{ + uint32_t id = bootloader_read_flash_id(); + + if (is_xmc_chip(id)) { + ESP_LOGE(TAG, "XMC chip detected(%08X) while support disable.", id); + return ESP_FAIL; + } else { + ESP_LOGI(TAG, "flash chip is %08X", id); + } + + return ESP_OK; +} +#endif +#endif + #endif diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index fda2a49f7..2ca04d11f 100644 --- a/components/bootloader_support/src/bootloader_init.c +++ b/components/bootloader_support/src/bootloader_init.c @@ -642,6 +642,8 @@ esp_err_t bootloader_init() static esp_err_t bootloader_main() { + esp_err_t ret; + #ifdef CONFIG_BOOTLOADER_DISABLE_JTAG_IO /* Set GPIO 12-15 to be normal GPIO */ PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12); @@ -655,6 +657,11 @@ static esp_err_t bootloader_main() uart_console_configure(); + if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) { + ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!"); + return ESP_FAIL; + } + esp_image_header_t fhdr; if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &fhdr, sizeof(esp_image_header_t), true) != ESP_OK) { ESP_LOGE(TAG, "failed to load bootloader header!"); diff --git a/components/coap/libcoap b/components/coap/libcoap index cfec0d072..0dbccca06 160000 --- a/components/coap/libcoap +++ b/components/coap/libcoap @@ -1 +1 @@ -Subproject commit cfec0d072c5b99ed3e54828ca50ea2f6b91e1f50 +Subproject commit 0dbccca06c3ea75a20ef0a51633eb424a35b5e2a diff --git a/components/esp-tls/esp_tls.c b/components/esp-tls/esp_tls.c index da4dfe291..a5daf24f9 100644 --- a/components/esp-tls/esp_tls.c +++ b/components/esp-tls/esp_tls.c @@ -54,6 +54,7 @@ static const char *TAG = "esp-tls"; #define _esp_tls_set_global_ca_store esp_mbedtls_set_global_ca_store /*!< Callback function for setting global CA store data for TLS/SSL */ #define _esp_tls_get_global_ca_store esp_mbedtls_get_global_ca_store #define _esp_tls_free_global_ca_store esp_mbedtls_free_global_ca_store /*!< Callback function for freeing global ca store for TLS/SSL */ +#define _esp_tls_get_ciphersuites_list esp_mbedtls_get_ciphersuites_list #elif CONFIG_ESP_TLS_USING_WOLFSSL /* CONFIG_ESP_TLS_USING_MBEDTLS */ #define _esp_create_ssl_handle esp_create_wolfssl_handle #define _esp_tls_handshake esp_wolfssl_handshake @@ -437,6 +438,10 @@ mbedtls_x509_crt *esp_tls_get_global_ca_store(void) return _esp_tls_get_global_ca_store(); } +const int *esp_tls_get_ciphersuites_list(void) +{ + return _esp_tls_get_ciphersuites_list(); +} #endif /* CONFIG_ESP_TLS_USING_MBEDTLS */ #ifdef CONFIG_ESP_TLS_SERVER /** diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index a5983b2e3..a9ff17d5d 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -200,7 +200,8 @@ typedef struct esp_tls_cfg { esp_err_t (*crt_bundle_attach)(void *conf); /*!< Function pointer to esp_crt_bundle_attach. Enables the use of certification bundle for server verification, must be enabled in menuconfig */ - + const int *ciphersuites_list; /*!< Pointer to a zero-terminated array of IANA identifiers of TLS ciphersuites. + Please check the list validity by esp_tls_get_ciphersuites_list() API */ } esp_tls_cfg_t; #ifdef CONFIG_ESP_TLS_SERVER @@ -574,6 +575,15 @@ esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *esp_tl */ mbedtls_x509_crt *esp_tls_get_global_ca_store(void); +/** + * @brief Get supported TLS ciphersuites list. + * + * See https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4 for the list of ciphersuites + * + * @return Pointer to a zero-terminated array of IANA identifiers of TLS ciphersuites. + * + */ +const int *esp_tls_get_ciphersuites_list(void); #endif /* CONFIG_ESP_TLS_USING_MBEDTLS */ #ifdef CONFIG_ESP_TLS_SERVER /** @@ -602,7 +612,6 @@ int esp_tls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls */ void esp_tls_server_session_delete(esp_tls_t *tls); #endif /* ! CONFIG_ESP_TLS_SERVER */ - #ifdef __cplusplus } #endif diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index 245921fd0..756a0a05e 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -270,8 +270,14 @@ static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki) return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; } +#ifdef CONFIG_MBEDTLS_V3 + ret = mbedtls_pk_parse_key(pki->pk_key, pki->privkey_pem_buf, pki->privkey_pem_bytes, + pki->privkey_password, pki->privkey_password_len, + mbedtls_ctr_drbg_random, &tls->ctr_drbg); +#else ret = mbedtls_pk_parse_key(pki->pk_key, pki->privkey_pem_buf, pki->privkey_pem_bytes, pki->privkey_password, pki->privkey_password_len); +#endif if (ret < 0) { ESP_LOGE(TAG, "mbedtls_pk_parse_keyfile returned -0x%x", -ret); ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); @@ -383,6 +389,10 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t return ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED; } free(use_host); +#ifdef CONFIG_MBEDTLS_V3 + } else { + mbedtls_ssl_set_hostname(&tls->ssl, NULL); +#endif } if ((ret = mbedtls_ssl_config_defaults(&tls->conf, @@ -468,6 +478,11 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t ESP_LOGE(TAG, "You have to provide both clientcert_buf and clientkey_buf for mutual authentication"); return ESP_ERR_INVALID_STATE; } + + if (cfg->ciphersuites_list != NULL && cfg->ciphersuites_list[0] != 0) { + ESP_LOGD(TAG, "Set the ciphersuites list"); + mbedtls_ssl_conf_ciphersuites(&tls->conf, cfg->ciphersuites_list); + } return ESP_OK; } @@ -564,3 +579,8 @@ void esp_mbedtls_free_global_ca_store(void) global_cacert = NULL; } } + +const int *esp_mbedtls_get_ciphersuites_list(void) +{ + return mbedtls_ssl_list_ciphersuites(); +} diff --git a/components/esp-tls/private_include/esp_tls_mbedtls.h b/components/esp-tls/private_include/esp_tls_mbedtls.h index 362a71fd6..4e542cbe6 100644 --- a/components/esp-tls/private_include/esp_tls_mbedtls.h +++ b/components/esp-tls/private_include/esp_tls_mbedtls.h @@ -102,3 +102,8 @@ mbedtls_x509_crt *esp_mbedtls_get_global_ca_store(void); * Callback function for freeing global ca store for TLS/SSL using mbedtls */ void esp_mbedtls_free_global_ca_store(void); + +/** + * Internal Callback for esp_tls_get_ciphersuites_list + */ +const int *esp_mbedtls_get_ciphersuites_list(void); diff --git a/components/esp8266/CMakeLists.txt b/components/esp8266/CMakeLists.txt index 26120f438..887f9b6e6 100644 --- a/components/esp8266/CMakeLists.txt +++ b/components/esp8266/CMakeLists.txt @@ -69,7 +69,12 @@ else() target_link_libraries(${COMPONENT_LIB} PUBLIC "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib" "-lstdc++") target_compile_definitions(${COMPONENT_LIB} PUBLIC -DUSING_IBUS_FASTER_GET) if(NOT CONFIG_NO_BLOBS) - set(blobs "gcc" "hal" "core" "net80211" "phy" "rtc" "clk" "pp" "smartconfig" "ssc" "espnow") + set(blobs "gcc" "hal" "phy" "rtc" "clk" "smartconfig" "ssc") + if(CONFIG_ESP8266_WIFI_DEBUG_LOG_ENABLE) + list(APPEND blobs "core_dbg" "net80211_dbg" "pp_dbg" "espnow_dbg") + else() + list(APPEND blobs "core" "net80211" "pp" "espnow") + endif() foreach(blob ${blobs}) add_library(${blob} STATIC IMPORTED) set_property(TARGET ${blob} PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lib/lib${blob}.a) diff --git a/components/esp8266/driver/uart.c b/components/esp8266/driver/uart.c index 63d2a92bb..ae067dd07 100644 --- a/components/esp8266/driver/uart.c +++ b/components/esp8266/driver/uart.c @@ -257,7 +257,18 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) uint32_t baudrate; uint32_t byte_delay_us = 0; BaseType_t res; + portTickType ticks_cur; + portTickType ticks_start = xTaskGetTickCount(); portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait; + /** + * Considering the overflow of the ticks_end and the ticks_cur (xTaskGetTickCount()), + * the possible tick timestamp is as follows: + * (one start tick timestamp, two end tick timestamps, four current tick timestamps) + * + * ticks: 0 0xFFFFFFFF + * |_______._______._______._______._______._______._______._______| + * cur1 end1 cur2 start cur3 end2 cur4 + */ // Take tx_mux res = xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)ticks_to_wait); @@ -273,10 +284,22 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) uart_get_baudrate(uart_num, &baudrate); byte_delay_us = (uint32_t)(10000000 / baudrate); // (1/baudrate)*10*1000_000 us - ticks_to_wait = ticks_end - xTaskGetTickCount(); + ticks_cur = xTaskGetTickCount(); + if (ticks_start <= ticks_cur) { + ticks_to_wait = ticks_to_wait - (ticks_cur - ticks_start); + } else { + ticks_to_wait = ticks_to_wait - (portMAX_DELAY - ticks_start + ticks_cur); + } // wait for tx done sem. if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, ticks_to_wait)) { while (1) { + ticks_cur = xTaskGetTickCount(); + bool end1_timeout = (ticks_end < ticks_start && ticks_cur < ticks_start && ticks_cur > ticks_end); + bool end2_timeout = (ticks_start < ticks_end && (ticks_cur < ticks_start || ticks_end < ticks_cur)); + if (end1_timeout || end2_timeout) { + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return ESP_ERR_TIMEOUT; + } if (UART[uart_num]->status.txfifo_cnt == 0) { ets_delay_us(byte_delay_us); // Delay one byte time to guarantee transmission completion break; diff --git a/components/esp8266/include/driver/soc.h b/components/esp8266/include/driver/soc.h index ac3e330de..894f64e95 100644 --- a/components/esp8266/include/driver/soc.h +++ b/components/esp8266/include/driver/soc.h @@ -31,7 +31,11 @@ static inline esp_irqflag_t soc_save_local_irq(void) esp_irqflag_t flag; __asm__ __volatile__( +#ifdef BOOTLOADER_BUILD + "rsil %0, 3\n" +#else "rsil %0, 1\n" +#endif : "=a"(flag) : : "memory" diff --git a/components/esp8266/include/esp_attr.h b/components/esp8266/include/esp_attr.h index f21fb7a54..d5b14d38b 100644 --- a/components/esp8266/include/esp_attr.h +++ b/components/esp8266/include/esp_attr.h @@ -68,4 +68,10 @@ #define _COUNTER_STRINGIFY(COUNTER) #COUNTER +#ifdef IDF_CI_BUILD +#define IDF_DEPRECATED(REASON) __attribute__((deprecated(REASON))) +#else +#define IDF_DEPRECATED(REASON) +#endif + #endif /* __ESP_ATTR_H__ */ diff --git a/components/esp8266/ld/esp8266.project.ld.in b/components/esp8266/ld/esp8266.project.ld.in index 54d7bb48b..a1c4ba09e 100644 --- a/components/esp8266/ld/esp8266.project.ld.in +++ b/components/esp8266/ld/esp8266.project.ld.in @@ -94,6 +94,15 @@ SECTIONS _iram_end = ABSOLUTE(.); } > iram0_0_seg + .patch.text : + { + . = ALIGN (4); + _iram_patch_text_start = ABSOLUTE(.); + *(.flash.patch.literal .flash.patch.text) + _iram_patch_text_end = ABSOLUTE(.); + _iram_text_end = ABSOLUTE(.); + } > iram0_0_seg + ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), "IRAM0 segment data does not fit.") @@ -155,6 +164,15 @@ SECTIONS _bss_end = ABSOLUTE(.); } > dram0_0_seg + .patch.bss : + { + . = ALIGN (4); + _iram_patch_bss_start = ABSOLUTE(.); + *(.flash.patch.bss) + _iram_patch_bss_end = ABSOLUTE(.); + *(.flash.patch.rodata) + } > dram0_0_seg + ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.") diff --git a/components/esp8266/lib/VERSION b/components/esp8266/lib/VERSION index 49d4d2e10..11b4ea06c 100644 --- a/components/esp8266/lib/VERSION +++ b/components/esp8266/lib/VERSION @@ -1,8 +1,8 @@ gwen: - core: cebfb0e - net80211: 8114f9c - pp: 52bb147 - espnow: 7a93d71 + core: db51cd0 + net80211: fbfeb71 + pp: 12d8a11 + espnow: db51cd0 - smartconfig: 3.0.0/5f550c40 + smartconfig: 3.0.0/283eacca phy: 1163.0 diff --git a/components/esp8266/lib/libcore.a b/components/esp8266/lib/libcore.a index 75f2cd848..8dfeb8e2e 100755 Binary files a/components/esp8266/lib/libcore.a and b/components/esp8266/lib/libcore.a differ diff --git a/components/esp8266/lib/libcore_dbg.a b/components/esp8266/lib/libcore_dbg.a index c59cd3276..9aa92b8fd 100755 Binary files a/components/esp8266/lib/libcore_dbg.a and b/components/esp8266/lib/libcore_dbg.a differ diff --git a/components/esp8266/lib/libespnow.a b/components/esp8266/lib/libespnow.a index 807bac791..95f45b9e9 100755 Binary files a/components/esp8266/lib/libespnow.a and b/components/esp8266/lib/libespnow.a differ diff --git a/components/esp8266/lib/libespnow_dbg.a b/components/esp8266/lib/libespnow_dbg.a index e3c2f9d3c..df26ea842 100755 Binary files a/components/esp8266/lib/libespnow_dbg.a and b/components/esp8266/lib/libespnow_dbg.a differ diff --git a/components/esp8266/lib/libnet80211.a b/components/esp8266/lib/libnet80211.a old mode 100755 new mode 100644 index ed88b9dcb..37e226052 Binary files a/components/esp8266/lib/libnet80211.a and b/components/esp8266/lib/libnet80211.a differ diff --git a/components/esp8266/lib/libnet80211_dbg.a b/components/esp8266/lib/libnet80211_dbg.a old mode 100755 new mode 100644 index 7f60cdb35..e50f2b95c Binary files a/components/esp8266/lib/libnet80211_dbg.a and b/components/esp8266/lib/libnet80211_dbg.a differ diff --git a/components/esp8266/lib/libpp.a b/components/esp8266/lib/libpp.a old mode 100755 new mode 100644 index 761b8be80..f95ae130f Binary files a/components/esp8266/lib/libpp.a and b/components/esp8266/lib/libpp.a differ diff --git a/components/esp8266/lib/libpp_dbg.a b/components/esp8266/lib/libpp_dbg.a old mode 100755 new mode 100644 index 26775d3d4..d0007ae0c Binary files a/components/esp8266/lib/libpp_dbg.a and b/components/esp8266/lib/libpp_dbg.a differ diff --git a/components/esp8266/lib/libsmartconfig.a b/components/esp8266/lib/libsmartconfig.a index ab3ccef63..519602ecf 100755 Binary files a/components/esp8266/lib/libsmartconfig.a and b/components/esp8266/lib/libsmartconfig.a differ diff --git a/components/esp8266/source/phy_init.c b/components/esp8266/source/phy_init.c index 722dec55c..21563f8bb 100644 --- a/components/esp8266/source/phy_init.c +++ b/components/esp8266/source/phy_init.c @@ -204,15 +204,15 @@ static const char* PHY_NAMESPACE = "phy"; static const char* PHY_CAL_DATA_KEY = "cal_data"; static const char* PHY_RX_GAIN_DC_TABLE_KEY = "dc_table"; -static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle, +static esp_err_t load_cal_data_from_nvs_handle(nvs_handle_t handle, esp_phy_calibration_data_t* out_cal_data); -static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle, +static esp_err_t store_cal_data_to_nvs_handle(nvs_handle_t handle, const esp_phy_calibration_data_t* cal_data); esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_data) { - nvs_handle handle; + nvs_handle_t handle; esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READONLY, &handle); if (err == ESP_ERR_NVS_NOT_INITIALIZED) { @@ -230,7 +230,7 @@ esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_dat esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_data) { - nvs_handle handle; + nvs_handle_t handle; esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READWRITE, &handle); if (err != ESP_OK) { @@ -243,7 +243,7 @@ esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_da } } -static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle, +static esp_err_t load_cal_data_from_nvs_handle(nvs_handle_t handle, esp_phy_calibration_data_t* out_cal_data) { esp_err_t err; @@ -278,7 +278,7 @@ static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle, return ESP_OK; } -static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle, +static esp_err_t store_cal_data_to_nvs_handle(nvs_handle_t handle, const esp_phy_calibration_data_t* cal_data) { esp_err_t err; diff --git a/components/esp8266/source/smartconfig_ack.c b/components/esp8266/source/smartconfig_ack.c index 7c4347470..34bd8eb30 100644 --- a/components/esp8266/source/smartconfig_ack.c +++ b/components/esp8266/source/smartconfig_ack.c @@ -31,6 +31,7 @@ #include "esp_wifi.h" #include "esp_smartconfig.h" #include "smartconfig_ack.h" +#include "lwip/inet.h" #define SC_ACK_TASK_PRIORITY 2 /*!< Priority of sending smartconfig ACK task */ #define SC_ACK_TASK_STACK_SIZE 2048 /*!< Stack size of sending smartconfig ACK task */ @@ -40,7 +41,7 @@ #define SC_ACK_TOUCH_V2_SERVER_PORT(i) (18266+i*10000) /*!< ESP touch_v2 UDP port of server on cellphone */ #define SC_ACK_AIRKISS_SERVER_PORT 10000 /*!< Airkiss UDP port of server on cellphone */ #define SC_ACK_AIRKISS_DEVICE_PORT 10001 /*!< Airkiss UDP port of server on device */ -#define SC_ACK_AIRKISS_TIMEOUT 1500 /*!< Airkiss read data timout millisecond */ +#define SC_ACK_TIMEOUT 1500 /*!< Airkiss and ESP touch_v2 read data timout millisecond */ #define SC_ACK_TOUCH_LEN 11 /*!< Length of ESP touch ACK context */ #define SC_ACK_AIRKISS_LEN 7 /*!< Length of Airkiss ACK context */ @@ -79,7 +80,7 @@ static void sc_ack_send_task(void* pvParameters) sc_ack_t* ack = (sc_ack_t*)pvParameters; tcpip_adapter_ip_info_t local_ip; uint8_t remote_ip[4]; - memset(remote_ip, 0xFF, sizeof(remote_ip)); + memcpy(remote_ip, ack->ctx.ip, sizeof(remote_ip)); struct sockaddr_in server_addr; socklen_t sin_size = sizeof(server_addr); int send_sock = -1; @@ -99,6 +100,7 @@ static void sc_ack_send_task(void* pvParameters) port_bit = 0; } remote_port = SC_ACK_TOUCH_V2_SERVER_PORT(port_bit); + memset(remote_ip, 0xFF, sizeof(remote_ip)); } else { remote_port = SC_ACK_AIRKISS_SERVER_PORT; } @@ -132,21 +134,24 @@ static void sc_ack_send_task(void* pvParameters) setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &optval, sizeof(int)); - if (ack->type == SC_TYPE_AIRKISS) { + if (ack->type == SC_TYPE_AIRKISS || ack->type == SC_TYPE_ESPTOUCH_V2) { char data = 0; struct sockaddr_in local_addr, from; socklen_t sockadd_len = sizeof(struct sockaddr); struct timeval timeout = { - SC_ACK_AIRKISS_TIMEOUT / 1000, - SC_ACK_AIRKISS_TIMEOUT % 1000 * 1000 + SC_ACK_TIMEOUT / 1000, + SC_ACK_TIMEOUT % 1000 * 1000 }; bzero(&local_addr, sizeof(struct sockaddr_in)); bzero(&from, sizeof(struct sockaddr_in)); local_addr.sin_family = AF_INET; local_addr.sin_addr.s_addr = INADDR_ANY; - local_addr.sin_port = htons(SC_ACK_AIRKISS_DEVICE_PORT); - + if (ack->type == SC_TYPE_AIRKISS) { + local_addr.sin_port = htons(SC_ACK_AIRKISS_DEVICE_PORT); + } else { + local_addr.sin_port = htons(SC_ACK_TOUCH_DEVICE_PORT); + } bind(send_sock, (struct sockaddr*)&local_addr, sockadd_len); setsockopt(send_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); @@ -155,31 +160,34 @@ static void sc_ack_send_task(void* pvParameters) if (from.sin_addr.s_addr != INADDR_ANY) { memcpy(remote_ip, &from.sin_addr, 4); server_addr.sin_addr.s_addr = from.sin_addr.s_addr; + ESP_LOGI(TAG, "cellphone_ip: %s", inet_ntoa(server_addr.sin_addr)); } else { - goto _end; + server_addr.sin_addr.s_addr = INADDR_BROADCAST; } } + uint32_t ip_addr = server_addr.sin_addr.s_addr; while (s_sc_ack_send) { /* Send smartconfig ACK every 100ms. */ vTaskDelay(100 / portTICK_RATE_MS); - sendlen = sendto(send_sock, &ack->ctx, ack_len, 0, (struct sockaddr*) &server_addr, sin_size); - - if (sendlen > 0) { - /* Totally send 60 smartconfig ACKs. Then smartconfig is successful. */ - if (packet_count++ >= SC_ACK_MAX_COUNT) { - esp_event_post(SC_EVENT, SC_EVENT_SEND_ACK_DONE, NULL, 0, portMAX_DELAY); - goto _end; - } + if (ip_addr != INADDR_BROADCAST) { + sendto(send_sock, &ack->ctx, ack_len, 0, (struct sockaddr*) &server_addr, sin_size); + server_addr.sin_addr.s_addr = INADDR_BROADCAST; + sendlen = sendto(send_sock, &ack->ctx, ack_len, 0, (struct sockaddr*) &server_addr, sin_size); + server_addr.sin_addr.s_addr = ip_addr; } else { - err = sc_ack_send_get_errno(send_sock); - - if (err == ENOMEM || err == EAGAIN) { - ESP_LOGD(TAG, "send failed, errno %d", err); - continue; - } + sendlen = sendto(send_sock, &ack->ctx, ack_len, 0, (struct sockaddr*) &server_addr, sin_size); + } + if (sendlen <= 0) { + err = sc_ack_send_get_errno(send_sock); ESP_LOGE(TAG, "send failed, errno %d", err); + vTaskDelay(200 / portTICK_RATE_MS); + } + + /* Send 60 smartconfig ACKs, exit regardless of failure or success. */ + if (packet_count++ >= SC_ACK_MAX_COUNT) { + esp_event_post(SC_EVENT, SC_EVENT_SEND_ACK_DONE, NULL, 0, portMAX_DELAY); goto _end; } } diff --git a/components/esp8266/source/startup.c b/components/esp8266/source/startup.c index b9e582cec..ecd020578 100644 --- a/components/esp8266/source/startup.c +++ b/components/esp8266/source/startup.c @@ -105,6 +105,7 @@ void call_start_cpu(size_t start_addr) extern int _bss_start, _bss_end; extern int _iram_bss_start, _iram_bss_end; + extern int _iram_patch_bss_start, _iram_patch_bss_end; #ifdef CONFIG_BOOTLOADER_FAST_BOOT REG_SET_BIT(DPORT_CTL_REG, DPORT_CTL_DOUBLE_CLK); @@ -151,6 +152,18 @@ void call_start_cpu(size_t start_addr) for (p = &_iram_bss_start; p < &_iram_bss_end; p++) *p = 0; + + for (p = &_iram_patch_bss_start; p < &_iram_patch_bss_end; p++) + *p = 0; + +#ifdef CONFIG_ENABLE_TH25Q16HB_PATCH_0 + assert(th25q16hb_apply_patch_0() == 0); +#endif + +#ifdef CONFIG_ENABLE_FM25Q16A_PATCH_0 + assert(fm25q16a_apply_patch_0() == 0); +#endif + __asm__ __volatile__( "rsil a2, 2\n" "movi a1, _chip_interrupt_tmp\n" diff --git a/components/esp8266/source/system_api.c b/components/esp8266/source/system_api.c index 080514e47..1a0c1aad3 100644 --- a/components/esp8266/source/system_api.c +++ b/components/esp8266/source/system_api.c @@ -136,7 +136,7 @@ static const char *BACKUP_MAC_DATA_KEY = "backup_mac_data"; static esp_err_t load_backup_mac_data(uint8_t *mac) { esp_err_t err; - nvs_handle handle; + nvs_handle_t handle; uint32_t efuse[4]; uint8_t efuse_crc = 0; uint8_t calc_crc = 0; @@ -221,7 +221,7 @@ static esp_err_t load_backup_mac_data(uint8_t *mac) static esp_err_t store_backup_mac_data() { esp_err_t err; - nvs_handle handle; + nvs_handle_t handle; uint32_t efuse[4]; efuse[0] = REG_READ(EFUSE_DATA0_REG); efuse[1] = REG_READ(EFUSE_DATA1_REG); diff --git a/components/esp_http_server/src/httpd_main.c b/components/esp_http_server/src/httpd_main.c index a67513195..5724383aa 100644 --- a/components/esp_http_server/src/httpd_main.c +++ b/components/esp_http_server/src/httpd_main.c @@ -262,6 +262,16 @@ static esp_err_t httpd_server_init(struct httpd_data *hd) .sin_port = htons(hd->config.server_port) }; #endif /* CONFIG_LWIP_IPV6 */ + + /* Enable SO_REUSEADDR to allow binding to the same + * address and port when restarting the server */ + int enable = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) { + /* This will fail if CONFIG_LWIP_SO_REUSE is not enabled. But + * it does not affect the normal working of the HTTP Server */ + ESP_LOGW(TAG, LOG_FMT("error in setsockopt SO_REUSEADDR (%d)"), errno); + } + int ret = bind(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); if (ret < 0) { ESP_LOGE(TAG, LOG_FMT("error in bind (%d)"), errno); diff --git a/components/freertos/freertos/queue.c b/components/freertos/freertos/queue.c index c37d285f3..a87d6d62e 100644 --- a/components/freertos/freertos/queue.c +++ b/components/freertos/freertos/queue.c @@ -360,6 +360,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; Queue_t *pxNewQueue; size_t xQueueSizeInBytes; uint8_t *pucQueueStorage; + BaseType_t overflow; configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); @@ -375,7 +376,29 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ } - pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); + /* Check for multiplication overflow. */ + overflow = ( uxItemSize != 0 ) && ( uxQueueLength != ( xQueueSizeInBytes / uxItemSize ) ); + + /* Check for addition overflow. */ + overflow = overflow || ( ( sizeof( Queue_t ) + xQueueSizeInBytes ) < xQueueSizeInBytes ); + + if ( overflow == (BaseType_t) 0 ) + { + /* Allocate the queue and storage area. Justification for MISRA + deviation as follows: pvPortMalloc() always ensures returned memory + blocks are aligned per the requirements of the MCU stack. In this case + pvPortMalloc() must return a pointer that is guaranteed to meet the + alignment requirements of the Queue_t structure - which in this case + is an int8_t *. Therefore, whenever the stack alignment requirements + are greater than or equal to the pointer to char requirements the cast + is safe. In other cases alignment requirements are not strict (one or + two bytes). */ + pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); /*lint !e9087 !e9079 see comment above. */ + } + else + { + pxNewQueue = NULL; + } if( pxNewQueue != NULL ) { diff --git a/components/freertos/freertos/stream_buffer.c b/components/freertos/freertos/stream_buffer.c index c60045f69..317be2355 100644 --- a/components/freertos/freertos/stream_buffer.c +++ b/components/freertos/freertos/stream_buffer.c @@ -242,8 +242,15 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, this is a quirk of the implementation that means otherwise the free space would be reported as one byte smaller than would be logically expected. */ - xBufferSizeBytes++; - pucAllocatedMemory = ( uint8_t * ) pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); /*lint !e9079 malloc() only returns void*. */ + if( xBufferSizeBytes < ( xBufferSizeBytes + 1 + sizeof( StreamBuffer_t ) ) ) + { + xBufferSizeBytes++; + pucAllocatedMemory = ( uint8_t * ) pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); /*lint !e9079 malloc() only returns void*. */ + } + else + { + pucAllocatedMemory = NULL; + } if( pucAllocatedMemory != NULL ) { diff --git a/components/freertos/freertos/tasks.c b/components/freertos/freertos/tasks.c index c747cd74e..61e10e501 100644 --- a/components/freertos/freertos/tasks.c +++ b/components/freertos/freertos/tasks.c @@ -3044,6 +3044,19 @@ BaseType_t xReturn; { ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); prvAddTaskToReadyList( pxUnblockedTCB ); + #if( configUSE_TICKLESS_IDLE != 0 ) + { + /* If a task is blocked on a kernel object then xNextTaskUnblockTime + might be set to the blocked task's time out time. If the task is + unblocked for a reason other than a timeout xNextTaskUnblockTime is + normally left unchanged, because it is automatically reset to a new + value when the tick count equals xNextTaskUnblockTime. However if + tickless idling is used it might be more important to enter sleep mode + at the earliest possible time - so reset xNextTaskUnblockTime here to + ensure it is updated at the earliest possible time. */ + prvResetNextTaskUnblockTime(); + } + #endif } else { @@ -3068,20 +3081,6 @@ BaseType_t xReturn; xReturn = pdFALSE; } - #if( configUSE_TICKLESS_IDLE != 0 ) - { - /* If a task is blocked on a kernel object then xNextTaskUnblockTime - might be set to the blocked task's time out time. If the task is - unblocked for a reason other than a timeout xNextTaskUnblockTime is - normally left unchanged, because it is automatically reset to a new - value when the tick count equals xNextTaskUnblockTime. However if - tickless idling is used it might be more important to enter sleep mode - at the earliest possible time - so reset xNextTaskUnblockTime here to - ensure it is updated at the earliest possible time. */ - prvResetNextTaskUnblockTime(); - } - #endif - return xReturn; } /*-----------------------------------------------------------*/ diff --git a/components/libsodium/libsodium/test/default/sign.c b/components/libsodium/libsodium/test/default/sign.c index 814f96729..4faacf368 100644 --- a/components/libsodium/libsodium/test/default/sign.c +++ b/components/libsodium/libsodium/test/default/sign.c @@ -14,7 +14,7 @@ typedef struct TestData_ { const char *m; } TestData; -static TestData test_data[] = { +static const TestData test_data[] = { {{0x9d,0x61,0xb1,0x9d,0xef,0xfd,0x5a,0x60,0xba,0x84,0x4a,0xf4,0x92,0xec,0x2c,0xc4,0x44,0x49,0xc5,0x69,0x7b,0x32,0x69,0x19,0x70,0x3b,0xac,0x03,0x1c,0xae,0x7f,0x60,},{0xd7,0x5a,0x98,0x01,0x82,0xb1,0x0a,0xb7,0xd5,0x4b,0xfe,0xd3,0xc9,0x64,0x07,0x3a,0x0e,0xe1,0x72,0xf3,0xda,0xa6,0x23,0x25,0xaf,0x02,0x1a,0x68,0xf7,0x07,0x51,0x1a,},{0xe5,0x56,0x43,0x00,0xc3,0x60,0xac,0x72,0x90,0x86,0xe2,0xcc,0x80,0x6e,0x82,0x8a,0x84,0x87,0x7f,0x1e,0xb8,0xe5,0xd9,0x74,0xd8,0x73,0xe0,0x65,0x22,0x49,0x01,0x55,0x5f,0xb8,0x82,0x15,0x90,0xa3,0x3b,0xac,0xc6,0x1e,0x39,0x70,0x1c,0xf9,0xb4,0x6b,0xd2,0x5b,0xf5,0xf0,0x59,0x5b,0xbe,0x24,0x65,0x51,0x41,0x43,0x8e,0x7a,0x10,0x0b,},""}, {{0x4c,0xcd,0x08,0x9b,0x28,0xff,0x96,0xda,0x9d,0xb6,0xc3,0x46,0xec,0x11,0x4e,0x0f,0x5b,0x8a,0x31,0x9f,0x35,0xab,0xa6,0x24,0xda,0x8c,0xf6,0xed,0x4f,0xb8,0xa6,0xfb,},{0x3d,0x40,0x17,0xc3,0xe8,0x43,0x89,0x5a,0x92,0xb7,0x0a,0xa7,0x4d,0x1b,0x7e,0xbc,0x9c,0x98,0x2c,0xcf,0x2e,0xc4,0x96,0x8c,0xc0,0xcd,0x55,0xf1,0x2a,0xf4,0x66,0x0c,},{0x92,0xa0,0x09,0xa9,0xf0,0xd4,0xca,0xb8,0x72,0x0e,0x82,0x0b,0x5f,0x64,0x25,0x40,0xa2,0xb2,0x7b,0x54,0x16,0x50,0x3f,0x8f,0xb3,0x76,0x22,0x23,0xeb,0xdb,0x69,0xda,0x08,0x5a,0xc1,0xe4,0x3e,0x15,0x99,0x6e,0x45,0x8f,0x36,0x13,0xd0,0xf1,0x1d,0x8c,0x38,0x7b,0x2e,0xae,0xb4,0x30,0x2a,0xee,0xb0,0x0d,0x29,0x16,0x12,0xbb,0x0c,0x00,},"\x72"}, {{0xc5,0xaa,0x8d,0xf4,0x3f,0x9f,0x83,0x7b,0xed,0xb7,0x44,0x2f,0x31,0xdc,0xb7,0xb1,0x66,0xd3,0x85,0x35,0x07,0x6f,0x09,0x4b,0x85,0xce,0x3a,0x2e,0x0b,0x44,0x58,0xf7,},{0xfc,0x51,0xcd,0x8e,0x62,0x18,0xa1,0xa3,0x8d,0xa4,0x7e,0xd0,0x02,0x30,0xf0,0x58,0x08,0x16,0xed,0x13,0xba,0x33,0x03,0xac,0x5d,0xeb,0x91,0x15,0x48,0x90,0x80,0x25,},{0x62,0x91,0xd6,0x57,0xde,0xec,0x24,0x02,0x48,0x27,0xe6,0x9c,0x3a,0xbe,0x01,0xa3,0x0c,0xe5,0x48,0xa2,0x84,0x74,0x3a,0x44,0x5e,0x36,0x80,0xd7,0xdb,0x5a,0xc3,0xac,0x18,0xff,0x9b,0x53,0x8d,0x16,0xf2,0x90,0xae,0x67,0xf7,0x60,0x98,0x4d,0xc6,0x59,0x4a,0x7c,0x15,0xe9,0x71,0x6e,0xd2,0x8d,0xc0,0x27,0xbe,0xce,0xea,0x1e,0xc4,0x0a,},"\xaf\x82"}, diff --git a/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c b/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c index 960e2bda0..66fecaabc 100644 --- a/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c +++ b/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c @@ -26,9 +26,9 @@ mbedTLS totals. This doesn't matter inside libsodium's documented API, but would matter if any callers try to use the state's bit count. */ -_Static_assert(sizeof(((crypto_hash_sha256_state *)0)->state) == sizeof(((mbedtls_sha256_context *)0)->state), "state mismatch"); -_Static_assert(sizeof(((crypto_hash_sha256_state *)0)->count) == sizeof(((mbedtls_sha256_context *)0)->total), "count mismatch"); -_Static_assert(sizeof(((crypto_hash_sha256_state *)0)->buf) == sizeof(((mbedtls_sha256_context *)0)->buffer), "buf mismatch"); +_Static_assert(sizeof(((crypto_hash_sha256_state *)0)->state) == sizeof(((mbedtls_sha256_context *)0)->MBEDTLS_PRIVATE(state)), "state mismatch"); +_Static_assert(sizeof(((crypto_hash_sha256_state *)0)->count) == sizeof(((mbedtls_sha256_context *)0)->MBEDTLS_PRIVATE(total)), "count mismatch"); +_Static_assert(sizeof(((crypto_hash_sha256_state *)0)->buf) == sizeof(((mbedtls_sha256_context *)0)->MBEDTLS_PRIVATE(buffer)), "buf mismatch"); /* Inline functions to convert between mbedTLS & libsodium context structures @@ -36,17 +36,17 @@ _Static_assert(sizeof(((crypto_hash_sha256_state *)0)->buf) == sizeof(((mbedtls_ static void sha256_mbedtls_to_libsodium(crypto_hash_sha256_state *ls_state, const mbedtls_sha256_context *mb_ctx) { - memcpy(&ls_state->count, mb_ctx->total, sizeof(ls_state->count)); - memcpy(ls_state->state, mb_ctx->state, sizeof(ls_state->state)); - memcpy(ls_state->buf, mb_ctx->buffer, sizeof(ls_state->buf)); + memcpy(&ls_state->count, mb_ctx->MBEDTLS_PRIVATE(total), sizeof(ls_state->count)); + memcpy(ls_state->state, mb_ctx->MBEDTLS_PRIVATE(state), sizeof(ls_state->state)); + memcpy(ls_state->buf, mb_ctx->MBEDTLS_PRIVATE(buffer), sizeof(ls_state->buf)); } static void sha256_libsodium_to_mbedtls(mbedtls_sha256_context *mb_ctx, crypto_hash_sha256_state *ls_state) { - memcpy(mb_ctx->total, &ls_state->count, sizeof(mb_ctx->total)); - memcpy(mb_ctx->state, ls_state->state, sizeof(mb_ctx->state)); - memcpy(mb_ctx->buffer, ls_state->buf, sizeof(mb_ctx->buffer)); - mb_ctx->is224 = 0; + memcpy(mb_ctx->MBEDTLS_PRIVATE(total), &ls_state->count, sizeof(mb_ctx->MBEDTLS_PRIVATE(total))); + memcpy(mb_ctx->MBEDTLS_PRIVATE(state), ls_state->state, sizeof(mb_ctx->MBEDTLS_PRIVATE(state))); + memcpy(mb_ctx->MBEDTLS_PRIVATE(buffer), ls_state->buf, sizeof(mb_ctx->MBEDTLS_PRIVATE(buffer))); + mb_ctx->MBEDTLS_PRIVATE(is224) = 0; } int diff --git a/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c b/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c index b005f0ce0..83a4cd708 100644 --- a/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c +++ b/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c @@ -27,9 +27,9 @@ mbedTLS totals. This doesn't matter inside libsodium's documented API, but would matter if any callers try to use the state's bit count. */ -_Static_assert(sizeof(((crypto_hash_sha512_state *)0)->state) == sizeof(((mbedtls_sha512_context *)0)->state), "state mismatch"); -_Static_assert(sizeof(((crypto_hash_sha512_state *)0)->count) == sizeof(((mbedtls_sha512_context *)0)->total), "count mismatch"); -_Static_assert(sizeof(((crypto_hash_sha512_state *)0)->buf) == sizeof(((mbedtls_sha512_context *)0)->buffer), "buf mismatch"); +_Static_assert(sizeof(((crypto_hash_sha512_state *)0)->state) == sizeof(((mbedtls_sha512_context *)0)->MBEDTLS_PRIVATE(state)), "state mismatch"); +_Static_assert(sizeof(((crypto_hash_sha512_state *)0)->count) == sizeof(((mbedtls_sha512_context *)0)->MBEDTLS_PRIVATE(total)), "count mismatch"); +_Static_assert(sizeof(((crypto_hash_sha512_state *)0)->buf) == sizeof(((mbedtls_sha512_context *)0)->MBEDTLS_PRIVATE(buffer)), "buf mismatch"); /* Inline functions to convert between mbedTLS & libsodium context structures @@ -37,17 +37,17 @@ _Static_assert(sizeof(((crypto_hash_sha512_state *)0)->buf) == sizeof(((mbedtls_ static void sha512_mbedtls_to_libsodium(crypto_hash_sha512_state *ls_state, const mbedtls_sha512_context *mb_ctx) { - memcpy(ls_state->count, mb_ctx->total, sizeof(ls_state->count)); - memcpy(ls_state->state, mb_ctx->state, sizeof(ls_state->state)); - memcpy(ls_state->buf, mb_ctx->buffer, sizeof(ls_state->buf)); + memcpy(ls_state->count, mb_ctx->MBEDTLS_PRIVATE(total), sizeof(ls_state->count)); + memcpy(ls_state->state, mb_ctx->MBEDTLS_PRIVATE(state), sizeof(ls_state->state)); + memcpy(ls_state->buf, mb_ctx->MBEDTLS_PRIVATE(buffer), sizeof(ls_state->buf)); } static void sha512_libsodium_to_mbedtls(mbedtls_sha512_context *mb_ctx, crypto_hash_sha512_state *ls_state) { - memcpy(mb_ctx->total, ls_state->count, sizeof(mb_ctx->total)); - memcpy(mb_ctx->state, ls_state->state, sizeof(mb_ctx->state)); - memcpy(mb_ctx->buffer, ls_state->buf, sizeof(mb_ctx->buffer)); - mb_ctx->is384 = 0; + memcpy(mb_ctx->MBEDTLS_PRIVATE(total), ls_state->count, sizeof(mb_ctx->MBEDTLS_PRIVATE(total))); + memcpy(mb_ctx->MBEDTLS_PRIVATE(state), ls_state->state, sizeof(mb_ctx->MBEDTLS_PRIVATE(state))); + memcpy(mb_ctx->MBEDTLS_PRIVATE(buffer), ls_state->buf, sizeof(mb_ctx->MBEDTLS_PRIVATE(buffer))); + mb_ctx->MBEDTLS_PRIVATE(is384) = 0; } int diff --git a/components/lwip/port/esp8266/netif/dhcp_state.c b/components/lwip/port/esp8266/netif/dhcp_state.c index 6ae00d700..8e2e3d9f3 100644 --- a/components/lwip/port/esp8266/netif/dhcp_state.c +++ b/components/lwip/port/esp8266/netif/dhcp_state.c @@ -31,7 +31,6 @@ static const char *interface_key[] = {"IF_STA", "IF_AP", "IF_ETH", "IF_TEST"}; _Static_assert(sizeof(interface_key) / sizeof(char*) == TCPIP_ADAPTER_IF_MAX, "Number interface keys differs from number of interfaces"); -typedef nvs_handle nvs_handle_t; bool dhcp_ip_addr_restore(void *netif) { nvs_handle_t nvs; diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index ea61a5217..ab8e1fd88 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -1,74 +1,2 @@ -idf_build_get_property(target IDF_TARGET) -idf_component_register(INCLUDE_DIRS "port/include" "port/include/${target}" "mbedtls/include" - REQUIRES lwip) - -# Only build mbedtls libraries -set(ENABLE_TESTING CACHE BOOL OFF) -set(ENABLE_PROGRAMS CACHE BOOL OFF) - -# Needed to for include_next includes to work from within mbedtls -include_directories("${COMPONENT_DIR}/port/include" "${COMPONENT_DIR}/port/include/${target}") - -# Import mbedtls library targets -add_subdirectory(mbedtls) - -# Use port specific implementation of net_socket.c instead of one from mbedtls -get_target_property(src_tls mbedtls SOURCES) -list(REMOVE_ITEM src_tls net_sockets.c) -set_property(TARGET mbedtls PROPERTY SOURCES ${src_tls}) - -set(mbedtls_targets mbedtls mbedcrypto mbedx509) - -# Add port files to mbedtls targets -set(mbedtls_target_sources "${COMPONENT_DIR}/port/mbedtls_debug.c" - "${COMPONENT_DIR}/port/net_sockets.c") - -if(CONFIG_MBEDTLS_DYNAMIC_BUFFER) -set(mbedtls_target_sources ${mbedtls_target_sources} - "${COMPONENT_DIR}/port/dynamic/esp_mbedtls_dynamic_impl.c" - "${COMPONENT_DIR}/port/dynamic/esp_ssl_cli.c" - "${COMPONENT_DIR}/port/dynamic/esp_ssl_srv.c" - "${COMPONENT_DIR}/port/dynamic/esp_ssl_tls.c") -endif() - -target_sources(mbedtls PRIVATE ${mbedtls_target_sources}) - -target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/esp_hardware.c" - "${COMPONENT_DIR}/port/esp_mem.c" - "${COMPONENT_DIR}/port/esp_timing.c" - "${COMPONENT_DIR}/port/esp_aes.c" - "${COMPONENT_DIR}/port/esp_sha1.c" - "${COMPONENT_DIR}/port/esp_sha256.c" - "${COMPONENT_DIR}/port/esp_sha512.c" - "${COMPONENT_DIR}/port/${target}/aes.c" - "${COMPONENT_DIR}/port/${target}/arc4.c" - "${COMPONENT_DIR}/port/${target}/base64.c" - "${COMPONENT_DIR}/port/${target}/md5.c" - "${COMPONENT_DIR}/port/${target}/sha1.c" - "${COMPONENT_DIR}/port/${target}/sha256.c" - "${COMPONENT_DIR}/port/${target}/sha512.c") - - -foreach(target ${mbedtls_targets}) - target_compile_definitions(${target} PUBLIC -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h" -DCONFIG_SSL_USING_MBEDTLS) -endforeach() - -if(CONFIG_MBEDTLS_DYNAMIC_BUFFER) - set(WRAP_FUNCTIONS - mbedtls_ssl_handshake_client_step - mbedtls_ssl_handshake_server_step - mbedtls_ssl_read - mbedtls_ssl_write - mbedtls_ssl_session_reset - mbedtls_ssl_free - mbedtls_ssl_setup - mbedtls_ssl_send_alert_message - mbedtls_ssl_close_notify) - - foreach(wrap ${WRAP_FUNCTIONS}) - target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=${wrap}") - endforeach() -endif() - -# Link mbedtls libraries to component library -target_link_libraries(${COMPONENT_LIB} INTERFACE ${mbedtls_targets}) +include("${IDF_PATH}/components/mbedtls/mbedtls_v2/CMakeLists.txt") +include("${IDF_PATH}/components/mbedtls/mbedtls_v3/CMakeLists.txt") \ No newline at end of file diff --git a/components/mbedtls/Kconfig b/components/mbedtls/Kconfig index 0bec091bd..e0ff70505 100644 --- a/components/mbedtls/Kconfig +++ b/components/mbedtls/Kconfig @@ -1,660 +1,21 @@ menu "mbedTLS" - choice MBEDTLS_MEM_ALLOC_MODE - prompt "Memory allocation strategy" - default MBEDTLS_INTERNAL_MEM_ALLOC - help - Allocation strategy for mbedTLS, essentially provides ability to - allocate all required dynamic allocations from, +choice MBEDTLS_VERSION + prompt "Mbedtls Version" + default MBEDTLS_V2 - - Internal DRAM memory only - - External SPIRAM memory only - - Either internal or external memory based on default malloc() - behavior in ESP-IDF - - Custom allocation mode, by overwriting calloc()/free() using - mbedtls_platform_set_calloc_free() function + config MBEDTLS_V2 + bool "MbedTls V2.x" - Recommended mode here is always internal, since that is most preferred - from security perspective. But if application requirement does not - allow sufficient free internal memory then alternate mode can be - selected. + config MBEDTLS_V3 + bool "MbedTls V3.x (Not Support openssl)" +endchoice - config MBEDTLS_INTERNAL_MEM_ALLOC - bool "Internal memory" +if MBEDTLS_V2 +source "$IDF_PATH/components/mbedtls/mbedtls_v2/Kconfig" +endif - config MBEDTLS_EXTERNAL_MEM_ALLOC - bool "External SPIRAM" - depends on ESP32_SPIRAM_SUPPORT - - config MBEDTLS_DEFAULT_MEM_ALLOC - bool "Default alloc mode" - - config MBEDTLS_CUSTOM_MEM_ALLOC - bool "Custom alloc mode" - - endchoice #MBEDTLS_MEM_ALLOC_MODE - - config MBEDTLS_SSL_MAX_CONTENT_LEN - int "TLS maximum message content length" - default 16384 - range 512 16384 - depends on !MBEDTLS_ASYMMETRIC_CONTENT_LEN - help - Maximum TLS message length (in bytes) supported by mbedTLS. - - 16384 is the default and this value is required to comply - fully with TLS standards. - - However you can set a lower value in order to save RAM. This - is safe if the other end of the connection supports Maximum - Fragment Length Negotiation Extension (max_fragment_length, - see RFC6066) or you know for certain that it will never send a - message longer than a certain number of bytes. - - If the value is set too low, symptoms are a failed TLS - handshake or a return value of MBEDTLS_ERR_SSL_INVALID_RECORD - (-0x7200). - - config MBEDTLS_ASYMMETRIC_CONTENT_LEN - bool "Asymmetric in/out fragment length" - default y - help - If enabled, this option allows customizing TLS in/out fragment length - in asymmetric way. Please note that enabling this with default values - saves 12KB of dynamic memory per TLS connection. - - config MBEDTLS_SSL_IN_CONTENT_LEN - int "TLS maximum incoming fragment length" - default 16384 - range 512 16384 - depends on MBEDTLS_ASYMMETRIC_CONTENT_LEN - help - This defines maximum incoming fragment length, overriding default - maximum content length (MBEDTLS_SSL_MAX_CONTENT_LEN). - - config MBEDTLS_SSL_OUT_CONTENT_LEN - int "TLS maximum outgoing fragment length" - default 4096 - range 512 16384 - depends on MBEDTLS_ASYMMETRIC_CONTENT_LEN - help - This defines maximum outgoing fragment length, overriding default - maximum content length (MBEDTLS_SSL_MAX_CONTENT_LEN). - - config MBEDTLS_DYNAMIC_BUFFER - bool "Using dynamic TX/RX buffer" - default n - select MBEDTLS_ASYMMETRIC_CONTENT_LEN - help - Using dynamic TX/RX buffer. After enabling this option, mbedTLS will - allocate TX buffer when need to send data and then free it if all data - is sent, allocate RX buffer when need to receive data and then free it - when all data is used or read by upper layer. - - By default, when SSL is initialized, mbedTLS also allocate TX and - RX buffer with the default value of "MBEDTLS_SSL_OUT_CONTENT_LEN" or - "MBEDTLS_SSL_IN_CONTENT_LEN", so to save more heap, users can set - the options to be an appropriate value. - - config MBEDTLS_DYNAMIC_FREE_PEER_CERT - bool "Free SSL peer certificate after its usage" - default n - depends on MBEDTLS_DYNAMIC_BUFFER - help - Free peer certificate after its usage in handshake process. - - config MBEDTLS_DYNAMIC_FREE_CONFIG_DATA - bool "Free certificate, key and DHM data after its usage" - default n - depends on MBEDTLS_DYNAMIC_BUFFER - help - Free certificate, private key and DHM data after its usage in handshake process. - - The option will decrease heap cost when handshake, but also lead to problem: - - Becasue all certificate, private key and DHM data are freed so users should register - certificate and private key to ssl config object again. - - config MBEDTLS_DEBUG - bool "Enable mbedTLS debugging" - default n - help - Enable mbedTLS debugging functions at compile time. - - If this option is enabled, you can include - "mbedtls/esp_debug.h" and call mbedtls_esp_enable_debug_log() - at runtime in order to enable mbedTLS debug output via the ESP - log mechanism. - - choice MBEDTLS_DEBUG_LEVEL - bool "Set mbedTLS debugging level" - depends on MBEDTLS_DEBUG - default MBEDTLS_DEBUG_LEVEL_VERBOSE - help - Set mbedTLS debugging level - - config MBEDTLS_DEBUG_LEVEL_WARN - bool "Warning" - config MBEDTLS_DEBUG_LEVEL_INFO - bool "Info" - config MBEDTLS_DEBUG_LEVEL_DEBUG - bool "Debug" - config MBEDTLS_DEBUG_LEVEL_VERBOSE - bool "Verbose" - endchoice - - config MBEDTLS_DEBUG_LEVEL - int - default 1 if MBEDTLS_DEBUG_LEVEL_WARN - default 2 if MBEDTLS_DEBUG_LEVEL_INFO - default 3 if MBEDTLS_DEBUG_LEVEL_DEBUG - default 4 if MBEDTLS_DEBUG_LEVEL_VERBOSE - - config MBEDTLS_HAVE_TIME - bool "Enable mbedtls time" - depends on !ESP32_TIME_SYSCALL_USE_NONE - default y - help - System has time.h and time(). - The time does not need to be correct, only time differences are used. - - config MBEDTLS_HAVE_TIME_DATE - bool "Enable mbedtls certificate expiry check" - depends on MBEDTLS_HAVE_TIME - default n - help - System has time.h and time(), gmtime() and the clock is correct. - The time needs to be correct (not necesarily very accurate, but at least - the date should be correct). This is used to verify the validity period of - X.509 certificates. - - It is suggested that you should get the real time by "SNTP". - - choice MBEDTLS_TLS_MODE - bool "TLS Protocol Role" - default MBEDTLS_TLS_SERVER_AND_CLIENT - help - mbedTLS can be compiled with protocol support for the TLS - server, TLS client, or both server and client. - - Reducing the number of TLS roles supported saves code size. - - config MBEDTLS_TLS_SERVER_AND_CLIENT - bool "Server & Client" - select MBEDTLS_TLS_SERVER - select MBEDTLS_TLS_CLIENT - config MBEDTLS_TLS_SERVER_ONLY - bool "Server" - select MBEDTLS_TLS_SERVER - config MBEDTLS_TLS_CLIENT_ONLY - bool "Client" - select MBEDTLS_TLS_CLIENT - config MBEDTLS_TLS_DISABLED - bool "None" - - endchoice - - config MBEDTLS_TLS_SERVER - bool - select MBEDTLS_TLS_ENABLED - config MBEDTLS_TLS_CLIENT - bool - select MBEDTLS_TLS_ENABLED - config MBEDTLS_TLS_ENABLED - bool - - menu "TLS Key Exchange Methods" - depends on MBEDTLS_TLS_ENABLED - - config MBEDTLS_PSK_MODES - bool "Enable pre-shared-key ciphersuites" - default n - help - Enable to show configuration for different types of pre-shared-key TLS authentatication methods. - - Leaving this options disabled will save code size if they are not used. - - config MBEDTLS_KEY_EXCHANGE_PSK - bool "Enable PSK based ciphersuite modes" - depends on MBEDTLS_PSK_MODES - default n - help - Enable to support symmetric key PSK (pre-shared-key) TLS key exchange modes. - - config MBEDTLS_KEY_EXCHANGE_DHE_PSK - bool "Enable DHE-PSK based ciphersuite modes" - depends on MBEDTLS_PSK_MODES - default y - help - Enable to support Diffie-Hellman PSK (pre-shared-key) TLS authentication modes. - - config MBEDTLS_KEY_EXCHANGE_ECDHE_PSK - bool "Enable ECDHE-PSK based ciphersuite modes" - depends on MBEDTLS_PSK_MODES && MBEDTLS_ECDH_C - default y - help - Enable to support Elliptic-Curve-Diffie-Hellman PSK (pre-shared-key) TLS authentication modes. - - config MBEDTLS_KEY_EXCHANGE_RSA_PSK - bool "Enable RSA-PSK based ciphersuite modes" - depends on MBEDTLS_PSK_MODES - default y - help - Enable to support RSA PSK (pre-shared-key) TLS authentication modes. - - config MBEDTLS_KEY_EXCHANGE_RSA - bool "Enable RSA-only based ciphersuite modes" - default y - help - Enable to support ciphersuites with prefix TLS-RSA-WITH- - - config MBEDTLS_KEY_EXCHANGE_DHE_RSA - bool "Enable DHE-RSA based ciphersuite modes" - default y - help - Enable to support ciphersuites with prefix TLS-DHE-RSA-WITH- - - config MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE - bool "Support Elliptic Curve based ciphersuites" - depends on MBEDTLS_ECP_C - default y - help - Enable to show Elliptic Curve based ciphersuite mode options. - - Disabling all Elliptic Curve ciphersuites saves code size and - can give slightly faster TLS handshakes, provided the server supports - RSA-only ciphersuite modes. - - config MBEDTLS_KEY_EXCHANGE_ECDHE_RSA - bool "Enable ECDHE-RSA based ciphersuite modes" - depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C - default y - help - Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH- - - config MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA - bool "Enable ECDHE-ECDSA based ciphersuite modes" - depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C && MBEDTLS_ECDSA_C - default y - help - Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH- - - config MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA - bool "Enable ECDH-ECDSA based ciphersuite modes" - depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C && MBEDTLS_ECDSA_C - default y - help - Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH- - - config MBEDTLS_KEY_EXCHANGE_ECDH_RSA - bool "Enable ECDH-RSA based ciphersuite modes" - depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C - default y - help - Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH- - - endmenu # TLS key exchange modes - - config MBEDTLS_SSL_RENEGOTIATION - bool "Support TLS renegotiation" - depends on MBEDTLS_TLS_ENABLED - default y - help - The two main uses of renegotiation are (1) refresh keys on long-lived - connections and (2) client authentication after the initial handshake. - If you don't need renegotiation, disabling it will save code size and - reduce the possibility of abuse/vulnerability. - - config MBEDTLS_SSL_PROTO_SSL3 - bool "Legacy SSL 3.0 support" - depends on MBEDTLS_TLS_ENABLED - default n - help - Support the legacy SSL 3.0 protocol. Most servers will speak a newer - TLS protocol these days. - - config MBEDTLS_SSL_PROTO_TLS1 - bool "Support TLS 1.0 protocol" - depends on MBEDTLS_TLS_ENABLED - default y - - config MBEDTLS_SSL_PROTO_TLS1_1 - bool "Support TLS 1.1 protocol" - depends on MBEDTLS_TLS_ENABLED - default y - - config MBEDTLS_SSL_PROTO_TLS1_2 - bool "Support TLS 1.2 protocol" - depends on MBEDTLS_TLS_ENABLED - default y - - config MBEDTLS_SSL_PROTO_DTLS - bool "Support DTLS protocol (all versions)" - default n - depends on MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 - help - Requires TLS 1.1 to be enabled for DTLS 1.0 - Requires TLS 1.2 to be enabled for DTLS 1.2 - - config MBEDTLS_SSL_ALPN - bool "Support ALPN (Application Layer Protocol Negotiation)" - depends on MBEDTLS_TLS_ENABLED - default y - help - Disabling this option will save some code size if it is not needed. - - config MBEDTLS_CLIENT_SSL_SESSION_TICKETS - bool "TLS: Client Support for RFC 5077 SSL session tickets" - default y - depends on MBEDTLS_TLS_ENABLED - help - Client support for RFC 5077 session tickets. See mbedTLS documentation for more details. - Disabling this option will save some code size. - - config MBEDTLS_SERVER_SSL_SESSION_TICKETS - bool "TLS: Server Support for RFC 5077 SSL session tickets" - default y - depends on MBEDTLS_TLS_ENABLED - depends on MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C - help - Server support for RFC 5077 session tickets. See mbedTLS documentation for more details. - Disabling this option will save some code size. - - menu "Symmetric Ciphers" - - config MBEDTLS_AES_C - bool "AES block cipher" - default y - - config MBEDTLS_CAMELLIA_C - bool "Camellia block cipher" - default n - - config MBEDTLS_DES_C - bool "DES block cipher (legacy, insecure)" - default n - help - Enables the DES block cipher to support 3DES-based TLS ciphersuites. - - 3DES is vulnerable to the Sweet32 attack and should only be enabled - if absolutely necessary. - - choice MBEDTLS_RC4_MODE - prompt "RC4 Stream Cipher (legacy, insecure)" - default MBEDTLS_RC4_DISABLED - help - ARCFOUR (RC4) stream cipher can be disabled entirely, enabled but not - added to default ciphersuites, or enabled completely. - - Please consider the security implications before enabling RC4. - - config MBEDTLS_RC4_DISABLED - bool "Disabled" - config MBEDTLS_RC4_ENABLED_NO_DEFAULT - bool "Enabled, not in default ciphersuites" - config MBEDTLS_RC4_ENABLED - bool "Enabled" - endchoice - - config MBEDTLS_BLOWFISH_C - bool "Blowfish block cipher (read help)" - default n - help - Enables the Blowfish block cipher (not used for TLS sessions.) - - The Blowfish cipher is not used for mbedTLS TLS sessions but can be - used for other purposes. Read up on the limitations of Blowfish (including - Sweet32) before enabling. - - config MBEDTLS_XTEA_C - bool "XTEA block cipher" - default n - help - Enables the XTEA block cipher. - - - config MBEDTLS_CCM_C - bool "CCM (Counter with CBC-MAC) block cipher modes" - default y - depends on MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C - help - Enable Counter with CBC-MAC (CCM) modes for AES and/or Camellia ciphers. - - Disabling this option saves some code size. - - config MBEDTLS_GCM_C - bool "GCM (Galois/Counter) block cipher modes" - default y - depends on MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C - help - Enable Galois/Counter Mode for AES and/or Camellia ciphers. - - This option is generally faster than CCM. - - endmenu # Symmetric Ciphers - - config MBEDTLS_RIPEMD160_C - bool "Enable RIPEMD-160 hash algorithm" - default n - help - Enable the RIPEMD-160 hash algorithm. - - menu "Certificates" - - config MBEDTLS_PEM_PARSE_C - bool "Read & Parse PEM formatted certificates" - default y - help - Enable decoding/parsing of PEM formatted certificates. - - If your certificates are all in the simpler DER format, disabling - this option will save some code size. - - config MBEDTLS_PEM_WRITE_C - bool "Write PEM formatted certificates" - default y - help - Enable writing of PEM formatted certificates. - - If writing certificate data only in DER format, disabling this - option will save some code size. - - config MBEDTLS_X509_CRL_PARSE_C - bool "X.509 CRL parsing" - default y - help - Support for parsing X.509 Certifificate Revocation Lists. - - config MBEDTLS_X509_CSR_PARSE_C - bool "X.509 CSR parsing" - default y - help - Support for parsing X.509 Certifificate Signing Requests - - endmenu # Certificates - - menuconfig MBEDTLS_ECP_C - bool "Elliptic Curve Ciphers" - default y - - config MBEDTLS_ECDH_C - bool "Elliptic Curve Diffie-Hellman (ECDH)" - depends on MBEDTLS_ECP_C - default y - help - Enable ECDH. Needed to use ECDHE-xxx TLS ciphersuites. - - config MBEDTLS_ECDSA_C - bool "Elliptic Curve DSA" - depends on MBEDTLS_ECDH_C - default y - help - Enable ECDSA. Needed to use ECDSA-xxx TLS ciphersuites. - - config MBEDTLS_ECP_DP_SECP192R1_ENABLED - bool "Enable SECP192R1 curve" - depends on MBEDTLS_ECP_C - default y - help - Enable support for SECP192R1 Elliptic Curve. - - config MBEDTLS_ECP_DP_SECP224R1_ENABLED - bool "Enable SECP224R1 curve" - depends on MBEDTLS_ECP_C - default y - help - Enable support for SECP224R1 Elliptic Curve. - - config MBEDTLS_ECP_DP_SECP256R1_ENABLED - bool "Enable SECP256R1 curve" - depends on MBEDTLS_ECP_C - default y - help - Enable support for SECP256R1 Elliptic Curve. - - config MBEDTLS_ECP_DP_SECP384R1_ENABLED - bool "Enable SECP384R1 curve" - depends on MBEDTLS_ECP_C - default y - help - Enable support for SECP384R1 Elliptic Curve. - - config MBEDTLS_ECP_DP_SECP521R1_ENABLED - bool "Enable SECP521R1 curve" - depends on MBEDTLS_ECP_C - default y - help - Enable support for SECP521R1 Elliptic Curve. - - config MBEDTLS_ECP_DP_SECP192K1_ENABLED - bool "Enable SECP192K1 curve" - depends on MBEDTLS_ECP_C - default y - help - Enable support for SECP192K1 Elliptic Curve. - - config MBEDTLS_ECP_DP_SECP224K1_ENABLED - bool "Enable SECP224K1 curve" - depends on MBEDTLS_ECP_C - default y - help - Enable support for SECP224K1 Elliptic Curve. - - config MBEDTLS_ECP_DP_SECP256K1_ENABLED - bool "Enable SECP256K1 curve" - depends on MBEDTLS_ECP_C - default y - help - Enable support for SECP256K1 Elliptic Curve. - - config MBEDTLS_ECP_DP_BP256R1_ENABLED - bool "Enable BP256R1 curve" - depends on MBEDTLS_ECP_C - default y - help - support for DP Elliptic Curve. - - config MBEDTLS_ECP_DP_BP384R1_ENABLED - bool "Enable BP384R1 curve" - depends on MBEDTLS_ECP_C - default y - help - support for DP Elliptic Curve. - - config MBEDTLS_ECP_DP_BP512R1_ENABLED - bool "Enable BP512R1 curve" - depends on MBEDTLS_ECP_C - default y - help - support for DP Elliptic Curve. - - config MBEDTLS_ECP_DP_CURVE25519_ENABLED - bool "Enable CURVE25519 curve" - depends on MBEDTLS_ECP_C - default y - help - Enable support for CURVE25519 Elliptic Curve. - - config MBEDTLS_ECP_NIST_OPTIM - bool "NIST 'modulo p' optimisations" - depends on MBEDTLS_ECP_C - default y - help - NIST 'modulo p' optimisations increase Elliptic Curve operation performance. - - Disabling this option saves some code size. - - # end of Elliptic Curve options - - menu "Util" - - config util_assert - bool "Enable assert for util components" - default n - help - Enable this option, util components will use assert to check if input - parameters are correct. - - Disable this option will speed up the process of some calculation a lot. - - config ESP_SHA - bool "Enable Espressif SHA" - default n - help - Enable Espressif SHA1, SHA256, SHA384 & SHA512 for other components to - save code size for ESP8285(ESP8266 + 1MB flash) users. - - Although this option is disable, bootloader will use it if booloader - is configured to use SHA256 to check hash. - - Disabling the "assert" function at menuconfig can speed up the calculation. - - config ESP_AES - bool "Enable Espressif AES" - default y - help - Enable Espressif AES ECB, CBC, CFB128, CFB8 & CRT for other components to - speed up process speed and save code size. - - ESP8285 is like ESP8266 + 1MB flash, but its internal I/O connection from CPU - core to flash is DIO not QIO, which makes it read flash data slower. - So the function will speed up ESP8285 obviously. - - The calculation uses "ibus_data" to speed up load data from instruction bus. - - Disabling the "assert" function at menuconfig can speed up the calculation. - - config ESP_MD5 - bool "Enable Espressif MD5" - default y - help - Enable Espressif MD5 for other components to - speed up process speed and save code size. - - ESP8285 is like ESP8266 + 1MB flash, but its internal I/O connection from CPU - core to flash is DIO not QIO, which makes it read flash data slower. - So the function will speed up ESP8285 obviously. - - The calculation uses "ibus_data" to speed up load data from instruction bus. - - Disabling the "assert" function at menuconfig can speed up the calculation. - - config ESP_ARC4 - bool "Enable Espressif ARC4" - default y - help - Enable Espressif ARC4 for other components to - speed up process speed and save code size. - - ESP8285 is like ESP8266 + 1MB flash, but its internal I/O connection from CPU - core to flash is DIO not QIO, which makes it read flash data slower. - So the function will speed up ESP8285 obviously. - - The calculation uses "ibus_data" to speed up load data from instruction bus. - - Disabling the "assert" function at menuconfig can speed up the calculation. - - endmenu # Util - - -endmenu # mbedTLS +if MBEDTLS_V3 +source "$IDF_PATH/components/mbedtls/mbedtls_v3/Kconfig" +endif +endmenu diff --git a/components/mbedtls/component.mk b/components/mbedtls/component.mk index 541009de6..1970e3b32 100644 --- a/components/mbedtls/component.mk +++ b/components/mbedtls/component.mk @@ -1,31 +1,10 @@ # # Component Makefile # - -COMPONENT_ADD_INCLUDEDIRS := port/include mbedtls/include port/include/$(IDF_TARGET) - -COMPONENT_SRCDIRS := mbedtls/library port port/$(IDF_TARGET) - -COMPONENT_OBJEXCLUDE := mbedtls/library/net_sockets.o - -COMPONENT_SUBMODULES += mbedtls - -ifdef CONFIG_MBEDTLS_DYNAMIC_BUFFER - -WRAP_FUNCTIONS = mbedtls_ssl_handshake_client_step \ - mbedtls_ssl_handshake_server_step \ - mbedtls_ssl_read \ - mbedtls_ssl_write \ - mbedtls_ssl_session_reset \ - mbedtls_ssl_free \ - mbedtls_ssl_setup \ - mbedtls_ssl_send_alert_message \ - mbedtls_ssl_close_notify - -WRAP_ARGUMENT := -Wl,--wrap= - -COMPONENT_ADD_LDFLAGS = -l$(COMPONENT_NAME) $(addprefix $(WRAP_ARGUMENT),$(WRAP_FUNCTIONS)) - -COMPONENT_SRCDIRS += port/dynamic - +ifdef CONFIG_MBEDTLS_V2 +include $(IDF_PATH)/components/mbedtls/mbedtls_v2/component.mk endif + +ifdef CONFIG_MBEDTLS_V3 +include $(IDF_PATH)/components/mbedtls/mbedtls_v3/component.mk +endif \ No newline at end of file diff --git a/components/mbedtls/mbedtls_v2/CMakeLists.txt b/components/mbedtls/mbedtls_v2/CMakeLists.txt new file mode 100644 index 000000000..3ece781de --- /dev/null +++ b/components/mbedtls/mbedtls_v2/CMakeLists.txt @@ -0,0 +1,81 @@ +if(CONFIG_MBEDTLS_V3) + return() +endif() + +idf_build_get_property(target IDF_TARGET) + +set(current_dir ${COMPONENT_DIR}/mbedtls_v2) + +idf_component_register(INCLUDE_DIRS "mbedtls_v2/port/include" "mbedtls_v2/port/include/${target}" "mbedtls_v2/mbedtls/include" + REQUIRES lwip) + +# Only build mbedtls libraries +set(ENABLE_TESTING CACHE BOOL OFF) +set(ENABLE_PROGRAMS CACHE BOOL OFF) + +# Needed to for include_next includes to work from within mbedtls +include_directories("${current_dir}/port/include" "${current_dir}/port/include/${target}") + +# Import mbedtls library targets +add_subdirectory(mbedtls_v2/mbedtls) + +# Use port specific implementation of net_socket.c instead of one from mbedtls +get_target_property(src_tls mbedtls SOURCES) +list(REMOVE_ITEM src_tls net_sockets.c) +set_property(TARGET mbedtls PROPERTY SOURCES ${src_tls}) + +set(mbedtls_targets mbedtls mbedcrypto mbedx509) + +# Add port files to mbedtls targets +set(mbedtls_target_sources "${current_dir}/port/mbedtls_debug.c" + "${current_dir}/port/net_sockets.c") + +if(CONFIG_MBEDTLS_DYNAMIC_BUFFER) +set(mbedtls_target_sources ${mbedtls_target_sources} + "${current_dir}/port/dynamic/esp_mbedtls_dynamic_impl.c" + "${current_dir}/port/dynamic/esp_ssl_cli.c" + "${current_dir}/port/dynamic/esp_ssl_srv.c" + "${current_dir}/port/dynamic/esp_ssl_tls.c") +endif() + +target_sources(mbedtls PRIVATE ${mbedtls_target_sources}) + +target_sources(mbedcrypto PRIVATE "${current_dir}/port/esp_hardware.c" + "${current_dir}/port/esp_mem.c" + "${current_dir}/port/esp_timing.c" + "${current_dir}/port/esp_aes.c" + "${current_dir}/port/esp_sha1.c" + "${current_dir}/port/esp_sha256.c" + "${current_dir}/port/esp_sha512.c" + "${current_dir}/port/${target}/aes.c" + "${current_dir}/port/${target}/arc4.c" + "${current_dir}/port/${target}/base64.c" + "${current_dir}/port/${target}/md5.c" + "${current_dir}/port/${target}/sha1.c" + "${current_dir}/port/${target}/sha256.c" + "${current_dir}/port/${target}/sha512.c") + + +foreach(target ${mbedtls_targets}) + target_compile_definitions(${target} PUBLIC -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h" -DCONFIG_SSL_USING_MBEDTLS) +endforeach() + +if(CONFIG_MBEDTLS_DYNAMIC_BUFFER) + set(WRAP_FUNCTIONS + mbedtls_ssl_handshake_client_step + mbedtls_ssl_handshake_server_step + mbedtls_ssl_read + mbedtls_ssl_write + mbedtls_ssl_session_reset + mbedtls_ssl_free + mbedtls_ssl_setup + mbedtls_ssl_send_alert_message + mbedtls_ssl_close_notify) + + foreach(wrap ${WRAP_FUNCTIONS}) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=${wrap}") + endforeach() +endif() + +# Link mbedtls libraries to component library +target_link_libraries(${COMPONENT_LIB} INTERFACE ${mbedtls_targets}) diff --git a/components/mbedtls/mbedtls_v2/Kconfig b/components/mbedtls/mbedtls_v2/Kconfig new file mode 100644 index 000000000..f60d42ff6 --- /dev/null +++ b/components/mbedtls/mbedtls_v2/Kconfig @@ -0,0 +1,656 @@ +choice MBEDTLS_MEM_ALLOC_MODE + prompt "Memory allocation strategy" + default MBEDTLS_INTERNAL_MEM_ALLOC + help + Allocation strategy for mbedTLS, essentially provides ability to + allocate all required dynamic allocations from, + + - Internal DRAM memory only + - External SPIRAM memory only + - Either internal or external memory based on default malloc() + behavior in ESP-IDF + - Custom allocation mode, by overwriting calloc()/free() using + mbedtls_platform_set_calloc_free() function + + Recommended mode here is always internal, since that is most preferred + from security perspective. But if application requirement does not + allow sufficient free internal memory then alternate mode can be + selected. + + config MBEDTLS_INTERNAL_MEM_ALLOC + bool "Internal memory" + + config MBEDTLS_EXTERNAL_MEM_ALLOC + bool "External SPIRAM" + depends on ESP32_SPIRAM_SUPPORT + + config MBEDTLS_DEFAULT_MEM_ALLOC + bool "Default alloc mode" + + config MBEDTLS_CUSTOM_MEM_ALLOC + bool "Custom alloc mode" + +endchoice #MBEDTLS_MEM_ALLOC_MODE + +config MBEDTLS_SSL_MAX_CONTENT_LEN + int "TLS maximum message content length" + default 16384 + range 512 16384 + depends on !MBEDTLS_ASYMMETRIC_CONTENT_LEN + help + Maximum TLS message length (in bytes) supported by mbedTLS. + + 16384 is the default and this value is required to comply + fully with TLS standards. + + However you can set a lower value in order to save RAM. This + is safe if the other end of the connection supports Maximum + Fragment Length Negotiation Extension (max_fragment_length, + see RFC6066) or you know for certain that it will never send a + message longer than a certain number of bytes. + + If the value is set too low, symptoms are a failed TLS + handshake or a return value of MBEDTLS_ERR_SSL_INVALID_RECORD + (-0x7200). + +config MBEDTLS_ASYMMETRIC_CONTENT_LEN + bool "Asymmetric in/out fragment length" + default y + help + If enabled, this option allows customizing TLS in/out fragment length + in asymmetric way. Please note that enabling this with default values + saves 12KB of dynamic memory per TLS connection. + +config MBEDTLS_SSL_IN_CONTENT_LEN + int "TLS maximum incoming fragment length" + default 16384 + range 512 16384 + depends on MBEDTLS_ASYMMETRIC_CONTENT_LEN + help + This defines maximum incoming fragment length, overriding default + maximum content length (MBEDTLS_SSL_MAX_CONTENT_LEN). + +config MBEDTLS_SSL_OUT_CONTENT_LEN + int "TLS maximum outgoing fragment length" + default 4096 + range 512 16384 + depends on MBEDTLS_ASYMMETRIC_CONTENT_LEN + help + This defines maximum outgoing fragment length, overriding default + maximum content length (MBEDTLS_SSL_MAX_CONTENT_LEN). + +config MBEDTLS_DYNAMIC_BUFFER + bool "Using dynamic TX/RX buffer" + default n + select MBEDTLS_ASYMMETRIC_CONTENT_LEN + help + Using dynamic TX/RX buffer. After enabling this option, mbedTLS will + allocate TX buffer when need to send data and then free it if all data + is sent, allocate RX buffer when need to receive data and then free it + when all data is used or read by upper layer. + + By default, when SSL is initialized, mbedTLS also allocate TX and + RX buffer with the default value of "MBEDTLS_SSL_OUT_CONTENT_LEN" or + "MBEDTLS_SSL_IN_CONTENT_LEN", so to save more heap, users can set + the options to be an appropriate value. + +config MBEDTLS_DYNAMIC_FREE_PEER_CERT + bool "Free SSL peer certificate after its usage" + default n + depends on MBEDTLS_DYNAMIC_BUFFER + help + Free peer certificate after its usage in handshake process. + +config MBEDTLS_DYNAMIC_FREE_CONFIG_DATA + bool "Free certificate, key and DHM data after its usage" + default n + depends on MBEDTLS_DYNAMIC_BUFFER + help + Free certificate, private key and DHM data after its usage in handshake process. + + The option will decrease heap cost when handshake, but also lead to problem: + + Becasue all certificate, private key and DHM data are freed so users should register + certificate and private key to ssl config object again. + +config MBEDTLS_DEBUG + bool "Enable mbedTLS debugging" + default n + help + Enable mbedTLS debugging functions at compile time. + + If this option is enabled, you can include + "mbedtls/esp_debug.h" and call mbedtls_esp_enable_debug_log() + at runtime in order to enable mbedTLS debug output via the ESP + log mechanism. + +choice MBEDTLS_DEBUG_LEVEL + bool "Set mbedTLS debugging level" + depends on MBEDTLS_DEBUG + default MBEDTLS_DEBUG_LEVEL_VERBOSE + help + Set mbedTLS debugging level + + config MBEDTLS_DEBUG_LEVEL_WARN + bool "Warning" + config MBEDTLS_DEBUG_LEVEL_INFO + bool "Info" + config MBEDTLS_DEBUG_LEVEL_DEBUG + bool "Debug" + config MBEDTLS_DEBUG_LEVEL_VERBOSE + bool "Verbose" +endchoice + +config MBEDTLS_DEBUG_LEVEL + int + default 1 if MBEDTLS_DEBUG_LEVEL_WARN + default 2 if MBEDTLS_DEBUG_LEVEL_INFO + default 3 if MBEDTLS_DEBUG_LEVEL_DEBUG + default 4 if MBEDTLS_DEBUG_LEVEL_VERBOSE + +config MBEDTLS_HAVE_TIME + bool "Enable mbedtls time" + depends on !ESP32_TIME_SYSCALL_USE_NONE + default y + help + System has time.h and time(). + The time does not need to be correct, only time differences are used. + +config MBEDTLS_HAVE_TIME_DATE + bool "Enable mbedtls certificate expiry check" + depends on MBEDTLS_HAVE_TIME + default n + help + System has time.h and time(), gmtime() and the clock is correct. + The time needs to be correct (not necesarily very accurate, but at least + the date should be correct). This is used to verify the validity period of + X.509 certificates. + + It is suggested that you should get the real time by "SNTP". + +choice MBEDTLS_TLS_MODE + bool "TLS Protocol Role" + default MBEDTLS_TLS_SERVER_AND_CLIENT + help + mbedTLS can be compiled with protocol support for the TLS + server, TLS client, or both server and client. + + Reducing the number of TLS roles supported saves code size. + + config MBEDTLS_TLS_SERVER_AND_CLIENT + bool "Server & Client" + select MBEDTLS_TLS_SERVER + select MBEDTLS_TLS_CLIENT + config MBEDTLS_TLS_SERVER_ONLY + bool "Server" + select MBEDTLS_TLS_SERVER + config MBEDTLS_TLS_CLIENT_ONLY + bool "Client" + select MBEDTLS_TLS_CLIENT + config MBEDTLS_TLS_DISABLED + bool "None" + +endchoice + +config MBEDTLS_TLS_SERVER + bool + select MBEDTLS_TLS_ENABLED +config MBEDTLS_TLS_CLIENT + bool + select MBEDTLS_TLS_ENABLED +config MBEDTLS_TLS_ENABLED + bool + +menu "TLS Key Exchange Methods" + depends on MBEDTLS_TLS_ENABLED + + config MBEDTLS_PSK_MODES + bool "Enable pre-shared-key ciphersuites" + default n + help + Enable to show configuration for different types of pre-shared-key TLS authentatication methods. + + Leaving this options disabled will save code size if they are not used. + + config MBEDTLS_KEY_EXCHANGE_PSK + bool "Enable PSK based ciphersuite modes" + depends on MBEDTLS_PSK_MODES + default n + help + Enable to support symmetric key PSK (pre-shared-key) TLS key exchange modes. + + config MBEDTLS_KEY_EXCHANGE_DHE_PSK + bool "Enable DHE-PSK based ciphersuite modes" + depends on MBEDTLS_PSK_MODES + default y + help + Enable to support Diffie-Hellman PSK (pre-shared-key) TLS authentication modes. + + config MBEDTLS_KEY_EXCHANGE_ECDHE_PSK + bool "Enable ECDHE-PSK based ciphersuite modes" + depends on MBEDTLS_PSK_MODES && MBEDTLS_ECDH_C + default y + help + Enable to support Elliptic-Curve-Diffie-Hellman PSK (pre-shared-key) TLS authentication modes. + + config MBEDTLS_KEY_EXCHANGE_RSA_PSK + bool "Enable RSA-PSK based ciphersuite modes" + depends on MBEDTLS_PSK_MODES + default y + help + Enable to support RSA PSK (pre-shared-key) TLS authentication modes. + + config MBEDTLS_KEY_EXCHANGE_RSA + bool "Enable RSA-only based ciphersuite modes" + default y + help + Enable to support ciphersuites with prefix TLS-RSA-WITH- + + config MBEDTLS_KEY_EXCHANGE_DHE_RSA + bool "Enable DHE-RSA based ciphersuite modes" + default y + help + Enable to support ciphersuites with prefix TLS-DHE-RSA-WITH- + + config MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE + bool "Support Elliptic Curve based ciphersuites" + depends on MBEDTLS_ECP_C + default y + help + Enable to show Elliptic Curve based ciphersuite mode options. + + Disabling all Elliptic Curve ciphersuites saves code size and + can give slightly faster TLS handshakes, provided the server supports + RSA-only ciphersuite modes. + + config MBEDTLS_KEY_EXCHANGE_ECDHE_RSA + bool "Enable ECDHE-RSA based ciphersuite modes" + depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C + default y + help + Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH- + + config MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA + bool "Enable ECDHE-ECDSA based ciphersuite modes" + depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C && MBEDTLS_ECDSA_C + default y + help + Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH- + + config MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA + bool "Enable ECDH-ECDSA based ciphersuite modes" + depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C && MBEDTLS_ECDSA_C + default y + help + Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH- + + config MBEDTLS_KEY_EXCHANGE_ECDH_RSA + bool "Enable ECDH-RSA based ciphersuite modes" + depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C + default y + help + Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH- + +endmenu # TLS key exchange modes + +config MBEDTLS_SSL_RENEGOTIATION + bool "Support TLS renegotiation" + depends on MBEDTLS_TLS_ENABLED + default y + help + The two main uses of renegotiation are (1) refresh keys on long-lived + connections and (2) client authentication after the initial handshake. + If you don't need renegotiation, disabling it will save code size and + reduce the possibility of abuse/vulnerability. + +config MBEDTLS_SSL_PROTO_SSL3 + bool "Legacy SSL 3.0 support" + depends on MBEDTLS_TLS_ENABLED + default n + help + Support the legacy SSL 3.0 protocol. Most servers will speak a newer + TLS protocol these days. + +config MBEDTLS_SSL_PROTO_TLS1 + bool "Support TLS 1.0 protocol" + depends on MBEDTLS_TLS_ENABLED + default y + +config MBEDTLS_SSL_PROTO_TLS1_1 + bool "Support TLS 1.1 protocol" + depends on MBEDTLS_TLS_ENABLED + default y + +config MBEDTLS_SSL_PROTO_TLS1_2 + bool "Support TLS 1.2 protocol" + depends on MBEDTLS_TLS_ENABLED + default y + +config MBEDTLS_SSL_PROTO_DTLS + bool "Support DTLS protocol (all versions)" + default n + depends on MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 + help + Requires TLS 1.1 to be enabled for DTLS 1.0 + Requires TLS 1.2 to be enabled for DTLS 1.2 + +config MBEDTLS_SSL_ALPN + bool "Support ALPN (Application Layer Protocol Negotiation)" + depends on MBEDTLS_TLS_ENABLED + default y + help + Disabling this option will save some code size if it is not needed. + +config MBEDTLS_CLIENT_SSL_SESSION_TICKETS + bool "TLS: Client Support for RFC 5077 SSL session tickets" + default y + depends on MBEDTLS_TLS_ENABLED + help + Client support for RFC 5077 session tickets. See mbedTLS documentation for more details. + Disabling this option will save some code size. + +config MBEDTLS_SERVER_SSL_SESSION_TICKETS + bool "TLS: Server Support for RFC 5077 SSL session tickets" + default y + depends on MBEDTLS_TLS_ENABLED + depends on MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C + help + Server support for RFC 5077 session tickets. See mbedTLS documentation for more details. + Disabling this option will save some code size. + +menu "Symmetric Ciphers" + + config MBEDTLS_AES_C + bool "AES block cipher" + default y + + config MBEDTLS_CAMELLIA_C + bool "Camellia block cipher" + default n + + config MBEDTLS_DES_C + bool "DES block cipher (legacy, insecure)" + default n + help + Enables the DES block cipher to support 3DES-based TLS ciphersuites. + + 3DES is vulnerable to the Sweet32 attack and should only be enabled + if absolutely necessary. + + choice MBEDTLS_RC4_MODE + prompt "RC4 Stream Cipher (legacy, insecure)" + default MBEDTLS_RC4_DISABLED + help + ARCFOUR (RC4) stream cipher can be disabled entirely, enabled but not + added to default ciphersuites, or enabled completely. + + Please consider the security implications before enabling RC4. + + config MBEDTLS_RC4_DISABLED + bool "Disabled" + config MBEDTLS_RC4_ENABLED_NO_DEFAULT + bool "Enabled, not in default ciphersuites" + config MBEDTLS_RC4_ENABLED + bool "Enabled" + endchoice + + config MBEDTLS_BLOWFISH_C + bool "Blowfish block cipher (read help)" + default n + help + Enables the Blowfish block cipher (not used for TLS sessions.) + + The Blowfish cipher is not used for mbedTLS TLS sessions but can be + used for other purposes. Read up on the limitations of Blowfish (including + Sweet32) before enabling. + + config MBEDTLS_XTEA_C + bool "XTEA block cipher" + default n + help + Enables the XTEA block cipher. + + + config MBEDTLS_CCM_C + bool "CCM (Counter with CBC-MAC) block cipher modes" + default y + depends on MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C + help + Enable Counter with CBC-MAC (CCM) modes for AES and/or Camellia ciphers. + + Disabling this option saves some code size. + + config MBEDTLS_GCM_C + bool "GCM (Galois/Counter) block cipher modes" + default y + depends on MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C + help + Enable Galois/Counter Mode for AES and/or Camellia ciphers. + + This option is generally faster than CCM. + +endmenu # Symmetric Ciphers + +config MBEDTLS_RIPEMD160_C + bool "Enable RIPEMD-160 hash algorithm" + default n + help + Enable the RIPEMD-160 hash algorithm. + +menu "Certificates" + + config MBEDTLS_PEM_PARSE_C + bool "Read & Parse PEM formatted certificates" + default y + help + Enable decoding/parsing of PEM formatted certificates. + + If your certificates are all in the simpler DER format, disabling + this option will save some code size. + + config MBEDTLS_PEM_WRITE_C + bool "Write PEM formatted certificates" + default y + help + Enable writing of PEM formatted certificates. + + If writing certificate data only in DER format, disabling this + option will save some code size. + + config MBEDTLS_X509_CRL_PARSE_C + bool "X.509 CRL parsing" + default y + help + Support for parsing X.509 Certifificate Revocation Lists. + + config MBEDTLS_X509_CSR_PARSE_C + bool "X.509 CSR parsing" + default y + help + Support for parsing X.509 Certifificate Signing Requests + +endmenu # Certificates + +menuconfig MBEDTLS_ECP_C + bool "Elliptic Curve Ciphers" + default y + +config MBEDTLS_ECDH_C + bool "Elliptic Curve Diffie-Hellman (ECDH)" + depends on MBEDTLS_ECP_C + default y + help + Enable ECDH. Needed to use ECDHE-xxx TLS ciphersuites. + +config MBEDTLS_ECDSA_C + bool "Elliptic Curve DSA" + depends on MBEDTLS_ECDH_C + default y + help + Enable ECDSA. Needed to use ECDSA-xxx TLS ciphersuites. + +config MBEDTLS_ECP_DP_SECP192R1_ENABLED + bool "Enable SECP192R1 curve" + depends on MBEDTLS_ECP_C + default y + help + Enable support for SECP192R1 Elliptic Curve. + +config MBEDTLS_ECP_DP_SECP224R1_ENABLED + bool "Enable SECP224R1 curve" + depends on MBEDTLS_ECP_C + default y + help + Enable support for SECP224R1 Elliptic Curve. + +config MBEDTLS_ECP_DP_SECP256R1_ENABLED + bool "Enable SECP256R1 curve" + depends on MBEDTLS_ECP_C + default y + help + Enable support for SECP256R1 Elliptic Curve. + +config MBEDTLS_ECP_DP_SECP384R1_ENABLED + bool "Enable SECP384R1 curve" + depends on MBEDTLS_ECP_C + default y + help + Enable support for SECP384R1 Elliptic Curve. + +config MBEDTLS_ECP_DP_SECP521R1_ENABLED + bool "Enable SECP521R1 curve" + depends on MBEDTLS_ECP_C + default y + help + Enable support for SECP521R1 Elliptic Curve. + +config MBEDTLS_ECP_DP_SECP192K1_ENABLED + bool "Enable SECP192K1 curve" + depends on MBEDTLS_ECP_C + default y + help + Enable support for SECP192K1 Elliptic Curve. + +config MBEDTLS_ECP_DP_SECP224K1_ENABLED + bool "Enable SECP224K1 curve" + depends on MBEDTLS_ECP_C + default y + help + Enable support for SECP224K1 Elliptic Curve. + +config MBEDTLS_ECP_DP_SECP256K1_ENABLED + bool "Enable SECP256K1 curve" + depends on MBEDTLS_ECP_C + default y + help + Enable support for SECP256K1 Elliptic Curve. + +config MBEDTLS_ECP_DP_BP256R1_ENABLED + bool "Enable BP256R1 curve" + depends on MBEDTLS_ECP_C + default y + help + support for DP Elliptic Curve. + +config MBEDTLS_ECP_DP_BP384R1_ENABLED + bool "Enable BP384R1 curve" + depends on MBEDTLS_ECP_C + default y + help + support for DP Elliptic Curve. + +config MBEDTLS_ECP_DP_BP512R1_ENABLED + bool "Enable BP512R1 curve" + depends on MBEDTLS_ECP_C + default y + help + support for DP Elliptic Curve. + +config MBEDTLS_ECP_DP_CURVE25519_ENABLED + bool "Enable CURVE25519 curve" + depends on MBEDTLS_ECP_C + default y + help + Enable support for CURVE25519 Elliptic Curve. + +config MBEDTLS_ECP_NIST_OPTIM + bool "NIST 'modulo p' optimisations" + depends on MBEDTLS_ECP_C + default y + help + NIST 'modulo p' optimisations increase Elliptic Curve operation performance. + + Disabling this option saves some code size. + + # end of Elliptic Curve options + +menu "Util" + + config util_assert + bool "Enable assert for util components" + default n + help + Enable this option, util components will use assert to check if input + parameters are correct. + + Disable this option will speed up the process of some calculation a lot. + + config ESP_SHA + bool "Enable Espressif SHA" + default n + help + Enable Espressif SHA1, SHA256, SHA384 & SHA512 for other components to + save code size for ESP8285(ESP8266 + 1MB flash) users. + + Although this option is disable, bootloader will use it if booloader + is configured to use SHA256 to check hash. + + Disabling the "assert" function at menuconfig can speed up the calculation. + + config ESP_AES + bool "Enable Espressif AES" + default y + help + Enable Espressif AES ECB, CBC, CFB128, CFB8 & CRT for other components to + speed up process speed and save code size. + + ESP8285 is like ESP8266 + 1MB flash, but its internal I/O connection from CPU + core to flash is DIO not QIO, which makes it read flash data slower. + So the function will speed up ESP8285 obviously. + + The calculation uses "ibus_data" to speed up load data from instruction bus. + + Disabling the "assert" function at menuconfig can speed up the calculation. + + config ESP_MD5 + bool "Enable Espressif MD5" + default y + help + Enable Espressif MD5 for other components to + speed up process speed and save code size. + + ESP8285 is like ESP8266 + 1MB flash, but its internal I/O connection from CPU + core to flash is DIO not QIO, which makes it read flash data slower. + So the function will speed up ESP8285 obviously. + + The calculation uses "ibus_data" to speed up load data from instruction bus. + + Disabling the "assert" function at menuconfig can speed up the calculation. + + config ESP_ARC4 + bool "Enable Espressif ARC4" + default y + help + Enable Espressif ARC4 for other components to + speed up process speed and save code size. + + ESP8285 is like ESP8266 + 1MB flash, but its internal I/O connection from CPU + core to flash is DIO not QIO, which makes it read flash data slower. + So the function will speed up ESP8285 obviously. + + The calculation uses "ibus_data" to speed up load data from instruction bus. + + Disabling the "assert" function at menuconfig can speed up the calculation. + +endmenu # Util + diff --git a/components/mbedtls/mbedtls_v2/Makefile.projbuild b/components/mbedtls/mbedtls_v2/Makefile.projbuild new file mode 100644 index 000000000..9992735ed --- /dev/null +++ b/components/mbedtls/mbedtls_v2/Makefile.projbuild @@ -0,0 +1,8 @@ +# Anyone compiling mbedTLS code needs the name of the +# alternative config file +CPPFLAGS += -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DCONFIG_SSL_USING_MBEDTLS + +# Catch usage of deprecated mbedTLS functions when building tests +ifneq ("$(filter mbedtls,$(TEST_COMPONENTS_LIST))","") +CPPFLAGS += -DMBEDTLS_DEPRECATED_WARNING +endif diff --git a/components/mbedtls/mbedtls_v2/component.mk b/components/mbedtls/mbedtls_v2/component.mk new file mode 100644 index 000000000..5bf42f7bf --- /dev/null +++ b/components/mbedtls/mbedtls_v2/component.mk @@ -0,0 +1,33 @@ +# +# Component Makefile +# + +CURRENT_DIR := mbedtls_v2 + +COMPONENT_ADD_INCLUDEDIRS := $(CURRENT_DIR)/port/include $(CURRENT_DIR)/mbedtls/include $(CURRENT_DIR)/port/include/$(IDF_TARGET) + +COMPONENT_SRCDIRS := $(CURRENT_DIR)/mbedtls/library $(CURRENT_DIR)/port $(CURRENT_DIR)/port/$(IDF_TARGET) + +COMPONENT_OBJEXCLUDE := $(CURRENT_DIR)/mbedtls/library/net_sockets.o + +COMPONENT_SUBMODULES += $(CURRENT_DIR)/mbedtls + +ifdef CONFIG_MBEDTLS_DYNAMIC_BUFFER + +WRAP_FUNCTIONS = mbedtls_ssl_handshake_client_step \ + mbedtls_ssl_handshake_server_step \ + mbedtls_ssl_read \ + mbedtls_ssl_write \ + mbedtls_ssl_session_reset \ + mbedtls_ssl_free \ + mbedtls_ssl_setup \ + mbedtls_ssl_send_alert_message \ + mbedtls_ssl_close_notify + +WRAP_ARGUMENT := -Wl,--wrap= + +COMPONENT_ADD_LDFLAGS = -l$(COMPONENT_NAME) $(addprefix $(WRAP_ARGUMENT),$(WRAP_FUNCTIONS)) + +COMPONENT_SRCDIRS += $(CURRENT_DIR)/port/dynamic + +endif diff --git a/components/mbedtls/mbedtls b/components/mbedtls/mbedtls_v2/mbedtls similarity index 100% rename from components/mbedtls/mbedtls rename to components/mbedtls/mbedtls_v2/mbedtls diff --git a/components/mbedtls/port/dynamic/esp_mbedtls_dynamic_impl.c b/components/mbedtls/mbedtls_v2/port/dynamic/esp_mbedtls_dynamic_impl.c similarity index 72% rename from components/mbedtls/port/dynamic/esp_mbedtls_dynamic_impl.c rename to components/mbedtls/mbedtls_v2/port/dynamic/esp_mbedtls_dynamic_impl.c index e78ea5afe..f64b09e35 100644 --- a/components/mbedtls/port/dynamic/esp_mbedtls_dynamic_impl.c +++ b/components/mbedtls/mbedtls_v2/port/dynamic/esp_mbedtls_dynamic_impl.c @@ -23,6 +23,33 @@ static const char *TAG = "Dynamic Impl"; +static void esp_mbedtls_set_buf_state(unsigned char *buf, esp_mbedtls_ssl_buf_states state) +{ + struct esp_mbedtls_ssl_buf *temp = __containerof(buf, struct esp_mbedtls_ssl_buf, buf[0]); + temp->state = state; +} + +static esp_mbedtls_ssl_buf_states esp_mbedtls_get_buf_state(unsigned char *buf) +{ + struct esp_mbedtls_ssl_buf *temp = __containerof(buf, struct esp_mbedtls_ssl_buf, buf[0]); + return temp->state; +} + +void esp_mbedtls_free_buf(unsigned char *buf) +{ + struct esp_mbedtls_ssl_buf *temp = __containerof(buf, struct esp_mbedtls_ssl_buf, buf[0]); + ESP_LOGV(TAG, "free buffer @ %p", temp); + mbedtls_free(temp); +} + +static void esp_mbedtls_init_ssl_buf(struct esp_mbedtls_ssl_buf *buf, unsigned int len) +{ + if (buf) { + buf->state = ESP_MBEDTLS_SSL_BUF_CACHED; + buf->len = len; + } +} + static void esp_mbedtls_parse_record_header(mbedtls_ssl_context *ssl) { ssl->in_msgtype = ssl->in_hdr[0]; @@ -118,29 +145,30 @@ static void init_rx_buffer(mbedtls_ssl_context *ssl, unsigned char *buf) static int esp_mbedtls_alloc_tx_buf(mbedtls_ssl_context *ssl, int len) { - unsigned char *buf; + struct esp_mbedtls_ssl_buf *esp_buf; if (ssl->out_buf) { - mbedtls_free(ssl->out_buf); + esp_mbedtls_free_buf(ssl->out_buf); ssl->out_buf = NULL; } - buf = mbedtls_calloc(1, len); - if (!buf) { - ESP_LOGE(TAG, "alloc(%d bytes) failed", len); + esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + len); + if (!esp_buf) { + ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + len); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } - ESP_LOGV(TAG, "add out buffer %d bytes @ %p", len, buf); + ESP_LOGV(TAG, "add out buffer %d bytes @ %p", len, esp_buf->buf); + esp_mbedtls_init_ssl_buf(esp_buf, len); /** * Mark the out_msg offset from ssl->out_buf. - * + * * In mbedtls, ssl->out_msg = ssl->out_buf + offset; */ ssl->out_msg = (unsigned char *)MBEDTLS_SSL_HEADER_LEN; - init_tx_buffer(ssl, buf); + init_tx_buffer(ssl, esp_buf->buf); return 0; } @@ -150,7 +178,7 @@ int esp_mbedtls_setup_tx_buffer(mbedtls_ssl_context *ssl) CHECK_OK(esp_mbedtls_alloc_tx_buf(ssl, TX_IDLE_BUFFER_SIZE)); /* mark the out buffer has no data cached */ - ssl->out_iv = NULL; + esp_mbedtls_set_buf_state(ssl->out_buf, ESP_MBEDTLS_SSL_BUF_NO_CACHED); return 0; } @@ -168,10 +196,7 @@ int esp_mbedtls_reset_add_tx_buffer(mbedtls_ssl_context *ssl) int esp_mbedtls_reset_free_tx_buffer(mbedtls_ssl_context *ssl) { - ESP_LOGV(TAG, "free out buffer @ %p", ssl->out_buf); - - mbedtls_free(ssl->out_buf); - + esp_mbedtls_free_buf(ssl->out_buf); init_tx_buffer(ssl, NULL); CHECK_OK(esp_mbedtls_setup_tx_buffer(ssl)); @@ -181,60 +206,57 @@ int esp_mbedtls_reset_free_tx_buffer(mbedtls_ssl_context *ssl) int esp_mbedtls_reset_add_rx_buffer(mbedtls_ssl_context *ssl) { - unsigned char *buf; + struct esp_mbedtls_ssl_buf *esp_buf; if (ssl->in_buf) { - mbedtls_free(ssl->in_buf); + esp_mbedtls_free_buf(ssl->in_buf); ssl->in_buf = NULL; } - buf = mbedtls_calloc(1, MBEDTLS_SSL_IN_BUFFER_LEN); - if (!buf) { - ESP_LOGE(TAG, "alloc(%d bytes) failed", MBEDTLS_SSL_IN_BUFFER_LEN); + esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + MBEDTLS_SSL_IN_BUFFER_LEN); + if (!esp_buf) { + ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + MBEDTLS_SSL_IN_BUFFER_LEN); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } - ESP_LOGV(TAG, "add in buffer %d bytes @ %p", MBEDTLS_SSL_IN_BUFFER_LEN, buf); + ESP_LOGV(TAG, "add in buffer %d bytes @ %p", MBEDTLS_SSL_IN_BUFFER_LEN, esp_buf->buf); + esp_mbedtls_init_ssl_buf(esp_buf, MBEDTLS_SSL_IN_BUFFER_LEN); /** * Mark the in_msg offset from ssl->in_buf. - * + * * In mbedtls, ssl->in_msg = ssl->in_buf + offset; */ ssl->in_msg = (unsigned char *)MBEDTLS_SSL_HEADER_LEN; - init_rx_buffer(ssl, buf); + init_rx_buffer(ssl, esp_buf->buf); - return 0; + return 0; } void esp_mbedtls_reset_free_rx_buffer(mbedtls_ssl_context *ssl) { - ESP_LOGV(TAG, "free in buffer @ %p", ssl->in_buf); - - mbedtls_free(ssl->in_buf); - - init_rx_buffer(ssl, NULL); + esp_mbedtls_free_buf(ssl->in_buf); + init_rx_buffer(ssl, NULL); } int esp_mbedtls_add_tx_buffer(mbedtls_ssl_context *ssl, size_t buffer_len) { int ret = 0; int cached = 0; - unsigned char *buf; + struct esp_mbedtls_ssl_buf *esp_buf; unsigned char cache_buf[CACHE_BUFFER_SIZE]; ESP_LOGV(TAG, "--> add out"); if (ssl->out_buf) { - if (ssl->out_iv) { + if (esp_mbedtls_get_buf_state(ssl->out_buf) == ESP_MBEDTLS_SSL_BUF_CACHED) { ESP_LOGV(TAG, "out buffer is not empty"); ret = 0; goto exit; } else { memcpy(cache_buf, ssl->out_buf, CACHE_BUFFER_SIZE); - - mbedtls_free(ssl->out_buf); + esp_mbedtls_free_buf(ssl->out_buf); init_tx_buffer(ssl, NULL); cached = 1; } @@ -242,15 +264,17 @@ int esp_mbedtls_add_tx_buffer(mbedtls_ssl_context *ssl, size_t buffer_len) buffer_len = tx_buffer_len(ssl, buffer_len); - buf = mbedtls_calloc(1, buffer_len); - if (!buf) { - ESP_LOGE(TAG, "alloc(%d bytes) failed", buffer_len); + esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + buffer_len); + if (!esp_buf) { + ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + buffer_len); ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto exit; } - ESP_LOGV(TAG, "add out buffer %d bytes @ %p", buffer_len, buf); - init_tx_buffer(ssl, buf); + ESP_LOGV(TAG, "add out buffer %d bytes @ %p", buffer_len, esp_buf->buf); + + esp_mbedtls_init_ssl_buf(esp_buf, buffer_len); + init_tx_buffer(ssl, esp_buf->buf); if (cached) { memcpy(ssl->out_ctr, cache_buf, COUNTER_SIZE); @@ -270,11 +294,11 @@ int esp_mbedtls_free_tx_buffer(mbedtls_ssl_context *ssl) { int ret = 0; unsigned char buf[CACHE_BUFFER_SIZE]; - unsigned char *pdata; + struct esp_mbedtls_ssl_buf *esp_buf; ESP_LOGV(TAG, "--> free out"); - if (!ssl->out_buf || (ssl->out_buf && !ssl->out_iv)) { + if (!ssl->out_buf || (ssl->out_buf && (esp_mbedtls_get_buf_state(ssl->out_buf) == ESP_MBEDTLS_SSL_BUF_NO_CACHED))) { ret = 0; goto exit; } @@ -282,22 +306,19 @@ int esp_mbedtls_free_tx_buffer(mbedtls_ssl_context *ssl) memcpy(buf, ssl->out_ctr, COUNTER_SIZE); memcpy(buf + COUNTER_SIZE, ssl->out_iv, CACHE_IV_SIZE); - ESP_LOGV(TAG, "free out buffer @ %p", ssl->out_buf); - - mbedtls_free(ssl->out_buf); - + esp_mbedtls_free_buf(ssl->out_buf); init_tx_buffer(ssl, NULL); - pdata = mbedtls_calloc(1, TX_IDLE_BUFFER_SIZE); - if (!pdata) { - ESP_LOGE(TAG, "alloc(%d bytes) failed", TX_IDLE_BUFFER_SIZE); + esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + TX_IDLE_BUFFER_SIZE); + if (!esp_buf) { + ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + TX_IDLE_BUFFER_SIZE); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } - memcpy(pdata, buf, CACHE_BUFFER_SIZE); - init_tx_buffer(ssl, pdata); - ssl->out_iv = NULL; - + esp_mbedtls_init_ssl_buf(esp_buf, TX_IDLE_BUFFER_SIZE); + memcpy(esp_buf->buf, buf, CACHE_BUFFER_SIZE); + init_tx_buffer(ssl, esp_buf->buf); + esp_mbedtls_set_buf_state(ssl->out_buf, ESP_MBEDTLS_SSL_BUF_NO_CACHED); exit: ESP_LOGV(TAG, "<-- free out"); @@ -309,7 +330,7 @@ int esp_mbedtls_add_rx_buffer(mbedtls_ssl_context *ssl) int cached = 0; int ret = 0; int buffer_len; - unsigned char *buf; + struct esp_mbedtls_ssl_buf *esp_buf; unsigned char cache_buf[16]; unsigned char msg_head[5]; size_t in_msglen, in_left; @@ -317,15 +338,11 @@ int esp_mbedtls_add_rx_buffer(mbedtls_ssl_context *ssl) ESP_LOGV(TAG, "--> add rx"); if (ssl->in_buf) { - if (ssl->in_iv) { + if (esp_mbedtls_get_buf_state(ssl->in_buf) == ESP_MBEDTLS_SSL_BUF_CACHED) { ESP_LOGV(TAG, "in buffer is not empty"); ret = 0; goto exit; } else { - memcpy(cache_buf, ssl->in_buf, 16); - - mbedtls_free(ssl->in_buf); - init_rx_buffer(ssl, NULL); cached = 1; } } @@ -341,7 +358,7 @@ int esp_mbedtls_add_rx_buffer(mbedtls_ssl_context *ssl) } else { ESP_LOGE(TAG, "mbedtls_ssl_fetch_input error=-0x%x", -ret); } - + goto exit; } @@ -354,16 +371,23 @@ int esp_mbedtls_add_rx_buffer(mbedtls_ssl_context *ssl) ESP_LOGV(TAG, "message length is %d RX buffer length should be %d left is %d", (int)in_msglen, (int)buffer_len, (int)ssl->in_left); - buf = mbedtls_calloc(1, buffer_len); - if (!buf) { - ESP_LOGE(TAG, "alloc(%d bytes) failed", buffer_len); + if (cached) { + memcpy(cache_buf, ssl->in_buf, 16); + esp_mbedtls_free_buf(ssl->in_buf); + init_rx_buffer(ssl, NULL); + } + + esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + buffer_len); + if (!esp_buf) { + ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + buffer_len); ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto exit; } - ESP_LOGV(TAG, "add in buffer %d bytes @ %p", buffer_len, buf); + ESP_LOGV(TAG, "add in buffer %d bytes @ %p", buffer_len, esp_buf->buf); - init_rx_buffer(ssl, buf); + esp_mbedtls_init_ssl_buf(esp_buf, buffer_len); + init_rx_buffer(ssl, esp_buf->buf); if (cached) { memcpy(ssl->in_ctr, cache_buf, 8); @@ -377,14 +401,14 @@ int esp_mbedtls_add_rx_buffer(mbedtls_ssl_context *ssl) exit: ESP_LOGV(TAG, "<-- add rx"); - return ret; + return ret; } int esp_mbedtls_free_rx_buffer(mbedtls_ssl_context *ssl) { int ret = 0; unsigned char buf[16]; - unsigned char *pdata; + struct esp_mbedtls_ssl_buf *esp_buf; ESP_LOGV(TAG, "--> free rx"); @@ -392,7 +416,7 @@ int esp_mbedtls_free_rx_buffer(mbedtls_ssl_context *ssl) * When have read multi messages once, can't free the input buffer directly. */ if (!ssl->in_buf || (ssl->in_hslen && (ssl->in_hslen < ssl->in_msglen)) || - (ssl->in_buf && !ssl->in_iv)) { + (ssl->in_buf && (esp_mbedtls_get_buf_state(ssl->in_buf) == ESP_MBEDTLS_SSL_BUF_NO_CACHED))) { ret = 0; goto exit; } @@ -407,23 +431,20 @@ int esp_mbedtls_free_rx_buffer(mbedtls_ssl_context *ssl) memcpy(buf, ssl->in_ctr, 8); memcpy(buf + 8, ssl->in_iv, 8); - ESP_LOGV(TAG, "free in buffer @ %p", ssl->out_buf); - - mbedtls_free(ssl->in_buf); - + esp_mbedtls_free_buf(ssl->in_buf); init_rx_buffer(ssl, NULL); - pdata = mbedtls_calloc(1, 16); - if (!pdata) { - ESP_LOGE(TAG, "alloc(%d bytes) failed", 16); + esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + 16); + if (!esp_buf) { + ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + 16); ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto exit; } - memcpy(pdata, buf, 16); - init_rx_buffer(ssl, pdata); - ssl->in_iv = NULL; - + esp_mbedtls_init_ssl_buf(esp_buf, 16); + memcpy(esp_buf->buf, buf, 16); + init_rx_buffer(ssl, esp_buf->buf); + esp_mbedtls_set_buf_state(ssl->in_buf, ESP_MBEDTLS_SSL_BUF_NO_CACHED); exit: ESP_LOGV(TAG, "<-- free rx"); @@ -438,7 +459,7 @@ size_t esp_mbedtls_get_crt_size(mbedtls_x509_crt *cert, size_t *num) while (cert) { bytes += cert->raw.len; n++; - + cert = cert->next; } diff --git a/components/mbedtls/port/dynamic/esp_mbedtls_dynamic_impl.h b/components/mbedtls/mbedtls_v2/port/dynamic/esp_mbedtls_dynamic_impl.h similarity index 87% rename from components/mbedtls/port/dynamic/esp_mbedtls_dynamic_impl.h rename to components/mbedtls/mbedtls_v2/port/dynamic/esp_mbedtls_dynamic_impl.h index 8f4bb144c..2c6b15c00 100644 --- a/components/mbedtls/port/dynamic/esp_mbedtls_dynamic_impl.h +++ b/components/mbedtls/mbedtls_v2/port/dynamic/esp_mbedtls_dynamic_impl.h @@ -41,6 +41,21 @@ \ }) +typedef enum { + ESP_MBEDTLS_SSL_BUF_CACHED, + ESP_MBEDTLS_SSL_BUF_NO_CACHED, +} esp_mbedtls_ssl_buf_states; + +struct esp_mbedtls_ssl_buf { + esp_mbedtls_ssl_buf_states state; + unsigned int len; + unsigned char buf[]; +}; + +#define SSL_BUF_HEAD_OFFSET_SIZE offsetof(struct esp_mbedtls_ssl_buf, buf) + +void esp_mbedtls_free_buf(unsigned char *buf); + int esp_mbedtls_setup_tx_buffer(mbedtls_ssl_context *ssl); void esp_mbedtls_setup_rx_buffer(mbedtls_ssl_context *ssl); diff --git a/components/mbedtls/port/dynamic/esp_ssl_cli.c b/components/mbedtls/mbedtls_v2/port/dynamic/esp_ssl_cli.c similarity index 100% rename from components/mbedtls/port/dynamic/esp_ssl_cli.c rename to components/mbedtls/mbedtls_v2/port/dynamic/esp_ssl_cli.c diff --git a/components/mbedtls/port/dynamic/esp_ssl_srv.c b/components/mbedtls/mbedtls_v2/port/dynamic/esp_ssl_srv.c similarity index 100% rename from components/mbedtls/port/dynamic/esp_ssl_srv.c rename to components/mbedtls/mbedtls_v2/port/dynamic/esp_ssl_srv.c diff --git a/components/mbedtls/port/dynamic/esp_ssl_tls.c b/components/mbedtls/mbedtls_v2/port/dynamic/esp_ssl_tls.c similarity index 98% rename from components/mbedtls/port/dynamic/esp_ssl_tls.c rename to components/mbedtls/mbedtls_v2/port/dynamic/esp_ssl_tls.c index 081e50af8..d8b4506b5 100644 --- a/components/mbedtls/port/dynamic/esp_ssl_tls.c +++ b/components/mbedtls/mbedtls_v2/port/dynamic/esp_ssl_tls.c @@ -108,12 +108,12 @@ int __wrap_mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t void __wrap_mbedtls_ssl_free(mbedtls_ssl_context *ssl) { if (ssl->out_buf) { - mbedtls_free(ssl->out_buf); + esp_mbedtls_free_buf(ssl->out_buf); ssl->out_buf = NULL; } if (ssl->in_buf) { - mbedtls_free(ssl->in_buf); + esp_mbedtls_free_buf(ssl->in_buf); ssl->in_buf = NULL; } diff --git a/components/mbedtls/port/esp8266/aes.c b/components/mbedtls/mbedtls_v2/port/esp8266/aes.c similarity index 100% rename from components/mbedtls/port/esp8266/aes.c rename to components/mbedtls/mbedtls_v2/port/esp8266/aes.c diff --git a/components/mbedtls/port/esp8266/arc4.c b/components/mbedtls/mbedtls_v2/port/esp8266/arc4.c similarity index 100% rename from components/mbedtls/port/esp8266/arc4.c rename to components/mbedtls/mbedtls_v2/port/esp8266/arc4.c diff --git a/components/mbedtls/port/esp8266/base64.c b/components/mbedtls/mbedtls_v2/port/esp8266/base64.c similarity index 100% rename from components/mbedtls/port/esp8266/base64.c rename to components/mbedtls/mbedtls_v2/port/esp8266/base64.c diff --git a/components/mbedtls/port/esp8266/md5.c b/components/mbedtls/mbedtls_v2/port/esp8266/md5.c similarity index 100% rename from components/mbedtls/port/esp8266/md5.c rename to components/mbedtls/mbedtls_v2/port/esp8266/md5.c diff --git a/components/mbedtls/port/esp8266/sha1.c b/components/mbedtls/mbedtls_v2/port/esp8266/sha1.c similarity index 100% rename from components/mbedtls/port/esp8266/sha1.c rename to components/mbedtls/mbedtls_v2/port/esp8266/sha1.c diff --git a/components/mbedtls/port/esp8266/sha256.c b/components/mbedtls/mbedtls_v2/port/esp8266/sha256.c similarity index 100% rename from components/mbedtls/port/esp8266/sha256.c rename to components/mbedtls/mbedtls_v2/port/esp8266/sha256.c diff --git a/components/mbedtls/port/esp8266/sha512.c b/components/mbedtls/mbedtls_v2/port/esp8266/sha512.c similarity index 100% rename from components/mbedtls/port/esp8266/sha512.c rename to components/mbedtls/mbedtls_v2/port/esp8266/sha512.c diff --git a/components/mbedtls/port/esp_aes.c b/components/mbedtls/mbedtls_v2/port/esp_aes.c similarity index 100% rename from components/mbedtls/port/esp_aes.c rename to components/mbedtls/mbedtls_v2/port/esp_aes.c diff --git a/components/mbedtls/port/esp_hardware.c b/components/mbedtls/mbedtls_v2/port/esp_hardware.c similarity index 100% rename from components/mbedtls/port/esp_hardware.c rename to components/mbedtls/mbedtls_v2/port/esp_hardware.c diff --git a/components/mbedtls/port/esp_mem.c b/components/mbedtls/mbedtls_v2/port/esp_mem.c similarity index 100% rename from components/mbedtls/port/esp_mem.c rename to components/mbedtls/mbedtls_v2/port/esp_mem.c diff --git a/components/mbedtls/port/esp_sha1.c b/components/mbedtls/mbedtls_v2/port/esp_sha1.c similarity index 100% rename from components/mbedtls/port/esp_sha1.c rename to components/mbedtls/mbedtls_v2/port/esp_sha1.c diff --git a/components/mbedtls/port/esp_sha256.c b/components/mbedtls/mbedtls_v2/port/esp_sha256.c similarity index 100% rename from components/mbedtls/port/esp_sha256.c rename to components/mbedtls/mbedtls_v2/port/esp_sha256.c diff --git a/components/mbedtls/port/esp_sha512.c b/components/mbedtls/mbedtls_v2/port/esp_sha512.c similarity index 100% rename from components/mbedtls/port/esp_sha512.c rename to components/mbedtls/mbedtls_v2/port/esp_sha512.c diff --git a/components/mbedtls/port/esp_timing.c b/components/mbedtls/mbedtls_v2/port/esp_timing.c similarity index 100% rename from components/mbedtls/port/esp_timing.c rename to components/mbedtls/mbedtls_v2/port/esp_timing.c diff --git a/components/mbedtls/port/include/aes_alt.h b/components/mbedtls/mbedtls_v2/port/include/aes_alt.h similarity index 100% rename from components/mbedtls/port/include/aes_alt.h rename to components/mbedtls/mbedtls_v2/port/include/aes_alt.h diff --git a/components/mbedtls/port/include/arc4_alt.h b/components/mbedtls/mbedtls_v2/port/include/arc4_alt.h similarity index 100% rename from components/mbedtls/port/include/arc4_alt.h rename to components/mbedtls/mbedtls_v2/port/include/arc4_alt.h diff --git a/components/mbedtls/port/include/esp8266/esp_aes.h b/components/mbedtls/mbedtls_v2/port/include/esp8266/esp_aes.h similarity index 100% rename from components/mbedtls/port/include/esp8266/esp_aes.h rename to components/mbedtls/mbedtls_v2/port/include/esp8266/esp_aes.h diff --git a/components/mbedtls/port/include/esp8266/esp_arc4.h b/components/mbedtls/mbedtls_v2/port/include/esp8266/esp_arc4.h similarity index 100% rename from components/mbedtls/port/include/esp8266/esp_arc4.h rename to components/mbedtls/mbedtls_v2/port/include/esp8266/esp_arc4.h diff --git a/components/mbedtls/port/include/esp8266/esp_base64.h b/components/mbedtls/mbedtls_v2/port/include/esp8266/esp_base64.h similarity index 100% rename from components/mbedtls/port/include/esp8266/esp_base64.h rename to components/mbedtls/mbedtls_v2/port/include/esp8266/esp_base64.h diff --git a/components/mbedtls/port/include/esp8266/esp_md5.h b/components/mbedtls/mbedtls_v2/port/include/esp8266/esp_md5.h similarity index 100% rename from components/mbedtls/port/include/esp8266/esp_md5.h rename to components/mbedtls/mbedtls_v2/port/include/esp8266/esp_md5.h diff --git a/components/mbedtls/port/include/esp_mem.h b/components/mbedtls/mbedtls_v2/port/include/esp_mem.h similarity index 100% rename from components/mbedtls/port/include/esp_mem.h rename to components/mbedtls/mbedtls_v2/port/include/esp_mem.h diff --git a/components/mbedtls/port/include/mbedtls/esp_config.h b/components/mbedtls/mbedtls_v2/port/include/mbedtls/esp_config.h similarity index 99% rename from components/mbedtls/port/include/mbedtls/esp_config.h rename to components/mbedtls/mbedtls_v2/port/include/mbedtls/esp_config.h index 3502aae6b..b36e427f9 100644 --- a/components/mbedtls/port/include/mbedtls/esp_config.h +++ b/components/mbedtls/mbedtls_v2/port/include/mbedtls/esp_config.h @@ -2255,6 +2255,8 @@ /* \} name SECTION: Module configuration options */ +#define MBEDTLS_PRIVATE(member) member + #if defined(TARGET_LIKE_MBED) #include "mbedtls/target_config.h" #endif diff --git a/components/mbedtls/port/include/mbedtls/esp_debug.h b/components/mbedtls/mbedtls_v2/port/include/mbedtls/esp_debug.h similarity index 100% rename from components/mbedtls/port/include/mbedtls/esp_debug.h rename to components/mbedtls/mbedtls_v2/port/include/mbedtls/esp_debug.h diff --git a/components/mbedtls/port/include/md5_alt.h b/components/mbedtls/mbedtls_v2/port/include/md5_alt.h similarity index 100% rename from components/mbedtls/port/include/md5_alt.h rename to components/mbedtls/mbedtls_v2/port/include/md5_alt.h diff --git a/components/mbedtls/port/include/sha1_alt.h b/components/mbedtls/mbedtls_v2/port/include/sha1_alt.h similarity index 100% rename from components/mbedtls/port/include/sha1_alt.h rename to components/mbedtls/mbedtls_v2/port/include/sha1_alt.h diff --git a/components/mbedtls/port/include/sha256_alt.h b/components/mbedtls/mbedtls_v2/port/include/sha256_alt.h similarity index 100% rename from components/mbedtls/port/include/sha256_alt.h rename to components/mbedtls/mbedtls_v2/port/include/sha256_alt.h diff --git a/components/mbedtls/port/include/sha512_alt.h b/components/mbedtls/mbedtls_v2/port/include/sha512_alt.h similarity index 100% rename from components/mbedtls/port/include/sha512_alt.h rename to components/mbedtls/mbedtls_v2/port/include/sha512_alt.h diff --git a/components/mbedtls/port/mbedtls_debug.c b/components/mbedtls/mbedtls_v2/port/mbedtls_debug.c similarity index 100% rename from components/mbedtls/port/mbedtls_debug.c rename to components/mbedtls/mbedtls_v2/port/mbedtls_debug.c diff --git a/components/mbedtls/port/net_sockets.c b/components/mbedtls/mbedtls_v2/port/net_sockets.c similarity index 100% rename from components/mbedtls/port/net_sockets.c rename to components/mbedtls/mbedtls_v2/port/net_sockets.c diff --git a/components/mbedtls/test/CMakeLists.txt b/components/mbedtls/mbedtls_v2/test/CMakeLists.txt similarity index 100% rename from components/mbedtls/test/CMakeLists.txt rename to components/mbedtls/mbedtls_v2/test/CMakeLists.txt diff --git a/components/mbedtls/test/component.mk b/components/mbedtls/mbedtls_v2/test/component.mk similarity index 100% rename from components/mbedtls/test/component.mk rename to components/mbedtls/mbedtls_v2/test/component.mk diff --git a/components/mbedtls/test/test_aes.c b/components/mbedtls/mbedtls_v2/test/test_aes.c similarity index 100% rename from components/mbedtls/test/test_aes.c rename to components/mbedtls/mbedtls_v2/test/test_aes.c diff --git a/components/mbedtls/test/test_aes_perf.c b/components/mbedtls/mbedtls_v2/test/test_aes_perf.c similarity index 100% rename from components/mbedtls/test/test_aes_perf.c rename to components/mbedtls/mbedtls_v2/test/test_aes_perf.c diff --git a/components/mbedtls/test/test_apb_dport_access.c b/components/mbedtls/mbedtls_v2/test/test_apb_dport_access.c similarity index 100% rename from components/mbedtls/test/test_apb_dport_access.c rename to components/mbedtls/mbedtls_v2/test/test_apb_dport_access.c diff --git a/components/mbedtls/test/test_apb_dport_access.h b/components/mbedtls/mbedtls_v2/test/test_apb_dport_access.h similarity index 100% rename from components/mbedtls/test/test_apb_dport_access.h rename to components/mbedtls/mbedtls_v2/test/test_apb_dport_access.h diff --git a/components/mbedtls/test/test_arc4.c b/components/mbedtls/mbedtls_v2/test/test_arc4.c similarity index 100% rename from components/mbedtls/test/test_arc4.c rename to components/mbedtls/mbedtls_v2/test/test_arc4.c diff --git a/components/mbedtls/test/test_base64.c b/components/mbedtls/mbedtls_v2/test/test_base64.c similarity index 100% rename from components/mbedtls/test/test_base64.c rename to components/mbedtls/mbedtls_v2/test/test_base64.c diff --git a/components/mbedtls/test/test_crc.c b/components/mbedtls/mbedtls_v2/test/test_crc.c similarity index 100% rename from components/mbedtls/test/test_crc.c rename to components/mbedtls/mbedtls_v2/test/test_crc.c diff --git a/components/mbedtls/test/test_ecp.c b/components/mbedtls/mbedtls_v2/test/test_ecp.c similarity index 100% rename from components/mbedtls/test/test_ecp.c rename to components/mbedtls/mbedtls_v2/test/test_ecp.c diff --git a/components/mbedtls/test/test_mbedtls.c b/components/mbedtls/mbedtls_v2/test/test_mbedtls.c similarity index 100% rename from components/mbedtls/test/test_mbedtls.c rename to components/mbedtls/mbedtls_v2/test/test_mbedtls.c diff --git a/components/mbedtls/test/test_mbedtls_mpi.c b/components/mbedtls/mbedtls_v2/test/test_mbedtls_mpi.c similarity index 100% rename from components/mbedtls/test/test_mbedtls_mpi.c rename to components/mbedtls/mbedtls_v2/test/test_mbedtls_mpi.c diff --git a/components/mbedtls/test/test_mbedtls_sha.c b/components/mbedtls/mbedtls_v2/test/test_mbedtls_sha.c similarity index 100% rename from components/mbedtls/test/test_mbedtls_sha.c rename to components/mbedtls/mbedtls_v2/test/test_mbedtls_sha.c diff --git a/components/mbedtls/test/test_md5.c b/components/mbedtls/mbedtls_v2/test/test_md5.c similarity index 100% rename from components/mbedtls/test/test_md5.c rename to components/mbedtls/mbedtls_v2/test/test_md5.c diff --git a/components/mbedtls/test/test_rsa.c b/components/mbedtls/mbedtls_v2/test/test_rsa.c similarity index 100% rename from components/mbedtls/test/test_rsa.c rename to components/mbedtls/mbedtls_v2/test/test_rsa.c diff --git a/components/mbedtls/test/test_sha.c b/components/mbedtls/mbedtls_v2/test/test_sha.c similarity index 100% rename from components/mbedtls/test/test_sha.c rename to components/mbedtls/mbedtls_v2/test/test_sha.c diff --git a/components/mbedtls/mbedtls_v3/CMakeLists.txt b/components/mbedtls/mbedtls_v3/CMakeLists.txt new file mode 100644 index 000000000..56ce65f5b --- /dev/null +++ b/components/mbedtls/mbedtls_v3/CMakeLists.txt @@ -0,0 +1,332 @@ +if(CONFIG_MBEDTLS_V2) + return() +endif() + +idf_build_get_property(idf_target IDF_TARGET) +idf_build_get_property(python PYTHON) + +set(current_dir ${COMPONENT_DIR}/mbedtls_v3) + +set(mbedtls_srcs "") +set(mbedtls_include_dirs "mbedtls_v3/port/include" "mbedtls_v3/mbedtls/include" "mbedtls_v3/mbedtls/library") + +if(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL) + list(APPEND mbedtls_include_dirs "port/mbedtls_rom") +endif() + +if(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE) + list(APPEND mbedtls_srcs "mbedtls_v3/esp_crt_bundle/esp_crt_bundle.c") + list(APPEND mbedtls_include_dirs "mbedtls_v3/esp_crt_bundle/include") +endif() + +idf_component_register(SRCS "${mbedtls_srcs}" + INCLUDE_DIRS "${mbedtls_include_dirs}" + PRIV_REQUIRES "${priv_requires}" + ) + +# Determine the type of mbedtls component library +if(mbedtls_srcs STREQUAL "") + # For no sources in component library we must use "INTERFACE" + set(linkage_type INTERFACE) +else() + set(linkage_type PUBLIC) +endif() + + +if(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE) + set(bundle_name "x509_crt_bundle") + set(DEFAULT_CRT_DIR ${current_dir}/esp_crt_bundle) + + # Generate custom certificate bundle using the generate_cert_bundle utility + set(GENERATE_CERT_BUNDLEPY ${python} ${current_dir}/esp_crt_bundle/gen_crt_bundle.py) + + if(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL) + list(APPEND crt_paths ${DEFAULT_CRT_DIR}/cacrt_all.pem ${DEFAULT_CRT_DIR}/cacrt_local.pem) + elseif(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN) + list(APPEND crt_paths ${DEFAULT_CRT_DIR}/cacrt_all.pem ${DEFAULT_CRT_DIR}/cacrt_local.pem) + list(APPEND args --filter ${DEFAULT_CRT_DIR}/cmn_crt_authorities.csv) + endif() + + if(CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE) + get_filename_component(custom_bundle_path + ${CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH} ABSOLUTE BASE_DIR "${project_dir}") + list(APPEND crt_paths ${custom_bundle_path}) + + endif() + list(APPEND args --input ${crt_paths} -q) + + get_filename_component(crt_bundle + ${bundle_name} + ABSOLUTE BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}") + + # Generate bundle according to config + add_custom_command(OUTPUT ${crt_bundle} + COMMAND ${GENERATE_CERT_BUNDLEPY} ${args} + DEPENDS ${custom_bundle_path} + VERBATIM) + + add_custom_target(custom_bundle DEPENDS ${cert_bundle}) + add_dependencies(${COMPONENT_LIB} custom_bundle) + + + target_add_binary_data(${COMPONENT_LIB} ${crt_bundle} BINARY) + set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + APPEND PROPERTY ADDITIONAL_CLEAN_FILES + "${crt_bundle}") +endif() + + +# Only build mbedtls libraries +set(ENABLE_TESTING CACHE BOOL OFF) +set(ENABLE_PROGRAMS CACHE BOOL OFF) + +# Use pre-generated source files in mbedtls repository +set(GEN_FILES CACHE BOOL OFF) + +# Make sure mbedtls finds the same Python interpreter as IDF uses +idf_build_get_property(python PYTHON) +set(Python3_EXECUTABLE ${python}) + +# Needed to for include_next includes to work from within mbedtls +set(include_dirs "${current_dir}/port/include") + +if(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE) + list(APPEND include_dirs "${current_dir}/esp_crt_bundle/include") +endif() + +include_directories(${include_dirs}) + +# Needed to for mbedtls_rom includes to work from within mbedtls +if(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL) + include_directories("${current_dir}/port/mbedtls_rom") +endif() + +# Import mbedtls library targets +add_subdirectory(mbedtls_v3/mbedtls) + +# Use port specific implementation of net_socket.c instead of one from mbedtls +get_target_property(src_tls mbedtls SOURCES) +list(REMOVE_ITEM src_tls net_sockets.c) +set_property(TARGET mbedtls PROPERTY SOURCES ${src_tls}) + +# Core libraries from the mbedTLS project +set(mbedtls_targets mbedtls mbedcrypto mbedx509) +# 3rd party libraries from the mbedTLS project +list(APPEND mbedtls_targets everest p256m) + +set(mbedtls_target_sources "${current_dir}/port/mbedtls_debug.c" + "${current_dir}/port/esp_platform_time.c" + "${current_dir}/port/net_sockets.c") + +if(CONFIG_MBEDTLS_DYNAMIC_BUFFER) +set(mbedtls_target_sources ${mbedtls_target_sources} + "${current_dir}/port/dynamic/esp_mbedtls_dynamic_impl.c" + "${current_dir}/port/dynamic/esp_ssl_cli.c" + "${current_dir}/port/dynamic/esp_ssl_srv.c" + "${current_dir}/port/dynamic/esp_ssl_tls.c") +endif() + +if(${IDF_TARGET} STREQUAL "linux") +set(mbedtls_target_sources ${mbedtls_target_sources} "${current_dir}/port/net_sockets.c") +endif() + +# While updating to MbedTLS release/v3.4.0, building mbedtls/library/psa_crypto.c +# clang produces an unreachable-code warning. +if(CMAKE_C_COMPILER_ID MATCHES "Clang") + target_compile_options(mbedcrypto PRIVATE "-Wno-unreachable-code") +endif() + +# net_sockets.c should only be compiled if BSD socket functions are available. +# Do this by checking if lwip component is included into the build. +idf_build_get_property(build_components BUILD_COMPONENTS) +if(lwip IN_LIST build_components) + list(APPEND mbedtls_target_sources "${current_dir}/port/net_sockets.c") + idf_component_get_property(lwip_lib lwip COMPONENT_LIB) + target_link_libraries(${COMPONENT_LIB} ${linkage_type} ${lwip_lib}) +endif() + +# Add port files to mbedtls targets +target_sources(mbedtls PRIVATE ${mbedtls_target_sources}) + +# Choose perihperal type + +if(CONFIG_SOC_SHA_SUPPORTED) + if(CONFIG_SOC_SHA_SUPPORT_DMA) + set(SHA_PERIPHERAL_TYPE "dma") + elseif(CONFIG_SOC_SHA_SUPPORT_PARALLEL_ENG) + set(SHA_PERIPHERAL_TYPE "parallel_engine") + else() + set(SHA_PERIPHERAL_TYPE "block") + endif() +endif() + +if(CONFIG_SOC_AES_SUPPORTED) + if(CONFIG_SOC_AES_SUPPORT_DMA) + set(AES_PERIPHERAL_TYPE "dma") + else() + set(AES_PERIPHERAL_TYPE "block") + endif() +endif() + +if(SHA_PERIPHERAL_TYPE STREQUAL "dma") + target_include_directories(mbedcrypto PRIVATE "${current_dir}/port/sha/dma/include") + + if(NOT CONFIG_SOC_SHA_GDMA) + set(SHA_DMA_SRCS "${current_dir}/port/sha/dma/esp_sha_crypto_dma_impl.c") + else() + set(SHA_DMA_SRCS "${current_dir}/port/sha/dma/esp_sha_gdma_impl.c") + + endif() + target_sources(mbedcrypto PRIVATE "${SHA_DMA_SRCS}") +endif() + +if(AES_PERIPHERAL_TYPE STREQUAL "dma") + if(NOT CONFIG_SOC_AES_GDMA) + set(AES_DMA_SRCS "${current_dir}/port/aes/dma/esp_aes_crypto_dma_impl.c") + else() + set(AES_DMA_SRCS "${current_dir}/port/aes/dma/esp_aes_gdma_impl.c" + "${current_dir}/port/crypto_shared_gdma/esp_crypto_shared_gdma.c") + endif() + + target_include_directories(mbedcrypto PRIVATE "${current_dir}/port/aes/dma/include") + target_sources(mbedcrypto PRIVATE "${AES_DMA_SRCS}") +endif() + +target_sources(mbedcrypto PRIVATE "${current_dir}/port/esp_mem.c" + "${current_dir}/port/esp_timing.c" + "${current_dir}/port/esp_hardware.c") + +if(CONFIG_MBEDTLS_MPI_EXP_MOD_ALT) + target_sources(mbedcrypto PRIVATE "${current_dir}/port/esp_bignum.c") +endif() + +if(CONFIG_SOC_AES_SUPPORTED) + target_sources(mbedcrypto PRIVATE "${current_dir}/port/aes/esp_aes_xts.c" + "${current_dir}/port/aes/esp_aes_common.c" + "${current_dir}/port/aes/${AES_PERIPHERAL_TYPE}/esp_aes.c" + ) +endif() + +if(CONFIG_SOC_SHA_SUPPORTED) + target_sources(mbedcrypto PRIVATE "${current_dir}/port/sha/esp_sha.c" + "${current_dir}/port/sha/${SHA_PERIPHERAL_TYPE}/sha.c" + ) +endif() + +# CONFIG_ESP_TLS_USE_DS_PERIPHERAL can be enabled only for the supported targets. +if(CONFIG_ESP_TLS_USE_DS_PERIPHERAL) + target_sources(mbedcrypto PRIVATE "${current_dir}/port/esp_ds/esp_rsa_sign_alt.c") +endif() + +# Note: some mbedTLS hardware acceleration can be enabled/disabled by config. +# +# We don't need to filter aes.c as this uses a different prefix (esp_aes_x) and the +# config option only changes the prefixes in the header so mbedtls_aes_x compiles to esp_aes_x +# +# The other port-specific files don't override internal mbedTLS functions, they just add new functions. + +if(CONFIG_MBEDTLS_HARDWARE_MPI) + target_sources(mbedcrypto PRIVATE "${current_dir}/port/esp_bignum.c" + "${current_dir}/port/${idf_target}/bignum.c" + ) +endif() + +if(CONFIG_MBEDTLS_HARDWARE_SHA) + target_sources(mbedcrypto PRIVATE "${current_dir}/port/sha/${SHA_PERIPHERAL_TYPE}/esp_sha1.c" + "${current_dir}/port/sha/${SHA_PERIPHERAL_TYPE}/esp_sha256.c" + "${current_dir}/port/sha/${SHA_PERIPHERAL_TYPE}/esp_sha512.c" + ) +endif() + +if(CONFIG_MBEDTLS_HARDWARE_GCM OR CONFIG_MBEDTLS_HARDWARE_AES) + target_sources(mbedcrypto PRIVATE "${current_dir}/port/aes/esp_aes_gcm.c") +endif() + +if(CONFIG_MBEDTLS_HARDWARE_ECC) + target_sources(mbedcrypto PRIVATE "${current_dir}/port/ecc/esp_ecc.c" + "${current_dir}/port/ecc/ecc_alt.c") +endif() + +if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) + target_sources(mbedcrypto PRIVATE "${current_dir}/port/ecdsa/ecdsa_alt.c") + + if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign") + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign_restartable") + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_write_signature") + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_write_signature_restartable") + endif() + + if(CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_verify") + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_verify_restartable") + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_read_signature") + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_read_signature_restartable") + endif() +endif() + +if(CONFIG_MBEDTLS_ROM_MD5) + target_sources(mbedcrypto PRIVATE "${current_dir}/port/md/esp_md.c") +endif() + +if(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL) + target_sources(mbedcrypto PRIVATE "${current_dir}/port/mbedtls_rom/mbedtls_rom_osi.c") + target_link_libraries(${COMPONENT_LIB} PRIVATE "-u mbedtls_rom_osi_functions_init") +endif() + +foreach(target ${mbedtls_targets}) + target_compile_definitions(${target} PUBLIC -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h") +endforeach() + +if(CONFIG_MBEDTLS_DYNAMIC_BUFFER) + set(WRAP_FUNCTIONS + mbedtls_ssl_write_client_hello + mbedtls_ssl_handshake_client_step + mbedtls_ssl_handshake_server_step + mbedtls_ssl_read + mbedtls_ssl_write + mbedtls_ssl_session_reset + mbedtls_ssl_free + mbedtls_ssl_setup + mbedtls_ssl_send_alert_message + mbedtls_ssl_close_notify) + + foreach(wrap ${WRAP_FUNCTIONS}) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=${wrap}") + endforeach() +endif() + +set_property(TARGET mbedcrypto APPEND PROPERTY LINK_INTERFACE_LIBRARIES mbedtls) + +# if(CONFIG_PM_ENABLE) +# target_link_libraries(mbedcrypto PRIVATE idf::esp_pm) +# endif() + +if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) + target_link_libraries(mbedcrypto PRIVATE idf::efuse) +endif() + +target_link_libraries(${COMPONENT_LIB} ${linkage_type} ${mbedtls_targets}) + +if(CONFIG_ESP_TLS_USE_DS_PERIPHERAL) + # The linker seems to be unable to resolve all the dependencies without increasing this + set_property(TARGET mbedcrypto APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 6) +endif() + +# Additional optional dependencies for the mbedcrypto library +function(mbedcrypto_optional_deps component_name) + idf_build_get_property(components BUILD_COMPONENTS) + if(${component_name} IN_LIST components) + idf_component_get_property(lib_name ${component_name} COMPONENT_LIB) + target_link_libraries(mbedcrypto PRIVATE ${lib_name}) + endif() +endfunction() + +if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM) + mbedcrypto_optional_deps(esp_timer idf::esp_timer) +endif() + +# Link esp-cryptoauthlib to mbedtls +if(CONFIG_ATCA_MBEDTLS_ECDSA) + idf_component_optional_requires(PRIVATE espressif__esp-cryptoauthlib esp-cryptoauthlib) +endif() diff --git a/components/mbedtls/mbedtls_v3/Kconfig b/components/mbedtls/mbedtls_v3/Kconfig new file mode 100644 index 000000000..dfb873eb7 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/Kconfig @@ -0,0 +1,1163 @@ +choice MBEDTLS_MEM_ALLOC_MODE + prompt "Memory allocation strategy" + default MBEDTLS_INTERNAL_MEM_ALLOC + help + Allocation strategy for mbedTLS, essentially provides ability to + allocate all required dynamic allocations from, + + - Internal DRAM memory only + - External SPIRAM memory only + - Either internal or external memory based on default malloc() + behavior in ESP-IDF + - Custom allocation mode, by overwriting calloc()/free() using + mbedtls_platform_set_calloc_free() function + - Internal IRAM memory wherever applicable else internal DRAM + + Recommended mode here is always internal (*), since that is most preferred + from security perspective. But if application requirement does not + allow sufficient free internal memory then alternate mode can be + selected. + + (*) In case of ESP32-S2/ESP32-S3, hardware allows encryption of external + SPIRAM contents provided hardware flash encryption feature is enabled. + In that case, using external SPIRAM allocation strategy is also safe choice + from security perspective. + + config MBEDTLS_INTERNAL_MEM_ALLOC + bool "Internal memory" + + config MBEDTLS_EXTERNAL_MEM_ALLOC + bool "External SPIRAM" + depends on SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC + + config MBEDTLS_DEFAULT_MEM_ALLOC + bool "Default alloc mode" + + config MBEDTLS_CUSTOM_MEM_ALLOC + bool "Custom alloc mode" + + config MBEDTLS_IRAM_8BIT_MEM_ALLOC + bool "Internal IRAM" + depends on ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY + help + Allows to use IRAM memory region as 8bit accessible region. + + TLS input and output buffers will be allocated in IRAM section which is 32bit aligned + memory. Every unaligned (8bit or 16bit) access will result in an exception + and incur penalty of certain clock cycles per unaligned read/write. + +endchoice #MBEDTLS_MEM_ALLOC_MODE + +config MBEDTLS_SSL_MAX_CONTENT_LEN + int "TLS maximum message content length" + default 16384 + range 512 16384 + depends on !MBEDTLS_ASYMMETRIC_CONTENT_LEN + help + Maximum TLS message length (in bytes) supported by mbedTLS. + + 16384 is the default and this value is required to comply + fully with TLS standards. + + However you can set a lower value in order to save RAM. This + is safe if the other end of the connection supports Maximum + Fragment Length Negotiation Extension (max_fragment_length, + see RFC6066) or you know for certain that it will never send a + message longer than a certain number of bytes. + + If the value is set too low, symptoms are a failed TLS + handshake or a return value of MBEDTLS_ERR_SSL_INVALID_RECORD + (-0x7200). + +config MBEDTLS_ASYMMETRIC_CONTENT_LEN + bool "Asymmetric in/out fragment length" + default y + help + If enabled, this option allows customizing TLS in/out fragment length + in asymmetric way. Please note that enabling this with default values + saves 12KB of dynamic memory per TLS connection. + +config MBEDTLS_SSL_IN_CONTENT_LEN + int "TLS maximum incoming fragment length" + default 16384 + range 512 16384 + depends on MBEDTLS_ASYMMETRIC_CONTENT_LEN + help + This defines maximum incoming fragment length, overriding default + maximum content length (MBEDTLS_SSL_MAX_CONTENT_LEN). + +config MBEDTLS_SSL_OUT_CONTENT_LEN + int "TLS maximum outgoing fragment length" + default 4096 + range 512 16384 + depends on MBEDTLS_ASYMMETRIC_CONTENT_LEN + help + This defines maximum outgoing fragment length, overriding default + maximum content length (MBEDTLS_SSL_MAX_CONTENT_LEN). + +config MBEDTLS_DYNAMIC_BUFFER + bool "Using dynamic TX/RX buffer" + default n + select MBEDTLS_ASYMMETRIC_CONTENT_LEN + # Dynamic buffer feature is not supported with DTLS + depends on !IDF_TARGET_LINUX && !MBEDTLS_SSL_PROTO_DTLS && !MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH + help + Using dynamic TX/RX buffer. After enabling this option, mbedTLS will + allocate TX buffer when need to send data and then free it if all data + is sent, allocate RX buffer when need to receive data and then free it + when all data is used or read by upper layer. + + By default, when SSL is initialized, mbedTLS also allocate TX and + RX buffer with the default value of "MBEDTLS_SSL_OUT_CONTENT_LEN" or + "MBEDTLS_SSL_IN_CONTENT_LEN", so to save more heap, users can set + the options to be an appropriate value. + +config MBEDTLS_DYNAMIC_FREE_CONFIG_DATA + bool "Free private key and DHM data after its usage" + default n + depends on MBEDTLS_DYNAMIC_BUFFER + help + Free private key and DHM data after its usage in handshake process. + + The option will decrease heap cost when handshake, but also lead to problem: + + Because all certificate, private key and DHM data are freed so users should register + certificate and private key to ssl config object again. + +config MBEDTLS_DYNAMIC_FREE_CA_CERT + bool "Free SSL CA certificate after its usage" + default y + depends on MBEDTLS_DYNAMIC_FREE_CONFIG_DATA + help + Free CA certificate after its usage in the handshake process. + This option will decrease the heap footprint for the TLS handshake, but may lead to a problem: + If the respective ssl object needs to perform the TLS handshake again, + the CA certificate should once again be registered to the ssl object. + +config MBEDTLS_DEBUG + bool "Enable mbedTLS debugging" + default n + help + Enable mbedTLS debugging functions at compile time. + + If this option is enabled, you can include + "mbedtls/esp_debug.h" and call mbedtls_esp_enable_debug_log() + at runtime in order to enable mbedTLS debug output via the ESP + log mechanism. + +choice MBEDTLS_DEBUG_LEVEL + bool "Set mbedTLS debugging level" + depends on MBEDTLS_DEBUG + default MBEDTLS_DEBUG_LEVEL_VERBOSE + help + Set mbedTLS debugging level + + config MBEDTLS_DEBUG_LEVEL_WARN + bool "Warning" + config MBEDTLS_DEBUG_LEVEL_INFO + bool "Info" + config MBEDTLS_DEBUG_LEVEL_DEBUG + bool "Debug" + config MBEDTLS_DEBUG_LEVEL_VERBOSE + bool "Verbose" +endchoice + +config MBEDTLS_DEBUG_LEVEL + int + default 1 if MBEDTLS_DEBUG_LEVEL_WARN + default 2 if MBEDTLS_DEBUG_LEVEL_INFO + default 3 if MBEDTLS_DEBUG_LEVEL_DEBUG + default 4 if MBEDTLS_DEBUG_LEVEL_VERBOSE + +menu "mbedTLS v3.x related" + # NOTE: MBEDTLS_DYNAMIC_BUFFER feature is not supported with TLS 1.3 yet. Ref: IDF-4762 + config MBEDTLS_SSL_PROTO_TLS1_3 + bool "Support TLS 1.3 protocol" + depends on MBEDTLS_TLS_ENABLED && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE && !MBEDTLS_DYNAMIC_BUFFER + select MBEDTLS_HKDF_C + default n + + menu "TLS 1.3 related configurations" + depends on MBEDTLS_SSL_PROTO_TLS1_3 + + config MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE + bool "TLS 1.3 middlebox compatibility mode" + default y + + config MBEDTLS_SSL_TLS1_3_KEXM_PSK + bool "TLS 1.3 PSK key exchange mode" + default y + + config MBEDTLS_SSL_TLS1_3_KEXM_EPHEMERAL + bool "TLS 1.3 ephemeral key exchange mode" + default y + + config MBEDTLS_SSL_TLS1_3_KEXM_PSK_EPHEMERAL + bool "TLS 1.3 PSK ephemeral key exchange mode" + default y + + endmenu + + config MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH + bool "Variable SSL buffer length" + default n + help + This enables the SSL buffer to be resized automatically + based on the negotiated maximum fragment length in each direction. + + config MBEDTLS_ECDH_LEGACY_CONTEXT + bool "Use a backward compatible ECDH context (Experimental)" + default n + depends on MBEDTLS_ECDH_C && MBEDTLS_ECP_RESTARTABLE + help + Use the legacy ECDH context format. + Define this option only if you enable MBEDTLS_ECP_RESTARTABLE or if you + want to access ECDH context fields directly. + + config MBEDTLS_X509_TRUSTED_CERT_CALLBACK + bool "Enable trusted certificate callbacks" + default n + help + Enables users to configure the set of trusted certificates + through a callback instead of a linked list. + + See mbedTLS documentation for required API and more details. + + config MBEDTLS_SSL_CONTEXT_SERIALIZATION + bool "Enable serialization of the TLS context structures" + default n + depends on MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C + help + Enable serialization of the TLS context structures + This is a local optimization in handling a single, potentially long-lived connection. + + See mbedTLS documentation for required API and more details. + Disabling this option will save some code size. + + config MBEDTLS_SSL_KEEP_PEER_CERTIFICATE + bool "Keep peer certificate after handshake completion" + default y + help + Keep the peer's certificate after completion of the handshake. + Disabling this option will save about 4kB of heap and some code size. + + See mbedTLS documentation for required API and more details. + + config MBEDTLS_PKCS7_C + bool "Enable PKCS #7" + default y + depends on MBEDTLS_X509_CRL_PARSE_C + help + Enable PKCS #7 core for using PKCS #7-formatted signatures. + + config MBEDTLS_SSL_CID_PADDING_GRANULARITY + int "Record plaintext padding" + default 16 + range 0 32 + depends on MBEDTLS_SSL_PROTO_TLS1_3 || MBEDTLS_SSL_DTLS_CONNECTION_ID + help + Controls the use of record plaintext padding in TLS 1.3 and + when using the Connection ID extension in DTLS 1.2. + + The padding will always be chosen so that the length of the + padded plaintext is a multiple of the value of this option. + + Notes: + A value of 1 means that no padding will be used for outgoing records. + On systems lacking division instructions, a power of two should be preferred. + + menu "DTLS-based configurations" + depends on MBEDTLS_SSL_PROTO_DTLS + + config MBEDTLS_SSL_DTLS_CONNECTION_ID + bool "Support for the DTLS Connection ID extension" + default n + help + Enable support for the DTLS Connection ID extension which allows to + identify DTLS connections across changes in the underlying transport. + + config MBEDTLS_SSL_CID_IN_LEN_MAX + int "Maximum length of CIDs used for incoming DTLS messages" + default 32 + range 0 32 + depends on MBEDTLS_SSL_DTLS_CONNECTION_ID + help + Maximum length of CIDs used for incoming DTLS messages + + config MBEDTLS_SSL_CID_OUT_LEN_MAX + int "Maximum length of CIDs used for outgoing DTLS messages" + default 32 + range 0 32 + depends on MBEDTLS_SSL_DTLS_CONNECTION_ID + help + Maximum length of CIDs used for outgoing DTLS messages + + config MBEDTLS_SSL_DTLS_SRTP + bool "Enable support for negotiation of DTLS-SRTP (RFC 5764)" + default n + help + Enable support for negotiation of DTLS-SRTP (RFC 5764) through the use_srtp extension. + + See mbedTLS documentation for required API and more details. + Disabling this option will save some code size. + + endmenu + +endmenu + +menu "Certificate Bundle" + depends on !IDF_TARGET_ESP8266 + config MBEDTLS_CERTIFICATE_BUNDLE + bool "Enable trusted root certificate bundle" + default y + help + Enable support for large number of default root certificates + + When enabled this option allows user to store default as well + as customer specific root certificates in compressed format rather + than storing full certificate. For the root certificates the public key and the subject name + will be stored. + + choice MBEDTLS_DEFAULT_CERTIFICATE_BUNDLE + bool "Default certificate bundle options" + depends on MBEDTLS_CERTIFICATE_BUNDLE + default MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL + + config MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL + bool "Use the full default certificate bundle" + config MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN + bool "Use only the most common certificates from the default bundles" + help + Use only the most common certificates from the default bundles, reducing the size with 50%, + while still having around 99% coverage. + config MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE + bool "Do not use the default certificate bundle" + endchoice + + config MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE + depends on MBEDTLS_CERTIFICATE_BUNDLE + default n + bool "Add custom certificates to the default bundle" + config MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH + depends on MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE + string "Custom certificate bundle path" + help + Name of the custom certificate directory or file. This path is evaluated + relative to the project root directory. + + config MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS + int "Maximum no of certificates allowed in certificate bundle" + default 200 + depends on MBEDTLS_CERTIFICATE_BUNDLE + +endmenu + +config MBEDTLS_ECP_RESTARTABLE + bool "Enable mbedTLS ecp restartable" + select MBEDTLS_ECDH_LEGACY_CONTEXT + depends on MBEDTLS_ECP_C + default n + help + Enable "non-blocking" ECC operations that can return early and be resumed. + +config MBEDTLS_CMAC_C + bool "Enable CMAC mode for block ciphers" + default n + depends on MBEDTLS_AES_C || MBEDTLS_DES_C + help + Enable the CMAC (Cipher-based Message Authentication Code) mode for + block ciphers. + +config MBEDTLS_HARDWARE_AES + bool "Enable hardware AES acceleration" + default y + depends on !SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST && SOC_AES_SUPPORTED + help + Enable hardware accelerated AES encryption & decryption. + + Note that if the ESP32 CPU is running at 240MHz, hardware AES does not + offer any speed boost over software AES. + +config MBEDTLS_AES_USE_INTERRUPT + bool "Use interrupt for long AES operations" + depends on !IDF_TARGET_ESP32 && MBEDTLS_HARDWARE_AES + default y + help + Use an interrupt to coordinate long AES operations. + + This allows other code to run on the CPU while an AES operation is pending. + Otherwise the CPU busy-waits. + +config MBEDTLS_HARDWARE_GCM + bool "Enable partially hardware accelerated GCM" + depends on SOC_AES_SUPPORT_GCM && MBEDTLS_HARDWARE_AES + default y + help + Enable partially hardware accelerated GCM. GHASH calculation is still done + in software. + + If MBEDTLS_HARDWARE_GCM is disabled and MBEDTLS_HARDWARE_AES is enabled then + mbedTLS will still use the hardware accelerated AES block operation, but + on a single block at a time. + +config MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER + bool "Enable support for non-AES ciphers in GCM operation" + depends on MBEDTLS_HARDWARE_AES + default n + help + Enable this config to support fallback to software definitions for a non-AES + cipher GCM operation as we support hardware acceleration only for AES cipher. + Some of the non-AES ciphers used in a GCM operation are DES, ARIA, CAMELLIA, + CHACHA20, BLOWFISH. + + If this config is disabled, performing a non-AES cipher GCM operation with + the config MBEDTLS_HARDWARE_AES enabled will result in calculation of an + AES-GCM operation instead for the given input values and thus could lead + to failure in certificate validation which would ultimately lead to a SSL + handshake failure. + + This config being by-default enabled leads to an increase in binary size + footprint of ~2.5KB. + In case you are sure that your use case (for example, client and server + configurations in case of a TLS handshake) would not involve any GCM + operations using a non-AES cipher, you can safely disable this config, + leading to reduction in binary size footprint. + +config MBEDTLS_HARDWARE_MPI + bool "Enable hardware MPI (bignum) acceleration" + default y + depends on !SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST && SOC_MPI_SUPPORTED + help + Enable hardware accelerated multiple precision integer operations. + + Hardware accelerated multiplication, modulo multiplication, + and modular exponentiation for up to SOC_RSA_MAX_BIT_LEN bit results. + + These operations are used by RSA. + +config MBEDTLS_LARGE_KEY_SOFTWARE_MPI + bool "Fallback to software implementation for larger MPI values" + depends on MBEDTLS_HARDWARE_MPI + default y if SOC_RSA_MAX_BIT_LEN <= 3072 # HW max 3072 bits + default n + help + Fallback to software implementation for RSA key lengths + larger than SOC_RSA_MAX_BIT_LEN. If this is not active + then the ESP will be unable to process keys greater + than SOC_RSA_MAX_BIT_LEN. + +config MBEDTLS_MPI_USE_INTERRUPT + bool "Use interrupt for MPI exp-mod operations" + depends on !IDF_TARGET_ESP32 && MBEDTLS_HARDWARE_MPI + default y + help + Use an interrupt to coordinate long MPI operations. + + This allows other code to run on the CPU while an MPI operation is pending. + Otherwise the CPU busy-waits. + +config MBEDTLS_HARDWARE_SHA + bool "Enable hardware SHA acceleration" + default y + depends on !SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST && SOC_SHA_SUPPORTED + help + Enable hardware accelerated SHA1, SHA256, SHA384 & SHA512 in mbedTLS. + + Due to a hardware limitation, on the ESP32 hardware acceleration is only + guaranteed if SHA digests are calculated one at a time. If more + than one SHA digest is calculated at the same time, one will + be calculated fully in hardware and the rest will be calculated + (at least partially calculated) in software. This happens automatically. + + SHA hardware acceleration is faster than software in some situations but + slower in others. You should benchmark to find the best setting for you. + +config MBEDTLS_HARDWARE_ECC + bool "Enable hardware ECC acceleration" + default y + depends on SOC_ECC_SUPPORTED + help + Enable hardware accelerated ECC point multiplication and point verification for points + on curve SECP192R1 and SECP256R1 in mbedTLS + +config MBEDTLS_ECC_OTHER_CURVES_SOFT_FALLBACK + bool "Fallback to software implementation for curves not supported in hardware" + depends on MBEDTLS_HARDWARE_ECC + default y + help + Fallback to software implementation of ECC point multiplication and point verification + for curves not supported in hardware. + +config MBEDTLS_ROM_MD5 + depends on !IDF_TARGET_ESP8266 + bool "Use MD5 implementation in ROM" + default y + help + Use ROM MD5 in mbedTLS. + +config MBEDTLS_HARDWARE_ECDSA_SIGN + bool "Enable ECDSA signing using on-chip ECDSA peripheral" + default n + depends on SOC_ECDSA_SUPPORTED + help + Enable hardware accelerated ECDSA peripheral to sign data + on curve SECP192R1 and SECP256R1 in mbedTLS. + + Note that for signing, the private key has to be burnt in an efuse key block + with key purpose set to ECDSA_KEY. + If no key is burnt, it will report an error + + The key should be burnt in little endian format. espefuse.py utility handles it internally + but care needs to be taken while burning using esp_efuse APIs + +menu "Enable Software Countermeasure for ECDSA signing using on-chip ECDSA peripheral" + depends on MBEDTLS_HARDWARE_ECDSA_SIGN + depends on IDF_TARGET_ESP32H2 + config MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM + bool "Mask original ECDSA sign operation under dummy sign operations" + select HAL_ECDSA_GEN_SIG_CM + # ToDo: IDF-11051 + default y + help + The ECDSA peripheral before ECO5 does not offer constant time ECDSA sign operation. + This time can be observed through power profiling of the device, + making the ECDSA private key vulnerable to side-channel timing attacks. + This countermeasure masks the real ECDSA sign operation + under dummy sign operations to add randomness in the generated power signature. + It is highly recommended to also enable Secure Boot for the device in addition to this countermeasure + so that only trusted software can execute on the device. + + config MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM + bool "Make ECDSA signature operation pseudo constant time for software" + default y + help + This option adds a delay after the actual ECDSA signature operation + so that the entire operation appears to be constant time for the software. + This fix helps in protecting the device only in case of remote timing attack on the ECDSA private key. + For e.g., When an interface is exposed by the device to perform ECDSA signature + of an arbitrary message. + The signature time would appear to be constant to the external entity after enabling + this option. + +endmenu + +config MBEDTLS_HARDWARE_ECDSA_VERIFY + bool "Enable ECDSA signature verification using on-chip ECDSA peripheral" + default y + depends on SOC_ECDSA_SUPPORTED + help + Enable hardware accelerated ECDSA peripheral to verify signature + on curve SECP192R1 and SECP256R1 in mbedTLS. + +config MBEDTLS_ATCA_HW_ECDSA_SIGN + depends on !IDF_TARGET_ESP8266 + bool "Enable hardware ECDSA sign acceleration when using ATECC608A" + default n + help + This option enables hardware acceleration for ECDSA sign function, only + when using ATECC608A cryptoauth chip (integrated with ESP32-WROOM-32SE) + +config MBEDTLS_ATCA_HW_ECDSA_VERIFY + depends on !IDF_TARGET_ESP8266 + bool "Enable hardware ECDSA verify acceleration when using ATECC608A" + default n + help + This option enables hardware acceleration for ECDSA sign function, only + when using ATECC608A cryptoauth chip (integrated with ESP32-WROOM-32SE) + +config MBEDTLS_HAVE_TIME + bool "Enable mbedtls time support" + depends on !ESP_TIME_FUNCS_USE_NONE + default y + help + Enable use of time.h functions (time() and gmtime()) by mbedTLS. + + This option doesn't require the system time to be correct, but enables + functionality that requires relative timekeeping - for example periodic + expiry of TLS session tickets or session cache entries. + + Disabling this option will save some firmware size, particularly if + the rest of the firmware doesn't call any standard timekeeeping + functions. + +config MBEDTLS_PLATFORM_TIME_ALT + bool "Enable mbedtls time support: platform-specific" + depends on MBEDTLS_HAVE_TIME + default n + help + Enabling this config will provide users with a function + "mbedtls_platform_set_time()" that allows to set an alternative + time function pointer. + +config MBEDTLS_HAVE_TIME_DATE + bool "Enable mbedtls certificate expiry check" + depends on MBEDTLS_HAVE_TIME + default n + help + Enables X.509 certificate expiry checks in mbedTLS. + + If this option is disabled (default) then X.509 certificate + "valid from" and "valid to" timestamp fields are ignored. + + If this option is enabled, these fields are compared with the + current system date and time. The time is retrieved using the + standard time() and gmtime() functions. If the certificate is not + valid for the current system time then verification will fail with + code MBEDTLS_X509_BADCERT_FUTURE or MBEDTLS_X509_BADCERT_EXPIRED. + + Enabling this option requires adding functionality in the firmware + to set the system clock to a valid timestamp before using TLS. The + recommended way to do this is via ESP-IDF's SNTP functionality, but + any method can be used. + + In the case where only a small number of certificates are trusted by + the device, please carefully consider the tradeoffs of enabling this + option. There may be undesired consequences, for example if all + trusted certificates expire while the device is offline and a TLS + connection is required to update. Or if an issue with the SNTP + server means that the system time is invalid for an extended period + after a reset. + +config MBEDTLS_ECDSA_DETERMINISTIC + bool "Enable deterministic ECDSA" + default y + help + Standard ECDSA is "fragile" in the sense that lack of entropy when signing + may result in a compromise of the long-term signing key. + +config MBEDTLS_SHA512_C + bool "Enable the SHA-384 and SHA-512 cryptographic hash algorithms" + default y + help + Enable MBEDTLS_SHA512_C adds support for SHA-384 and SHA-512. + +config MBEDTLS_SHA3_C + bool "Enable the SHA3 cryptographic hash algorithm" + default n + help + Enabling MBEDTLS_SHA3_C adds support for SHA3. + Enabling this configuration option increases the flash footprint + by almost 4KB. + +config MBEDTLS_MPI_EXP_MOD_ALT + bool "Enable the alternative exponentiation" + default y + help + Perform an exponentiation by the algorithm of mbedtls V2, + which is faster when calling "mbedtls_mpi_exp_mod()". + +choice MBEDTLS_TLS_MODE + bool "TLS Protocol Role" + default MBEDTLS_TLS_SERVER_AND_CLIENT + help + mbedTLS can be compiled with protocol support for the TLS + server, TLS client, or both server and client. + + Reducing the number of TLS roles supported saves code size. + + config MBEDTLS_TLS_SERVER_AND_CLIENT + bool "Server & Client" + select MBEDTLS_TLS_SERVER + select MBEDTLS_TLS_CLIENT + config MBEDTLS_TLS_SERVER_ONLY + bool "Server" + select MBEDTLS_TLS_SERVER + config MBEDTLS_TLS_CLIENT_ONLY + bool "Client" + select MBEDTLS_TLS_CLIENT + config MBEDTLS_TLS_DISABLED + bool "None" + +endchoice + +config MBEDTLS_TLS_SERVER + bool + select MBEDTLS_TLS_ENABLED +config MBEDTLS_TLS_CLIENT + bool + select MBEDTLS_TLS_ENABLED +config MBEDTLS_TLS_ENABLED + bool + +menu "TLS Key Exchange Methods" + depends on MBEDTLS_TLS_ENABLED + + config MBEDTLS_PSK_MODES + bool "Enable pre-shared-key ciphersuites" + default n + help + Enable to show configuration for different types of pre-shared-key TLS authentatication methods. + + Leaving this options disabled will save code size if they are not used. + + config MBEDTLS_KEY_EXCHANGE_PSK + bool "Enable PSK based ciphersuite modes" + depends on MBEDTLS_PSK_MODES + default n + help + Enable to support symmetric key PSK (pre-shared-key) TLS key exchange modes. + + config MBEDTLS_KEY_EXCHANGE_DHE_PSK + bool "Enable DHE-PSK based ciphersuite modes" + depends on MBEDTLS_PSK_MODES && MBEDTLS_DHM_C + default y + help + Enable to support Diffie-Hellman PSK (pre-shared-key) TLS authentication modes. + + config MBEDTLS_KEY_EXCHANGE_ECDHE_PSK + bool "Enable ECDHE-PSK based ciphersuite modes" + depends on MBEDTLS_PSK_MODES && MBEDTLS_ECDH_C + default y + help + Enable to support Elliptic-Curve-Diffie-Hellman PSK (pre-shared-key) TLS authentication modes. + + config MBEDTLS_KEY_EXCHANGE_RSA_PSK + bool "Enable RSA-PSK based ciphersuite modes" + depends on MBEDTLS_PSK_MODES + default y + help + Enable to support RSA PSK (pre-shared-key) TLS authentication modes. + + config MBEDTLS_KEY_EXCHANGE_RSA + bool "Enable RSA-only based ciphersuite modes" + default y + help + Enable to support ciphersuites with prefix TLS-RSA-WITH- + + config MBEDTLS_KEY_EXCHANGE_DHE_RSA + bool "Enable DHE-RSA based ciphersuite modes" + default y + depends on MBEDTLS_DHM_C + help + Enable to support ciphersuites with prefix TLS-DHE-RSA-WITH- + + config MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE + bool "Support Elliptic Curve based ciphersuites" + depends on MBEDTLS_ECP_C + default y + help + Enable to show Elliptic Curve based ciphersuite mode options. + + Disabling all Elliptic Curve ciphersuites saves code size and + can give slightly faster TLS handshakes, provided the server supports + RSA-only ciphersuite modes. + + config MBEDTLS_KEY_EXCHANGE_ECDHE_RSA + bool "Enable ECDHE-RSA based ciphersuite modes" + depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C + default y + help + Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH- + + config MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA + bool "Enable ECDHE-ECDSA based ciphersuite modes" + depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C && MBEDTLS_ECDSA_C + default y + help + Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH- + + config MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA + bool "Enable ECDH-ECDSA based ciphersuite modes" + depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C && MBEDTLS_ECDSA_C + default y + help + Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH- + + config MBEDTLS_KEY_EXCHANGE_ECDH_RSA + bool "Enable ECDH-RSA based ciphersuite modes" + depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C + default y + help + Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH- + + config MBEDTLS_KEY_EXCHANGE_ECJPAKE + bool "Enable ECJPAKE based ciphersuite modes" + depends on MBEDTLS_ECJPAKE_C && MBEDTLS_ECP_DP_SECP256R1_ENABLED + default n + help + Enable to support ciphersuites with prefix TLS-ECJPAKE-WITH- + +endmenu # TLS key exchange modes + +config MBEDTLS_SSL_RENEGOTIATION + bool "Support TLS renegotiation" + depends on MBEDTLS_TLS_ENABLED + default y + help + The two main uses of renegotiation are (1) refresh keys on long-lived + connections and (2) client authentication after the initial handshake. + If you don't need renegotiation, disabling it will save code size and + reduce the possibility of abuse/vulnerability. + +config MBEDTLS_SSL_PROTO_TLS1_2 + bool "Support TLS 1.2 protocol" + depends on MBEDTLS_TLS_ENABLED + default y + +config MBEDTLS_SSL_PROTO_GMTSSL1_1 + bool "Support GM/T SSL 1.1 protocol" + depends on MBEDTLS_TLS_ENABLED + default n + help + Provisions for GM/T SSL 1.1 support + +config MBEDTLS_SSL_PROTO_DTLS + bool "Support DTLS protocol (all versions)" + default n + depends on MBEDTLS_SSL_PROTO_TLS1_2 + help + Requires TLS 1.2 to be enabled for DTLS 1.2 + +config MBEDTLS_SSL_ALPN + bool "Support ALPN (Application Layer Protocol Negotiation)" + depends on MBEDTLS_TLS_ENABLED + default y + help + Disabling this option will save some code size if it is not needed. + +config MBEDTLS_CLIENT_SSL_SESSION_TICKETS + bool "TLS: Client Support for RFC 5077 SSL session tickets" + default y + depends on MBEDTLS_TLS_ENABLED + help + Client support for RFC 5077 session tickets. See mbedTLS documentation for more details. + Disabling this option will save some code size. + +config MBEDTLS_SERVER_SSL_SESSION_TICKETS + bool "TLS: Server Support for RFC 5077 SSL session tickets" + default y + depends on MBEDTLS_TLS_ENABLED && (MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C) + help + Server support for RFC 5077 session tickets. See mbedTLS documentation for more details. + Disabling this option will save some code size. + +menu "Symmetric Ciphers" + + config MBEDTLS_AES_C + bool "AES block cipher" + default y + + config MBEDTLS_CAMELLIA_C + bool "Camellia block cipher" + default n + + config MBEDTLS_DES_C + bool "DES block cipher (legacy, insecure)" + default n + help + Enables the DES block cipher to support 3DES-based TLS ciphersuites. + + 3DES is vulnerable to the Sweet32 attack and should only be enabled + if absolutely necessary. + + config MBEDTLS_BLOWFISH_C + bool "Blowfish block cipher (read help)" + default n + help + Enables the Blowfish block cipher (not used for TLS sessions.) + + The Blowfish cipher is not used for mbedTLS TLS sessions but can be + used for other purposes. Read up on the limitations of Blowfish (including + Sweet32) before enabling. + + config MBEDTLS_XTEA_C + bool "XTEA block cipher" + default n + help + Enables the XTEA block cipher. + + + config MBEDTLS_CCM_C + bool "CCM (Counter with CBC-MAC) block cipher modes" + default y + depends on MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C + help + Enable Counter with CBC-MAC (CCM) modes for AES and/or Camellia ciphers. + + Disabling this option saves some code size. + + config MBEDTLS_GCM_C + bool "GCM (Galois/Counter) block cipher modes" + default y + depends on MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C + help + Enable Galois/Counter Mode for AES and/or Camellia ciphers. + + This option is generally faster than CCM. + + config MBEDTLS_NIST_KW_C + bool "NIST key wrapping (KW) and KW padding (KWP)" + default n + depends on MBEDTLS_AES_C + help + Enable NIST key wrapping and key wrapping padding. + +endmenu # Symmetric Ciphers + +config MBEDTLS_RIPEMD160_C + bool "Enable RIPEMD-160 hash algorithm" + default n + help + Enable the RIPEMD-160 hash algorithm. + +menu "Certificates" + + config MBEDTLS_PEM_PARSE_C + bool "Read & Parse PEM formatted certificates" + default y + help + Enable decoding/parsing of PEM formatted certificates. + + If your certificates are all in the simpler DER format, disabling + this option will save some code size. + + config MBEDTLS_PEM_WRITE_C + bool "Write PEM formatted certificates" + default y + help + Enable writing of PEM formatted certificates. + + If writing certificate data only in DER format, disabling this + option will save some code size. + + config MBEDTLS_X509_CRL_PARSE_C + bool "X.509 CRL parsing" + default y + help + Support for parsing X.509 Certificate Revocation Lists. + + config MBEDTLS_X509_CSR_PARSE_C + bool "X.509 CSR parsing" + default y + help + Support for parsing X.509 Certificate Signing Requests + +endmenu # Certificates + +menuconfig MBEDTLS_ECP_C + bool "Elliptic Curve Ciphers" + default y + +config MBEDTLS_DHM_C + bool "Diffie-Hellman-Merkle key exchange (DHM)" + default n + help + Enable DHM. Needed to use DHE-xxx TLS ciphersuites. + + Note that the security of Diffie-Hellman key exchanges depends on + a suitable prime being used for the exchange. Please see detailed + warning text about this in file `mbedtls/dhm.h` file. + +config MBEDTLS_ECDH_C + bool "Elliptic Curve Diffie-Hellman (ECDH)" + depends on MBEDTLS_ECP_C + default y + help + Enable ECDH. Needed to use ECDHE-xxx TLS ciphersuites. + +config MBEDTLS_ECDSA_C + bool "Elliptic Curve DSA" + depends on MBEDTLS_ECDH_C + default y + help + Enable ECDSA. Needed to use ECDSA-xxx TLS ciphersuites. + +config MBEDTLS_ECJPAKE_C + bool "Elliptic curve J-PAKE" + depends on MBEDTLS_ECP_C + default n + help + Enable ECJPAKE. Needed to use ECJPAKE-xxx TLS ciphersuites. + +config MBEDTLS_ECP_DP_SECP192R1_ENABLED + bool "Enable SECP192R1 curve" + depends on MBEDTLS_ECP_C + default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + help + Enable support for SECP192R1 Elliptic Curve. + +config MBEDTLS_ECP_DP_SECP224R1_ENABLED + bool "Enable SECP224R1 curve" + depends on MBEDTLS_ECP_C + default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + help + Enable support for SECP224R1 Elliptic Curve. + +config MBEDTLS_ECP_DP_SECP256R1_ENABLED + bool "Enable SECP256R1 curve" + depends on MBEDTLS_ECP_C + default y + help + Enable support for SECP256R1 Elliptic Curve. + +config MBEDTLS_ECP_DP_SECP384R1_ENABLED + bool "Enable SECP384R1 curve" + depends on MBEDTLS_ECP_C + default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + help + Enable support for SECP384R1 Elliptic Curve. + +config MBEDTLS_ECP_DP_SECP521R1_ENABLED + bool "Enable SECP521R1 curve" + depends on MBEDTLS_ECP_C + default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + help + Enable support for SECP521R1 Elliptic Curve. + +config MBEDTLS_ECP_DP_SECP192K1_ENABLED + bool "Enable SECP192K1 curve" + depends on MBEDTLS_ECP_C + default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + help + Enable support for SECP192K1 Elliptic Curve. + +config MBEDTLS_ECP_DP_SECP224K1_ENABLED + bool "Enable SECP224K1 curve" + depends on MBEDTLS_ECP_C + default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + help + Enable support for SECP224K1 Elliptic Curve. + +config MBEDTLS_ECP_DP_SECP256K1_ENABLED + bool "Enable SECP256K1 curve" + depends on MBEDTLS_ECP_C + default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + help + Enable support for SECP256K1 Elliptic Curve. + +config MBEDTLS_ECP_DP_BP256R1_ENABLED + bool "Enable BP256R1 curve" + depends on MBEDTLS_ECP_C + default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + help + support for DP Elliptic Curve. + +config MBEDTLS_ECP_DP_BP384R1_ENABLED + bool "Enable BP384R1 curve" + depends on MBEDTLS_ECP_C + default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + help + support for DP Elliptic Curve. + +config MBEDTLS_ECP_DP_BP512R1_ENABLED + bool "Enable BP512R1 curve" + depends on MBEDTLS_ECP_C + default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + help + support for DP Elliptic Curve. + +config MBEDTLS_ECP_DP_CURVE25519_ENABLED + bool "Enable CURVE25519 curve" + depends on MBEDTLS_ECP_C + default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + help + Enable support for CURVE25519 Elliptic Curve. + +config MBEDTLS_ECP_NIST_OPTIM + bool "NIST 'modulo p' optimisations" + depends on MBEDTLS_ECP_C + default y + help + NIST 'modulo p' optimisations increase Elliptic Curve operation performance. + + Disabling this option saves some code size. + +config MBEDTLS_ECP_FIXED_POINT_OPTIM + bool "Enable fixed-point multiplication optimisations" + depends on MBEDTLS_ECP_C + default n + help + This configuration option enables optimizations to speedup (about 3 ~ 4 times) the ECP + fixed point multiplication using pre-computed tables in the flash memory. + Enabling this configuration option increases the flash footprint + (about 29KB if all Elliptic Curve selected) in the application binary. + + # end of Elliptic Curve options + +config MBEDTLS_POLY1305_C + bool "Poly1305 MAC algorithm" + default n + help + Enable support for Poly1305 MAC algorithm. + +config MBEDTLS_CHACHA20_C + bool "Chacha20 stream cipher" + default n + help + Enable support for Chacha20 stream cipher. + +config MBEDTLS_CHACHAPOLY_C + bool "ChaCha20-Poly1305 AEAD algorithm" + default n + depends on MBEDTLS_CHACHA20_C && MBEDTLS_POLY1305_C + help + Enable support for ChaCha20-Poly1305 AEAD algorithm. + +config MBEDTLS_HKDF_C + bool "HKDF algorithm (RFC 5869)" + default n + help + Enable support for the Hashed Message Authentication Code + (HMAC)-based key derivation function (HKDF). + +config MBEDTLS_THREADING_C + depends on !IDF_TARGET_ESP8266 + bool "Enable the threading abstraction layer" + default n + help + If you do intend to use contexts between threads, you will need to enable + this layer to prevent race conditions. + +config MBEDTLS_THREADING_ALT + bool "Enable threading alternate implementation" + depends on MBEDTLS_THREADING_C + default y + help + Enable threading alt to allow your own alternate threading implementation. + +config MBEDTLS_THREADING_PTHREAD + bool "Enable threading pthread implementation" + depends on MBEDTLS_THREADING_C + default n + help + Enable the pthread wrapper layer for the threading layer. + +config MBEDTLS_ERROR_STRINGS + bool "Enable error code to error string conversion" + default y + help + Enables mbedtls_strerror() for converting error codes to error strings. + Disabling this config can save some code/rodata size as the error + string conversion implementation is replaced with an empty stub. + +config MBEDTLS_USE_CRYPTO_ROM_IMPL + bool "Use ROM implementation of the crypto algorithm" + depends on ESP_ROM_HAS_MBEDTLS_CRYPTO_LIB + default "n" + select MBEDTLS_SHA512_C + select MBEDTLS_AES_C + select MBEDTLS_CCM_C + select MBEDTLS_CMAC_C + select MBEDTLS_ROM_MD5 + select MBEDTLS_HARDWARE_SHA + select MBEDTLS_ECP_RESTARTABLE + select MBEDTLS_THREADING_C + help + Enable this flag to use mbedtls crypto algorithm from ROM instead of ESP-IDF. + + This configuration option saves flash footprint in the application binary. + Note that the version of mbedtls crypto algorithm library in ROM(ECO1~ECO3) is v2.16.12, + and the version of mbedtls crypto algorithm library in ROM(ECO4) is v3.6.0. + We have done the security analysis of the mbedtls revision in ROM (ECO1~ECO4) + and ensured that affected symbols have been patched (removed). If in the future + mbedtls revisions there are security issues that also affects the version in + ROM (ECO1~ECO4) then we shall patch the relevant symbols. This would increase + the flash footprint and hence care must be taken to keep some reserved space + for the application binary in flash layout. + + config MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION + bool "Allow weak certificate verification" + default n + help + This options allows weak certificate verification by skipping the hostname verification. + It is not recommended to use this option. diff --git a/components/mbedtls/mbedtls_v3/component.mk b/components/mbedtls/mbedtls_v3/component.mk new file mode 100644 index 000000000..227e1bcf0 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/component.mk @@ -0,0 +1,38 @@ +# +# Component Makefile +# + +CURRENT_DIR := mbedtls_v3 + +COMPONENT_ADD_INCLUDEDIRS := $(CURRENT_DIR)/port/include $(CURRENT_DIR)/mbedtls/include $(CURRENT_DIR)/mbedtls/library + +COMPONENT_SRCDIRS := $(CURRENT_DIR)/mbedtls/library $(CURRENT_DIR)/port + +COMPONENT_OBJEXCLUDE := $(CURRENT_DIR)/mbedtls/library/net_sockets.o + +ifndef CONFIG_MBEDTLS_MPI_EXP_MOD_ALT +COMPONENT_OBJEXCLUDE += $(CURRENT_DIR)/port/esp_bignum.o +endif + +COMPONENT_SUBMODULES += $(CURRENT_DIR)/mbedtls + +ifdef CONFIG_MBEDTLS_DYNAMIC_BUFFER + +WRAP_FUNCTIONS = mbedtls_ssl_write_client_hello \ + mbedtls_ssl_handshake_client_step \ + mbedtls_ssl_handshake_server_step \ + mbedtls_ssl_read \ + mbedtls_ssl_write \ + mbedtls_ssl_session_reset \ + mbedtls_ssl_free \ + mbedtls_ssl_setup \ + mbedtls_ssl_send_alert_message \ + mbedtls_ssl_close_notify + +WRAP_ARGUMENT := -Wl,--wrap= + +COMPONENT_ADD_LDFLAGS = -l$(COMPONENT_NAME) $(addprefix $(WRAP_ARGUMENT),$(WRAP_FUNCTIONS)) + +COMPONENT_SRCDIRS += $(CURRENT_DIR)/port/dynamic + +endif diff --git a/components/mbedtls/mbedtls_v3/esp_crt_bundle/cacrt_all.pem b/components/mbedtls/mbedtls_v3/esp_crt_bundle/cacrt_all.pem new file mode 100644 index 000000000..2ae7b6cb2 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/esp_crt_bundle/cacrt_all.pem @@ -0,0 +1,3372 @@ +## +## Bundle of CA Root Certificates +## +## Certificate data from Mozilla as of: Tue Jan 10 04:12:06 2023 GMT +## +## This is a bundle of X.509 certificates of public Certificate Authorities +## (CA). These were automatically extracted from Mozilla's root certificates +## file (certdata.txt). This file can be found in the mozilla source tree: +## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt +## +## It contains the certificates in PEM format and therefore +## can be directly used with curl / libcurl / php_curl, or with +## an Apache+mod_ssl webserver for SSL client authentication. +## Just configure this file as the SSLCACertificateFile. +## +## Conversion done with mk-ca-bundle.pl version 1.29. +## SHA256: 90c470e705b4b5f36f09684dc50e2b79c8b86989a848b62cd1a7bd6460ee65f6 +## + + +GlobalSign Root CA +================== +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx +GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds +b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV +BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD +VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa +DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc +THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb +Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP +c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX +gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF +AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj +Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG +j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH +hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC +X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +Entrust.net Premium 2048 Secure Server CA +========================================= +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u +ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp +bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx +NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 +d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u +ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL +Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr +hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW +nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi +VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ +KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy +T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT +J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e +nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- + +Baltimore CyberTrust Root +========================= +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE +ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li +ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC +SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs +dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME +uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB +UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C +G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 +XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr +l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI +VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB +BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh +cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 +hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa +Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H +RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +Entrust Root Certification Authority +==================================== +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw +b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG +A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 +MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu +MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu +Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz +A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww +Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 +j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN +rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 +MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH +hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM +Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa +v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS +W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 +tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +Comodo AAA Services root +======================== +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw +MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl +c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV +BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG +C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs +i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW +Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH +Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK +Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f +BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl +cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz +LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm +7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z +8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C +12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +QuoVadis Root CA 2 +================== +-----BEGIN CERTIFICATE----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT +EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx +ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6 +XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk +lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB +lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy +lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt +66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn +wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh +D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy +BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie +J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud +DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU +a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv +Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3 +UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm +VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK ++JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW +IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1 +WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X +f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II +4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8 +VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- + +QuoVadis Root CA 3 +================== +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT +EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx +OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg +DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij +KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K +DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv +BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp +p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8 +nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX +MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM +Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz +uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT +BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj +YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB +BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD +VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4 +ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE +AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV +qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s +hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z +POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2 +Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp +8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC +bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu +g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p +vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr +qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- + +Security Communication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw +8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM +DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX +5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd +DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 +JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g +0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a +mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ +s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ +6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi +FL39vmwLAw== +-----END CERTIFICATE----- + +XRamp Global CA Root +==================== +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE +BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj +dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx +HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg +U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu +IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx +foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE +zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs +AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry +xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap +oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC +AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc +/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n +nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz +8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +Go Daddy Class 2 CA +=================== +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY +VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG +A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g +RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD +ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv +2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 +qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j +YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY +vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O +BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o +atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu +MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim +PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt +I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI +Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b +vZ8= +-----END CERTIFICATE----- + +Starfield Class 2 CA +==================== +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc +U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo +MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG +A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG +SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY +bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ +JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm +epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN +F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF +MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f +hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo +bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs +afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM +PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD +KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 +QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + +DigiCert Assured ID Root CA +=========================== +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx +MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO +9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy +UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW +/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy +oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf +GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF +66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq +hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc +EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn +SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i +8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- + +DigiCert Global Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw +MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn +TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 +BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H +4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y +7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB +o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm +8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF +BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr +EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt +tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 +UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- + +DigiCert High Assurance EV Root CA +================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw +KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw +MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ +MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu +Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t +Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS +OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 +MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ +NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe +h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB +Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY +JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ +V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp +myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK +mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K +-----END CERTIFICATE----- + +SwissSign Gold CA - G2 +====================== +-----BEGIN CERTIFICATE----- +MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw +EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN +MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp +c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq +t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C +jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg +vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF +ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR +AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend +jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO +peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR +7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi +GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64 +OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov +L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm +5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr +44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf +Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m +Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp +mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk +vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf +KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br +NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj +viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ +-----END CERTIFICATE----- + +SwissSign Silver CA - G2 +======================== +-----BEGIN CERTIFICATE----- +MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT +BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X +DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3 +aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG +9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644 +N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm ++/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH +6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu +MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h +qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5 +FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs +ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc +celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X +CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB +tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 +cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P +4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F +kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L +3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx +/uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa +DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP +e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu +WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ +DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub +DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u +-----END CERTIFICATE----- + +SecureTrust CA +============== +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy +dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe +BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX +OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t +DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH +GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b +01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH +ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj +aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ +KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu +SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf +mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ +nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +Secure Global CA +================ +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH +bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg +MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg +Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx +YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ +bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g +8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV +HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi +0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn +oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA +MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ +OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn +CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 +3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +COMODO Certification Authority +============================== +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb +MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD +T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH ++7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww +xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV +4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA +1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI +rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k +b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC +AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP +OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc +IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN ++8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== +-----END CERTIFICATE----- + +COMODO ECC Certification Authority +================================== +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix +GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo +b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X +4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni +wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG +FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA +U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- + +Certigna +======== +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw +EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 +MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI +Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q +XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH +GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p +ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg +DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf +Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ +tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ +BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J +SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA +hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ +ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu +PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY +1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +ePKI Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG +EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx +MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq +MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs +IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi +lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv +qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX +12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O +WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ +ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao +lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ +vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi +Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi +MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 +1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq +KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV +xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP +NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r +GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE +xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx +gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy +sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD +BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +certSIGN ROOT CA +================ +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD +VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa +Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE +CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I +JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH +rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 +ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD +0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 +AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B +Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB +AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 +SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 +x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt +vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz +TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +NetLock Arany (Class Gold) Főtanúsítvány +======================================== +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G +A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 +dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB +cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx +MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO +ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 +c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu +0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw +/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk +H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw +fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 +neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW +qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta +YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna +NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu +dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +Hongkong Post Root CA 1 +======================= +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT +DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx +NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n +IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 +ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr +auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh +qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY +V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV +HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i +h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio +l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei +IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps +T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT +c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== +-----END CERTIFICATE----- + +SecureSign RootCA11 +=================== +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi +SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS +b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw +KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 +cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL +TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO +wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq +g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP +O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA +bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX +t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh +OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r +bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ +Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 +y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 +lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + +Microsec e-Szigno Root CA 2009 +============================== +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER +MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv +c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE +BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt +U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA +fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG +0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA +pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm +1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC +AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf +QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE +FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o +lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX +I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 +yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi +LXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +GlobalSign Root CA - R3 +======================= +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt +iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ +0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 +rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl +OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 +xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 +lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 +EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E +bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 +YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r +kpeDMdmztcpHWD9f +-----END CERTIFICATE----- + +Autoridad de Certificacion Firmaprofesional CIF A62634068 +========================================================= +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw +QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB +NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD +Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P +B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY +7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH +ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI +plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX +MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX +LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK +bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU +vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud +EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH +DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA +bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx +ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx +51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk +R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP +T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f +Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl +osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR +crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR +saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD +KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi +6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +Izenpe.com +========== +-----BEGIN CERTIFICATE----- +MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG +EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz +MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu +QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ +03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK +ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU ++zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC +PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT +OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK +F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK +0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+ +0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB +leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID +AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+ +SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG +NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx +MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l +Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga +kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q +hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs +g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5 +aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5 +nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC +ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo +Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z +WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== +-----END CERTIFICATE----- + +Go Daddy Root Certificate Authority - G2 +======================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu +MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G +A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq +9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD ++qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd +fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl +NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 +BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac +vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r +5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV +N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 +-----END CERTIFICATE----- + +Starfield Root Certificate Authority - G2 +========================================= +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 +eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw +DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg +VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB +dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv +W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs +bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk +N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf +ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU +JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol +TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx +4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw +F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ +c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +Starfield Services Root Certificate Authority - G2 +================================================== +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl +IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT +dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 +h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa +hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP +LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB +rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG +SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP +E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy +xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza +YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 +-----END CERTIFICATE----- + +AffirmTrust Commercial +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw +MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb +DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV +C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 +BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww +MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV +HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG +hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi +qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv +0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh +sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +AffirmTrust Networking +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw +MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE +Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI +dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 +/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb +h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV +HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu +UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 +12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 +WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 +/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +AffirmTrust Premium +=================== +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy +OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy +dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn +BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV +5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs ++7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd +GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R +p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI +S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 +6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 +/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo ++Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv +MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC +6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S +L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK ++4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV +BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg +IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 +g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb +zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== +-----END CERTIFICATE----- + +AffirmTrust Premium ECC +======================= +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV +BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx +MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U +cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ +N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW +BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK +BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X +57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM +eQ== +-----END CERTIFICATE----- + +Certum Trusted Network CA +========================= +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK +ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy +MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU +ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC +l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J +J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 +fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 +cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB +Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw +DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj +jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 +mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj +Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +TWCA Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ +VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG +EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB +IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx +QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC +oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP +4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r +y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG +9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC +mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW +QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY +T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny +Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- + +Security Communication RootCA2 +============================== +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh +dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC +SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy +aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ ++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R +3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV +spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K +EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 +QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB +CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj +u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk +3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q +tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 +mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- + +Actalis Authentication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM +BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE +AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky +MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz +IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ +wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa +by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6 +zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f +YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2 +oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l +EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7 +hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8 +EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5 +jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY +iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI +WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0 +JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx +K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+ +Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC +4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo +2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz +lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem +OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9 +vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----END CERTIFICATE----- + +Buypass Class 2 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X +DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 +g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn +9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b +/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU +CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff +awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI +zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn +Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX +Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs +M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI +osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S +aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd +DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD +LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 +oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC +wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS +CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN +rJgWVqA= +-----END CERTIFICATE----- + +Buypass Class 3 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X +DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH +sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR +5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh +7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ +ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH +2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV +/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ +RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA +Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq +j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G +uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG +Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 +ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 +KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz +6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug +UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe +eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi +Cp/HuZc= +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 3 +============================ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx +MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK +9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU +NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF +iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W +0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr +AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb +fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT +ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h +P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== +-----END CERTIFICATE----- + +D-TRUST Root Class 3 CA 2 2009 +============================== +-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe +Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE +LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD +ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA +BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv +KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z +p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC +AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ +4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y +eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw +MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G +PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw +OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm +2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV +dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph +X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE----- + +D-TRUST Root Class 3 CA 2 EV 2009 +================================= +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw +OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw +OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS +egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh +zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T +7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60 +sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35 +11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv +cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v +ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El +MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp +b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh +c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+ +PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX +ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA +NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv +w9y4AyHqnxbxLFS1 +-----END CERTIFICATE----- + +CA Disig Root R2 +================ +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw +EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp +ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx +EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp +c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC +w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia +xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7 +A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S +GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV +g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa +5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE +koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A +Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i +Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u +Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV +sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je +dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8 +1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx +mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01 +utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0 +sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg +UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV +7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE----- + +ACCVRAIZ1 +========= +-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB +SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1 +MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH +UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM +jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0 +RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD +aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ +0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG +WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7 +8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR +5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J +9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK +Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw +Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu +Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM +Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA +QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh +AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA +YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj +AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA +IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk +aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0 +dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2 +MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI +hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E +R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN +YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49 +nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ +TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3 +sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg +Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd +3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p +EfbRD0tVNEYqi4Y7 +-----END CERTIFICATE----- + +TWCA Global Root CA +=================== +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT +CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD +QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK +EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg +Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C +nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV +r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR +Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV +tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W +KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99 +sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p +yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn +kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI +zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g +cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M +8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg +/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg +lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP +A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m +i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8 +EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3 +zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0= +-----END CERTIFICATE----- + +TeliaSonera Root CA v1 +====================== +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE +CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4 +MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW +VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+ +6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA +3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k +B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn +Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH +oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3 +F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ +oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7 +gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc +TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB +AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW +DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm +zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx +0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW +pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV +G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc +c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT +JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2 +qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6 +Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems +WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= +-----END CERTIFICATE----- + +E-Tugra Certification Authority +=============================== +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w +DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls +ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN +ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw +NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx +QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl +cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD +DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd +hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K +CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g +ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ +BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0 +E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz +rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq +jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn +rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5 +dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB +/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG +MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK +kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO +XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807 +VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo +a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc +dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV +KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT +Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0 +8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G +C7TbO6Orb1wdtn7os4I07QZcJA== +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 2 +============================ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx +MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ +SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F +vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970 +2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV +WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy +YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4 +r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf +vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR +3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN +9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg== +-----END CERTIFICATE----- + +Atos TrustedRoot 2011 +===================== +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU +cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4 +MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG +A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV +hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr +54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+ +DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320 +HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR +z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R +l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ +bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB +CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h +k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh +TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9 +61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G +3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- + +QuoVadis Root CA 1 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE +PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm +PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6 +Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN +ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l +g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV +7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX +9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f +iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg +t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI +hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC +MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3 +GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct +Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP ++V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh +3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa +wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6 +O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0 +FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV +hMJKzRwuJIczYOXD +-----END CERTIFICATE----- + +QuoVadis Root CA 2 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh +ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY +NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t +oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o +MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l +V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo +L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ +sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD +6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh +lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI +hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K +pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9 +x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz +dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X +U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw +mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD +zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN +JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr +O3jtZsSOeWmD3n+M +-----END CERTIFICATE----- + +QuoVadis Root CA 3 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286 +IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL +Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe +6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3 +I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U +VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7 +5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi +Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM +dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt +rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI +hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px +KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS +t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ +TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du +DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib +Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD +hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX +0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW +dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2 +PpxxVJkES/1Y+Zj0 +-----END CERTIFICATE----- + +DigiCert Assured ID Root G2 +=========================== +-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw +MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH +35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq +bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw +VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP +YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn +lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO +w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv +0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz +d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW +hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M +jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo +IhNzbM8m9Yop5w== +-----END CERTIFICATE----- + +DigiCert Assured ID Root G3 +=========================== +-----BEGIN CERTIFICATE----- +MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD +VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 +MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb +RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs +KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF +UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy +YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy +1vUhZscv6pZjamVFkpUBtA== +-----END CERTIFICATE----- + +DigiCert Global Root G2 +======================= +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx +MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ +kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO +3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV +BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM +UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB +o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu +5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr +F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U +WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH +QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/ +iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE----- + +DigiCert Global Root G3 +======================= +-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD +VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw +MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k +aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C +AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O +YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp +Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y +3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34 +VOKa5Vt8sycX +-----END CERTIFICATE----- + +DigiCert Trusted Root G4 +======================== +-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw +HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 +MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp +pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o +k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa +vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY +QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6 +MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm +mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7 +f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH +dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8 +oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY +ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr +yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy +7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah +ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN +5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb +/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa +5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK +G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP +82Z+ +-----END CERTIFICATE----- + +COMODO RSA Certification Authority +================================== +-----BEGIN CERTIFICATE----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn +dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ +FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+ +5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG +x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX +2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL +OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3 +sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C +GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5 +WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt +rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+ +nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg +tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW +sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp +pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA +zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq +ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52 +7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I +LaZRfyHBNVOFBkpdn627G190 +-----END CERTIFICATE----- + +USERTrust RSA Certification Authority +===================================== +-----BEGIN CERTIFICATE----- +MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE +BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK +ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE +BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK +ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz +0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j +Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn +RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O ++T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq +/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE +Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM +lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8 +yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+ +eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd +BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW +FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ +7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ +Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM +8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi +FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi +yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c +J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw +sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx +Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9 +-----END CERTIFICATE----- + +USERTrust ECC Certification Authority +===================================== +-----BEGIN CERTIFICATE----- +MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2 +0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez +nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV +HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB +HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu +9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= +-----END CERTIFICATE----- + +GlobalSign ECC Root CA - R5 +=========================== +-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6 +SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS +h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx +uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7 +yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3 +-----END CERTIFICATE----- + +IdenTrust Commercial Root CA 1 +============================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG +EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS +b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES +MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB +IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld +hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/ +mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi +1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C +XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl +3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy +NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV +WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg +xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix +uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI +hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg +ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt +ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV +YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX +feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro +kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe +2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz +Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R +cGzM7vRX+Bi6hG6H +-----END CERTIFICATE----- + +IdenTrust Public Sector Root CA 1 +================================= +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG +EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv +ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV +UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS +b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy +P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6 +Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI +rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf +qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS +mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn +ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh +LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v +iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL +4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B +Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw +DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj +t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A +mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt +GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt +m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx +NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4 +Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI +ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC +ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ +3Wl9af0AVqW3rLatt8o+Ae+c +-----END CERTIFICATE----- + +Entrust Root Certification Authority - G2 +========================================= +-----BEGIN CERTIFICATE----- +MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy +bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug +b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw +HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT +DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx +OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP +/vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz +HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU +s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y +TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx +AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6 +0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z +iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ +Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi +nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+ +vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO +e4pIb4tF9g== +-----END CERTIFICATE----- + +Entrust Root Certification Authority - EC1 +========================================== +-----BEGIN CERTIFICATE----- +MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx +FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn +YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl +ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw +FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs +LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg +dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt +IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy +AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef +9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h +vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8 +kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G +-----END CERTIFICATE----- + +CFCA EV ROOT +============ +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE +CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB +IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw +MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD +DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV +BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD +7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN +uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW +ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7 +xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f +py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K +gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol +hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ +tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf +BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB +ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q +ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua +4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG +E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX +BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn +aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy +PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX +kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C +ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GB CA +=============================== +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG +EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw +MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds +b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX +scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP +rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk +9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o +Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg +GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI +hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD +dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0 +VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui +HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- + +SZAFIR ROOT CA2 +=============== +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG +A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV +BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ +BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD +VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q +qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK +DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE +2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ +ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi +ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC +AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5 +O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67 +oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul +4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6 ++/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- + +Certum Trusted Network CA 2 +=========================== +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE +BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1 +bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y +ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ +TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB +IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9 +7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o +CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b +Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p +uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130 +GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ +9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB +Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye +hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM +BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI +hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW +Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA +L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo +clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM +pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb +w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo +J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm +ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX +is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7 +zAYspsbiDrW5viSP +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2015 +======================================================= +-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT +BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0 +aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl +YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx +MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg +QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV +BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw +MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv +bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh +iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+ +6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd +FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr +i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F +GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2 +fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu +iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI +hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+ +D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM +d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y +d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn +82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb +davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F +Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt +J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa +JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q +p/UsQu0yrbYhnr68 +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions ECC RootCA 2015 +=========================================================== +-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0 +aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u +cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj +aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw +MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj +IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD +VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290 +Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP +dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK +Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA +GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn +dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE----- + +ISRG Root X1 +============ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE +BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD +EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG +EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT +DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r +Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1 +3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K +b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN +Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ +4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf +1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu +hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH +usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r +OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G +A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY +9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV +0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt +hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw +TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx +e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA +JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD +YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n +JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ +m+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- + +AC RAIZ FNMT-RCM +================ +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT +AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw +MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD +TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf +qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr +btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL +j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou +08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw +WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT +tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ +47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC +ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa +i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o +dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s +D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ +j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT +Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW ++YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7 +Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d +8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm +5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG +rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE----- + +Amazon Root CA 1 +================ +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1 +MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH +FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ +gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t +dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce +VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3 +DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM +CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy +8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa +2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2 +xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- + +Amazon Root CA 2 +================ +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1 +MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4 +kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp +N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9 +AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd +fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx +kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS +btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0 +Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN +c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+ +3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw +DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA +A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE +YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW +xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ +gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW +aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV +Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3 +KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi +JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw= +-----END CERTIFICATE----- + +Amazon Root CA 3 +================ +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB +f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr +Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43 +rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc +eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw== +-----END CERTIFICATE----- + +Amazon Root CA 4 +================ +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN +/sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri +83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA +MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1 +AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- + +TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 +============================================= +-----BEGIN CERTIFICATE----- +MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT +D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr +IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g +TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp +ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD +VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt +c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth +bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11 +IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8 +6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc +wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0 +3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9 +WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU +ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh +AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc +lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R +e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j +q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= +-----END CERTIFICATE----- + +GDCA TrustAUTH R5 ROOT +====================== +-----BEGIN CERTIFICATE----- +MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw +BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD +DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow +YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ +IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs +AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p +OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr +pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ +9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ +xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM +R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ +D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4 +oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx +9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg +p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9 +H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35 +6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd ++PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ +HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD +F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ +8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv +/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT +aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== +-----END CERTIFICATE----- + +SSL.com Root Certification Authority RSA +======================================== +-----BEGIN CERTIFICATE----- +MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM +BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x +MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw +MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx +EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM +LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C +Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8 +P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge +oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp +k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z +fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ +gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2 +UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8 +1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s +bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr +dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf +ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl +u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq +erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj +MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ +vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI +Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y +wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI +WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k= +-----END CERTIFICATE----- + +SSL.com Root Certification Authority ECC +======================================== +-----BEGIN CERTIFICATE----- +MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV +BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv +BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy +MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO +BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv +bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA +BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+ +8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR +hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT +jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW +e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z +5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl +-----END CERTIFICATE----- + +SSL.com EV Root Certification Authority RSA R2 +============================================== +-----BEGIN CERTIFICATE----- +MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w +DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u +MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy +MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI +DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD +VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh +hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w +cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO +Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+ +B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh +CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim +9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto +RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm +JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48 ++qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV +HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp +qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1 +++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx +Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G +guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz +OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7 +CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq +lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR +rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1 +hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX +9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== +-----END CERTIFICATE----- + +SSL.com EV Root Certification Authority ECC +=========================================== +-----BEGIN CERTIFICATE----- +MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV +BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy +BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw +MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx +EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM +LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy +3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O +BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe +5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ +N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm +m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== +-----END CERTIFICATE----- + +GlobalSign Root CA - R6 +======================= +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX +R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds +b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i +YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs +U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss +grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE +3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF +vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM +PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+ +azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O +WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy +CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP +0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN +b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV +HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0 +lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY +BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym +Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr +3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1 +0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T +uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK +oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t +JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GC CA +=============================== +-----BEGIN CERTIFICATE----- +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD +SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo +MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa +Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL +ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh +bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr +VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab +NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E +AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk +AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 +-----END CERTIFICATE----- + +UCA Global G2 Root +================== +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG +EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x +NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU +cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT +oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV +8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS +h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o +LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/ +R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe +KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa +4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc +OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97 +8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo +5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 +1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A +Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9 +yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX +c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo +jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk +bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x +ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn +RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A== +-----END CERTIFICATE----- + +UCA Extended Validation Root +============================ +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG +EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u +IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G +A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs +iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF +Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu +eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR +59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH +0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR +el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv +B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth +WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS +NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS +3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL +BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR +ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM +aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4 +dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb ++7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW +F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi +GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc +GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi +djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr +dhh2n1ax +-----END CERTIFICATE----- + +Certigna Root CA +================ +-----BEGIN CERTIFICATE----- +MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE +BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ +MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda +MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz +MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX +stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz +KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8 +JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16 +XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq +4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej +wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ +lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI +jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/ +/TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of +1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy +dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h +LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl +cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt +OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP +TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq +7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3 +4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd +8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS +6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY +tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS +aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde +E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= +-----END CERTIFICATE----- + +emSign Root CA - G1 +=================== +-----BEGIN CERTIFICATE----- +MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET +MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl +ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx +ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk +aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN +LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1 +cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW +DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ +6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH +hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG +MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2 +vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q +NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q ++Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih +U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx +iN66zB+Afko= +-----END CERTIFICATE----- + +emSign ECC Root CA - G3 +======================= +-----BEGIN CERTIFICATE----- +MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG +A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg +MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4 +MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11 +ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g +RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc +58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr +MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D +CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7 +jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj +-----END CERTIFICATE----- + +emSign Root CA - C1 +=================== +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx +EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp +Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE +BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD +ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up +ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/ +Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX +OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V +I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms +lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+ +XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD +ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp +/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1 +NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9 +wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ +BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI= +-----END CERTIFICATE----- + +emSign ECC Root CA - C3 +======================= +-----BEGIN CERTIFICATE----- +MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG +A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF +Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE +BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD +ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd +6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9 +SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA +B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA +MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU +ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== +-----END CERTIFICATE----- + +Hongkong Post Root CA 3 +======================= +-----BEGIN CERTIFICATE----- +MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG +A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK +Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2 +MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv +bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX +SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz +iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf +jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim +5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe +sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj +0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/ +JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u +y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h ++bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG +xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID +AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e +i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN +AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw +W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld +y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov ++BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc +eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw +9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7 +nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY +hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB +60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq +dBb9HxEGmpv0 +-----END CERTIFICATE----- + +Entrust Root Certification Authority - G4 +========================================= +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAwgb4xCzAJBgNV +BAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu +bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1 +dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eSAtIEc0MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYT +AlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 +L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eSAtIEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3D +umSXbcr3DbVZwbPLqGgZ2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV +3imz/f3ET+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j5pds +8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAMC1rlLAHGVK/XqsEQ +e9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73TDtTUXm6Hnmo9RR3RXRv06QqsYJn7 +ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNXwbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5X +xNMhIWNlUpEbsZmOeX7m640A2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV +7rtNOzK+mndmnqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 +dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwlN4y6mACXi0mW +Hv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNjc0kCAwEAAaNCMEAwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9n +MA0GCSqGSIb3DQEBCwUAA4ICAQAS5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4Q +jbRaZIxowLByQzTSGwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht +7LGrhFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/B7NTeLUK +YvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uIAeV8KEsD+UmDfLJ/fOPt +jqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbwH5Lk6rWS02FREAutp9lfx1/cH6NcjKF+ +m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKW +RGhXxNUzzxkvFMSUHHuk2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjA +JOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G ++TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPT +kcpG2om3PVODLAgfi49T3f+sHw== +-----END CERTIFICATE----- + +Microsoft ECC Root Certificate Authority 2017 +============================================= +-----BEGIN CERTIFICATE----- +MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV +UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQgRUND +IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4 +MjMxNjA0WjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw +NAYDVQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZRogPZnZH6 +thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYbhGBKia/teQ87zvH2RPUB +eMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIy5lycFIM ++Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlf +Xu5gKcs68tvWMoQZP3zVL8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaR +eNtUjGUBiudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= +-----END CERTIFICATE----- + +Microsoft RSA Root Certificate Authority 2017 +============================================= +-----BEGIN CERTIFICATE----- +MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQG +EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQg +UlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIw +NzE4MjMwMDIzWjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u +MTYwNAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZNt9GkMml +7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0ZdDMbRnMlfl7rEqUrQ7e +S0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw7 +1VdyvD/IybLeS2v4I2wDwAW9lcfNcztmgGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+ +dkC0zVJhUXAoP8XFWvLJjEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49F +yGcohJUcaDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaGYaRS +MLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6W6IYZVcSn2i51BVr +lMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4KUGsTuqwPN1q3ErWQgR5WrlcihtnJ +0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJ +ClTUFLkqqNfs+avNJVgyeY+QW5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZCLgLNFgVZJ8og +6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OCgMNPOsduET/m4xaRhPtthH80 +dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk ++ONVFT24bcMKpBLBaYVu32TxU5nhSnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex +/2kskZGT4d9Mozd2TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDy +AmH3pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGRxpl/j8nW +ZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiAppGWSZI1b7rCoucL5mxAyE +7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKT +c0QWbej09+CVgI+WXTik9KveCjCHk9hNAHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D +5KbvtwEwXlGjefVwaaZBRA+GsCyRxj3qrg+E +-----END CERTIFICATE----- + +e-Szigno Root CA 2017 +===================== +-----BEGIN CERTIFICATE----- +MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNVBAYTAkhVMREw +DwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUt +MjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJvb3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZa +Fw00MjA4MjIxMjA3MDZaMHExCzAJBgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UE +CgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3pp +Z25vIFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtvxie+RJCx +s1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+HWyx7xf58etqjYzBhMA8G +A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSHERUI0arBeAyxr87GyZDv +vzAEwDAfBgNVHSMEGDAWgBSHERUI0arBeAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEA +tVfd14pVCzbhhkT61NlojbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxO +svxyqltZ+efcMQ== +-----END CERTIFICATE----- + +certSIGN Root CA G2 +=================== +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAlJPMRQw +EgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjAeFw0xNzAy +MDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJBgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lH +TiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAMDFdRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05 +N0IwvlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZuIt4Imfk +abBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhpn+Sc8CnTXPnGFiWeI8Mg +wT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKscpc/I1mbySKEwQdPzH/iV8oScLumZfNp +dWO9lfsbl83kqK/20U6o2YpxJM02PbyWxPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91Qqh +ngLjYl/rNUssuHLoPj1PrCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732 +jcZZroiFDsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fxDTvf +95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgyLcsUDFDYg2WD7rlc +z8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6CeWRgKRM+o/1Pcmqr4tTluCRVLERL +iohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud +DgQWBBSCIS1mxteg4BXrzkwJd8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOB +ywaK8SJJ6ejqkX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC +b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQlqiCA2ClV9+BB +/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0OJD7uNGzcgbJceaBxXntC6Z5 +8hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+cNywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5 +BiKDUyUM/FHE5r7iOZULJK2v0ZXkltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklW +atKcsWMy5WHgUyIOpwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tU +Sxfj03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZkPuXaTH4M +NMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE1LlSVHJ7liXMvGnjSG4N +0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MXQRBdJ3NghVdJIgc= +-----END CERTIFICATE----- + +Trustwave Global Certification Authority +======================================== +-----BEGIN CERTIFICATE----- +MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV +UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2 +ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTAeFw0xNzA4MjMxOTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJV +UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2 +ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALldUShLPDeS0YLOvR29 +zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0XznswuvCAAJWX/NKSqIk4cXGIDtiLK0thAf +LdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4Bq +stTnoApTAbqOl5F2brz81Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9o +WN0EACyW80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotPJqX+ +OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1lRtzuzWniTY+HKE40 +Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfwhI0Vcnyh78zyiGG69Gm7DIwLdVcE +uE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm ++9jaJXLE9gCxInm943xZYkqcBW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqj +ifLJS3tBEW1ntwiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1UdDwEB/wQEAwIB +BjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W0OhUKDtkLSGm+J1WE2pIPU/H +PinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfeuyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0H +ZJDmHvUqoai7PF35owgLEQzxPy0QlG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla +4gt5kNdXElE1GYhBaCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5R +vbbEsLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPTMaCm/zjd +zyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qequ5AvzSxnI9O4fKSTx+O +856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxhVicGaeVyQYHTtgGJoC86cnn+OjC/QezH +Yj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu +3R3y4G5OBVixwJAWKqQ9EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP +29FpHOTKyeC2nOnOcXHebD8WpHk= +-----END CERTIFICATE----- + +Trustwave Global ECC P256 Certification Authority +================================================= +-----BEGIN CERTIFICATE----- +MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYDVQQGEwJVUzER +MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy +dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1 +NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH77bOYj +43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoNFWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqm +P62jQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt +0UrrdaVKEJmzsaGLSvcwCgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjz +RM4q3wghDDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 +-----END CERTIFICATE----- + +Trustwave Global ECC P384 Certification Authority +================================================= +-----BEGIN CERTIFICATE----- +MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYDVQQGEwJVUzER +MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy +dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4 +NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGvaDXU1CDFH +Ba5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJj9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr +/TklZvFe/oyujUF5nQlgziip04pt89ZF1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNV +HQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNn +ADBkAjA3AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsCMGcl +CrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVuSw== +-----END CERTIFICATE----- + +NAVER Global Root Certification Authority +========================================= +-----BEGIN CERTIFICATE----- +MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEMBQAwaTELMAkG +A1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRGT1JNIENvcnAuMTIwMAYDVQQD +DClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4 +NDJaFw0zNzA4MTgyMzU5NTlaMGkxCzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVT +UyBQTEFURk9STSBDb3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVAiQqrDZBb +UGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH38dq6SZeWYp34+hInDEW ++j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lEHoSTGEq0n+USZGnQJoViAbbJAh2+g1G7 +XNr4rRVqmfeSVPc0W+m/6imBEtRTkZazkVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2 +aacp+yPOiNgSnABIqKYPszuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4 +Yb8ObtoqvC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHfnZ3z +VHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaGYQ5fG8Ir4ozVu53B +A0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo0es+nPxdGoMuK8u180SdOqcXYZai +cdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3aCJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejy +YhbLgGvtPe31HzClrkvJE+2KAQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNV +HQ4EFgQU0p+I36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoNqo0hV4/GPnrK +21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatjcu3cvuzHV+YwIHHW1xDBE1UB +jCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bx +hYTeodoS76TiEJd6eN4MUZeoIUCLhr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTg +E34h5prCy8VCZLQelHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTH +D8z7p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8piKCk5XQ +A76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLRLBT/DShycpWbXgnbiUSY +qqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oG +I/hGoiLtk/bdmuYqh7GYVPEi92tF4+KOdh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmg +kpzNNIaRkPpkUZ3+/uul9XXeifdy +-----END CERTIFICATE----- + +AC RAIZ FNMT-RCM SERVIDORES SEGUROS +=================================== +-----BEGIN CERTIFICATE----- +MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQswCQYDVQQGEwJF +UzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgwFgYDVQRhDA9WQVRFUy1RMjgy +NjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1SQ00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4 +MTIyMDA5MzczM1oXDTQzMTIyMDA5MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQt +UkNNMQ4wDAYDVQQLDAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNB +QyBSQUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuBBAAiA2IA +BPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LHsbI6GA60XYyzZl2hNPk2 +LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oKUm8BA06Oi6NCMEAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqG +SM49BAMDA2kAMGYCMQCuSuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoD +zBOQn5ICMQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJyv+c= +-----END CERTIFICATE----- + +GlobalSign Root R46 +=================== +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUAMEYxCzAJBgNV +BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJv +b3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAX +BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08Es +CVeJOaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQGvGIFAha/ +r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud316HCkD7rRlr+/fKYIje +2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo0q3v84RLHIf8E6M6cqJaESvWJ3En7YEt +bWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSEy132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvj +K8Cd+RTyG/FWaha/LIWFzXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD4 +12lPFzYE+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCNI/on +ccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzsx2sZy/N78CsHpdls +eVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqaByFrgY/bxFn63iLABJzjqls2k+g9 +vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEM +BQADggIBAHx47PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg +JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti2kM3S+LGteWy +gxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIkpnnpHs6i58FZFZ8d4kuaPp92 +CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRFFRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZm +OUdkLG5NrmJ7v2B0GbhWrJKsFjLtrWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qq +JZ4d16GLuc1CLgSkZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwye +qiv5u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP4vkYxboz +nxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6N3ec592kD3ZDZopD8p/7 +DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3vouXsXgxT7PntgMTzlSdriVZzH81Xwj3 +QEUxeCp6 +-----END CERTIFICATE----- + +GlobalSign Root E46 +=================== +-----BEGIN CERTIFICATE----- +MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYxCzAJBgNVBAYT +AkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJvb3Qg +RTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNV +BAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkB +jtjqR+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGddyXqBPCCj +QjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQxCpCPtsad0kRL +gLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZk +vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+ +CAezNIm8BZ/3Hobui3A= +-----END CERTIFICATE----- + +GLOBALTRUST 2020 +================ +-----BEGIN CERTIFICATE----- +MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkGA1UEBhMCQVQx +IzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVT +VCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYxMDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAh +BgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAy +MDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWi +D59bRatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9ZYybNpyrO +VPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3QWPKzv9pj2gOlTblzLmM +CcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPwyJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCm +fecqQjuCgGOlYx8ZzHyyZqjC0203b+J+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKA +A1GqtH6qRNdDYfOiaxaJSaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9OR +JitHHmkHr96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj04KlG +DfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9MedKZssCz3AwyIDMvU +clOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIwq7ejMZdnrY8XD2zHc+0klGvIg5rQ +mjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1Ud +IwQYMBaAFNwuH9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA +VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJCXtzoRlgHNQIw +4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd6IwPS3BD0IL/qMy/pJTAvoe9 +iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf+I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS +8cE54+X1+NZK3TTN+2/BT+MAi1bikvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2 +HcqtbepBEX4tdJP7wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxS +vTOBTI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6CMUO+1918 +oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn4rnvyOL2NSl6dPrFf4IF +YqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+IaFvowdlxfv1k7/9nR4hYJS8+hge9+6jl +gqispdNpQ80xiEmEU5LAsTkbOYMBMMTyqfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== +-----END CERTIFICATE----- + +ANF Secure Server Root CA +========================= +-----BEGIN CERTIFICATE----- +MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNVBAUTCUc2MzI4 +NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lv +bjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNVBAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3Qg +Q0EwHhcNMTkwOTA0MTAwMDM4WhcNMzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEw +MQswCQYDVQQGEwJFUzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQw +EgYDVQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9vdCBDQTCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCjcqQZAZ2cC4Ffc0m6p6zz +BE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9qyGFOtibBTI3/TO80sh9l2Ll49a2pcbnv +T1gdpd50IJeh7WhM3pIXS7yr/2WanvtH2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcv +B2VSAKduyK9o7PQUlrZXH1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXse +zx76W0OLzc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyRp1RM +VwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQzW7i1o0TJrH93PB0j +7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/SiOL9V8BY9KHcyi1Swr1+KuCLH5z +JTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJnLNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe +8TZBAQIvfXOn3kLMTOmJDVb3n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVO +Hj1tyRRM4y5Bu8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj +o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAOBgNVHQ8BAf8E +BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEATh65isagmD9uw2nAalxJ +UqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzx +j6ptBZNscsdW699QIyjlRRA96Gejrw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDt +dD+4E5UGUcjohybKpFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM +5gf0vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjqOknkJjCb +5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ/zo1PqVUSlJZS2Db7v54 +EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ92zg/LFis6ELhDtjTO0wugumDLmsx2d1H +hk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI+PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGy +g77FGr8H6lnco4g175x2MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3 +r5+qPeoott7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw= +-----END CERTIFICATE----- + +Certum EC-384 CA +================ +-----BEGIN CERTIFICATE----- +MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQswCQYDVQQGEwJQ +TDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2 +MDcyNDU0WhcNNDMwMzI2MDcyNDU0WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERh +dGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx +GTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATEKI6rGFtq +vm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7TmFy8as10CW4kjPMIRBSqn +iBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68KjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFI0GZnQkdjrzife81r1HfS+8EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNo +ADBlAjADVS2m5hjEfO/JUG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0 +QoSZ/6vnnvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= +-----END CERTIFICATE----- + +Certum Trusted Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6MQswCQYDVQQG +EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0g +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0Ew +HhcNMTgwMzE2MTIxMDEzWhcNNDMwMzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMY +QXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZn0EGze2jusDbCSzBfN8p +fktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/qp1x4EaTByIVcJdPTsuclzxFUl6s1wB52 +HO8AU5853BSlLCIls3Jy/I2z5T4IHhQqNwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2 +fJmItdUDmj0VDT06qKhF8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGt +g/BKEiJ3HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGamqi4 +NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi7VdNIuJGmj8PkTQk +fVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSFytKAQd8FqKPVhJBPC/PgP5sZ0jeJ +P/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0PqafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSY +njYJdmZm/Bo/6khUHL4wvYBQv3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHK +HRzQ+8S1h9E6Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1 +vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQADggIBAEii1QAL +LtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4WxmB82M+w85bj/UvXgF2Ez8s +ALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvozMrnadyHncI013nR03e4qllY/p0m+jiGPp2K +h2RX5Rc64vmNueMzeMGQ2Ljdt4NR5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8 +CYyqOhNf6DR5UMEQGfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA +4kZf5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq0Uc9Nneo +WWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7DP78v3DSk+yshzWePS/Tj +6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTMqJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmT +OPQD8rv7gmsHINFSH5pkAnuYZttcTVoP0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZck +bxJF0WddCajJFdr60qZfE2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb +-----END CERTIFICATE----- + +TunTrust Root CA +================ +-----BEGIN CERTIFICATE----- +MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQELBQAwYTELMAkG +A1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUgQ2VydGlmaWNhdGlvbiBFbGVj +dHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJvb3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQw +NDI2MDg1NzU2WjBhMQswCQYDVQQGEwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBD +ZXJ0aWZpY2F0aW9uIEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZn56eY+hz +2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd2JQDoOw05TDENX37Jk0b +bjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgFVwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7 +NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZGoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAd +gjH8KcwAWJeRTIAAHDOFli/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViW +VSHbhlnUr8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2eY8f +Tpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIbMlEsPvLfe/ZdeikZ +juXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISgjwBUFfyRbVinljvrS5YnzWuioYas +DXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwS +VXAkPcvCFDVDXSdOvsC9qnyW5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI +04Y+oXNZtPdEITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0 +90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+zxiD2BkewhpMl +0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYuQEkHDVneixCwSQXi/5E/S7fd +Ao74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRY +YdZ2vyJ/0Adqp2RT8JeNnYA/u8EH22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJp +adbGNjHh/PqAulxPxOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65x +xBzndFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5Xc0yGYuP +jCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7bnV2UqL1g52KAdoGDDIzM +MEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQCvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9z +ZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZHu/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3r +AZ3r2OvEhJn7wAzMMujjd9qDRIueVSjAi1jTkD5OGwDxFa2DK5o= +-----END CERTIFICATE----- + +HARICA TLS RSA Root CA 2021 +=========================== +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG +EwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u +cyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0EgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUz +OFoXDTQ1MDIxMzEwNTUzN1owbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRl +bWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNB +IFJvb3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569lmwVnlskN +JLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE4VGC/6zStGndLuwRo0Xu +a2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uva9of08WRiFukiZLRgeaMOVig1mlDqa2Y +Ulhu2wr7a89o+uOkXjpFc5gH6l8Cct4MpbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K +5FrZx40d/JiZ+yykgmvwKh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEv +dmn8kN3bLW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcYAuUR +0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqBAGMUuTNe3QvboEUH +GjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYqE613TBoYm5EPWNgGVMWX+Ko/IIqm +haZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHrW2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQ +CPxrvrNQKlr9qEgYRtaQQJKQCoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8G +A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAUX15QvWiWkKQU +EapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3f5Z2EMVGpdAgS1D0NTsY9FVq +QRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxajaH6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxD +QpSbIPDRzbLrLFPCU3hKTwSUQZqPJzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcR +j88YxeMn/ibvBZ3PzzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5 +vZStjBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0/L5H9MG0 +qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pTBGIBnfHAT+7hOtSLIBD6 +Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79aPib8qXPMThcFarmlwDB31qlpzmq6YR/ +PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YWxw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnn +kf3/W9b3raYvAwtt41dU63ZTGI0RmLo= +-----END CERTIFICATE----- + +HARICA TLS ECC Root CA 2021 +=========================== +-----BEGIN CERTIFICATE----- +MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQswCQYDVQQGEwJH +UjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBD +QTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoX +DTQ1MDIxMzExMDEwOVowbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWlj +IGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJv +b3QgQ0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7KKrxcm1l +AEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9YSTHMmE5gEYd103KUkE+b +ECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW +0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAi +rcJRQO9gcS3ujwLEXQNwSaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/Qw +CZ61IygNnxS2PFOiTAZpffpskcYqSUXm7LcT4Tps +-----END CERTIFICATE----- + +Autoridad de Certificacion Firmaprofesional CIF A62634068 +========================================================= +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIw +QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB +NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD +Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P +B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY +7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH +ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI +plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX +MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX +LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK +bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU +vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1Ud +DgQWBBRlzeurNR4APn7VdMActHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4w +gZswgZgGBFUdIAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j +b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABCAG8AbgBhAG4A +bwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAwADEANzAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9miWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL +4QjbEwj4KKE1soCzC1HA01aajTNFSa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDb +LIpgD7dvlAceHabJhfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1il +I45PVf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZEEAEeiGaP +cjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV1aUsIC+nmCjuRfzxuIgA +LI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2tCsvMo2ebKHTEm9caPARYpoKdrcd7b/+A +lun4jWq9GJAd/0kakFI3ky88Al2CdgtR5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH +9IBk9W6VULgRfhVwOEqwf9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpf +NIbnYrX9ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNKGbqE +ZycPvEJdvSRUDewdcAZfpLz6IHxV +-----END CERTIFICATE----- + +vTrus ECC Root CA +================= +-----BEGIN CERTIFICATE----- +MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMwRzELMAkGA1UE +BhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBS +b290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDczMTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAa +BgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYw +EAYHKoZIzj0CAQYFK4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+c +ToL0v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUde4BdS49n +TPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIwV53dVvHH4+m4SVBrm2nDb+zDfSXkV5UT +QJtS0zvzQBm8JsctBp61ezaf9SXUY2sAAjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQL +YgmRWAD5Tfs0aNoJrSEGGJTO +-----END CERTIFICATE----- + +vTrus Root CA +============= +-----BEGIN CERTIFICATE----- +MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQELBQAwQzELMAkG +A1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xFjAUBgNVBAMTDXZUcnVzIFJv +b3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMxMDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoG +A1UEChMTaVRydXNDaGluYSBDby4sTHRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZots +SKYcIrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykUAyyNJJrI +ZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+GrPSbcKvdmaVayqwlHeF +XgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z98Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KA +YPxMvDVTAWqXcoKv8R1w6Jz1717CbMdHflqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70 +kLJrxLT5ZOrpGgrIDajtJ8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2 +AXPKBlim0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZNpGvu +/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQUqqzApVg+QxMaPnu +1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHWOXSuTEGC2/KmSNGzm/MzqvOmwMVO +9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMBAAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYg +scasGrz2iTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOC +AgEAKbqSSaet8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd +nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1jbhd47F18iMjr +jld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvMKar5CKXiNxTKsbhm7xqC5PD4 +8acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIivTDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJn +xDHO2zTlJQNgJXtxmOTAGytfdELSS8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554Wg +icEFOwE30z9J4nfrI8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4 +sEb9b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNBUvupLnKW +nyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1PTi07NEPhmg4NpGaXutIc +SkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929vensBxXVsFy6K2ir40zSbofitzmdHxghm+H +l3s= +-----END CERTIFICATE----- + +ISRG Root X2 +============ +-----BEGIN CERTIFICATE----- +MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQswCQYDVQQGEwJV +UzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElT +UkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVT +MSkwJwYDVQQKEyBJbnRlcm5ldCBTZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNS +RyBSb290IFgyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0H +ttwW+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9ItgKbppb +d9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZIzj0EAwMDaAAwZQIwe3lORlCEwkSHRhtF +cP9Ymd70/aTSVaYgLXTWNLxBo1BfASdWtL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5 +U6VR5CmD1/iQMVtCnwr1/q4AaOeMSQ+2b1tbFfLn +-----END CERTIFICATE----- + +HiPKI Root CA - G1 +================== +-----BEGIN CERTIFICATE----- +MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQG +EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xGzAZBgNVBAMMEkhpUEtJ +IFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRaFw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYT +AlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kg +Um9vdCBDQSAtIEcxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0 +o9QwqNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twvVcg3Px+k +wJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6lZgRZq2XNdZ1AYDgr/SE +YYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnzQs7ZngyzsHeXZJzA9KMuH5UHsBffMNsA +GJZMoYFL3QRtU6M9/Aes1MU3guvklQgZKILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfd +hSi8MEyr48KxRURHH+CKFgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj +1jOXTyFjHluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDry+K4 +9a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ/W3c1pzAtH2lsN0/ +Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgMa/aOEmem8rJY5AIJEzypuxC00jBF +8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQD +AgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi +7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqcSE5XCV0vrPSl +tJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6FzaZsT0pPBWGTMpWmWSBUdGSquE +wx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9TcXzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07Q +JNBAsNB1CI69aO4I1258EHBGG3zgiLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv +5wiZqAxeJoBF1PhoL5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+Gpz +jLrFNe85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wrkkVbbiVg +hUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+vhV4nYWBSipX3tUZQ9rb +yltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQUYDksswBVLuT1sw5XxJFBAJw/6KXf6vb/ +yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ== +-----END CERTIFICATE----- + +GlobalSign ECC Root CA - R4 +=========================== +-----BEGIN CERTIFICATE----- +MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYDVQQLExtHbG9i +YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds +b2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgwMTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9i +YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds +b2JhbFNpZ24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkW +ymOxuYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNVHQ8BAf8E +BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/+wpu+74zyTyjhNUwCgYI +KoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147bmF0774BxL4YSFlhgjICICadVGNA3jdg +UM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm +-----END CERTIFICATE----- + +GTS Root R1 +=========== +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV +UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg +UjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE +ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM +f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7raKb0 +xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnWr4+w +B7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXW +nOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk +9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zq +kUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92wO1A +K/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om3xPX +V2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDW +cfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQAD +ggIBAJ+qQibbC5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe +QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuyh6f88/qBVRRi +ClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM47HLwEXWdyzRSjeZ2axfG34ar +J45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8JZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYci +NuaCp+0KueIHoI17eko8cdLiA6EfMgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5me +LMFrUKTX5hgUvYU/Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJF +fbdT6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ0E6yove+ +7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm2tIMPNuzjsmhDYAPexZ3 +FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bbbP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3 +gm3c +-----END CERTIFICATE----- + +GTS Root R2 +=========== +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV +UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg +UjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE +ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv +CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo7JUl +e3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWIm8Wb +a96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS ++LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7M +kogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJG +r61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RWIr9q +S34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73VululycslaVNV +J1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy5okL +dWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQAD +ggIBAB/Kzt3HvqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8 +0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyCB19m3H0Q/gxh +swWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2uNmSRXbBoGOqKYcl3qJfEycel +/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMgyALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVn +jWQye+mew4K6Ki3pHrTgSAai/GevHyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y5 +9PYjJbigapordwj6xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M +7YNRTOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924SgJPFI/2R8 +0L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV7LXTWtiBmelDGDfrs7vR +WGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjW +HYbL +-----END CERTIFICATE----- + +GTS Root R3 +=========== +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi +MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMw +HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ +R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjO +PQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout +736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24CejQjBA +MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP0/Eq +Er24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azT +L818+FsuVbu/3ZL3pAzcMeGiAjEA/JdmZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV +11RZt+cRLInUue4X +-----END CERTIFICATE----- + +GTS Root R4 +=========== +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi +MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQw +HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ +R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjO +PQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu +hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqjQjBA +MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV2Py1 +PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/C +r8deVl5c1RxYIigL9zC2L7F8AjEA8GE8p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh +4rsUecrNIdSUtUlD +-----END CERTIFICATE----- + +Telia Root CA v2 +================ +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQxCzAJBgNVBAYT +AkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2 +MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQK +DBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ7 +6zBqAMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9vVYiQJ3q +9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9lRdU2HhE8Qx3FZLgmEKn +pNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTODn3WhUidhOPFZPY5Q4L15POdslv5e2QJl +tI5c0BE0312/UqeBAMN/mUWZFdUXyApT7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW +5olWK8jjfN7j/4nlNW4o6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNr +RBH0pUPCTEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6WT0E +BXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63RDolUK5X6wK0dmBR4 +M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZIpEYslOqodmJHixBTB0hXbOKSTbau +BcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGjYzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7W +xy+G2CQ5MB0GA1UdDgQWBBRyrOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ +8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi0f6X+J8wfBj5 +tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMMA8iZGok1GTzTyVR8qPAs5m4H +eW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBSSRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+C +y748fdHif64W1lZYudogsYMVoe+KTTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygC +QMez2P2ccGrGKMOF6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15 +h2Er3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMtTy3EHD70 +sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pTVmBds9hCG1xLEooc6+t9 +xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAWysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQ +raVplI/owd8k+BsHMYeB2F326CjYSlKArBPuUBQemMc= +-----END CERTIFICATE----- + +D-TRUST BR Root CA 1 2020 +========================= +-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE +RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEJSIFJvb3QgQ0EgMSAy +MDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNV +BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7 +dPYSzuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0QVK5buXu +QqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/VbNafAkl1bK6CKBrqx9t +MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu +bmV0L2NybC9kLXRydXN0X2JyX3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP +PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD +AwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFWwKrY7RjEsK70Pvom +AjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHVdWNbFJWcHwHP2NVypw87 +-----END CERTIFICATE----- + +D-TRUST EV Root CA 1 2020 +========================= +-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE +RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEVWIFJvb3QgQ0EgMSAy +MDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNV +BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8 +ZRCC/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rDwpdhQntJ +raOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3OqQo5FD4pPfsazK2/umL +MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu +bmV0L2NybC9kLXRydXN0X2V2X3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP +PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD +AwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CAy/m0sRtW9XLS/BnR +AjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJbgfM0agPnIjhQW+0ZT0MW +-----END CERTIFICATE----- + +DigiCert TLS ECC P384 Root G5 +============================= +-----BEGIN CERTIFICATE----- +MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURpZ2lDZXJ0IFRMUyBFQ0MgUDM4 +NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMx +FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQg +Um9vdCBHNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1Tzvd +lHJS7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp0zVozptj +n4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICISB4CIfBFqMA4GA1UdDwEB +/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQCJao1H5+z8blUD2Wds +Jk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQLgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIx +AJSdYsiJvRmEFOml+wG4DXZDjC5Ty3zfDBeWUA== +-----END CERTIFICATE----- + +DigiCert TLS RSA4096 Root G5 +============================ +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBNMQswCQYDVQQG +EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0 +MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcNNDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2 +IFJvb3QgRzUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS8 +7IE+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG02C+JFvuU +AT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgpwgscONyfMXdcvyej/Ces +tyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZMpG2T6T867jp8nVid9E6P/DsjyG244gXa +zOvswzH016cpVIDPRFtMbzCe88zdH5RDnU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnV +DdXifBBiqmvwPXbzP6PosMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9q +TXeXAaDxZre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cdLvvy +z6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvXKyY//SovcfXWJL5/ +MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNeXoVPzthwiHvOAbWWl9fNff2C+MIk +wcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPLtgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4E +FgQUUTMc7TZArxfTJc1paPKvTiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw +GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7HPNtQOa27PShN +lnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLFO4uJ+DQtpBflF+aZfTCIITfN +MBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQREtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/ +u4cnYiWB39yhL/btp/96j1EuMPikAdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9G +OUrYU9DzLjtxpdRv/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh +47a+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilwMUc/dNAU +FvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WFqUITVuwhd4GTWgzqltlJ +yqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCKovfepEWFJqgejF0pW8hL2JpqA15w8oVP +bEtoL8pU9ozaMv7Da4M/OMZ+ +-----END CERTIFICATE----- + +Certainly Root R1 +================= +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAwPTELMAkGA1UE +BhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2VydGFpbmx5IFJvb3QgUjEwHhcN +MjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2Vy +dGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBANA21B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O +5MQTvqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbedaFySpvXl +8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b01C7jcvk2xusVtyWMOvwl +DbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGI +XsXwClTNSaa/ApzSRKft43jvRl5tcdF5cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkN +KPl6I7ENPT2a/Z2B7yyQwHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQ +AjeZjOVJ6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA2Cnb +rlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyHWyf5QBGenDPBt+U1 +VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMReiFPCyEQtkA6qyI6BJyLm4SGcprS +p6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBTgqj8ljZ9EXME66C6ud0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAsz +HQNTVfSVcOQrPbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d +8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi1wrykXprOQ4v +MMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrdrRT90+7iIgXr0PK3aBLXWopB +GsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9ditaY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+ +gjwN/KUD+nsa2UUeYNrEjvn8K8l7lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgH +JBu6haEaBQmAupVjyTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7 +fpYnKx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLyyCwzk5Iw +x06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5nwXARPbv0+Em34yaXOp/S +X3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6OV+KmalBWQewLK8= +-----END CERTIFICATE----- + +Certainly Root E1 +================= +-----BEGIN CERTIFICATE----- +MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQswCQYDVQQGEwJV +UzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBFMTAeFw0yMTA0 +MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlu +bHkxGjAYBgNVBAMTEUNlcnRhaW5seSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4 +fxzf7flHh4axpMCK+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9 +YBk2QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4hevIIgcwCgYIKoZIzj0E +AwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozmut6Dacpps6kFtZaSF4fC0urQe87YQVt8 +rgIwRt7qy12a7DLCZRawTDBcMPPaTnOGBtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR +-----END CERTIFICATE----- + +E-Tugra Global Root CA RSA v3 +============================= +-----BEGIN CERTIFICATE----- +MIIF8zCCA9ugAwIBAgIUDU3FzRYilZYIfrgLfxUGNPt5EDQwDQYJKoZIhvcNAQELBQAwgYAxCzAJ +BgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAb +BgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290 +IENBIFJTQSB2MzAeFw0yMDAzMTgwOTA3MTdaFw00NTAzMTIwOTA3MTdaMIGAMQswCQYDVQQGEwJU +UjEPMA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRF +LVR1Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBSU0Eg +djMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCiZvCJt3J77gnJY9LTQ91ew6aEOErx +jYG7FL1H6EAX8z3DeEVypi6Q3po61CBxyryfHUuXCscxuj7X/iWpKo429NEvx7epXTPcMHD4QGxL +sqYxYdE0PD0xesevxKenhOGXpOhL9hd87jwH7eKKV9y2+/hDJVDqJ4GohryPUkqWOmAalrv9c/SF +/YP9f4RtNGx/ardLAQO/rWm31zLZ9Vdq6YaCPqVmMbMWPcLzJmAy01IesGykNz709a/r4d+ABs8q +QedmCeFLl+d3vSFtKbZnwy1+7dZ5ZdHPOrbRsV5WYVB6Ws5OUDGAA5hH5+QYfERaxqSzO8bGwzrw +bMOLyKSRBfP12baqBqG3q+Sx6iEUXIOk/P+2UNOMEiaZdnDpwA+mdPy70Bt4znKS4iicvObpCdg6 +04nmvi533wEKb5b25Y08TVJ2Glbhc34XrD2tbKNSEhhw5oBOM/J+JjKsBY04pOZ2PJ8QaQ5tndLB +eSBrW88zjdGUdjXnXVXHt6woq0bM5zshtQoK5EpZ3IE1S0SVEgpnpaH/WwAH0sDM+T/8nzPyAPiM +bIedBi3x7+PmBvrFZhNb/FAHnnGGstpvdDDPk1Po3CLW3iAfYY2jLqN4MpBs3KwytQXk9TwzDdbg +h3cXTJ2w2AmoDVf3RIXwyAS+XF1a4xeOVGNpf0l0ZAWMowIDAQABo2MwYTAPBgNVHRMBAf8EBTAD +AQH/MB8GA1UdIwQYMBaAFLK0ruYt9ybVqnUtdkvAG1Mh0EjvMB0GA1UdDgQWBBSytK7mLfcm1ap1 +LXZLwBtTIdBI7zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAImocn+M684uGMQQ +gC0QDP/7FM0E4BQ8Tpr7nym/Ip5XuYJzEmMmtcyQ6dIqKe6cLcwsmb5FJ+Sxce3kOJUxQfJ9emN4 +38o2Fi+CiJ+8EUdPdk3ILY7r3y18Tjvarvbj2l0Upq7ohUSdBm6O++96SmotKygY/r+QLHUWnw/q +ln0F7psTpURs+APQ3SPh/QMSEgj0GDSz4DcLdxEBSL9htLX4GdnLTeqjjO/98Aa1bZL0SmFQhO3s +SdPkvmjmLuMxC1QLGpLWgti2omU8ZgT5Vdps+9u1FGZNlIM7zR6mK7L+d0CGq+ffCsn99t2HVhjY +sCxVYJb6CH5SkPVLpi6HfMsg2wY+oF0Dd32iPBMbKaITVaA9FCKvb7jQmhty3QUBjYZgv6Rn7rWl +DdF/5horYmbDB7rnoEgcOMPpRfunf/ztAmgayncSd6YAVSgU7NbHEqIbZULpkejLPoeJVF3Zr52X +nGnnCv8PWniLYypMfUeUP95L6VPQMPHF9p5J3zugkaOj/s1YzOrfr28oO6Bpm4/srK4rVJ2bBLFH +IK+WEj5jlB0E5y67hscMmoi/dkfv97ALl2bSRM9gUgfh1SxKOidhd8rXj+eHDjD/DLsE4mHDosiX +YY60MGo8bcIHX0pzLz/5FooBZu+6kcpSV3uu1OYP3Qt6f4ueJiDPO++BcYNZ +-----END CERTIFICATE----- + +E-Tugra Global Root CA ECC v3 +============================= +-----BEGIN CERTIFICATE----- +MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMwgYAxCzAJBgNV +BAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAbBgNV +BAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENB +IEVDQyB2MzAeFw0yMDAzMTgwOTQ2NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEP +MA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1 +Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBFQ0MgdjMw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQKczLWYHMjLiSF4mDKpL2 +w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YKfWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31 +Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQ +zPUwHQYDVR0OBBYEFP+CMXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO +PQQDAwNpADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/67W4W +Aie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFxvmjkI6TZraE3 +-----END CERTIFICATE----- + +Security Communication RootCA3 +============================== +-----BEGIN CERTIFICATE----- +MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNVBAYTAkpQMSUw +IwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQDEx5TZWN1cml0eSBD +b21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQsw +CQYDVQQGEwJKUDElMCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UE +AxMeU2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4rCmDvu20r +hvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzAlrenfna84xtSGc4RHwsE +NPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MGTfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2 +/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF79+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGm +npjKIG58u4iFW/vAEGK78vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtY +XLVqAvO4g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3weGVPK +p7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst+3A7caoreyYn8xrC +3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M0V9hvqG8OmpI6iZVIhZdXw3/JzOf +GAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQT9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0Vcw +CBEF/VfR2ccCAwEAAaNCMEAwHQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB +/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS +YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PAFNr0Y/Dq9HHu +Tofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd9XbXv8S2gVj/yP9kaWJ5rW4O +H3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQIUYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASx +YfQAW0q3nHE3GYV5v4GwxxMOdnE+OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZ +XSEIx2C/pHF7uNkegr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml ++LLfiAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUVnuiZIesn +KwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD2NCcnWXL0CsnMQMeNuE9 +dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI//1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm +6Vwdp6POXiUyK+OVrCoHzrQoeIY8LaadTdJ0MN1kURXbg4NR16/9M51NZg== +-----END CERTIFICATE----- + +Security Communication ECC RootCA1 +================================== +-----BEGIN CERTIFICATE----- +MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYTAkpQMSUwIwYD +VQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYDVQQDEyJTZWN1cml0eSBDb21t +dW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYxNjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTEL +MAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNV +BAMTIlNlY3VyaXR5IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+CnnfdldB9sELLo +5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpKULGjQjBAMB0GA1UdDgQW +BBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAK +BggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3L +snNdo4gIxwwCMQDAqy0Obe0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70e +N9k= +-----END CERTIFICATE----- diff --git a/components/mbedtls/mbedtls_v3/esp_crt_bundle/cacrt_local.pem b/components/mbedtls/mbedtls_v3/esp_crt_bundle/cacrt_local.pem new file mode 100644 index 000000000..3633ed161 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/esp_crt_bundle/cacrt_local.pem @@ -0,0 +1,33 @@ +## +## Local CA Root Certificates +## +## Local CA Root Certificates that gets appended to "cacrt_all.pem" + + +## letsencrypt has generated a cross signed certificate with DST ROOT CA X3 +## for compatibility after the expiry of the certificate. +## The new certificate has the ISSUER name as DST Root CA X3. +## Thus, the handshake fails if esp_crt_bundle does not find the +## respective name in the crt_bundle. +## Keeping this certificate for compatibility reasons. +## This will be removed once the cross-signed certificate expires in Sep 2024. + +DST Root CA X3 +============== +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK +ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X +DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1 +cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT +rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9 +UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy +xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d +utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ +MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug +dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE +GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw +RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS +fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- diff --git a/components/mbedtls/mbedtls_v3/esp_crt_bundle/cmn_crt_authorities.csv b/components/mbedtls/mbedtls_v3/esp_crt_bundle/cmn_crt_authorities.csv new file mode 100644 index 000000000..0e10c7013 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/esp_crt_bundle/cmn_crt_authorities.csv @@ -0,0 +1,42 @@ +Owner,Common Name or Certificate Name +Amazon Trust Services,Amazon Root CA 1 +Amazon Trust Services,Amazon Root CA 2 +Amazon Trust Services,Amazon Root CA 3 +Amazon Trust Services,Amazon Root CA 4 +Amazon Trust Services,Starfield Services Root Certificate Authority - G2 +DigiCert,Baltimore CyberTrust Root +DigiCert,DigiCert Assured ID Root CA +DigiCert,DigiCert Assured ID Root G2 +DigiCert,DigiCert Assured ID Root G3 +DigiCert,DigiCert Global Root CA +DigiCert,DigiCert Global Root G2 +DigiCert,DigiCert Global Root G3 +DigiCert,DigiCert High Assurance EV Root CA +DigiCert,DigiCert TLS ECC P384 Root G5 +DigiCert,DigiCert TLS RSA4096 Root G5 +DigiCert,DigiCert Trusted Root G4 +GlobalSign nv-sa,GlobalSign Root CA - R3 +GlobalSign nv-sa,GlobalSign ECC Root CA - R5 +GlobalSign nv-sa,GlobalSign Root CA - R6 +GlobalSign nv-sa,GlobalSign Root CA +GlobalSign nv-sa,GlobalSign Root E46 +GlobalSign nv-sa,GlobalSign Root R46 +GoDaddy,Go Daddy Class 2 CA +GoDaddy,Go Daddy Root Certificate Authority - G2 +GoDaddy,Starfield Class 2 CA +GoDaddy,Starfield Root Certificate Authority - G2 +Google Trust Services LLC,GlobalSign ECC Root CA - R4 +Google Trust Services LLC,GTS Root R1 +Google Trust Services LLC,GTS Root R2 +Google Trust Services LLC,GTS Root R3 +Google Trust Services LLC,GTS Root R4 +"IdenTrust Services, LLC",DST Root CA X3 +"IdenTrust Services, LLC",IdenTrust Commercial Root CA 1 +"IdenTrust Services, LLC",IdenTrust Public Sector Root CA 1 +Internet Security Research Group,ISRG Root X1 +Internet Security Research Group,ISRG Root X2 +Sectigo,COMODO Certification Authority +Sectigo,COMODO ECC Certification Authority +Sectigo,COMODO RSA Certification Authority +Sectigo,USERTrust ECC Certification Authority +Sectigo,USERTrust RSA Certification Authority diff --git a/components/mbedtls/mbedtls_v3/esp_crt_bundle/esp_crt_bundle.c b/components/mbedtls/mbedtls_v3/esp_crt_bundle/esp_crt_bundle.c new file mode 100644 index 000000000..e1b042b8c --- /dev/null +++ b/components/mbedtls/mbedtls_v3/esp_crt_bundle/esp_crt_bundle.c @@ -0,0 +1,244 @@ +/* + * SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "esp_crt_bundle.h" +#include "esp_log.h" + +#define BUNDLE_HEADER_OFFSET 2 +#define CRT_HEADER_OFFSET 4 + +static const char *TAG = "esp-x509-crt-bundle"; + +/* a dummy certificate so that + * cacert_ptr passes non-NULL check during handshake */ +static const mbedtls_x509_crt s_dummy_crt; + +extern const uint8_t x509_crt_imported_bundle_bin_start[] asm("_binary_x509_crt_bundle_start"); +extern const uint8_t x509_crt_imported_bundle_bin_end[] asm("_binary_x509_crt_bundle_end"); + + +typedef struct crt_bundle_t { + const uint8_t **crts; + uint16_t num_certs; + size_t x509_crt_bundle_len; +} crt_bundle_t; + +static crt_bundle_t s_crt_bundle; + +static int esp_crt_check_signature(mbedtls_x509_crt *child, const uint8_t *pub_key_buf, size_t pub_key_len); + + +static int esp_crt_check_signature(mbedtls_x509_crt *child, const uint8_t *pub_key_buf, size_t pub_key_len) +{ + int ret = 0; + mbedtls_x509_crt parent; + const mbedtls_md_info_t *md_info; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + + mbedtls_x509_crt_init(&parent); + + if ( (ret = mbedtls_pk_parse_public_key(&parent.pk, pub_key_buf, pub_key_len) ) != 0) { + ESP_LOGE(TAG, "PK parse failed with error %X", ret); + goto cleanup; + } + + + // Fast check to avoid expensive computations when not necessary + if (!mbedtls_pk_can_do(&parent.pk, child->MBEDTLS_PRIVATE(sig_pk))) { + ESP_LOGE(TAG, "Simple compare failed"); + ret = -1; + goto cleanup; + } + + md_info = mbedtls_md_info_from_type(child->MBEDTLS_PRIVATE(sig_md)); + if ( (ret = mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash )) != 0 ) { + ESP_LOGE(TAG, "Internal mbedTLS error %X", ret); + goto cleanup; + } + + if ( (ret = mbedtls_pk_verify_ext( child->MBEDTLS_PRIVATE(sig_pk), child->MBEDTLS_PRIVATE(sig_opts), &parent.pk, + child->MBEDTLS_PRIVATE(sig_md), hash, mbedtls_md_get_size( md_info ), + child->MBEDTLS_PRIVATE(sig).p, child->MBEDTLS_PRIVATE(sig).len )) != 0 ) { + + ESP_LOGE(TAG, "PK verify failed with error %X", ret); + goto cleanup; + } +cleanup: + mbedtls_x509_crt_free(&parent); + + return ret; +} + + +/* This callback is called for every certificate in the chain. If the chain + * is proper each intermediate certificate is validated through its parent + * in the x509_crt_verify_chain() function. So this callback should + * only verify the first untrusted link in the chain is signed by the + * root certificate in the trusted bundle +*/ +int esp_crt_verify_callback(void *buf, mbedtls_x509_crt *crt, int depth, uint32_t *flags) +{ + mbedtls_x509_crt *child = crt; + + /* It's OK for a trusted cert to have a weak signature hash alg. + as we already trust this certificate */ + uint32_t flags_filtered = *flags & ~(MBEDTLS_X509_BADCERT_BAD_MD); + + if (flags_filtered != MBEDTLS_X509_BADCERT_NOT_TRUSTED) { + return 0; + } + + + if (s_crt_bundle.crts == NULL) { + ESP_LOGE(TAG, "No certificates in bundle"); + return MBEDTLS_ERR_X509_FATAL_ERROR; + } + + ESP_LOGD(TAG, "%d certificates in bundle", s_crt_bundle.num_certs); + + size_t name_len = 0; + const uint8_t *crt_name; + + bool crt_found = false; + int start = 0; + int end = s_crt_bundle.num_certs - 1; + int middle = (end - start) / 2; + + /* Look for the certificate using binary search on subject name */ + while (start <= end) { + name_len = s_crt_bundle.crts[middle][0] << 8 | s_crt_bundle.crts[middle][1]; + crt_name = s_crt_bundle.crts[middle] + CRT_HEADER_OFFSET; + + int cmp_res = memcmp(child->issuer_raw.p, crt_name, name_len ); + if (cmp_res == 0) { + crt_found = true; + break; + } else if (cmp_res < 0) { + end = middle - 1; + } else { + start = middle + 1; + } + middle = (start + end) / 2; + } + + int ret = MBEDTLS_ERR_X509_FATAL_ERROR; + if (crt_found) { + size_t key_len = s_crt_bundle.crts[middle][2] << 8 | s_crt_bundle.crts[middle][3]; + ret = esp_crt_check_signature(child, s_crt_bundle.crts[middle] + CRT_HEADER_OFFSET + name_len, key_len); + } + + if (ret == 0) { + ESP_LOGI(TAG, "Certificate validated"); + *flags = 0; + return 0; + } + + ESP_LOGE(TAG, "Failed to verify certificate"); + return MBEDTLS_ERR_X509_FATAL_ERROR; +} + + +/* Initialize the bundle into an array so we can do binary search for certs, + the bundle generated by the python utility is already presorted by subject name + */ +static esp_err_t esp_crt_bundle_init(const uint8_t *x509_bundle, size_t bundle_size) +{ + if (bundle_size < BUNDLE_HEADER_OFFSET + CRT_HEADER_OFFSET) { + ESP_LOGE(TAG, "Invalid certificate bundle"); + return ESP_ERR_INVALID_ARG; + } + + uint16_t num_certs = (x509_bundle[0] << 8) | x509_bundle[1]; + if (num_certs > CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS) { + ESP_LOGE(TAG, "No. of certs in the certificate bundle = %d exceeds\n" + "Max allowed certificates in the certificate bundle = %d\n" + "Please update the menuconfig option with appropriate value", num_certs, CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS); + return ESP_ERR_INVALID_ARG; + } + + const uint8_t **crts = calloc(num_certs, sizeof(x509_bundle)); + if (crts == NULL) { + ESP_LOGE(TAG, "Unable to allocate memory for bundle"); + return ESP_ERR_NO_MEM; + } + + const uint8_t *cur_crt; + /* This is the maximum region that is allowed to access */ + const uint8_t *bundle_end = x509_bundle + bundle_size; + cur_crt = x509_bundle + BUNDLE_HEADER_OFFSET; + + for (int i = 0; i < num_certs; i++) { + crts[i] = cur_crt; + if (cur_crt + CRT_HEADER_OFFSET > bundle_end) { + ESP_LOGE(TAG, "Invalid certificate bundle"); + free(crts); + return ESP_ERR_INVALID_ARG; + } + size_t name_len = cur_crt[0] << 8 | cur_crt[1]; + size_t key_len = cur_crt[2] << 8 | cur_crt[3]; + cur_crt = cur_crt + CRT_HEADER_OFFSET + name_len + key_len; + } + + if (cur_crt > bundle_end) { + ESP_LOGE(TAG, "Invalid certificate bundle"); + free(crts); + return ESP_ERR_INVALID_ARG; + } + + /* The previous crt bundle is only updated when initialization of the + * current crt_bundle is successful */ + /* Free previous crt_bundle */ + free(s_crt_bundle.crts); + s_crt_bundle.num_certs = num_certs; + s_crt_bundle.crts = crts; + return ESP_OK; +} + +esp_err_t esp_crt_bundle_attach(void *conf) +{ + esp_err_t ret = ESP_OK; + // If no bundle has been set by the user then use the bundle embedded in the binary + if (s_crt_bundle.crts == NULL) { + ret = esp_crt_bundle_init(x509_crt_imported_bundle_bin_start, x509_crt_imported_bundle_bin_end - x509_crt_imported_bundle_bin_start); + } + + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to attach bundle"); + return ret; + } + + if (conf) { + /* point to a dummy certificate + * This is only required so that the + * cacert_ptr passes non-NULL check during handshake + */ + mbedtls_ssl_config *ssl_conf = (mbedtls_ssl_config *)conf; + mbedtls_ssl_conf_ca_chain(ssl_conf, (mbedtls_x509_crt*)&s_dummy_crt, NULL); + mbedtls_ssl_conf_verify(ssl_conf, esp_crt_verify_callback, NULL); + } + + return ret; +} + +void esp_crt_bundle_detach(mbedtls_ssl_config *conf) +{ + free(s_crt_bundle.crts); + s_crt_bundle.crts = NULL; + if (conf) { + mbedtls_ssl_conf_verify(conf, NULL, NULL); + } +} + +esp_err_t esp_crt_bundle_set(const uint8_t *x509_bundle, size_t bundle_size) +{ + return esp_crt_bundle_init(x509_bundle, bundle_size); +} + +bool esp_crt_bundle_in_use(const mbedtls_x509_crt* ca_chain) +{ + return ((ca_chain == &s_dummy_crt) ? true : false); +} diff --git a/components/mbedtls/mbedtls_v3/esp_crt_bundle/gen_crt_bundle.py b/components/mbedtls/mbedtls_v3/esp_crt_bundle/gen_crt_bundle.py new file mode 100755 index 000000000..0211514a4 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/esp_crt_bundle/gen_crt_bundle.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python +# +# ESP32 x509 certificate bundle generation utility +# +# Converts PEM and DER certificates to a custom bundle format which stores just the +# subject name and public key to reduce space +# +# The bundle will have the format: number of certificates; crt 1 subject name length; crt 1 public key length; +# crt 1 subject name; crt 1 public key; crt 2... +# +# SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import with_statement + +import argparse +import csv +import os +import re +import struct +import sys +from io import open + +try: + from cryptography import x509 + from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives import serialization +except ImportError: + print('The cryptography package is not installed.' + 'Please refer to the Get Started section of the ESP-IDF Programming Guide for ' + 'setting up the required packages.') + raise + +ca_bundle_bin_file = 'x509_crt_bundle' + +quiet = False + + +def status(msg): + """ Print status message to stderr """ + if not quiet: + critical(msg) + + +def critical(msg): + """ Print critical message to stderr """ + sys.stderr.write('gen_crt_bundle.py: ') + sys.stderr.write(msg) + sys.stderr.write('\n') + + +class CertificateBundle: + def __init__(self): + self.certificates = [] + self.compressed_crts = [] + + if os.path.isfile(ca_bundle_bin_file): + os.remove(ca_bundle_bin_file) + + def add_from_path(self, crts_path): + + found = False + for file_path in os.listdir(crts_path): + found |= self.add_from_file(os.path.join(crts_path, file_path)) + + if found is False: + raise InputError('No valid x509 certificates found in %s' % crts_path) + + def add_from_file(self, file_path): + try: + if file_path.endswith('.pem'): + status('Parsing certificates from %s' % file_path) + with open(file_path, 'r', encoding='utf-8') as f: + crt_str = f.read() + self.add_from_pem(crt_str) + return True + + elif file_path.endswith('.der'): + status('Parsing certificates from %s' % file_path) + with open(file_path, 'rb') as f: + crt_str = f.read() + self.add_from_der(crt_str) + return True + + except ValueError: + critical('Invalid certificate in %s' % file_path) + raise InputError('Invalid certificate') + + return False + + def add_from_pem(self, crt_str): + """ A single PEM file may have multiple certificates """ + + crt = '' + count = 0 + start = False + + for strg in crt_str.splitlines(True): + if strg == '-----BEGIN CERTIFICATE-----\n' and start is False: + crt = '' + start = True + elif strg == '-----END CERTIFICATE-----\n' and start is True: + crt += strg + '\n' + start = False + self.certificates.append(x509.load_pem_x509_certificate(crt.encode(), default_backend())) + count += 1 + if start is True: + crt += strg + + if count == 0: + raise InputError('No certificate found') + + status('Successfully added %d certificates' % count) + + def add_from_der(self, crt_str): + self.certificates.append(x509.load_der_x509_certificate(crt_str, default_backend())) + status('Successfully added 1 certificate') + + def create_bundle(self): + # Sort certificates in order to do binary search when looking up certificates + self.certificates = sorted(self.certificates, key=lambda cert: cert.subject.public_bytes(default_backend())) + + bundle = struct.pack('>H', len(self.certificates)) + + for crt in self.certificates: + """ Read the public key as DER format """ + pub_key = crt.public_key() + pub_key_der = pub_key.public_bytes(serialization.Encoding.DER, serialization.PublicFormat.SubjectPublicKeyInfo) + + """ Read the subject name as DER format """ + sub_name_der = crt.subject.public_bytes(default_backend()) + + name_len = len(sub_name_der) + key_len = len(pub_key_der) + len_data = struct.pack('>HH', name_len, key_len) + + bundle += len_data + bundle += sub_name_der + bundle += pub_key_der + + return bundle + + def add_with_filter(self, crts_path, filter_path): + + filter_set = set() + with open(filter_path, 'r', encoding='utf-8') as f: + csv_reader = csv.reader(f, delimiter=',') + + # Skip header + next(csv_reader) + for row in csv_reader: + filter_set.add(row[1]) + + status('Parsing certificates from %s' % crts_path) + crt_str = [] + with open(crts_path, 'r', encoding='utf-8') as f: + crt_str = f.read() + + # Split all certs into a list of (name, certificate string) tuples + pem_crts = re.findall(r'(^.+?)\n(=+\n[\s\S]+?END CERTIFICATE-----\n)', crt_str, re.MULTILINE) + + filtered_crts = '' + for name, crt in pem_crts: + if name in filter_set: + filtered_crts += crt + + self.add_from_pem(filtered_crts) + + +class InputError(RuntimeError): + def __init__(self, e): + super(InputError, self).__init__(e) + + +def main(): + global quiet + + parser = argparse.ArgumentParser(description='ESP-IDF x509 certificate bundle utility') + + parser.add_argument('--quiet', '-q', help="Don't print non-critical status messages to stderr", action='store_true') + parser.add_argument('--input', '-i', nargs='+', required=True, + help='Paths to the custom certificate folders or files to parse, parses all .pem or .der files') + parser.add_argument('--filter', '-f', help='Path to CSV-file where the second columns contains the name of the certificates \ + that should be included from cacrt_all.pem') + + args = parser.parse_args() + + quiet = args.quiet + + bundle = CertificateBundle() + + for path in args.input: + if os.path.isfile(path): + if os.path.basename(path) == 'cacrt_all.pem' and args.filter: + bundle.add_with_filter(path, args.filter) + else: + bundle.add_from_file(path) + elif os.path.isdir(path): + bundle.add_from_path(path) + else: + raise InputError('Invalid --input=%s, is neither file nor folder' % args.input) + + status('Successfully added %d certificates in total' % len(bundle.certificates)) + + crt_bundle = bundle.create_bundle() + + with open(ca_bundle_bin_file, 'wb') as f: + f.write(crt_bundle) + + +if __name__ == '__main__': + try: + main() + except InputError as e: + print(e) + sys.exit(2) diff --git a/components/mbedtls/mbedtls_v3/esp_crt_bundle/include/esp_crt_bundle.h b/components/mbedtls/mbedtls_v3/esp_crt_bundle/include/esp_crt_bundle.h new file mode 100644 index 000000000..61c09f0bd --- /dev/null +++ b/components/mbedtls/mbedtls_v3/esp_crt_bundle/include/esp_crt_bundle.h @@ -0,0 +1,76 @@ +/* + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#ifndef _ESP_CRT_BUNDLE_H_ +#define _ESP_CRT_BUNDLE_H_ + +#include "esp_err.h" +#include "mbedtls/ssl.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Attach and enable use of a bundle for certificate verification + * + * Attach and enable use of a bundle for certificate verification through a verification callback. + * If no specific bundle has been set through esp_crt_bundle_set() it will default to the + * bundle defined in menuconfig and embedded in the binary. + * + * @param[in] conf The config struct for the SSL connection. + * + * @return + * - ESP_OK if adding certificates was successful. + * - Other if an error occurred or an action must be taken by the calling process. + */ +esp_err_t esp_crt_bundle_attach(void *conf); + + +/** + * @brief Disable and dealloc the certification bundle + * + * Removes the certificate verification callback and deallocates used resources + * + * @param[in] conf The config struct for the SSL connection. + */ +void esp_crt_bundle_detach(mbedtls_ssl_config *conf); + + +/** + * @brief Set the default certificate bundle used for verification + * + * Overrides the default certificate bundle only in case of successful initialization. In most use cases the bundle should be + * set through menuconfig. The bundle needs to be sorted by subject name since binary search is + * used to find certificates. + * + * @param[in] x509_bundle A pointer to the certificate bundle. + * + * @param[in] bundle_size Size of the certificate bundle in bytes. + * + * @return + * - ESP_OK if adding certificates was successful. + * - Other if an error occurred or an action must be taken by the calling process. + */ +esp_err_t esp_crt_bundle_set(const uint8_t *x509_bundle, size_t bundle_size); + +/** + * @brief Check if the given CA certificate chain is the default "dummy" + * certificate chain attached by the esp_crt_bundle + * + * @param ca_chain A pointer to the CA chain. + * @return true if the ca_chain is the dummy CA chain attached by esp_crt_bundle + * @return false otherwise + */ +bool esp_crt_bundle_in_use(const mbedtls_x509_crt* ca_chain); + +#ifdef __cplusplus +} +#endif + +#endif //_ESP_CRT_BUNDLE_H_ diff --git a/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/baltimore.der b/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/baltimore.der new file mode 100644 index 000000000..da96dbb2c Binary files /dev/null and b/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/baltimore.der differ diff --git a/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/baltimore_crt_bundle b/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/baltimore_crt_bundle new file mode 100644 index 000000000..070685894 Binary files /dev/null and b/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/baltimore_crt_bundle differ diff --git a/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/entrust.pem b/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/entrust.pem new file mode 100644 index 000000000..82e3bc0bf --- /dev/null +++ b/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/entrust.pem @@ -0,0 +1,25 @@ +Entrust Root Certification Authority +==================================== +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw +b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG +A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 +MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu +MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu +Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz +A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww +Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 +j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN +rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 +MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH +hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM +Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa +v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS +W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 +tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- diff --git a/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/entrust_crt_bundle b/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/entrust_crt_bundle new file mode 100644 index 000000000..cc20092c0 Binary files /dev/null and b/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/entrust_crt_bundle differ diff --git a/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/invalid_crt.pem b/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/invalid_crt.pem new file mode 100644 index 000000000..6bd1a0920 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/invalid_crt.pem @@ -0,0 +1,25 @@ +Entrust Root Certification Authority +==================================== +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw +b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG +A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 +MloXDTI2MTEyNzIwNTM0MFFwgFFxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu +MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu +Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz +A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww +Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 +j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN +rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 +MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH +hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBFFDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM +Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxR22IkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa +v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi447pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS +W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 +tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- diff --git a/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/non_ascii_crt.pem b/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/non_ascii_crt.pem new file mode 100644 index 000000000..10ad8a1ca --- /dev/null +++ b/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/non_ascii_crt.pem @@ -0,0 +1,23 @@ +NetLock Arany (Class Gold) Főtanúsítvány +======================================== +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G +A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 +dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB +cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx +MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO +ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 +c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu +0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw +/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk +H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw +fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 +neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW +qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta +YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna +NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu +dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- diff --git a/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/test_gen_crt_bundle.py b/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/test_gen_crt_bundle.py new file mode 100755 index 000000000..4ad3b72b9 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/esp_crt_bundle/test_gen_crt_bundle/test_gen_crt_bundle.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python + +import os +import sys +import unittest + +try: + import gen_crt_bundle +except ImportError: + sys.path.append('..') + import gen_crt_bundle + + +idf_path = os.environ['IDF_PATH'] +ca_crts_path = idf_path + '/components/mbedtls/esp_crt_bundle/' +test_crts_path = idf_path + '/components/mbedtls/esp_crt_bundle/test_gen_crt_bundle/' + +ca_bundle_bin_file = 'x509_crt_bundle' + +der_test_file = 'baltimore.der' +pem_test_file = 'entrust.pem' +verified_der_bundle = 'baltimore_crt_bundle' +verified_pem_bundle = 'entrust_crt_bundle' +invalid_test_file = 'invalid_crt.pem' +non_ascii_file = 'non_ascii_crt.pem' +ca_crts_all_file = 'cacrt_all.pem' + + +class Py23TestCase(unittest.TestCase): + + def __init__(self, *args, **kwargs): + super(Py23TestCase, self).__init__(*args, **kwargs) + try: + self.assertRaisesRegex + except AttributeError: + # assertRaisesRegexp is deprecated in Python3 but assertRaisesRegex doesn't exist in Python2 + # This fix is used in order to avoid using the alias from the six library + self.assertRaisesRegex = self.assertRaisesRegexp + + +class GenCrtBundleTests(Py23TestCase): + + # Verify generation from der vs known certificate + def test_gen_from_der(self): + bundle = gen_crt_bundle.CertificateBundle() + bundle.add_from_file(test_crts_path + der_test_file) + + crt_bundle = bundle.create_bundle() + + with open(test_crts_path + verified_der_bundle, 'rb') as f: + verified_bundle = f.read() + + self.assertEqual(crt_bundle, verified_bundle) + + # Verify generation from pem vs known certificate + def test_gen_from_pem(self): + bundle = gen_crt_bundle.CertificateBundle() + bundle.add_from_file(test_crts_path + pem_test_file) + + crt_bundle = bundle.create_bundle() + + with open(test_crts_path + verified_pem_bundle, 'rb') as f: + verified_bundle = f.read() + + self.assertEqual(crt_bundle, verified_bundle) + + def test_invalid_crt_input(self): + bundle = gen_crt_bundle.CertificateBundle() + + with self.assertRaisesRegex(gen_crt_bundle.InputError, 'Invalid certificate'): + bundle.add_from_file(test_crts_path + invalid_test_file) + + with self.assertRaisesRegex(gen_crt_bundle.InputError, 'No certificate found'): + bundle.add_from_pem('') + + def test_non_ascii_crt_input(self): + bundle = gen_crt_bundle.CertificateBundle() + + bundle.add_from_file(test_crts_path + non_ascii_file) + self.assertTrue(len(bundle.certificates)) + + +if __name__ == '__main__': + unittest.main() diff --git a/components/mbedtls/mbedtls_v3/mbedtls b/components/mbedtls/mbedtls_v3/mbedtls new file mode 160000 index 000000000..1d34215ad --- /dev/null +++ b/components/mbedtls/mbedtls_v3/mbedtls @@ -0,0 +1 @@ +Subproject commit 1d34215adb0ab8a0533e17420eb5967d99d860d1 diff --git a/components/mbedtls/mbedtls_v3/port/aes/block/esp_aes.c b/components/mbedtls/mbedtls_v3/port/aes/block/esp_aes.c new file mode 100644 index 000000000..fcf4e2a67 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/aes/block/esp_aes.c @@ -0,0 +1,580 @@ +/** + * \brief AES block cipher, ESP block hardware accelerated version + * Based on mbedTLS FIPS-197 compliant version. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Additions Copyright (C) 2016-2017, Espressif Systems (Shanghai) PTE Ltd + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ +#include +#include "mbedtls/aes.h" +#include "mbedtls/platform_util.h" +#include "esp_log.h" +#include "aes/esp_aes.h" +#include "soc/hwcrypto_periph.h" +#include +#include "hal/aes_hal.h" +#include "aes/esp_aes_internal.h" + +#include + +#include +#include "esp_private/periph_ctrl.h" + + +static const char *TAG = "esp-aes"; +/* AES uses a spinlock mux not a lock as the underlying block operation + only takes 208 cycles (to write key & compute block), +600 cycles + for DPORT protection but +3400 cycles again if you use a full sized lock. + + For CBC, CFB, etc. this may mean that interrupts are disabled for a longer + period of time for bigger lengths. However at the moment this has to happen + anyway due to DPORT protection... +*/ +static portMUX_TYPE aes_spinlock = portMUX_INITIALIZER_UNLOCKED; + + +void esp_aes_acquire_hardware( void ) +{ + portENTER_CRITICAL(&aes_spinlock); + + /* Enable AES hardware */ + periph_module_enable(PERIPH_AES_MODULE); +} + +void esp_aes_release_hardware( void ) +{ + /* Disable AES hardware */ + periph_module_disable(PERIPH_AES_MODULE); + + portEXIT_CRITICAL(&aes_spinlock); +} + + + +/* Run a single 16 byte block of AES, using the hardware engine. + * + * Call only while holding esp_aes_acquire_hardware(). + * + * The function esp_aes_block zeroises the output buffer in the case of following conditions: + * 1. If key is not written in the hardware + * 2. If the fault injection check failed + */ +static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output) +{ + uint32_t i0, i1, i2, i3; + const uint32_t *input_words = (uint32_t *)input; + uint32_t *output_words = (uint32_t *)output; + + /* If no key is written to hardware yet, either the user hasn't called + mbedtls_aes_setkey_enc/mbedtls_aes_setkey_dec - meaning we also don't + know which mode to use - or a fault skipped the + key write to hardware. Treat this as a fatal error and zero the output block. + */ + if (ctx->key_in_hardware != ctx->key_bytes) { + mbedtls_platform_zeroize(output, 16); + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + } + i0 = input_words[0]; + i1 = input_words[1]; + i2 = input_words[2]; + i3 = input_words[3]; + + aes_hal_transform_block(input, output); + + /* Physical security check: Verify the AES accelerator actually ran, and wasn't + skipped due to external fault injection while starting the peripheral. + + Note that i0,i1,i2,i3 are copied from input buffer in case input==output. + + Bypassing this check requires at least one additional fault. + */ + if (i0 == output_words[0] && i1 == output_words[1] && i2 == output_words[2] && i3 == output_words[3]) { + // calling zeroing functions to narrow the + // window for a double-fault of the abort step, here + memset(output, 0, 16); + mbedtls_platform_zeroize(output, 16); + abort(); + } + + return 0; +} + +static int esp_aes_validate_input(esp_aes_context *ctx, const unsigned char *input, + const unsigned char *output ) +{ + if (!ctx) { + ESP_LOGD(TAG, "No AES context supplied"); + return -1; + } + if (!input) { + ESP_LOGD(TAG, "No input supplied"); + return -1; + } + if (!output) { + ESP_LOGD(TAG, "No output supplied"); + return -1; + } + + return 0; +} + + +void esp_aes_encrypt(esp_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + esp_internal_aes_encrypt(ctx, input, output); +} + +/* + * AES-ECB block encryption + */ +int esp_internal_aes_encrypt(esp_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int r = -1; + + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT); + r = esp_aes_block(ctx, input, output); + esp_aes_release_hardware(); + return r; +} + +void esp_aes_decrypt(esp_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + esp_internal_aes_decrypt(ctx, input, output); +} + +/* + * AES-ECB block decryption + */ + +int esp_internal_aes_decrypt(esp_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int r = -1; + + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT); + r = esp_aes_block(ctx, input, output); + esp_aes_release_hardware(); + return r; +} + +/* + * AES-ECB block encryption/decryption + */ +int esp_aes_crypt_ecb(esp_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int r = -1; + + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode); + r = esp_aes_block(ctx, input, output); + esp_aes_release_hardware(); + return r; +} + + +/* + * AES-CBC buffer encryption/decryption + */ +int esp_aes_crypt_cbc(esp_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = -1; + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!iv) { + ESP_LOGD(TAG, "No IV supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + uint32_t *output_words = (uint32_t *)output; + const uint32_t *input_words = (const uint32_t *)input; + uint32_t *iv_words = (uint32_t *)iv; + unsigned char temp[16]; + + if ( length % 16 ) { + return ( ERR_ESP_AES_INVALID_INPUT_LENGTH ); + } + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode); + + + if ( mode == ESP_AES_DECRYPT ) { + while ( length > 0 ) { + memcpy(temp, input_words, 16); + ret = esp_aes_block(ctx, input_words, output_words); + if (ret != 0) { + goto cleanup; + } + + output_words[0] = output_words[0] ^ iv_words[0]; + output_words[1] = output_words[1] ^ iv_words[1]; + output_words[2] = output_words[2] ^ iv_words[2]; + output_words[3] = output_words[3] ^ iv_words[3]; + + memcpy( iv_words, temp, 16 ); + + input_words += 4; + output_words += 4; + length -= 16; + } + } else { // ESP_AES_ENCRYPT + while ( length > 0 ) { + + output_words[0] = input_words[0] ^ iv_words[0]; + output_words[1] = input_words[1] ^ iv_words[1]; + output_words[2] = input_words[2] ^ iv_words[2]; + output_words[3] = input_words[3] ^ iv_words[3]; + + ret = esp_aes_block(ctx, output_words, output_words); + if (ret != 0) { + goto cleanup; + } + + memcpy( iv_words, output_words, 16 ); + + input_words += 4; + output_words += 4; + length -= 16; + } + } + ret = 0; + +cleanup: + esp_aes_release_hardware(); + return ret; +} + +/* + * AES-CFB128 buffer encryption/decryption + */ +int esp_aes_crypt_cfb128(esp_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = -1; + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!iv) { + ESP_LOGE(TAG, "No IV supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!iv_off) { + ESP_LOGE(TAG, "No IV offset supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + int c; + size_t n = *iv_off; + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT); + + if ( mode == ESP_AES_DECRYPT ) { + while ( length-- ) { + if ( n == 0 ) { + ret = esp_aes_block(ctx, iv, iv); + if (ret != 0) { + goto cleanup; + } + } + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } else { + while ( length-- ) { + if ( n == 0 ) { + ret = esp_aes_block(ctx, iv, iv); + if (ret != 0) { + goto cleanup; + } + } + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + ret = 0; + +cleanup: + esp_aes_release_hardware(); + return ret; +} + +/* + * AES-CFB8 buffer encryption/decryption + */ +int esp_aes_crypt_cfb8(esp_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = -1; + unsigned char c; + unsigned char ov[17]; + + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!iv) { + ESP_LOGE(TAG, "No IV supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT); + + + while ( length-- ) { + memcpy( ov, iv, 16 ); + ret = esp_aes_block(ctx, iv, iv); + if (ret != 0) { + goto cleanup; + } + + if ( mode == ESP_AES_DECRYPT ) { + ov[16] = *input; + } + + c = *output++ = (unsigned char)( iv[0] ^ *input++ ); + + if ( mode == ESP_AES_ENCRYPT ) { + ov[16] = c; + } + + memcpy( iv, ov + 1, 16 ); + } + ret = 0; + +cleanup: + esp_aes_release_hardware(); + return ret; +} + +/* + * AES-CTR buffer encryption/decryption + */ +int esp_aes_crypt_ctr(esp_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i, ret = -1; + + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!stream_block) { + ESP_LOGE(TAG, "No stream supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!nonce_counter) { + ESP_LOGE(TAG, "No nonce supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!nc_off) { + ESP_LOGE(TAG, "No nonce offset supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + size_t n = *nc_off; + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT); + + + while ( length-- ) { + if ( n == 0 ) { + ret = esp_aes_block(ctx, nonce_counter, stream_block); + if (ret != 0) { + goto cleanup; + } + + for ( i = 16; i > 0; i-- ) { + if ( ++nonce_counter[i - 1] != 0 ) { + break; + } + } + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + ret = 0; + +cleanup: + esp_aes_release_hardware(); + return ret; +} + +/* + * AES-OFB (Output Feedback Mode) buffer encryption/decryption + */ +int esp_aes_crypt_ofb(esp_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = -1; + size_t n; + + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!iv) { + ESP_LOGE(TAG, "No IV supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!iv_off) { + ESP_LOGE(TAG, "No IV offset supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + n = *iv_off; + + if (n > 15) { + return (MBEDTLS_ERR_AES_BAD_INPUT_DATA); + } + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT); + + + while (length--) { + if ( n == 0 ) { + ret = esp_aes_block(ctx, iv, iv); + if (ret != 0) { + goto cleanup; + } + } + *output++ = *input++ ^ iv[n]; + + n = ( n + 1 ) & 0x0F; + } + + *iv_off = n; + ret = 0; + +cleanup: + esp_aes_release_hardware(); + + return ( ret ); +} diff --git a/components/mbedtls/mbedtls_v3/port/aes/dma/esp_aes.c b/components/mbedtls/mbedtls_v3/port/aes/dma/esp_aes.c new file mode 100644 index 000000000..1dd940186 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/aes/dma/esp_aes.c @@ -0,0 +1,1103 @@ +/** + * \brief AES block cipher, ESP DMA hardware accelerated version + * Based on mbedTLS FIPS-197 compliant version. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE Ltd + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ + +#include +#include "mbedtls/aes.h" +#include "esp_intr_alloc.h" +#include "esp_private/periph_ctrl.h" +#include "esp_log.h" +#include "esp_attr.h" +#include "soc/lldesc.h" +#include "esp_heap_caps.h" +#include "esp_memory_utils.h" +#include "sys/param.h" +#if CONFIG_PM_ENABLE +#include "esp_pm.h" +#endif +#include "esp_crypto_lock.h" +#include "hal/aes_hal.h" +#include "aes/esp_aes_internal.h" +#include "esp_aes_dma_priv.h" + +#if CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/rom/cache.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/cache.h" +#endif + +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +#if SOC_AES_GDMA +#define AES_LOCK() esp_crypto_sha_aes_lock_acquire() +#define AES_RELEASE() esp_crypto_sha_aes_lock_release() +#elif SOC_AES_CRYPTO_DMA +#define AES_LOCK() esp_crypto_dma_lock_acquire() +#define AES_RELEASE() esp_crypto_dma_lock_release() +#endif + +/* Max size of each chunk to process when output buffer is in unaligned external ram + must be a multiple of block size +*/ +#define AES_MAX_CHUNK_WRITE_SIZE 1600 + +/* Input over this length will yield and wait for interrupt instead of + busy-waiting, 30000 bytes is approx 0.5 ms */ +#define AES_DMA_INTR_TRIG_LEN 2000 + +/* With buffers in PSRAM (worst condition) we still achieve a speed of 4 MB/s + thus a 2 second timeout value should be suffient for even very large buffers. + */ +#define AES_WAIT_INTR_TIMEOUT_MS 2000 + +#if defined(CONFIG_MBEDTLS_AES_USE_INTERRUPT) +static SemaphoreHandle_t op_complete_sem; +#if defined(CONFIG_PM_ENABLE) +static esp_pm_lock_handle_t s_pm_cpu_lock; +static esp_pm_lock_handle_t s_pm_sleep_lock; +#endif +#endif + +#if SOC_PSRAM_DMA_CAPABLE + +#if (CONFIG_ESP32S2_DATA_CACHE_LINE_16B || CONFIG_ESP32S3_DATA_CACHE_LINE_16B) +#define DCACHE_LINE_SIZE 16 +#elif (CONFIG_ESP32S2_DATA_CACHE_LINE_32B || CONFIG_ESP32S3_DATA_CACHE_LINE_32B) +#define DCACHE_LINE_SIZE 32 +#elif CONFIG_ESP32S3_DATA_CACHE_LINE_64B +#define DCACHE_LINE_SIZE 64 +#endif //(CONFIG_ESP32S2_DATA_CACHE_LINE_16B || CONFIG_ESP32S3_DATA_CACHE_LINE_16B) + +#endif //SOC_PSRAM_DMA_CAPABLE + +static const char *TAG = "esp-aes"; +static bool s_check_dma_capable(const void *p); + +/* These are static due to: + * * Must be in DMA capable memory, so stack is not a safe place to put them + * * To avoid having to malloc/free them for every DMA operation + */ +static DRAM_ATTR lldesc_t s_stream_in_desc; +static DRAM_ATTR lldesc_t s_stream_out_desc; +static DRAM_ATTR uint8_t s_stream_in[AES_BLOCK_BYTES]; +static DRAM_ATTR uint8_t s_stream_out[AES_BLOCK_BYTES]; + +static inline void esp_aes_wait_dma_done(lldesc_t *output) +{ + /* Wait for DMA write operation to complete */ + while (1) { + if ( esp_aes_dma_done(output) ) { + break; + } + } +} + +/* Append a descriptor to the chain, set head if chain empty */ +static inline void lldesc_append(lldesc_t **head, lldesc_t *item) +{ + lldesc_t *it; + if (*head == NULL) { + *head = item; + return; + } + + it = *head; + + while (it->empty != 0) { + it = (lldesc_t *)it->empty; + } + it->eof = 0; + it->empty = (uint32_t)item; +} + +void esp_aes_acquire_hardware( void ) +{ + /* Released by esp_aes_release_hardware()*/ + AES_LOCK(); + + /* Enable AES and DMA hardware */ +#if SOC_AES_CRYPTO_DMA + periph_module_enable(PERIPH_AES_DMA_MODULE); +#elif SOC_AES_GDMA + periph_module_enable(PERIPH_AES_MODULE); +#endif +} + +/* Function to disable AES and Crypto DMA clocks and release locks */ +void esp_aes_release_hardware( void ) +{ + /* Disable AES and DMA hardware */ +#if SOC_AES_CRYPTO_DMA + periph_module_disable(PERIPH_AES_DMA_MODULE); +#elif SOC_AES_GDMA + periph_module_disable(PERIPH_AES_MODULE); +#endif + + AES_RELEASE(); +} + + +#if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT) +static IRAM_ATTR void esp_aes_complete_isr(void *arg) +{ + BaseType_t higher_woken; + aes_hal_interrupt_clear(); + xSemaphoreGiveFromISR(op_complete_sem, &higher_woken); + if (higher_woken) { + portYIELD_FROM_ISR(); + } +} + +void esp_aes_intr_alloc(void) +{ + if (op_complete_sem == NULL) { + + esp_err_t ret = esp_intr_alloc(ETS_AES_INTR_SOURCE, 0, esp_aes_complete_isr, NULL, NULL); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to allocate AES interrupt %d", ret); + // This should be treated as fatal error as this API would mostly + // be invoked within mbedTLS interface. There is no way for the system + // to proceed if the AES interrupt allocation fails here. + abort(); + } + + static StaticSemaphore_t op_sem_buf; + op_complete_sem = xSemaphoreCreateBinaryStatic(&op_sem_buf); + // Static semaphore creation is unlikley to fail but still basic sanity + assert(op_complete_sem != NULL); + } +} + +static esp_err_t esp_aes_isr_initialise( void ) +{ + aes_hal_interrupt_clear(); + aes_hal_interrupt_enable(true); + + /* AES is clocked proportionally to CPU clock, take power management lock */ +#ifdef CONFIG_PM_ENABLE + if (s_pm_cpu_lock == NULL) { + if (esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "aes_sleep", &s_pm_sleep_lock) != ESP_OK) { + ESP_LOGE(TAG, "Failed to create PM sleep lock"); + return ESP_FAIL; + } + if (esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, "aes_cpu", &s_pm_cpu_lock) != ESP_OK) { + ESP_LOGE(TAG, "Failed to create PM CPU lock"); + return ESP_FAIL; + } + } + esp_pm_lock_acquire(s_pm_cpu_lock); + esp_pm_lock_acquire(s_pm_sleep_lock); +#endif + + return ESP_OK; +} +#endif // CONFIG_MBEDTLS_AES_USE_INTERRUPT + +/* Wait for AES hardware block operation to complete */ +static int esp_aes_dma_wait_complete(bool use_intr, lldesc_t *output_desc) +{ +#if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT) + if (use_intr) { + if (!xSemaphoreTake(op_complete_sem, AES_WAIT_INTR_TIMEOUT_MS / portTICK_PERIOD_MS)) { + /* indicates a fundamental problem with driver */ + ESP_LOGE(TAG, "Timed out waiting for completion of AES Interrupt"); + return -1; + } +#ifdef CONFIG_PM_ENABLE + esp_pm_lock_release(s_pm_cpu_lock); + esp_pm_lock_release(s_pm_sleep_lock); +#endif // CONFIG_PM_ENABLE + } +#endif + /* Checking this if interrupt is used also, to avoid + issues with AES fault injection + */ + aes_hal_wait_done(); + + esp_aes_wait_dma_done(output_desc); + return 0; +} + + +static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out); + + +/* Output buffers in external ram needs to be 16-byte aligned and DMA cant access input in the iCache mem range, + reallocate them into internal memory and encrypt in chunks to avoid + having to malloc too big of a buffer + + The function esp_aes_process_dma_ext_ram zeroises the output buffer in the case of memory allocation failure. +*/ + +static int esp_aes_process_dma_ext_ram(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out, bool realloc_input, bool realloc_output) +{ + size_t chunk_len; + int ret = 0; + int offset = 0; + unsigned char *input_buf = NULL; + unsigned char *output_buf = NULL; + const unsigned char *dma_input; + chunk_len = MIN(AES_MAX_CHUNK_WRITE_SIZE, len); + + if (realloc_input) { + input_buf = heap_caps_malloc(chunk_len, MALLOC_CAP_DMA); + + if (input_buf == NULL) { + mbedtls_platform_zeroize(output, len); + ESP_LOGE(TAG, "Failed to allocate memory"); + return -1; + } + } + + if (realloc_output) { + output_buf = heap_caps_malloc(chunk_len, MALLOC_CAP_DMA); + + if (output_buf == NULL) { + mbedtls_platform_zeroize(output, len); + ESP_LOGE(TAG, "Failed to allocate memory"); + return -1; + } + } else { + output_buf = output; + } + + while (len) { + chunk_len = MIN(AES_MAX_CHUNK_WRITE_SIZE, len); + + /* If input needs realloc then copy it, else use the input with offset*/ + if (realloc_input) { + memcpy(input_buf, input + offset, chunk_len); + dma_input = input_buf; + } else { + dma_input = input + offset; + } + + if (esp_aes_process_dma(ctx, dma_input, output_buf, chunk_len, stream_out) != 0) { + ret = -1; + goto cleanup; + } + + if (realloc_output) { + memcpy(output + offset, output_buf, chunk_len); + } else { + output_buf = output + offset + chunk_len; + } + + len -= chunk_len; + offset += chunk_len; + } + +cleanup: + + if (realloc_input) { + free(input_buf); + } + if (realloc_output) { + free(output_buf); + } + + return ret; +} + +/* Encrypt/decrypt the input using DMA + * The function esp_aes_process_dma zeroises the output buffer in the case of following conditions: + * 1. If key is not written in the hardware + * 2. Memory allocation failures + * 3. If AES interrupt is enabled and ISR initialisation fails + * 4. Failure in any of the AES operations + */ +static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out) +{ + lldesc_t *in_desc_head = NULL, *out_desc_head = NULL; + lldesc_t *out_desc_tail = NULL; /* pointer to the final output descriptor */ + lldesc_t *block_desc = NULL, *block_in_desc = NULL, *block_out_desc = NULL; + size_t lldesc_num; + unsigned stream_bytes = len % AES_BLOCK_BYTES; // bytes which aren't in a full block + unsigned block_bytes = len - stream_bytes; // bytes which are in a full block + unsigned blocks = (block_bytes / AES_BLOCK_BYTES) + ((stream_bytes > 0) ? 1 : 0); + bool use_intr = false; + bool input_needs_realloc = false; + bool output_needs_realloc = false; + int ret = 0; + + assert(len > 0); // caller shouldn't ever have len set to zero + assert(stream_bytes == 0 || stream_out != NULL); // stream_out can be NULL if we're processing full block(s) + + /* If no key is written to hardware yet, either the user hasn't called + mbedtls_aes_setkey_enc/mbedtls_aes_setkey_dec - meaning we also don't + know which mode to use - or a fault skipped the + key write to hardware. Treat this as a fatal error and zero the output block. + */ + if (ctx->key_in_hardware != ctx->key_bytes) { + mbedtls_platform_zeroize(output, len); + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + } + + if (block_bytes > 0) { + /* Flush cache if input in external ram */ +#if (CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE) + if (esp_ptr_external_ram(input)) { + Cache_WriteBack_Addr((uint32_t)input, len); + } + if (esp_ptr_external_ram(output)) { + if ((((intptr_t)(output) & (DCACHE_LINE_SIZE - 1)) != 0) || (block_bytes % DCACHE_LINE_SIZE != 0)) { + // Non aligned ext-mem buffer + output_needs_realloc = true; + } + } +#endif + /* DMA cannot access memory in the iCache range, copy input to internal ram */ + if (!s_check_dma_capable(input)) { + input_needs_realloc = true; + } + + if (!s_check_dma_capable(output)) { + output_needs_realloc = true; + } + + /* If either input or output is unaccessible to the DMA then they need to be reallocated */ + if (input_needs_realloc || output_needs_realloc) { + return esp_aes_process_dma_ext_ram(ctx, input, output, len, stream_out, input_needs_realloc, output_needs_realloc); + } + + /* Set up dma descriptors for input and output considering the 16 byte alignment requirement for EDMA */ + lldesc_num = lldesc_get_required_num_constrained(block_bytes, LLDESC_MAX_NUM_PER_DESC_16B_ALIGNED); + + /* Allocate both in and out descriptors to save a malloc/free per function call */ + block_desc = heap_caps_calloc(lldesc_num * 2, sizeof(lldesc_t), MALLOC_CAP_DMA); + if (block_desc == NULL) { + mbedtls_platform_zeroize(output, len); + ESP_LOGE(TAG, "Failed to allocate memory"); + return -1; + } + + block_in_desc = block_desc; + block_out_desc = block_desc + lldesc_num; + + lldesc_setup_link(block_in_desc, input, block_bytes, 0); + //Limit max inlink descriptor length to be 16 byte aligned, require for EDMA + lldesc_setup_link_constrained(block_out_desc, output, block_bytes, LLDESC_MAX_NUM_PER_DESC_16B_ALIGNED, 0); + + /* Setup in/out start descriptors */ + lldesc_append(&in_desc_head, block_in_desc); + lldesc_append(&out_desc_head, block_out_desc); + + out_desc_tail = &block_out_desc[lldesc_num - 1]; + } + + /* Any leftover bytes which are appended as an additional DMA list */ + if (stream_bytes > 0) { + + memset(&s_stream_in_desc, 0, sizeof(lldesc_t)); + memset(&s_stream_out_desc, 0, sizeof(lldesc_t)); + + memset(s_stream_in, 0, AES_BLOCK_BYTES); + memset(s_stream_out, 0, AES_BLOCK_BYTES); + + memcpy(s_stream_in, input + block_bytes, stream_bytes); + + lldesc_setup_link(&s_stream_in_desc, s_stream_in, AES_BLOCK_BYTES, 0); + lldesc_setup_link(&s_stream_out_desc, s_stream_out, AES_BLOCK_BYTES, 0); + + /* Link with block descriptors */ + lldesc_append(&in_desc_head, &s_stream_in_desc); + lldesc_append(&out_desc_head, &s_stream_out_desc); + + out_desc_tail = &s_stream_out_desc; + } + +#if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT) + /* Only use interrupt for long AES operations */ + if (len > AES_DMA_INTR_TRIG_LEN) { + use_intr = true; + if (esp_aes_isr_initialise() != ESP_OK) { + ESP_LOGE(TAG, "ESP-AES ISR initialisation failed"); + ret = -1; + goto cleanup; + } + } else +#endif + { + aes_hal_interrupt_enable(false); + } + + if (esp_aes_dma_start(in_desc_head, out_desc_head) != ESP_OK) { + ESP_LOGE(TAG, "esp_aes_dma_start failed, no DMA channel available"); + ret = -1; + goto cleanup; + } + + aes_hal_transform_dma_start(blocks); + + if (esp_aes_dma_wait_complete(use_intr, out_desc_tail) < 0) { + ESP_LOGE(TAG, "esp_aes_dma_wait_complete failed"); + ret = -1; + goto cleanup; + } + +#if (CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE) + if (block_bytes > 0) { + if (esp_ptr_external_ram(output)) { + Cache_Invalidate_Addr((uint32_t)output, block_bytes); + } + } +#endif + aes_hal_transform_dma_finish(); + + if (stream_bytes > 0) { + memcpy(output + block_bytes, s_stream_out, stream_bytes); + memcpy(stream_out, s_stream_out, AES_BLOCK_BYTES); + } + +cleanup: + if (ret != 0) { + mbedtls_platform_zeroize(output, len); + } + free(block_desc); + return ret; +} + + +#if CONFIG_MBEDTLS_HARDWARE_GCM + +/* Encrypt/decrypt with AES-GCM the input using DMA + * The function esp_aes_process_dma_gcm zeroises the output buffer in the case of following conditions: + * 1. If key is not written in the hardware + * 2. Memory allocation failures + * 3. If AES interrupt is enabled and ISR initialisation fails + * 4. Failure in any of the AES operations + */ +int esp_aes_process_dma_gcm(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, lldesc_t *aad_desc, size_t aad_len) +{ + lldesc_t *in_desc_head = NULL, *out_desc_head = NULL, *len_desc = NULL; + lldesc_t *out_desc_tail = NULL; /* pointer to the final output descriptor */ + lldesc_t stream_in_desc, stream_out_desc; + lldesc_t *block_desc = NULL, *block_in_desc = NULL, *block_out_desc = NULL; + size_t lldesc_num; + uint32_t len_buf[4] = {}; + uint8_t stream_in[16] = {}; + uint8_t stream_out[16] = {}; + unsigned stream_bytes = len % AES_BLOCK_BYTES; // bytes which aren't in a full block + unsigned block_bytes = len - stream_bytes; // bytes which are in a full block + + unsigned blocks = (block_bytes / AES_BLOCK_BYTES) + ((stream_bytes > 0) ? 1 : 0); + + bool use_intr = false; + int ret = 0; + + /* If no key is written to hardware yet, either the user hasn't called + mbedtls_aes_setkey_enc/mbedtls_aes_setkey_dec - meaning we also don't + know which mode to use - or a fault skipped the + key write to hardware. Treat this as a fatal error and zero the output block. + */ + if (ctx->key_in_hardware != ctx->key_bytes) { + mbedtls_platform_zeroize(output, len); + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + } + + /* Set up dma descriptors for input and output */ + lldesc_num = lldesc_get_required_num(block_bytes); + + /* Allocate both in and out descriptors to save a malloc/free per function call, add 1 for length descriptor */ + block_desc = heap_caps_calloc( (lldesc_num * 2) + 1, sizeof(lldesc_t), MALLOC_CAP_DMA); + if (block_desc == NULL) { + mbedtls_platform_zeroize(output, len); + ESP_LOGE(TAG, "Failed to allocate memory"); + return -1; + } + + block_in_desc = block_desc; + len_desc = block_desc + lldesc_num; + block_out_desc = block_desc + lldesc_num + 1; + + if (aad_desc != NULL) { + lldesc_append(&in_desc_head, aad_desc); + } + + if (block_bytes > 0) { + lldesc_setup_link(block_in_desc, input, block_bytes, 0); + lldesc_setup_link(block_out_desc, output, block_bytes, 0); + + lldesc_append(&in_desc_head, block_in_desc); + lldesc_append(&out_desc_head, block_out_desc); + + out_desc_tail = &block_out_desc[lldesc_num - 1]; + } + + /* Any leftover bytes which are appended as an additional DMA list */ + if (stream_bytes > 0) { + memcpy(stream_in, input + block_bytes, stream_bytes); + + lldesc_setup_link(&stream_in_desc, stream_in, AES_BLOCK_BYTES, 0); + lldesc_setup_link(&stream_out_desc, stream_out, AES_BLOCK_BYTES, 0); + + lldesc_append(&in_desc_head, &stream_in_desc); + lldesc_append(&out_desc_head, &stream_out_desc); + + out_desc_tail = &stream_out_desc; + } + + + len_buf[1] = __builtin_bswap32(aad_len * 8); + len_buf[3] = __builtin_bswap32(len * 8); + + len_desc->length = sizeof(len_buf); + len_desc->size = sizeof(len_buf); + len_desc->owner = 1; + len_desc->eof = 1; + len_desc->buf = (uint8_t *)len_buf; + + lldesc_append(&in_desc_head, len_desc); + +#if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT) + /* Only use interrupt for long AES operations */ + if (len > AES_DMA_INTR_TRIG_LEN) { + use_intr = true; + if (esp_aes_isr_initialise() != ESP_OK) { + ESP_LOGE(TAG, "ESP-AES ISR initialisation failed"); + ret = -1; + goto cleanup; + } + } else +#endif + { + aes_hal_interrupt_enable(false); + } + + /* Start AES operation */ + if (esp_aes_dma_start(in_desc_head, out_desc_head) != ESP_OK) { + ESP_LOGE(TAG, "esp_aes_dma_start failed, no DMA channel available"); + ret = -1; + goto cleanup; + } + + aes_hal_transform_dma_gcm_start(blocks); + + if (esp_aes_dma_wait_complete(use_intr, out_desc_tail) < 0) { + ESP_LOGE(TAG, "esp_aes_dma_wait_complete failed"); + ret = -1; + goto cleanup; + } + + aes_hal_transform_dma_finish(); + + if (stream_bytes > 0) { + memcpy(output + block_bytes, stream_out, stream_bytes); + } + +cleanup: + if (ret != 0) { + mbedtls_platform_zeroize(output, len); + } + free(block_desc); + return ret; +} + +#endif //CONFIG_MBEDTLS_HARDWARE_GCM + +static int esp_aes_validate_input(esp_aes_context *ctx, const unsigned char *input, + unsigned char *output ) +{ + if (!ctx) { + ESP_LOGE(TAG, "No AES context supplied"); + return -1; + } + if (!input) { + ESP_LOGE(TAG, "No input supplied"); + return -1; + } + if (!output) { + ESP_LOGE(TAG, "No output supplied"); + return -1; + } + + return 0; +} + + +/* + * AES-ECB single block encryption + */ +int esp_internal_aes_encrypt(esp_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int r = -1; + + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT); + aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB); + r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL); + esp_aes_release_hardware(); + + return r; +} + +void esp_aes_encrypt(esp_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + esp_internal_aes_encrypt(ctx, input, output); +} + +/* + * AES-ECB single block decryption + */ +int esp_internal_aes_decrypt(esp_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int r = -1; + + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT); + aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB); + r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL); + esp_aes_release_hardware(); + + return r; +} + +void esp_aes_decrypt(esp_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + esp_internal_aes_decrypt(ctx, input, output); +} + + +/* + * AES-ECB block encryption/decryption + */ +int esp_aes_crypt_ecb(esp_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int r = -1; + + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode); + aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB); + r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL); + esp_aes_release_hardware(); + + return r; +} + +/* + * AES-CBC buffer encryption/decryption + */ +int esp_aes_crypt_cbc(esp_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int r = -1; + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!iv) { + ESP_LOGE(TAG, "No IV supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + /* For CBC input length should be multiple of + * AES BLOCK BYTES + * */ + if ( (length % AES_BLOCK_BYTES) || (length == 0) ) { + return ERR_ESP_AES_INVALID_INPUT_LENGTH; + } + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode); + aes_hal_mode_init(ESP_AES_BLOCK_MODE_CBC); + aes_hal_set_iv(iv); + + r = esp_aes_process_dma(ctx, input, output, length, NULL); + if (r != 0) { + goto cleanup; + } + + aes_hal_read_iv(iv); + +cleanup: + esp_aes_release_hardware(); + return r; +} + +/* + * AES-CFB8 buffer encryption/decryption + */ +int esp_aes_crypt_cfb8(esp_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int r = -1; + unsigned char c; + unsigned char ov[17]; + size_t block_bytes = length - (length % AES_BLOCK_BYTES); + + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!iv) { + ESP_LOGE(TAG, "No IV supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + /* The DMA engine will only output correct IV if it runs + full blocks of input in CFB8 mode + */ + esp_aes_acquire_hardware(); + + if (block_bytes > 0) { + + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode); + aes_hal_mode_init(ESP_AES_BLOCK_MODE_CFB8); + aes_hal_set_iv(iv); + r = esp_aes_process_dma(ctx, input, output, block_bytes, NULL); + if (r != 0) { + goto cleanup; + } + + aes_hal_read_iv(iv); + + length -= block_bytes; + input += block_bytes; + output += block_bytes; + } + + // Process remaining bytes block-at-a-time in ECB mode + if (length > 0) { + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, MBEDTLS_AES_ENCRYPT); + aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB); + + while ( length-- ) { + memcpy( ov, iv, 16 ); + + r = esp_aes_process_dma(ctx, iv, iv, AES_BLOCK_BYTES, NULL); + if (r != 0) { + goto cleanup; + } + + if ( mode == MBEDTLS_AES_DECRYPT ) { + ov[16] = *input; + } + + c = *output++ = ( iv[0] ^ *input++ ); + + if ( mode == MBEDTLS_AES_ENCRYPT ) { + ov[16] = c; + } + memcpy( iv, ov + 1, 16 ); + } + + } + r = 0; + +cleanup: + esp_aes_release_hardware(); + return r; +} + +/* + * AES-CFB128 buffer encryption/decryption + */ +int esp_aes_crypt_cfb128(esp_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) + +{ + uint8_t c; + size_t stream_bytes = 0; + size_t n; + + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!iv) { + ESP_LOGE(TAG, "No IV supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!iv_off) { + ESP_LOGE(TAG, "No IV offset supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + n = *iv_off; + + /* First process the *iv_off bytes + * which are pending from the previous call to this API + */ + while (n > 0 && length > 0) { + if (mode == MBEDTLS_AES_ENCRYPT) { + iv[n] = *output++ = *input++ ^ iv[n]; + } else { + c = *input++; + *output++ = c ^ iv[n]; + iv[n] = c; + } + n = (n + 1) % AES_BLOCK_BYTES; + length--; + } + + + if (length > 0) { + stream_bytes = length % AES_BLOCK_BYTES; + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode); + aes_hal_mode_init(ESP_AES_BLOCK_MODE_CFB128); + aes_hal_set_iv(iv); + + int r = esp_aes_process_dma(ctx, input, output, length, iv); + if (r != 0) { + esp_aes_release_hardware(); + return r; + } + + if (stream_bytes == 0) { + // if we didn't need the partial 'stream block' then the new IV is in the IV register + aes_hal_read_iv(iv); + } else { + // if we did process a final partial block the new IV is already processed via DMA (and has some bytes of output in it), + // In decrypt mode any partial bytes are output plaintext (iv ^ c) and need to be swapped back to ciphertext (as the next + // block uses ciphertext as its IV input) + // + // Note: It may be more efficient to not process the partial block via DMA in this case. + if (mode == MBEDTLS_AES_DECRYPT) { + memcpy(iv, input + length - stream_bytes, stream_bytes); + } + } + esp_aes_release_hardware(); + } + + *iv_off = n + stream_bytes; + return 0; +} + +/* + * AES-OFB (Output Feedback Mode) buffer encryption/decryption + */ + +int esp_aes_crypt_ofb(esp_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + size_t n; + size_t stream_bytes = 0; + + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!iv) { + ESP_LOGE(TAG, "No IV supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!iv_off) { + ESP_LOGE(TAG, "No IV offset supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + n = *iv_off; + + /* If there is an offset then use the output of the previous AES block + (the updated IV) to calculate the new output */ + while (n > 0 && length > 0) { + *output++ = (*input++ ^ iv[n]); + n = (n + 1) & 0xF; + length--; + } + if (length > 0) { + stream_bytes = (length % AES_BLOCK_BYTES); + + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT); + aes_hal_mode_init(ESP_AES_BLOCK_MODE_OFB); + aes_hal_set_iv(iv); + + int r = esp_aes_process_dma(ctx, input, output, length, iv); + if (r != 0) { + esp_aes_release_hardware(); + return r; + } + + aes_hal_read_iv(iv); + esp_aes_release_hardware(); + } + + *iv_off = n + stream_bytes; + + return 0; +} + +/* + * AES-CTR buffer encryption/decryption + */ +int esp_aes_crypt_ctr(esp_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + size_t n; + + if (esp_aes_validate_input(ctx, input, output)) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!stream_block) { + ESP_LOGE(TAG, "No stream supplied"); + return -1; + } + + if (!nonce_counter) { + ESP_LOGE(TAG, "No nonce supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (!nc_off) { + ESP_LOGE(TAG, "No nonce offset supplied"); + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + n = *nc_off; + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + /* Process any unprocessed bytes left in stream block from + last operation */ + while (n > 0 && length > 0) { + *output++ = (unsigned char)(*input++ ^ stream_block[n]); + n = (n + 1) & 0xF; + length--; + } + + if (length > 0) { + + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT); + + aes_hal_mode_init(ESP_AES_BLOCK_MODE_CTR); + aes_hal_set_iv(nonce_counter); + + int r = esp_aes_process_dma(ctx, input, output, length, stream_block); + + if (r != 0) { + esp_aes_release_hardware(); + return r; + } + + aes_hal_read_iv(nonce_counter); + + esp_aes_release_hardware(); + + } + *nc_off = n + (length % AES_BLOCK_BYTES); + + return 0; +} + +static bool s_check_dma_capable(const void *p) +{ + bool is_capable = false; +#if CONFIG_SPIRAM + is_capable |= esp_ptr_dma_ext_capable(p); +#endif + is_capable |= esp_ptr_dma_capable(p); + + return is_capable; +} diff --git a/components/mbedtls/mbedtls_v3/port/aes/dma/esp_aes_crypto_dma_impl.c b/components/mbedtls/mbedtls_v3/port/aes/dma/esp_aes_crypto_dma_impl.c new file mode 100644 index 000000000..df8fd4bf4 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/aes/dma/esp_aes_crypto_dma_impl.c @@ -0,0 +1,42 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include "esp_aes_dma_priv.h" + +#include "soc/soc_caps.h" +#include "soc/crypto_dma_reg.h" +#include "hal/crypto_dma_ll.h" + + +esp_err_t esp_aes_dma_start(const lldesc_t *input, const lldesc_t *output) +{ + crypto_dma_ll_reset(); + crypto_dma_ll_set_mode(CRYPTO_DMA_AES); + + /* Set descriptors, input to AES comes from outlink DMA and viceversa */ + crypto_dma_ll_outlink_set((uint32_t)input); + crypto_dma_ll_inlink_set((uint32_t)output); + + /* Start transfer */ + crypto_dma_ll_outlink_start(); + crypto_dma_ll_inlink_start(); + + return ESP_OK; +} + +bool esp_aes_dma_done(const lldesc_t *output) +{ + return (crypto_dma_ll_inlink_is_eof() && (output->owner == 0)); +} diff --git a/components/mbedtls/mbedtls_v3/port/aes/dma/esp_aes_gdma_impl.c b/components/mbedtls/mbedtls_v3/port/aes/dma/esp_aes_gdma_impl.c new file mode 100644 index 000000000..94e970709 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/aes/dma/esp_aes_gdma_impl.c @@ -0,0 +1,27 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_aes_dma_priv.h" +#include "hal/gdma_ll.h" +#include "esp_crypto_shared_gdma.h" + +esp_err_t esp_aes_dma_start(const lldesc_t *input, const lldesc_t *output) +{ + return esp_crypto_shared_gdma_start(input, output, GDMA_TRIG_PERIPH_AES); +} + +bool esp_aes_dma_done(const lldesc_t *output) +{ + return (output->owner == 0); +} diff --git a/components/mbedtls/mbedtls_v3/port/aes/dma/include/esp_aes_dma_priv.h b/components/mbedtls/mbedtls_v3/port/aes/dma/include/esp_aes_dma_priv.h new file mode 100644 index 000000000..d8ddac8d2 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/aes/dma/include/esp_aes_dma_priv.h @@ -0,0 +1,45 @@ +/* + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "soc/lldesc.h" +#include "soc/soc_caps.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Start the DMA engine + * + * @param input AES input descriptor (outlink) + * @param output AES output descriptor (inlink) + * @return + * - ESP_OK: Successfully started the DMA + * - ESP_ERR_INVALID_STATE: No DMA channel available + */ +esp_err_t esp_aes_dma_start(const lldesc_t *input, const lldesc_t *output); + +/** + * @brief Check if the DMA engine is finished reading the result + * + * @param output AES output descriptor (inlink) + * @return + * - true: DMA finished + * - false: DMA not yet finished + */ +bool esp_aes_dma_done(const lldesc_t *output); + +/** + * @brief Allocate AES peripheral interrupt handler + */ +void esp_aes_intr_alloc(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/aes/esp_aes_common.c b/components/mbedtls/mbedtls_v3/port/aes/esp_aes_common.c new file mode 100644 index 000000000..578ec6656 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/aes/esp_aes_common.c @@ -0,0 +1,79 @@ +/* + * AES block cipher, ESP hardware accelerated version, common + * Based on mbedTLS FIPS-197 compliant version. + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ +#include "sdkconfig.h" +#include "aes/esp_aes_internal.h" +#include "mbedtls/aes.h" +#include "hal/aes_hal.h" +#include "hal/aes_types.h" +#include "soc/soc_caps.h" +#include "mbedtls/error.h" + +#include +#include "mbedtls/platform.h" + +#if SOC_AES_SUPPORT_DMA +#include "esp_aes_dma_priv.h" +#endif + +bool valid_key_length(const esp_aes_context *ctx) +{ + bool valid_len = (ctx->key_bytes == AES_128_KEY_BYTES) || (ctx->key_bytes == AES_256_KEY_BYTES); + +#if SOC_AES_SUPPORT_AES_192 + valid_len |= ctx->key_bytes == AES_192_KEY_BYTES; +#endif + + return valid_len; +} + +void esp_aes_init(esp_aes_context *ctx) +{ + bzero(ctx, sizeof(esp_aes_context)); +#if SOC_AES_SUPPORT_DMA && CONFIG_MBEDTLS_AES_USE_INTERRUPT + esp_aes_intr_alloc(); +#endif +} + +void esp_aes_free( esp_aes_context *ctx ) +{ + if ( ctx == NULL ) { + return; + } + + bzero( ctx, sizeof( esp_aes_context ) ); +} + +/* + * AES key schedule (same for encryption or decryption, as hardware handles schedule) + * + */ +int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ +#if !SOC_AES_SUPPORT_AES_192 + if (keybits == 192) { + return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; + } +#endif + if (keybits != 128 && keybits != 192 && keybits != 256) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + ctx->key_bytes = keybits / 8; + memcpy(ctx->key, key, ctx->key_bytes); + ctx->key_in_hardware = 0; + return 0; +} diff --git a/components/mbedtls/mbedtls_v3/port/aes/esp_aes_gcm.c b/components/mbedtls/mbedtls_v3/port/aes/esp_aes_gcm.c new file mode 100644 index 000000000..17c2ec84d --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/aes/esp_aes_gcm.c @@ -0,0 +1,820 @@ +/* + * GCM block cipher, ESP DMA hardware accelerated version + * Based on mbedTLS FIPS-197 compliant version. + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2016-2024 Espressif Systems (Shanghai) CO LTD + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ +#include + +#include "aes/esp_aes.h" +#include "aes/esp_aes_gcm.h" +#include "aes/esp_aes_internal.h" +#include "hal/aes_hal.h" + +#include "mbedtls/aes.h" +#include "mbedtls/error.h" +#include "mbedtls/gcm.h" + +#include "esp_heap_caps.h" +#include "esp_log.h" +#include "soc/soc_caps.h" +#include "soc/soc_memory_layout.h" + +#include "sdkconfig.h" + +#if SOC_AES_SUPPORT_DMA +#include "esp_aes_dma_priv.h" +#endif + +#define ESP_PUT_BE64(a, val) \ + do { \ + *(uint64_t*)(a) = __builtin_bswap64( (uint64_t)(val) ); \ + } while (0) + +/* For simplicity limit the maxium amount of aad bytes to a single DMA descriptor + This should cover all normal, e.g. mbedtls, use cases */ +#define ESP_AES_GCM_AAD_MAX_BYTES 4080 + +static const char *TAG = "esp-aes-gcm"; + +static void esp_gcm_ghash(esp_gcm_context *ctx, const unsigned char *x, size_t x_len, uint8_t *z); + +/* + * Calculates the Initial Counter Block, J0 + * and copies to to the esp_gcm_context + */ +static void esp_gcm_derive_J0(esp_gcm_context *ctx) +{ + uint8_t len_buf[16]; + + memset(ctx->J0, 0, AES_BLOCK_BYTES); + memset(len_buf, 0, AES_BLOCK_BYTES); + + /* If IV is 96 bits J0 = ( IV || 0^31 || 1 ) */ + if (ctx->iv_len == 12) { + memcpy(ctx->J0, ctx->iv, ctx->iv_len); + ctx->J0[AES_BLOCK_BYTES - 1] |= 1; + } else { + /* For IV != 96 bit, J0 = GHASH(IV || 0[s+64] || [len(IV)]64) */ + /* First calculate GHASH on IV */ + esp_gcm_ghash(ctx, ctx->iv, ctx->iv_len, ctx->J0); + /* Next create 128 bit block which is equal to + 64 bit 0 + iv length truncated to 64 bits */ + ESP_PUT_BE64(len_buf + 8, ctx->iv_len * 8); + /* Calculate GHASH on last block */ + esp_gcm_ghash(ctx, len_buf, 16, ctx->J0); + + + } +} + + +/* + * Increment J0 as per GCM spec, by applying the Standard Incrementing + Function INC_32 to it. + * j is the counter which needs to be incremented which is + * copied to ctx->J0 after incrementing + */ +static void increment32_j0(esp_gcm_context *ctx, uint8_t *j) +{ + uint8_t j_len = AES_BLOCK_BYTES; + memcpy(j, ctx->J0, AES_BLOCK_BYTES); + if (j) { + for (uint32_t i = j_len; i > (j_len - 4); i--) { + if (++j[i - 1] != 0) { + break; + } + } + memcpy(ctx->J0, j, AES_BLOCK_BYTES); + } +} + +/* Function to xor two data blocks */ +static void xor_data(uint8_t *d, const uint8_t *s) +{ + for (int i = 0; i < AES_BLOCK_BYTES; i++) { + d[i] ^= s[i]; + } +} + + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* Based on MbedTLS's implemenation + * + * Precompute small multiples of H, that is set + * HH[i] || HL[i] = H times i, + * where i is seen as a field element as in [MGV], ie high-order bits + * correspond to low powers of P. The result is stored in the same way, that + * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL + * corresponds to P^127. + */ +static int gcm_gen_table( esp_gcm_context *ctx ) +{ + int i, j; + uint64_t hi, lo; + uint64_t vl, vh; + unsigned char *h; + + h = ctx->H; + + /* pack h as two 64-bits ints, big-endian */ + GET_UINT32_BE( hi, h, 0 ); + GET_UINT32_BE( lo, h, 4 ); + vh = (uint64_t) hi << 32 | lo; + + GET_UINT32_BE( hi, h, 8 ); + GET_UINT32_BE( lo, h, 12 ); + vl = (uint64_t) hi << 32 | lo; + + /* 8 = 1000 corresponds to 1 in GF(2^128) */ + ctx->HL[8] = vl; + ctx->HH[8] = vh; + + /* 0 corresponds to 0 in GF(2^128) */ + ctx->HH[0] = 0; + ctx->HL[0] = 0; + + for ( i = 4; i > 0; i >>= 1 ) { + uint32_t T = ( vl & 1 ) * 0xe1000000U; + vl = ( vh << 63 ) | ( vl >> 1 ); + vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32); + + ctx->HL[i] = vl; + ctx->HH[i] = vh; + } + + for ( i = 2; i <= 8; i *= 2 ) { + uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; + vh = *HiH; + vl = *HiL; + for ( j = 1; j < i; j++ ) { + HiH[j] = vh ^ ctx->HH[j]; + HiL[j] = vl ^ ctx->HL[j]; + } + } + + return ( 0 ); +} +/* + * Shoup's method for multiplication use this table with + * last4[x] = x times P^128 + * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] + */ +static const uint32_t last4[16] = { + 0x00000000, 0x1c200000, 0x38400000, 0x24600000, + 0x70800000, 0x6ca00000, 0x48c00000, 0x54e00000, + 0xe1000000, 0xfd200000, 0xd9400000, 0xc5600000, + 0x91800000, 0x8da00000, 0xa9c00000, 0xb5e00000 +}; +/* Based on MbedTLS's implemenation + * + * Sets output to x times H using the precomputed tables. + * x and output are seen as elements of GF(2^128) as in [MGV]. + */ +static void gcm_mult( esp_gcm_context *ctx, const unsigned char x[16], + unsigned char output[16] ) +{ + int i = 0; + unsigned char lo, hi, rem; + uint64_t zh, zl; + + lo = x[15] & 0xf; + hi = x[15] >> 4; + + zh = ctx->HH[lo]; + zl = ctx->HL[lo]; + + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 32; + zh ^= ctx->HH[hi]; + zl ^= ctx->HL[hi]; + + for ( i = 14; i >= 0; i-- ) { + lo = x[i] & 0xf; + hi = x[i] >> 4; + + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 32; + zh ^= ctx->HH[lo]; + zl ^= ctx->HL[lo]; + + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 32; + zh ^= ctx->HH[hi]; + zl ^= ctx->HL[hi]; + } + + PUT_UINT32_BE( zh >> 32, output, 0 ); + PUT_UINT32_BE( zh, output, 4 ); + PUT_UINT32_BE( zl >> 32, output, 8 ); + PUT_UINT32_BE( zl, output, 12 ); +} + + + +/* Update the key value in gcm context */ +int esp_aes_gcm_setkey( esp_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + /* Fallback to software implementation of GCM operation when a non-AES + * cipher is selected, as we support hardware acceleration only for a + * GCM operation using AES cipher. + */ +#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK) + if (ctx->ctx_soft != NULL) { + mbedtls_gcm_free_soft(ctx->ctx_soft); + free(ctx->ctx_soft); + ctx->ctx_soft = NULL; + } + + if (cipher != MBEDTLS_CIPHER_ID_AES) { + ctx->ctx_soft = (mbedtls_gcm_context_soft*) malloc(sizeof(mbedtls_gcm_context_soft)); + if (ctx->ctx_soft == NULL) { + return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; + } + mbedtls_gcm_init_soft(ctx->ctx_soft); + return mbedtls_gcm_setkey_soft(ctx->ctx_soft, cipher, key, keybits); + } +#endif + +#if !SOC_AES_SUPPORT_AES_192 + if (keybits == 192) { + return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; + } +#endif + if (keybits != 128 && keybits != 192 && keybits != 256) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + + ctx->aes_ctx.key_bytes = keybits / 8; + + memcpy(ctx->aes_ctx.key, key, ctx->aes_ctx.key_bytes); + + return ( 0 ); +} + + +/* AES-GCM GHASH calculation z = GHASH(x) using h0 hash key +*/ +static void esp_gcm_ghash(esp_gcm_context *ctx, const unsigned char *x, size_t x_len, uint8_t *z) +{ + + uint8_t tmp[AES_BLOCK_BYTES]; + + memset(tmp, 0, AES_BLOCK_BYTES); + /* GHASH(X) is calculated on input string which is multiple of 128 bits + * If input string bit length is not multiple of 128 bits it needs to + * be padded by 0 + * + * Steps: + * 1. Let X1, X2, ... , Xm-1, Xm denote the unique sequence of blocks such + * that X = X1 || X2 || ... || Xm-1 || Xm. + * 2. Let Y0 be the “zero block,†0128. + * 3. Fori=1,...,m,letYi =(Yi-1 ^ Xi)•H. + * 4. Return Ym + */ + + /* If input bit string is >= 128 bits, process full 128 bit blocks */ + while (x_len >= AES_BLOCK_BYTES) { + + xor_data(z, x); + gcm_mult(ctx, z, z); + + x += AES_BLOCK_BYTES; + x_len -= AES_BLOCK_BYTES; + } + + /* If input bit string is not multiple of 128 create last 128 bit + * block by padding necessary 0s + */ + if (x_len) { + memcpy(tmp, x, x_len); + xor_data(z, tmp); + gcm_mult(ctx, z, z); + } +} + + +/* Function to init AES GCM context to zero */ +void esp_aes_gcm_init( esp_gcm_context *ctx) +{ + if (ctx == NULL) { + return; + } + + bzero(ctx, sizeof(esp_gcm_context)); + +#if SOC_AES_SUPPORT_DMA && CONFIG_MBEDTLS_AES_USE_INTERRUPT + esp_aes_intr_alloc(); +#endif + + ctx->gcm_state = ESP_AES_GCM_STATE_INIT; +} + +/* Function to clear AES-GCM context */ +void esp_aes_gcm_free( esp_gcm_context *ctx) +{ + if (ctx == NULL) { + return; + } +#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK) + if (ctx->ctx_soft != NULL) { + mbedtls_gcm_free_soft(ctx->ctx_soft); + free(ctx->ctx_soft); + /* Note that the value of ctx->ctx_soft should be NULL'ed out + and here it is taken care by the bzero call below */ + } +#endif + bzero(ctx, sizeof(esp_gcm_context)); +} + +/* Setup AES-GCM */ +int esp_aes_gcm_starts( esp_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len ) +{ + if (!ctx) { + ESP_LOGE(TAG, "No AES context supplied"); + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + +#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK) + if (ctx->ctx_soft != NULL) { + return mbedtls_gcm_starts_soft(ctx->ctx_soft, mode, iv, iv_len); + } +#endif + + /* IV is limited to 2^32 bits, so 2^29 bytes */ + /* IV is not allowed to be zero length */ + if ( iv_len == 0 || + ( (uint32_t) iv_len ) >> 29 != 0 ) { + return ( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + if (!iv) { + ESP_LOGE(TAG, "No IV supplied"); + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + + /* Initialize AES-GCM context */ + memset(ctx->ghash, 0, sizeof(ctx->ghash)); + ctx->data_len = 0; + ctx->aad = NULL; + ctx->aad_len = 0; + + ctx->iv = iv; + ctx->iv_len = iv_len; + ctx->mode = mode; + + /* H and the lookup table are only generated once per ctx */ + if (ctx->gcm_state == ESP_AES_GCM_STATE_INIT) { + /* Lock the AES engine to calculate ghash key H in hardware */ +#if CONFIG_MBEDTLS_HARDWARE_GCM + esp_aes_acquire_hardware(); + ctx->aes_ctx.key_in_hardware = aes_hal_setkey(ctx->aes_ctx.key, ctx->aes_ctx.key_bytes, mode); + aes_hal_mode_init(ESP_AES_BLOCK_MODE_GCM); + + aes_hal_gcm_calc_hash(ctx->H); + + esp_aes_release_hardware(); +#else + memset(ctx->H, 0, sizeof(ctx->H)); + int ret = esp_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->H, ctx->H); + if (ret != 0) { + return ret; + } +#endif + gcm_gen_table(ctx); + } + + /* Once H is obtained we need to derive J0 (Initial Counter Block) */ + esp_gcm_derive_J0(ctx); + + /* The initial counter block keeps updating during the esp_gcm_update call + * however to calculate final authentication tag T we need original J0 + * so we make a copy here + */ + memcpy(ctx->ori_j0, ctx->J0, 16); + + ctx->gcm_state = ESP_AES_GCM_STATE_START; + + return ( 0 ); +} + +int esp_aes_gcm_update_ad( esp_gcm_context *ctx, + const unsigned char *aad, + size_t aad_len ) +{ + if (!ctx) { + ESP_LOGE(TAG, "No AES context supplied"); + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + +#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK) + if (ctx->ctx_soft != NULL) { + return mbedtls_gcm_update_ad_soft(ctx->ctx_soft, aad, aad_len); + } +#endif + + /* AD are limited to 2^32 bits, so 2^29 bytes */ + if ( ( (uint32_t) aad_len ) >> 29 != 0 ) { + return ( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + if ( (aad_len > 0) && !aad) { + ESP_LOGE(TAG, "No aad supplied"); + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + + if (ctx->gcm_state != ESP_AES_GCM_STATE_START) { + ESP_LOGE(TAG, "AES context in invalid state!"); + return -1; + } + + /* Initialise associated data */ + ctx->aad = aad; + ctx->aad_len = aad_len; + + esp_gcm_ghash(ctx, ctx->aad, ctx->aad_len, ctx->ghash); + + return ( 0 ); +} + +/* Perform AES-GCM operation */ +int esp_aes_gcm_update( esp_gcm_context *ctx, + const unsigned char *input, size_t input_length, + unsigned char *output, size_t output_size, + size_t *output_length ) +{ + if (!ctx) { + ESP_LOGE(TAG, "No GCM context supplied"); + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + +#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK) + if (ctx->ctx_soft != NULL) { + return mbedtls_gcm_update_soft(ctx->ctx_soft, input, input_length, output, output_size, output_length); + } +#endif + + size_t nc_off = 0; + uint8_t nonce_counter[AES_BLOCK_BYTES] = {0}; + uint8_t stream[AES_BLOCK_BYTES] = {0}; + + if (!output_length) { + ESP_LOGE(TAG, "No output length supplied"); + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + *output_length = input_length; + + if (!input) { + ESP_LOGE(TAG, "No input supplied"); + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + if (!output) { + ESP_LOGE(TAG, "No output supplied"); + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + + if ( output > input && (size_t) ( output - input ) < input_length ) { + return ( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + /* If this is the first time esp_gcm_update is getting called + * calculate GHASH on aad and preincrement the ICB + */ + if (ctx->gcm_state == ESP_AES_GCM_STATE_START) { + /* Jo needs to be incremented first time, later the CTR + * operation will auto update it + */ + increment32_j0(ctx, nonce_counter); + ctx->gcm_state = ESP_AES_GCM_STATE_UPDATE; + } else if (ctx->gcm_state == ESP_AES_GCM_STATE_UPDATE) { + memcpy(nonce_counter, ctx->J0, AES_BLOCK_BYTES); + } + + /* Perform intermediate GHASH on "encrypted" data during decryption */ + if (ctx->mode == ESP_AES_DECRYPT) { + esp_gcm_ghash(ctx, input, input_length, ctx->ghash); + } + + /* Output = GCTR(J0, Input): Encrypt/Decrypt the input */ + int ret = esp_aes_crypt_ctr(&ctx->aes_ctx, input_length, &nc_off, nonce_counter, stream, input, output); + if (ret != 0) { + return ret; + } + + /* ICB gets auto incremented after GCTR operation here so update the context */ + memcpy(ctx->J0, nonce_counter, AES_BLOCK_BYTES); + + /* Keep updating the length counter for final tag calculation */ + ctx->data_len += input_length; + + /* Perform intermediate GHASH on "encrypted" data during encryption*/ + if (ctx->mode == ESP_AES_ENCRYPT) { + esp_gcm_ghash(ctx, output, input_length, ctx->ghash); + } + + return 0; +} + +/* Function to read the tag value */ +int esp_aes_gcm_finish( esp_gcm_context *ctx, + unsigned char *output, size_t output_size, + size_t *output_length, + unsigned char *tag, size_t tag_len ) +{ +#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK) + if (ctx->ctx_soft != NULL) { + return mbedtls_gcm_finish_soft(ctx->ctx_soft, output, output_size, output_length, tag, tag_len); + } +#endif + size_t nc_off = 0; + uint8_t len_block[AES_BLOCK_BYTES] = {0}; + uint8_t stream[AES_BLOCK_BYTES] = {0}; + + if ( tag_len > 16 || tag_len < 4 ) { + return ( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + /* Calculate final GHASH on aad_len, data length */ + ESP_PUT_BE64(len_block, ctx->aad_len * 8); + ESP_PUT_BE64(len_block + 8, ctx->data_len * 8); + esp_gcm_ghash(ctx, len_block, AES_BLOCK_BYTES, ctx->ghash); + + /* Tag T = GCTR(J0, ) where T is truncated to tag_len */ + return esp_aes_crypt_ctr(&ctx->aes_ctx, tag_len, &nc_off, ctx->ori_j0, stream, ctx->ghash, tag); +} + +#if CONFIG_MBEDTLS_HARDWARE_GCM +/* Due to restrictions in the hardware (e.g. need to do the whole conversion in one go), + some combinations of inputs are not supported */ +static bool esp_aes_gcm_input_support_hw_accel(size_t length, const unsigned char *aad, size_t aad_len, + const unsigned char *input, unsigned char *output, uint8_t *stream_in) +{ + bool support_hw_accel = true; + + if (aad_len > ESP_AES_GCM_AAD_MAX_BYTES) { + support_hw_accel = false; + } else if (!esp_ptr_dma_capable(aad) && aad_len > 0) { + /* aad in non internal DMA memory */ + support_hw_accel = false; + } else if (!esp_ptr_dma_capable(input) && length > 0) { + /* input in non internal DMA memory */ + support_hw_accel = false; + } else if (!esp_ptr_dma_capable(output) && length > 0) { + /* output in non internal DMA memory */ + support_hw_accel = false; + } else if (!esp_ptr_dma_capable(stream_in)) { + /* Stream in (and therefor other descriptors and buffers that come from the stack) + in non internal DMA memory */ + support_hw_accel = false; + } else if (length == 0) { + support_hw_accel = false; + } + + + return support_hw_accel; +} +#endif + +static int esp_aes_gcm_crypt_and_tag_partial_hw( esp_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ) +{ + int ret = 0; + size_t olen; + + if ( ( ret = esp_aes_gcm_starts( ctx, mode, iv, iv_len ) ) != 0 ) { + return ( ret ); + } + + if ( ( ret = esp_aes_gcm_update_ad( ctx, aad, aad_len ) ) != 0 ) { + return ( ret ); + } + + if ( ( ret = esp_aes_gcm_update( ctx, input, length, output, 0, &olen ) ) != 0 ) { + return ( ret ); + } + + if ( ( ret = esp_aes_gcm_finish( ctx, output, 0, &olen, tag, tag_len ) ) != 0 ) { + return ( ret ); + } + + return ret; +} + +int esp_aes_gcm_crypt_and_tag( esp_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ) +{ + if (!ctx) { + ESP_LOGE(TAG, "No AES context supplied"); + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + +#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK) + if (ctx->ctx_soft != NULL) { + return mbedtls_gcm_crypt_and_tag_soft(ctx->ctx_soft, mode, length, iv, iv_len, aad, aad_len, input, output, tag_len, tag); + } +#endif +#if CONFIG_MBEDTLS_HARDWARE_GCM + int ret; + lldesc_t aad_desc[2] = {}; + lldesc_t *aad_head_desc = NULL; + size_t remainder_bit; + uint8_t stream_in[AES_BLOCK_BYTES] = {}; + unsigned stream_bytes = aad_len % AES_BLOCK_BYTES; // bytes which aren't in a full block + unsigned block_bytes = aad_len - stream_bytes; // bytes which are in a full block + + /* Due to hardware limition only certain cases are fully supported in HW */ + if (!esp_aes_gcm_input_support_hw_accel(length, aad, aad_len, input, output, stream_in)) { + return esp_aes_gcm_crypt_and_tag_partial_hw(ctx, mode, length, iv, iv_len, aad, aad_len, input, output, tag_len, tag); + } + + /* Limit aad len to a single DMA descriptor to simplify DMA handling + In practice, e.g. with mbedtls the length of aad will always be short + */ + if (aad_len > LLDESC_MAX_NUM_PER_DESC) { + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + /* IV and AD are limited to 2^32 bits, so 2^29 bytes */ + /* IV is not allowed to be zero length */ + if ( iv_len == 0 || + ( (uint32_t) iv_len ) >> 29 != 0 || + ( (uint32_t) aad_len ) >> 29 != 0 ) { + return ( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + if (!iv) { + ESP_LOGE(TAG, "No IV supplied"); + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + + if ( (aad_len > 0) && !aad) { + ESP_LOGE(TAG, "No aad supplied"); + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + + /* Initialize AES-GCM context */ + memset(ctx->ghash, 0, sizeof(ctx->ghash)); + ctx->data_len = 0; + + ctx->iv = iv; + ctx->iv_len = iv_len; + ctx->aad = aad; + ctx->aad_len = aad_len; + ctx->mode = mode; + + esp_aes_acquire_hardware(); + ctx->aes_ctx.key_in_hardware = 0; + ctx->aes_ctx.key_in_hardware = aes_hal_setkey(ctx->aes_ctx.key, ctx->aes_ctx.key_bytes, mode); + + if (block_bytes > 0) { + aad_desc[0].length = block_bytes; + aad_desc[0].size = block_bytes; + aad_desc[0].owner = 1; + aad_desc[0].buf = aad; + } + + if (stream_bytes > 0) { + memcpy(stream_in, aad + block_bytes, stream_bytes); + + aad_desc[0].empty = (uint32_t)&aad_desc[1]; + aad_desc[1].length = AES_BLOCK_BYTES; + aad_desc[1].size = AES_BLOCK_BYTES; + aad_desc[1].owner = 1; + aad_desc[1].buf = stream_in; + } + + if (block_bytes > 0) { + aad_head_desc = &aad_desc[0]; + } else if (stream_bytes > 0) { + aad_head_desc = &aad_desc[1]; + } + + aes_hal_mode_init(ESP_AES_BLOCK_MODE_GCM); + + /* See TRM GCM chapter for description of this calculation */ + remainder_bit = (8 * length) % 128; + aes_hal_gcm_init( (aad_len + AES_BLOCK_BYTES - 1) / AES_BLOCK_BYTES, remainder_bit); + aes_hal_gcm_calc_hash(ctx->H); + + gcm_gen_table(ctx); + esp_gcm_derive_J0(ctx); + + aes_hal_gcm_set_j0(ctx->J0); + + ret = esp_aes_process_dma_gcm(&ctx->aes_ctx, input, output, length, aad_head_desc, aad_len); + if (ret != 0) { + esp_aes_release_hardware(); + return ret; + } + + aes_hal_gcm_read_tag(tag, tag_len); + + esp_aes_release_hardware(); + + return ( ret ); +#else + return esp_aes_gcm_crypt_and_tag_partial_hw(ctx, mode, length, iv, iv_len, aad, aad_len, input, output, tag_len, tag); +#endif +} + + +int esp_aes_gcm_auth_decrypt( esp_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *aad, + size_t aad_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ) +{ +#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK) + if (ctx->ctx_soft != NULL) { + return mbedtls_gcm_auth_decrypt_soft(ctx->ctx_soft, length, iv, iv_len, aad, aad_len, tag, tag_len, input, output); + } +#endif + int ret; + unsigned char check_tag[16]; + size_t i; + int diff; + + if ( ( ret = esp_aes_gcm_crypt_and_tag( ctx, ESP_AES_DECRYPT, length, + iv, iv_len, aad, aad_len, + input, output, tag_len, check_tag ) ) != 0 ) { + return ( ret ); + } + + /* Check tag in "constant-time" */ + for ( diff = 0, i = 0; i < tag_len; i++ ) { + diff |= tag[i] ^ check_tag[i]; + } + + if ( diff != 0 ) { + bzero( output, length ); + return ( MBEDTLS_ERR_GCM_AUTH_FAILED ); + } + + return ( 0 ); +} diff --git a/components/mbedtls/mbedtls_v3/port/aes/esp_aes_xts.c b/components/mbedtls/mbedtls_v3/port/aes/esp_aes_xts.c new file mode 100644 index 000000000..d91f17e4e --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/aes/esp_aes_xts.c @@ -0,0 +1,284 @@ +/** + * \brief AES block cipher, ESP32-S2 hardware accelerated version + * Based on mbedTLS FIPS-197 compliant version. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE Ltd + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ + + +/* Below XTS implementation is copied aes.c of mbedtls library. + * When MBEDTLS_AES_ALT is defined mbedtls expects alternate + * definition of XTS functions to be available. Even if this + * could have been avoided, it is done for consistency reason. + */ + +#include +#include +#include +#include "mbedtls/aes.h" + +#include "aes/esp_aes.h" + +void esp_aes_xts_init( esp_aes_xts_context *ctx ) +{ + esp_aes_init( &ctx->crypt ); + esp_aes_init( &ctx->tweak ); +} + +void esp_aes_xts_free( esp_aes_xts_context *ctx ) +{ + esp_aes_free( &ctx->crypt ); + esp_aes_free( &ctx->tweak ); +} + +static int esp_aes_xts_decode_keys( const unsigned char *key, + unsigned int keybits, + const unsigned char **key1, + unsigned int *key1bits, + const unsigned char **key2, + unsigned int *key2bits ) +{ + const unsigned int half_keybits = keybits / 2; + const unsigned int half_keybytes = half_keybits / 8; + + switch ( keybits ) { + case 256: break; + case 512: break; + default : return ( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + *key1bits = half_keybits; + *key2bits = half_keybits; + *key1 = &key[0]; + *key2 = &key[half_keybytes]; + + return 0; +} + +int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + ret = esp_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if ( ret != 0 ) { + return ( ret ); + } + + /* Set the tweak key. Always set tweak key for the encryption mode. */ + ret = esp_aes_setkey( &ctx->tweak, key2, key2bits ); + if ( ret != 0 ) { + return ( ret ); + } + + /* Set crypt key for encryption. */ + return esp_aes_setkey( &ctx->crypt, key1, key1bits ); +} + +int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + ret = esp_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if ( ret != 0 ) { + return ( ret ); + } + + /* Set the tweak key. Always set tweak key for encryption. */ + ret = esp_aes_setkey( &ctx->tweak, key2, key2bits ); + if ( ret != 0 ) { + return ( ret ); + } + + /* Set crypt key for decryption. */ + return esp_aes_setkey( &ctx->crypt, key1, key1bits ); +} + +/* Endianess with 64 bits values */ +#ifndef GET_UINT64_LE +#define GET_UINT64_LE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \ + | ( (uint64_t) (b)[(i) + 6] << 48 ) \ + | ( (uint64_t) (b)[(i) + 5] << 40 ) \ + | ( (uint64_t) (b)[(i) + 4] << 32 ) \ + | ( (uint64_t) (b)[(i) + 3] << 24 ) \ + | ( (uint64_t) (b)[(i) + 2] << 16 ) \ + | ( (uint64_t) (b)[(i) + 1] << 8 ) \ + | ( (uint64_t) (b)[(i) ] ); \ +} +#endif + +#ifndef PUT_UINT64_LE +#define PUT_UINT64_LE(n,b,i) \ +{ \ + (b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) ] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * GF(2^128) multiplication function + * + * This function multiplies a field element by x in the polynomial field + * representation. It uses 64-bit word operations to gain speed but compensates + * for machine endianess and hence works correctly on both big and little + * endian machines. + */ +static void esp_gf128mul_x_ble( unsigned char r[16], + const unsigned char x[16] ) +{ + uint64_t a, b, ra, rb; + + GET_UINT64_LE( a, x, 0 ); + GET_UINT64_LE( b, x, 8 ); + + ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) ); + rb = ( a >> 63 ) | ( b << 1 ); + + PUT_UINT64_LE( ra, r, 0 ); + PUT_UINT64_LE( rb, r, 8 ); +} + +/* + * AES-XTS buffer encryption/decryption + */ +int esp_aes_crypt_xts( esp_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t blocks = length / 16; + size_t leftover = length % 16; + unsigned char tweak[16]; + unsigned char prev_tweak[16]; + unsigned char tmp[16]; + + /* Sectors must be at least 16 bytes. */ + if ( length < 16 ) { + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + } + + /* NIST SP 80-38E disallows data units larger than 2**20 blocks. */ + if ( length > ( 1 << 20 ) * 16 ) { + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + } + + /* Compute the tweak. */ + ret = esp_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT, + data_unit, tweak ); + if ( ret != 0 ) { + return ( ret ); + } + + while ( blocks-- ) { + size_t i; + + if ( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 ) { + /* We are on the last block in a decrypt operation that has + * leftover bytes, so we need to use the next tweak for this block, + * and this tweak for the lefover bytes. Save the current tweak for + * the leftovers and then update the current tweak for use on this, + * the last full block. */ + memcpy( prev_tweak, tweak, sizeof( tweak ) ); + esp_gf128mul_x_ble( tweak, tweak ); + } + + for ( i = 0; i < 16; i++ ) { + tmp[i] = input[i] ^ tweak[i]; + } + + ret = esp_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if ( ret != 0 ) { + return ( ret ); + } + + for ( i = 0; i < 16; i++ ) { + output[i] = tmp[i] ^ tweak[i]; + } + + /* Update the tweak for the next block. */ + esp_gf128mul_x_ble( tweak, tweak ); + + output += 16; + input += 16; + } + + if ( leftover ) { + /* If we are on the leftover bytes in a decrypt operation, we need to + * use the previous tweak for these bytes (as saved in prev_tweak). */ + unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak; + + /* We are now on the final part of the data unit, which doesn't divide + * evenly by 16. It's time for ciphertext stealing. */ + size_t i; + unsigned char *prev_output = output - 16; + + /* Copy ciphertext bytes from the previous block to our output for each + * byte of cyphertext we won't steal. At the same time, copy the + * remainder of the input for this final round (since the loop bounds + * are the same). */ + for ( i = 0; i < leftover; i++ ) { + output[i] = prev_output[i]; + tmp[i] = input[i] ^ t[i]; + } + + /* Copy ciphertext bytes from the previous block for input in this + * round. */ + for ( ; i < 16; i++ ) { + tmp[i] = prev_output[i] ^ t[i]; + } + + ret = esp_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if ( ret != 0 ) { + return ret; + } + + /* Write the result back to the previous block, overriding the previous + * output we copied. */ + for ( i = 0; i < 16; i++ ) { + prev_output[i] = tmp[i] ^ t[i]; + } + } + + return ( 0 ); +} diff --git a/components/mbedtls/mbedtls_v3/port/crypto_shared_gdma/esp_crypto_shared_gdma.c b/components/mbedtls/mbedtls_v3/port/crypto_shared_gdma/esp_crypto_shared_gdma.c new file mode 100644 index 000000000..b9899c344 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/crypto_shared_gdma/esp_crypto_shared_gdma.c @@ -0,0 +1,148 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_crypto_shared_gdma.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "hal/gdma_ll.h" +#include "soc/soc_caps.h" +#include "esp_log.h" +#include "esp_err.h" +#include "esp_crypto_lock.h" + +#define NEW_CHANNEL_TIMEOUT_MS 1000 +#define NEW_CHANNEL_DELAY_MS 100 + +static const char *TAG = "crypto_shared_gdma"; + +static gdma_channel_handle_t rx_channel; +static gdma_channel_handle_t tx_channel; + +/* Allocate a new GDMA channel, will keep trying until NEW_CHANNEL_TIMEOUT_MS */ +static inline esp_err_t crypto_shared_gdma_new_channel(gdma_channel_alloc_config_t *channel_config, gdma_channel_handle_t *channel) +{ + esp_err_t ret; + int time_waited_ms = 0; + + while (1) { + ret = gdma_new_channel(channel_config, channel); + + if (ret == ESP_OK) { + break; + } else if (time_waited_ms >= NEW_CHANNEL_TIMEOUT_MS) { + *channel = NULL; + break; + } + + time_waited_ms += NEW_CHANNEL_DELAY_MS; + vTaskDelay(NEW_CHANNEL_DELAY_MS / portTICK_PERIOD_MS); + } + return ret; +} + +/* Initialize GDMA module and channels */ +static esp_err_t crypto_shared_gdma_init(void) +{ + esp_err_t ret; + + gdma_channel_alloc_config_t channel_config_tx = { + .direction = GDMA_CHANNEL_DIRECTION_TX, + }; + + gdma_channel_alloc_config_t channel_config_rx = { + .direction = GDMA_CHANNEL_DIRECTION_RX, + }; + + gdma_transfer_ability_t transfer_ability = { + .sram_trans_align = 1, + }; + + + ret = crypto_shared_gdma_new_channel(&channel_config_tx, &tx_channel); + if (ret != ESP_OK) { + goto err; + } + + ret = crypto_shared_gdma_new_channel(&channel_config_rx, &rx_channel); + if (ret != ESP_OK) { + gdma_del_channel(tx_channel); // Clean up already allocated TX channel + goto err; + } + + + gdma_set_transfer_ability(tx_channel, &transfer_ability); + gdma_set_transfer_ability(rx_channel, &transfer_ability); + + gdma_connect(rx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_AES, 0)); + gdma_connect(tx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_AES, 0)); + + return ESP_OK; + +err: + ESP_LOGE(TAG, "Failed to acquire DMA channel, Err=%d", ret); + tx_channel = NULL; + rx_channel = NULL; + + return ret; +} + + +esp_err_t esp_crypto_shared_gdma_start(const lldesc_t *input, const lldesc_t *output, gdma_trigger_peripheral_t peripheral) +{ + int rx_ch_id = 0; + esp_err_t ret = ESP_OK; + + if (tx_channel == NULL) { + /* Allocate a pair of RX and TX for crypto, should only happen the first time we use the GMDA + or if user called esp_crypto_shared_gdma_release */ + ret = crypto_shared_gdma_init(); + } + + if (ret != ESP_OK) { + return ret; + } + + /* Tx channel is shared between AES and SHA, need to connect to peripheral every time */ + gdma_disconnect(tx_channel); + + if (peripheral == GDMA_TRIG_PERIPH_SHA) { + gdma_connect(tx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SHA, 0)); + } else if (peripheral == GDMA_TRIG_PERIPH_AES) { + gdma_connect(tx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_AES, 0)); + } else { + return ESP_ERR_INVALID_ARG; + } + + /* tx channel is reset by gdma_connect(), also reset rx to ensure a known state */ + gdma_get_channel_id(rx_channel, &rx_ch_id); + gdma_ll_rx_reset_channel(&GDMA, rx_ch_id); + + gdma_start(tx_channel, (intptr_t)input); + gdma_start(rx_channel, (intptr_t)output); + + return ESP_OK; +} + +void esp_crypto_shared_gdma_free() +{ + esp_crypto_sha_aes_lock_acquire(); + + if (rx_channel != NULL) { + gdma_disconnect(rx_channel); + gdma_del_channel(rx_channel); + rx_channel = NULL; + } + + if (tx_channel != NULL) { + gdma_disconnect(tx_channel); + gdma_del_channel(tx_channel); + tx_channel = NULL; + } + + esp_crypto_sha_aes_lock_release(); +} diff --git a/components/mbedtls/mbedtls_v3/port/dynamic/esp_mbedtls_dynamic_impl.c b/components/mbedtls/mbedtls_v3/port/dynamic/esp_mbedtls_dynamic_impl.c new file mode 100644 index 000000000..d76f6b504 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/dynamic/esp_mbedtls_dynamic_impl.c @@ -0,0 +1,555 @@ +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_mbedtls_dynamic_impl.h" +#include "sdkconfig.h" + +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE +#include "esp_crt_bundle.h" +#endif + +#define COUNTER_SIZE (8) +#define CACHE_IV_SIZE (16) +#define CACHE_BUFFER_SIZE (CACHE_IV_SIZE + COUNTER_SIZE) + +#define TX_IDLE_BUFFER_SIZE (MBEDTLS_SSL_HEADER_LEN + CACHE_BUFFER_SIZE) + +static const char *TAG = "Dynamic Impl"; + +static void esp_mbedtls_set_buf_state(unsigned char *buf, esp_mbedtls_ssl_buf_states state) +{ + struct esp_mbedtls_ssl_buf *temp = __containerof(buf, struct esp_mbedtls_ssl_buf, buf[0]); + temp->state = state; +} + +static esp_mbedtls_ssl_buf_states esp_mbedtls_get_buf_state(unsigned char *buf) +{ + struct esp_mbedtls_ssl_buf *temp = __containerof(buf, struct esp_mbedtls_ssl_buf, buf[0]); + return temp->state; +} + +void esp_mbedtls_free_buf(unsigned char *buf) +{ + struct esp_mbedtls_ssl_buf *temp = __containerof(buf, struct esp_mbedtls_ssl_buf, buf[0]); + ESP_LOGV(TAG, "free buffer @ %p", temp); + mbedtls_free(temp); +} + +static void esp_mbedtls_init_ssl_buf(struct esp_mbedtls_ssl_buf *buf, unsigned int len) +{ + if (buf) { + buf->state = ESP_MBEDTLS_SSL_BUF_CACHED; + buf->len = len; + } +} + +static void esp_mbedtls_parse_record_header(mbedtls_ssl_context *ssl) +{ + ssl->MBEDTLS_PRIVATE(in_msgtype) = ssl->MBEDTLS_PRIVATE(in_hdr)[0]; + ssl->MBEDTLS_PRIVATE(in_msglen) = (ssl->MBEDTLS_PRIVATE(in_len)[0] << 8) | ssl->MBEDTLS_PRIVATE(in_len)[1]; +} + +static int tx_buffer_len(mbedtls_ssl_context *ssl, int len) +{ + (void)ssl; + + if (!len) { + return MBEDTLS_SSL_OUT_BUFFER_LEN; + } else { + return len + MBEDTLS_SSL_HEADER_LEN + + MBEDTLS_MAX_IV_LENGTH + + MBEDTLS_SSL_MAC_ADD + + MBEDTLS_SSL_PADDING_ADD + + MBEDTLS_SSL_MAX_CID_EXPANSION; + } +} + +static void init_tx_buffer(mbedtls_ssl_context *ssl, unsigned char *buf) +{ + /** + * In mbedtls, ssl->MBEDTLS_PRIVATE(out_msg) = ssl->MBEDTLS_PRIVATE(out_buf) + offset; + */ + if (!buf) { + int out_msg_off = (int)ssl->MBEDTLS_PRIVATE(out_msg) - (int)ssl->MBEDTLS_PRIVATE(out_buf); + + if (!out_msg_off) { + out_msg_off = MBEDTLS_SSL_HEADER_LEN; + } + + ssl->MBEDTLS_PRIVATE(out_buf) = NULL; + ssl->MBEDTLS_PRIVATE(out_ctr) = NULL; + ssl->MBEDTLS_PRIVATE(out_hdr) = NULL; + ssl->MBEDTLS_PRIVATE(out_len) = NULL; + ssl->MBEDTLS_PRIVATE(out_iv) = NULL; + ssl->MBEDTLS_PRIVATE(out_msg) = (unsigned char *)out_msg_off; + } else { + int out_msg_off = (int)ssl->MBEDTLS_PRIVATE(out_msg); + + ssl->MBEDTLS_PRIVATE(out_buf) = buf; + ssl->MBEDTLS_PRIVATE(out_ctr) = ssl->MBEDTLS_PRIVATE(out_buf); + ssl->MBEDTLS_PRIVATE(out_hdr) = ssl->MBEDTLS_PRIVATE(out_buf) + 8; + ssl->MBEDTLS_PRIVATE(out_len) = ssl->MBEDTLS_PRIVATE(out_buf) + 11; + ssl->MBEDTLS_PRIVATE(out_iv) = ssl->MBEDTLS_PRIVATE(out_buf) + MBEDTLS_SSL_HEADER_LEN; + ssl->MBEDTLS_PRIVATE(out_msg) = ssl->MBEDTLS_PRIVATE(out_buf) + out_msg_off; + + ESP_LOGV(TAG, "out msg offset is %d", out_msg_off); + } + + ssl->MBEDTLS_PRIVATE(out_msgtype) = 0; + ssl->MBEDTLS_PRIVATE(out_msglen) = 0; + ssl->MBEDTLS_PRIVATE(out_left) = 0; +} + +static void init_rx_buffer(mbedtls_ssl_context *ssl, unsigned char *buf) +{ + /** + * In mbedtls, ssl->MBEDTLS_PRIVATE(in_msg) = ssl->MBEDTLS_PRIVATE(in_buf) + offset; + */ + if (!buf) { + int in_msg_off = (int)ssl->MBEDTLS_PRIVATE(in_msg) - (int)ssl->MBEDTLS_PRIVATE(in_buf); + + if (!in_msg_off) { + in_msg_off = MBEDTLS_SSL_HEADER_LEN; + } + + ssl->MBEDTLS_PRIVATE(in_buf) = NULL; + ssl->MBEDTLS_PRIVATE(in_ctr) = NULL; + ssl->MBEDTLS_PRIVATE(in_hdr) = NULL; + ssl->MBEDTLS_PRIVATE(in_len) = NULL; + ssl->MBEDTLS_PRIVATE(in_iv) = NULL; + ssl->MBEDTLS_PRIVATE(in_msg) = (unsigned char *)in_msg_off; + } else { + int in_msg_off = (int)ssl->MBEDTLS_PRIVATE(in_msg); + + ssl->MBEDTLS_PRIVATE(in_buf) = buf; + ssl->MBEDTLS_PRIVATE(in_ctr) = ssl->MBEDTLS_PRIVATE(in_buf); + ssl->MBEDTLS_PRIVATE(in_hdr) = ssl->MBEDTLS_PRIVATE(in_buf) + 8; + ssl->MBEDTLS_PRIVATE(in_len) = ssl->MBEDTLS_PRIVATE(in_buf) + 11; + ssl->MBEDTLS_PRIVATE(in_iv) = ssl->MBEDTLS_PRIVATE(in_buf) + MBEDTLS_SSL_HEADER_LEN; + ssl->MBEDTLS_PRIVATE(in_msg) = ssl->MBEDTLS_PRIVATE(in_buf) + in_msg_off; + + ESP_LOGV(TAG, "in msg offset is %d", in_msg_off); + } + + ssl->MBEDTLS_PRIVATE(in_msgtype) = 0; + ssl->MBEDTLS_PRIVATE(in_msglen) = 0; + ssl->MBEDTLS_PRIVATE(in_left) = 0; +} + +static int esp_mbedtls_alloc_tx_buf(mbedtls_ssl_context *ssl, int len) +{ + struct esp_mbedtls_ssl_buf *esp_buf; + + if (ssl->MBEDTLS_PRIVATE(out_buf)) { + esp_mbedtls_free_buf(ssl->MBEDTLS_PRIVATE(out_buf)); + ssl->MBEDTLS_PRIVATE(out_buf) = NULL; + } + + esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + len); + if (!esp_buf) { + ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + len); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + ESP_LOGV(TAG, "add out buffer %d bytes @ %p", len, esp_buf->buf); + + esp_mbedtls_init_ssl_buf(esp_buf, len); + /** + * Mark the out_msg offset from ssl->MBEDTLS_PRIVATE(out_buf). + * + * In mbedtls, ssl->MBEDTLS_PRIVATE(out_msg) = ssl->MBEDTLS_PRIVATE(out_buf) + offset; + */ + ssl->MBEDTLS_PRIVATE(out_msg) = (unsigned char *)MBEDTLS_SSL_HEADER_LEN; + + init_tx_buffer(ssl, esp_buf->buf); + + return 0; +} + +int esp_mbedtls_setup_tx_buffer(mbedtls_ssl_context *ssl) +{ + CHECK_OK(esp_mbedtls_alloc_tx_buf(ssl, TX_IDLE_BUFFER_SIZE)); + + /* mark the out buffer has no data cached */ + esp_mbedtls_set_buf_state(ssl->MBEDTLS_PRIVATE(out_buf), ESP_MBEDTLS_SSL_BUF_NO_CACHED); + + return 0; +} + +void esp_mbedtls_setup_rx_buffer(mbedtls_ssl_context *ssl) +{ + ssl->MBEDTLS_PRIVATE(in_msg) = ssl->MBEDTLS_PRIVATE(in_buf) = NULL; + init_rx_buffer(ssl, NULL); +} + +int esp_mbedtls_reset_add_tx_buffer(mbedtls_ssl_context *ssl) +{ + return esp_mbedtls_alloc_tx_buf(ssl, MBEDTLS_SSL_OUT_BUFFER_LEN); +} + +int esp_mbedtls_reset_free_tx_buffer(mbedtls_ssl_context *ssl) +{ + esp_mbedtls_free_buf(ssl->MBEDTLS_PRIVATE(out_buf)); + init_tx_buffer(ssl, NULL); + + CHECK_OK(esp_mbedtls_setup_tx_buffer(ssl)); + + return 0; +} + +int esp_mbedtls_reset_add_rx_buffer(mbedtls_ssl_context *ssl) +{ + struct esp_mbedtls_ssl_buf *esp_buf; + + if (ssl->MBEDTLS_PRIVATE(in_buf)) { + esp_mbedtls_free_buf(ssl->MBEDTLS_PRIVATE(in_buf)); + ssl->MBEDTLS_PRIVATE(in_buf) = NULL; + } + + esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + MBEDTLS_SSL_IN_BUFFER_LEN); + if (!esp_buf) { + ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + MBEDTLS_SSL_IN_BUFFER_LEN); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + ESP_LOGV(TAG, "add in buffer %d bytes @ %p", MBEDTLS_SSL_IN_BUFFER_LEN, esp_buf->buf); + + esp_mbedtls_init_ssl_buf(esp_buf, MBEDTLS_SSL_IN_BUFFER_LEN); + /** + * Mark the in_msg offset from ssl->MBEDTLS_PRIVATE(in_buf). + * + * In mbedtls, ssl->MBEDTLS_PRIVATE(in_msg) = ssl->MBEDTLS_PRIVATE(in_buf) + offset; + */ + ssl->MBEDTLS_PRIVATE(in_msg) = (unsigned char *)MBEDTLS_SSL_HEADER_LEN; + + init_rx_buffer(ssl, esp_buf->buf); + + return 0; +} + +void esp_mbedtls_reset_free_rx_buffer(mbedtls_ssl_context *ssl) +{ + esp_mbedtls_free_buf(ssl->MBEDTLS_PRIVATE(in_buf)); + init_rx_buffer(ssl, NULL); +} + +int esp_mbedtls_add_tx_buffer(mbedtls_ssl_context *ssl, size_t buffer_len) +{ + int ret = 0; + int cached = 0; + struct esp_mbedtls_ssl_buf *esp_buf; + unsigned char cache_buf[CACHE_BUFFER_SIZE]; + + ESP_LOGV(TAG, "--> add out"); + + if (ssl->MBEDTLS_PRIVATE(out_buf)) { + if (esp_mbedtls_get_buf_state(ssl->MBEDTLS_PRIVATE(out_buf)) == ESP_MBEDTLS_SSL_BUF_CACHED) { + ESP_LOGV(TAG, "out buffer is not empty"); + ret = 0; + goto exit; + } else { + memcpy(cache_buf, ssl->MBEDTLS_PRIVATE(out_buf), CACHE_BUFFER_SIZE); + esp_mbedtls_free_buf(ssl->MBEDTLS_PRIVATE(out_buf)); + init_tx_buffer(ssl, NULL); + cached = 1; + } + } + + buffer_len = tx_buffer_len(ssl, buffer_len); + + esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + buffer_len); + if (!esp_buf) { + ESP_LOGE(TAG, "alloc(%zu bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + buffer_len); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + + ESP_LOGV(TAG, "add out buffer %zu bytes @ %p", buffer_len, esp_buf->buf); + + esp_mbedtls_init_ssl_buf(esp_buf, buffer_len); + init_tx_buffer(ssl, esp_buf->buf); + + if (cached) { + memcpy(ssl->MBEDTLS_PRIVATE(out_ctr), cache_buf, COUNTER_SIZE); + memcpy(ssl->MBEDTLS_PRIVATE(out_iv), cache_buf + COUNTER_SIZE, CACHE_IV_SIZE); + } + + ESP_LOGV(TAG, "ssl->MBEDTLS_PRIVATE(out_buf)=%p ssl->MBEDTLS_PRIVATE(out_msg)=%p", ssl->MBEDTLS_PRIVATE(out_buf), ssl->MBEDTLS_PRIVATE(out_msg)); + +exit: + ESP_LOGV(TAG, "<-- add out"); + + return ret; +} + + +int esp_mbedtls_free_tx_buffer(mbedtls_ssl_context *ssl) +{ + int ret = 0; + unsigned char buf[CACHE_BUFFER_SIZE]; + struct esp_mbedtls_ssl_buf *esp_buf; + + ESP_LOGV(TAG, "--> free out"); + + if (!ssl->MBEDTLS_PRIVATE(out_buf) || (ssl->MBEDTLS_PRIVATE(out_buf) && (esp_mbedtls_get_buf_state(ssl->MBEDTLS_PRIVATE(out_buf)) == ESP_MBEDTLS_SSL_BUF_NO_CACHED))) { + ret = 0; + goto exit; + } + + memcpy(buf, ssl->MBEDTLS_PRIVATE(out_ctr), COUNTER_SIZE); + memcpy(buf + COUNTER_SIZE, ssl->MBEDTLS_PRIVATE(out_iv), CACHE_IV_SIZE); + + esp_mbedtls_free_buf(ssl->MBEDTLS_PRIVATE(out_buf)); + init_tx_buffer(ssl, NULL); + + esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + TX_IDLE_BUFFER_SIZE); + if (!esp_buf) { + ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + TX_IDLE_BUFFER_SIZE); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + esp_mbedtls_init_ssl_buf(esp_buf, TX_IDLE_BUFFER_SIZE); + memcpy(esp_buf->buf, buf, CACHE_BUFFER_SIZE); + init_tx_buffer(ssl, esp_buf->buf); + esp_mbedtls_set_buf_state(ssl->MBEDTLS_PRIVATE(out_buf), ESP_MBEDTLS_SSL_BUF_NO_CACHED); +exit: + ESP_LOGV(TAG, "<-- free out"); + + return ret; +} + +int esp_mbedtls_add_rx_buffer(mbedtls_ssl_context *ssl) +{ + int cached = 0; + int ret = 0; + int buffer_len; + struct esp_mbedtls_ssl_buf *esp_buf; + unsigned char cache_buf[16]; + unsigned char msg_head[5]; + size_t in_msglen, in_left; + + ESP_LOGV(TAG, "--> add rx"); + + if (ssl->MBEDTLS_PRIVATE(in_buf)) { + if (esp_mbedtls_get_buf_state(ssl->MBEDTLS_PRIVATE(in_buf)) == ESP_MBEDTLS_SSL_BUF_CACHED) { + ESP_LOGV(TAG, "in buffer is not empty"); + ret = 0; + goto exit; + } else { + cached = 1; + } + } + + ssl->MBEDTLS_PRIVATE(in_hdr) = msg_head; + ssl->MBEDTLS_PRIVATE(in_len) = msg_head + 3; + + if ((ret = mbedtls_ssl_fetch_input(ssl, mbedtls_ssl_in_hdr_len(ssl))) != 0) { + if (ret == MBEDTLS_ERR_SSL_TIMEOUT) { + ESP_LOGD(TAG, "mbedtls_ssl_fetch_input reads data times out"); + } else if (ret == MBEDTLS_ERR_SSL_WANT_READ) { + ESP_LOGD(TAG, "mbedtls_ssl_fetch_input wants to read more data"); + } else { + ESP_LOGE(TAG, "mbedtls_ssl_fetch_input error=%d", -ret); + } + + goto exit; + } + + esp_mbedtls_parse_record_header(ssl); + + in_left = ssl->MBEDTLS_PRIVATE(in_left); + in_msglen = ssl->MBEDTLS_PRIVATE(in_msglen); + buffer_len = tx_buffer_len(ssl, in_msglen); + + ESP_LOGV(TAG, "message length is %d RX buffer length should be %d left is %d", + (int)in_msglen, (int)buffer_len, (int)ssl->MBEDTLS_PRIVATE(in_left)); + + if (cached) { + memcpy(cache_buf, ssl->MBEDTLS_PRIVATE(in_buf), 16); + esp_mbedtls_free_buf(ssl->MBEDTLS_PRIVATE(in_buf)); + init_rx_buffer(ssl, NULL); + } + + esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + buffer_len); + if (!esp_buf) { + ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + buffer_len); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + + ESP_LOGV(TAG, "add in buffer %d bytes @ %p", buffer_len, esp_buf->buf); + + esp_mbedtls_init_ssl_buf(esp_buf, buffer_len); + init_rx_buffer(ssl, esp_buf->buf); + + if (cached) { + memcpy(ssl->MBEDTLS_PRIVATE(in_ctr), cache_buf, 8); + memcpy(ssl->MBEDTLS_PRIVATE(in_iv), cache_buf + 8, 8); + } + + memcpy(ssl->MBEDTLS_PRIVATE(in_hdr), msg_head, in_left); + ssl->MBEDTLS_PRIVATE(in_left) = in_left; + ssl->MBEDTLS_PRIVATE(in_msglen) = 0; + +exit: + ESP_LOGV(TAG, "<-- add rx"); + + return ret; +} + +int esp_mbedtls_free_rx_buffer(mbedtls_ssl_context *ssl) +{ + int ret = 0; + unsigned char buf[16]; + struct esp_mbedtls_ssl_buf *esp_buf; + + ESP_LOGV(TAG, "--> free rx"); + + /** + * When have read multi messages once, can't free the input buffer directly. + */ + if (!ssl->MBEDTLS_PRIVATE(in_buf) || (ssl->MBEDTLS_PRIVATE(in_hslen) && (ssl->MBEDTLS_PRIVATE(in_hslen) < ssl->MBEDTLS_PRIVATE(in_msglen))) || + (ssl->MBEDTLS_PRIVATE(in_buf) && (esp_mbedtls_get_buf_state(ssl->MBEDTLS_PRIVATE(in_buf)) == ESP_MBEDTLS_SSL_BUF_NO_CACHED))) { + ret = 0; + goto exit; + } + + /** + * The previous processing is just skipped, so "ssl->MBEDTLS_PRIVATE(in_msglen) = 0" + */ + if (!ssl->MBEDTLS_PRIVATE(in_msgtype) +#if defined(MBEDTLS_SSL_SRV_C) + /** + * The ssl server read ClientHello manually without mbedtls_ssl_read_record(), so in_msgtype is not set and is zero. + * ClientHello has been processed and rx buffer should be freed. + * After processing ClientHello, the ssl state has been changed to MBEDTLS_SSL_SERVER_HELLO. + */ + && !(ssl->MBEDTLS_PRIVATE(conf)->MBEDTLS_PRIVATE(endpoint) == MBEDTLS_SSL_IS_SERVER && ssl->MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_SERVER_HELLO) +#endif + ) { + goto exit; + } + + memcpy(buf, ssl->MBEDTLS_PRIVATE(in_ctr), 8); + memcpy(buf + 8, ssl->MBEDTLS_PRIVATE(in_iv), 8); + + esp_mbedtls_free_buf(ssl->MBEDTLS_PRIVATE(in_buf)); + init_rx_buffer(ssl, NULL); + + esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + 16); + if (!esp_buf) { + ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + 16); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + + esp_mbedtls_init_ssl_buf(esp_buf, 16); + memcpy(esp_buf->buf, buf, 16); + init_rx_buffer(ssl, esp_buf->buf); + esp_mbedtls_set_buf_state(ssl->MBEDTLS_PRIVATE(in_buf), ESP_MBEDTLS_SSL_BUF_NO_CACHED); +exit: + ESP_LOGV(TAG, "<-- free rx"); + + return ret; +} + +size_t esp_mbedtls_get_crt_size(mbedtls_x509_crt *cert, size_t *num) +{ + size_t n = 0; + size_t bytes = 0; + + while (cert) { + bytes += cert->raw.len; + n++; + + cert = cert->next; + } + + *num = n; + + return bytes; +} + +#ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA +void esp_mbedtls_free_dhm(mbedtls_ssl_context *ssl) +{ +#ifdef CONFIG_MBEDTLS_DHM_C + const mbedtls_ssl_config *conf = mbedtls_ssl_context_get_config(ssl); + mbedtls_mpi_free((mbedtls_mpi *)&conf->MBEDTLS_PRIVATE(dhm_P)); + mbedtls_mpi_free((mbedtls_mpi *)&conf->MBEDTLS_PRIVATE(dhm_G)); +#endif /* CONFIG_MBEDTLS_DHM_C */ +} + +void esp_mbedtls_free_keycert(mbedtls_ssl_context *ssl) +{ + mbedtls_ssl_config *conf = (mbedtls_ssl_config * )mbedtls_ssl_context_get_config(ssl); + mbedtls_ssl_key_cert *keycert = conf->MBEDTLS_PRIVATE(key_cert), *next; + + while (keycert) { + next = keycert->next; + + if (keycert) { + mbedtls_free(keycert); + } + + keycert = next; + } + + conf->MBEDTLS_PRIVATE(key_cert) = NULL; +} + +void esp_mbedtls_free_keycert_key(mbedtls_ssl_context *ssl) +{ + const mbedtls_ssl_config *conf = mbedtls_ssl_context_get_config(ssl); + mbedtls_ssl_key_cert *keycert = conf->MBEDTLS_PRIVATE(key_cert); + + while (keycert) { + if (keycert->key) { + mbedtls_pk_free(keycert->key); + keycert->key = NULL; + } + keycert = keycert->next; + } +} + +void esp_mbedtls_free_keycert_cert(mbedtls_ssl_context *ssl) +{ + const mbedtls_ssl_config *conf = mbedtls_ssl_context_get_config(ssl); + mbedtls_ssl_key_cert *keycert = conf->MBEDTLS_PRIVATE(key_cert); + + while (keycert) { + if (keycert->cert) { + mbedtls_x509_crt_free(keycert->cert); + keycert->cert = NULL; + } + keycert = keycert->next; + } +} +#endif /* CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA */ + +#ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT +void esp_mbedtls_free_cacert(mbedtls_ssl_context *ssl) +{ + if (ssl->MBEDTLS_PRIVATE(conf)->MBEDTLS_PRIVATE(ca_chain)) { + mbedtls_ssl_config *conf = (mbedtls_ssl_config * )mbedtls_ssl_context_get_config(ssl); + +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE + /* In case of mbedtls certificate bundle, we attach a "static const" + * dummy cert, thus we need to avoid the write operations (memset()) + * performed by `mbedtls_x509_crt_free()` + */ + if (!esp_crt_bundle_in_use(conf->MBEDTLS_PRIVATE(ca_chain))) { + mbedtls_x509_crt_free(conf->MBEDTLS_PRIVATE(ca_chain)); + } +#else + mbedtls_x509_crt_free(conf->MBEDTLS_PRIVATE(ca_chain)); +#endif + + conf->MBEDTLS_PRIVATE(ca_chain) = NULL; + } +} +#endif /* CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT */ diff --git a/components/mbedtls/mbedtls_v3/port/dynamic/esp_mbedtls_dynamic_impl.h b/components/mbedtls/mbedtls_v3/port/dynamic/esp_mbedtls_dynamic_impl.h new file mode 100644 index 000000000..ad7a716be --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/dynamic/esp_mbedtls_dynamic_impl.h @@ -0,0 +1,101 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _DYNAMIC_IMPL_H_ +#define _DYNAMIC_IMPL_H_ + +#include +#include +#include + +/* TODO: Remove this once the appropriate solution is found + * + * ssl_misc.h header uses private elements from + * mbedtls, which become undefined if the following flag + * is not defined + */ +#define MBEDTLS_ALLOW_PRIVATE_ACCESS + +// located at mbedtls/library/ssl_misc.h +#include "ssl_misc.h" + +#include "mbedtls/ssl.h" +#include "mbedtls/platform.h" +#include "esp_log.h" +#include "sdkconfig.h" + +#define TRACE_CHECK(_fn, _state) \ +({ \ + ESP_LOGV(TAG, "%d " _state " to do \"%s\"", __LINE__, # _fn); \ +}) + +#define CHECK_OK(_fn) \ +({ \ + int _ret; \ + \ + TRACE_CHECK(_fn, "state"); \ + \ + if ((_ret = _fn) != 0) { \ + ESP_LOGV(TAG, "\"%s\" result is %d", # _fn, -_ret); \ + TRACE_CHECK(_fn, "fail"); \ + return _ret; \ + } \ + \ + TRACE_CHECK(_fn, "end"); \ + \ +}) + +typedef enum { + ESP_MBEDTLS_SSL_BUF_CACHED, + ESP_MBEDTLS_SSL_BUF_NO_CACHED, +} esp_mbedtls_ssl_buf_states; + +struct esp_mbedtls_ssl_buf { + esp_mbedtls_ssl_buf_states state; + unsigned int len; + unsigned char buf[]; +}; + +#define SSL_BUF_HEAD_OFFSET_SIZE ((int)offsetof(struct esp_mbedtls_ssl_buf, buf)) + +void esp_mbedtls_free_buf(unsigned char *buf); + +int esp_mbedtls_setup_tx_buffer(mbedtls_ssl_context *ssl); + +void esp_mbedtls_setup_rx_buffer(mbedtls_ssl_context *ssl); + +int esp_mbedtls_reset_add_tx_buffer(mbedtls_ssl_context *ssl); + +int esp_mbedtls_reset_add_rx_buffer(mbedtls_ssl_context *ssl); + +int esp_mbedtls_reset_free_tx_buffer(mbedtls_ssl_context *ssl); + +void esp_mbedtls_reset_free_rx_buffer(mbedtls_ssl_context *ssl); + +int esp_mbedtls_add_tx_buffer(mbedtls_ssl_context *ssl, size_t buffer_len); + +int esp_mbedtls_add_rx_buffer(mbedtls_ssl_context *ssl); + +int esp_mbedtls_free_tx_buffer(mbedtls_ssl_context *ssl); + +int esp_mbedtls_free_rx_buffer(mbedtls_ssl_context *ssl); + +size_t esp_mbedtls_get_crt_size(mbedtls_x509_crt *cert, size_t *num); + +#ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA +void esp_mbedtls_free_dhm(mbedtls_ssl_context *ssl); + +void esp_mbedtls_free_keycert(mbedtls_ssl_context *ssl); + +void esp_mbedtls_free_keycert_cert(mbedtls_ssl_context *ssl); + +void esp_mbedtls_free_keycert_key(mbedtls_ssl_context *ssl); +#endif + +#ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT +void esp_mbedtls_free_cacert(mbedtls_ssl_context *ssl); +#endif + +#endif /* _DYNAMIC_IMPL_H_ */ diff --git a/components/mbedtls/mbedtls_v3/port/dynamic/esp_ssl_cli.c b/components/mbedtls/mbedtls_v3/port/dynamic/esp_ssl_cli.c new file mode 100644 index 000000000..0ea78df59 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/dynamic/esp_ssl_cli.c @@ -0,0 +1,221 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "esp_mbedtls_dynamic_impl.h" + +int __real_mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl); +int __real_mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl); + +int __wrap_mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl); +int __wrap_mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl); + +static const char *TAG = "SSL client"; + +static int manage_resource(mbedtls_ssl_context *ssl, bool add) +{ + int state = add ? ssl->MBEDTLS_PRIVATE(state) : ssl->MBEDTLS_PRIVATE(state) - 1; + + if (mbedtls_ssl_is_handshake_over(ssl) || ssl->MBEDTLS_PRIVATE(handshake) == NULL) { + return 0; + } + + if (!add) { + if (!ssl->MBEDTLS_PRIVATE(out_left)) { + CHECK_OK(esp_mbedtls_free_tx_buffer(ssl)); + } + } + + /* Change state now, so that it is right in mbedtls_ssl_read_record(), used + * by DTLS for dropping out-of-sequence ChangeCipherSpec records */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC && + ssl->handshake->new_session_ticket != 0 ) + { + ssl->state = MBEDTLS_SSL_NEW_SESSION_TICKET; + } +#endif + + switch (state) { + case MBEDTLS_SSL_HELLO_REQUEST: + break; + case MBEDTLS_SSL_CLIENT_HELLO: + if (add) { + size_t buffer_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, buffer_len)); + } + break; + + + case MBEDTLS_SSL_SERVER_HELLO: + if (add) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } else { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + } + break; + case MBEDTLS_SSL_SERVER_CERTIFICATE: + if (add) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } else { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + +#ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT + esp_mbedtls_free_cacert(ssl); +#endif + } + break; + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + if (add) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } else { + if (!ssl->MBEDTLS_PRIVATE(keep_current_message)) { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + } + } + break; + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + if (add) { + if (!ssl->MBEDTLS_PRIVATE(keep_current_message)) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } + } else { + if (!ssl->MBEDTLS_PRIVATE(keep_current_message)) { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + } + } + break; + case MBEDTLS_SSL_SERVER_HELLO_DONE: + if (add) { + if (!ssl->MBEDTLS_PRIVATE(keep_current_message)) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } + } else { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + } + break; + + + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + if (add) { + size_t buffer_len = 3; + + const mbedtls_ssl_config *conf = mbedtls_ssl_context_get_config(ssl); + mbedtls_ssl_key_cert *key_cert = conf->MBEDTLS_PRIVATE(key_cert); + + while (key_cert && key_cert->cert) { + size_t num; + + buffer_len += esp_mbedtls_get_crt_size(key_cert->cert, &num); + buffer_len += num * 3; + + key_cert = key_cert->next; + } + + buffer_len = MAX(buffer_len, MBEDTLS_SSL_OUT_BUFFER_LEN); + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, buffer_len)); + } + break; + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + if (add) { + size_t buffer_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, buffer_len)); + } + break; + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + if (add) { + size_t buffer_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, buffer_len)); + } else { +#ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA + esp_mbedtls_free_dhm(ssl); + esp_mbedtls_free_keycert_key(ssl); + esp_mbedtls_free_keycert(ssl); +#endif + } + break; + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + if (add) { + size_t buffer_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, buffer_len)); + } + break; + case MBEDTLS_SSL_CLIENT_FINISHED: + if (add) { + size_t buffer_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, buffer_len)); + } + break; + + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_SSL_NEW_SESSION_TICKET: + if (add) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } else { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + } + break; +#endif + + + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: + if (add) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } else { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + } + break; + case MBEDTLS_SSL_SERVER_FINISHED: + if (add) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } else { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + } + break; + case MBEDTLS_SSL_FLUSH_BUFFERS: + break; + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if (add && ssl->MBEDTLS_PRIVATE(renego_status)) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } +#endif + break; + default: + break; + } + + return 0; +} + +int __wrap_mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl) +{ + CHECK_OK(manage_resource(ssl, true)); + + CHECK_OK(__real_mbedtls_ssl_handshake_client_step(ssl)); + + CHECK_OK(manage_resource(ssl, false)); + + return 0; +} + +int __wrap_mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl) +{ + CHECK_OK(manage_resource(ssl, true)); + + CHECK_OK(__real_mbedtls_ssl_write_client_hello(ssl)); + + CHECK_OK(manage_resource(ssl, false)); + + return 0; +} diff --git a/components/mbedtls/mbedtls_v3/port/dynamic/esp_ssl_srv.c b/components/mbedtls/mbedtls_v3/port/dynamic/esp_ssl_srv.c new file mode 100644 index 000000000..5a657b56c --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/dynamic/esp_ssl_srv.c @@ -0,0 +1,219 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "esp_mbedtls_dynamic_impl.h" + +int __real_mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl); + +int __wrap_mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl); + +static const char *TAG = "SSL Server"; + +#ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA +/** + * Check if ciphersuite uses rsa key exchange methods. + */ +static bool ssl_ciphersuite_uses_rsa_key_ex(mbedtls_ssl_context *ssl) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->MBEDTLS_PRIVATE(handshake)->ciphersuite_info; + + if (ciphersuite_info->MBEDTLS_PRIVATE(key_exchange) == MBEDTLS_KEY_EXCHANGE_RSA || + ciphersuite_info->MBEDTLS_PRIVATE(key_exchange) == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { + return true; + } else { + return false; + } +} +#endif + +static int manage_resource(mbedtls_ssl_context *ssl, bool add) +{ + int state = add ? ssl->MBEDTLS_PRIVATE(state) : ssl->MBEDTLS_PRIVATE(state) - 1; + + if (mbedtls_ssl_is_handshake_over(ssl) || ssl->MBEDTLS_PRIVATE(handshake) == NULL) { + return 0; + } + + if (!add) { + if (!ssl->MBEDTLS_PRIVATE(out_left)) { + CHECK_OK(esp_mbedtls_free_tx_buffer(ssl)); + } + } + + switch (state) { + case MBEDTLS_SSL_HELLO_REQUEST: + break; + case MBEDTLS_SSL_CLIENT_HELLO: + if (add) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } else { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + } + break; + + + case MBEDTLS_SSL_SERVER_HELLO: + if (add) { + size_t buffer_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, buffer_len)); + } + break; + case MBEDTLS_SSL_SERVER_CERTIFICATE: + if (add) { + size_t buffer_len = 3; + + const mbedtls_ssl_config *conf = mbedtls_ssl_context_get_config(ssl); + mbedtls_ssl_key_cert *key_cert = conf->MBEDTLS_PRIVATE(key_cert); + + while (key_cert && key_cert->cert) { + size_t num; + + buffer_len += esp_mbedtls_get_crt_size(key_cert->cert, &num); + buffer_len += num * 3; + + key_cert = key_cert->next; + } + + buffer_len = MAX(buffer_len, MBEDTLS_SSL_OUT_BUFFER_LEN); + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, buffer_len)); + } else { +#ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA + /** + * Not free keycert->cert until MBEDTLS_SSL_CLIENT_KEY_EXCHANGE for rsa key exchange methods. + * For ssl server will use keycert->cert to parse client key exchange. + */ + if (!ssl_ciphersuite_uses_rsa_key_ex(ssl)) { + esp_mbedtls_free_keycert_cert(ssl); + } +#endif + } + break; + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + if (add) { + size_t buffer_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, buffer_len)); + } else { +#ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA + esp_mbedtls_free_dhm(ssl); + /** + * Not free keycert->key and keycert until MBEDTLS_SSL_CLIENT_KEY_EXCHANGE for rsa key exchange methods. + * For ssl server will use keycert->key to parse client key exchange. + */ + if (!ssl_ciphersuite_uses_rsa_key_ex(ssl)) { + esp_mbedtls_free_keycert_key(ssl); + esp_mbedtls_free_keycert(ssl); + } +#endif + } + break; + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + if (add) { + size_t buffer_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, buffer_len)); + } + break; + case MBEDTLS_SSL_SERVER_HELLO_DONE: + if (add) { + size_t buffer_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, buffer_len)); + } + break; + + + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + if (add) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } else { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + +#ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT + esp_mbedtls_free_cacert(ssl); +#endif + } + break; + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + if (add) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } else { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + +#ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA + /** + * Free keycert after MBEDTLS_SSL_CLIENT_KEY_EXCHANGE for rsa key exchange methods. + * For ssl server will use keycert->cert and keycert->key to parse client key exchange. + */ + if (ssl_ciphersuite_uses_rsa_key_ex(ssl)) { + esp_mbedtls_free_keycert_cert(ssl); + esp_mbedtls_free_keycert_key(ssl); + esp_mbedtls_free_keycert(ssl); + } +#endif + } + break; + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + if (add) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } else { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + } + break; + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + if (add) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } else { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + } + break; + case MBEDTLS_SSL_CLIENT_FINISHED: + if (add) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } else { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + } + break; + + + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: + if (add) { + size_t buffer_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, buffer_len)); + } + break; + case MBEDTLS_SSL_SERVER_FINISHED: + if (add) { + size_t buffer_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, buffer_len)); + } + break; + case MBEDTLS_SSL_FLUSH_BUFFERS: + break; + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + break; + default: + break; + } + + return 0; +} + +int __wrap_mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl) +{ + CHECK_OK(manage_resource(ssl, true)); + + CHECK_OK(__real_mbedtls_ssl_handshake_server_step(ssl)); + + CHECK_OK(manage_resource(ssl, false)); + + return 0; +} diff --git a/components/mbedtls/mbedtls_v3/port/dynamic/esp_ssl_tls.c b/components/mbedtls/mbedtls_v3/port/dynamic/esp_ssl_tls.c new file mode 100644 index 000000000..f12bc2bf7 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/dynamic/esp_ssl_tls.c @@ -0,0 +1,398 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "mbedtls/error.h" +#include "esp_mbedtls_dynamic_impl.h" + +int __real_mbedtls_ssl_write(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len); +int __real_mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len); +void __real_mbedtls_ssl_free(mbedtls_ssl_context *ssl); +int __real_mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl); +int __real_mbedtls_ssl_setup(mbedtls_ssl_context *ssl, const mbedtls_ssl_config *conf); +int __real_mbedtls_ssl_send_alert_message(mbedtls_ssl_context *ssl, unsigned char level, unsigned char message); +int __real_mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl); + +int __wrap_mbedtls_ssl_write(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len); +int __wrap_mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len); +void __wrap_mbedtls_ssl_free(mbedtls_ssl_context *ssl); +int __wrap_mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl); +int __wrap_mbedtls_ssl_setup(mbedtls_ssl_context *ssl, const mbedtls_ssl_config *conf); +int __wrap_mbedtls_ssl_send_alert_message(mbedtls_ssl_context *ssl, unsigned char level, unsigned char message); +int __wrap_mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl); + +static const char *TAG = "SSL TLS"; + +static int tx_done(mbedtls_ssl_context *ssl) +{ + if (!ssl->MBEDTLS_PRIVATE(out_left)) + return 1; + + return 0; +} + +static int rx_done(mbedtls_ssl_context *ssl) +{ + if (!ssl->MBEDTLS_PRIVATE(in_msglen)) { + return 1; + } + + ESP_LOGD(TAG, "RX left %zu bytes", ssl->MBEDTLS_PRIVATE(in_msglen)); + return 0; +} + +static int ssl_update_checksum_start( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_SHA256_C) + ret = mbedtls_md_update( &ssl->handshake->fin_sha256, buf, len ); +#endif +#if defined(MBEDTLS_SHA512_C) + ret = mbedtls_md_update( &ssl->handshake->fin_sha384, buf, len ); +#endif + return ret; +} + +static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) +{ + memset( handshake, 0, sizeof( mbedtls_ssl_handshake_params ) ); + +#if defined(MBEDTLS_SHA256_C) + mbedtls_md_init( &handshake->fin_sha256 ); + mbedtls_md_setup( &handshake->fin_sha256, + mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), + 0 ); + mbedtls_md_starts( &handshake->fin_sha256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_md_init( &handshake->fin_sha384 ); + mbedtls_md_setup( &handshake->fin_sha384, + mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), + 0 ); + mbedtls_md_starts( &handshake->fin_sha384 ); +#endif + + handshake->update_checksum = ssl_update_checksum_start; + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_init( &handshake->dhm_ctx ); +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_init( &handshake->ecdh_ctx ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_init( &handshake->ecjpake_ctx ); +#if defined(MBEDTLS_SSL_CLI_C) + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE) + mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx ); +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_pk_init( &handshake->peer_pubkey ); +#endif +} + +static int ssl_handshake_init( mbedtls_ssl_context *ssl ) +{ + /* Clear old handshake information if present */ + if( ssl->transform_negotiate ) + mbedtls_ssl_transform_free( ssl->transform_negotiate ); + if( ssl->session_negotiate ) + mbedtls_ssl_session_free( ssl->session_negotiate ); + if( ssl->handshake ) + mbedtls_ssl_handshake_free( ssl ); + + /* + * Either the pointers are now NULL or cleared properly and can be freed. + * Now allocate missing structures. + */ + if( ssl->transform_negotiate == NULL ) + { + ssl->transform_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_transform) ); + } + + if( ssl->session_negotiate == NULL ) + { + ssl->session_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_session) ); + } + + if( ssl->handshake == NULL ) + { + ssl->handshake = mbedtls_calloc( 1, sizeof(mbedtls_ssl_handshake_params) ); + } +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + /* If the buffers are too small - reallocate */ + + handle_buffer_resizing( ssl, 0, MBEDTLS_SSL_IN_BUFFER_LEN, + MBEDTLS_SSL_OUT_BUFFER_LEN ); +#endif + + /* All pointers should exist and can be directly freed without issue */ + if( ssl->handshake == NULL || + ssl->transform_negotiate == NULL || + ssl->session_negotiate == NULL ) + { + ESP_LOGD(TAG, "alloc() of ssl sub-contexts failed"); + + mbedtls_free( ssl->handshake ); + mbedtls_free( ssl->transform_negotiate ); + mbedtls_free( ssl->session_negotiate ); + + ssl->handshake = NULL; + ssl->transform_negotiate = NULL; + ssl->session_negotiate = NULL; + + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Initialize structures */ + mbedtls_ssl_session_init( ssl->session_negotiate ); + mbedtls_ssl_transform_init( ssl->transform_negotiate ); + ssl_handshake_params_init( ssl->handshake ); + +/* + * curve_list is translated to IANA TLS group identifiers here because + * mbedtls_ssl_conf_curves returns void and so can't return + * any error codes. + */ +#if defined(MBEDTLS_ECP_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + /* Heap allocate and translate curve_list from internal to IANA group ids */ + if ( ssl->conf->curve_list != NULL ) + { + size_t length; + const mbedtls_ecp_group_id *curve_list = ssl->conf->curve_list; + + for( length = 0; ( curve_list[length] != MBEDTLS_ECP_DP_NONE ) && + ( length < MBEDTLS_ECP_DP_MAX ); length++ ) {} + + /* Leave room for zero termination */ + uint16_t *group_list = mbedtls_calloc( length + 1, sizeof(uint16_t) ); + if ( group_list == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + for( size_t i = 0; i < length; i++ ) + { + const mbedtls_ecp_curve_info *info = + mbedtls_ecp_curve_info_from_grp_id( curve_list[i] ); + if ( info == NULL ) + { + mbedtls_free( group_list ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + group_list[i] = info->tls_id; + } + + group_list[length] = 0; + + ssl->handshake->group_list = group_list; + ssl->handshake->group_list_heap_allocated = 1; + } + else + { + ssl->handshake->group_list = ssl->conf->group_list; + ssl->handshake->group_list_heap_allocated = 0; + } +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* Heap allocate and translate sig_hashes from internal hash identifiers to + signature algorithms IANA identifiers. */ + if ( mbedtls_ssl_conf_is_tls12_only( ssl->conf ) && + ssl->conf->sig_hashes != NULL ) + { + const int *md; + const int *sig_hashes = ssl->conf->sig_hashes; + size_t sig_algs_len = 0; + uint16_t *p; + +#if defined(static_assert) + static_assert( MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN + <= ( SIZE_MAX - ( 2 * sizeof(uint16_t) ) ), + "MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN too big" ); +#endif + + for( md = sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { + if( mbedtls_ssl_hash_from_md_alg( *md ) == MBEDTLS_SSL_HASH_NONE ) + continue; +#if defined(MBEDTLS_ECDSA_C) + sig_algs_len += sizeof( uint16_t ); +#endif + +#if defined(MBEDTLS_RSA_C) + sig_algs_len += sizeof( uint16_t ); +#endif + if( sig_algs_len > MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + + if( sig_algs_len < MBEDTLS_SSL_MIN_SIG_ALG_LIST_LEN ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + ssl->handshake->sig_algs = mbedtls_calloc( 1, sig_algs_len + + sizeof( uint16_t )); + if( ssl->handshake->sig_algs == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + p = (uint16_t *)ssl->handshake->sig_algs; + for( md = sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { + unsigned char hash = mbedtls_ssl_hash_from_md_alg( *md ); + if( hash == MBEDTLS_SSL_HASH_NONE ) + continue; +#if defined(MBEDTLS_ECDSA_C) + *p = (( hash << 8 ) | MBEDTLS_SSL_SIG_ECDSA); + p++; +#endif +#if defined(MBEDTLS_RSA_C) + *p = (( hash << 8 ) | MBEDTLS_SSL_SIG_RSA); + p++; +#endif + } + *p = MBEDTLS_TLS_SIG_NONE; + ssl->handshake->sig_algs_heap_allocated = 1; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + ssl->handshake->sig_algs_heap_allocated = 0; + } +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + + return( 0 ); +} + +int __wrap_mbedtls_ssl_setup(mbedtls_ssl_context *ssl, const mbedtls_ssl_config *conf) +{ + ssl->conf = conf; + ssl->tls_version = ssl->conf->max_tls_version; + + CHECK_OK(ssl_handshake_init(ssl)); + + mbedtls_free(ssl->MBEDTLS_PRIVATE(out_buf)); + ssl->MBEDTLS_PRIVATE(out_buf) = NULL; + CHECK_OK(esp_mbedtls_setup_tx_buffer(ssl)); + + mbedtls_free(ssl->MBEDTLS_PRIVATE(in_buf)); + ssl->MBEDTLS_PRIVATE(in_buf) = NULL; + esp_mbedtls_setup_rx_buffer(ssl); + + return 0; +} + +int __wrap_mbedtls_ssl_write(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) +{ + int ret; + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, 0)); + + ret = __real_mbedtls_ssl_write(ssl, buf, len); + + if (tx_done(ssl)) { + CHECK_OK(esp_mbedtls_free_tx_buffer(ssl)); + } + + return ret; +} + +int __wrap_mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) +{ + int ret; + + ESP_LOGD(TAG, "add mbedtls RX buffer"); + ret = esp_mbedtls_add_rx_buffer(ssl); + if (ret == MBEDTLS_ERR_SSL_CONN_EOF) { + ESP_LOGD(TAG, "fail, the connection indicated an EOF"); + return 0; + } else if (ret < 0) { + ESP_LOGD(TAG, "fail, error=%d", -ret); + return ret; + } + ESP_LOGD(TAG, "end"); + + ret = __real_mbedtls_ssl_read(ssl, buf, len); + + if (rx_done(ssl)) { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + } + + return ret; +} + +void __wrap_mbedtls_ssl_free(mbedtls_ssl_context *ssl) +{ + if (ssl->MBEDTLS_PRIVATE(out_buf)) { + esp_mbedtls_free_buf(ssl->MBEDTLS_PRIVATE(out_buf)); + ssl->MBEDTLS_PRIVATE(out_buf) = NULL; + } + + if (ssl->MBEDTLS_PRIVATE(in_buf)) { + esp_mbedtls_free_buf(ssl->MBEDTLS_PRIVATE(in_buf)); + ssl->MBEDTLS_PRIVATE(in_buf) = NULL; + } + + __real_mbedtls_ssl_free(ssl); +} + +int __wrap_mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl) +{ + CHECK_OK(esp_mbedtls_reset_add_tx_buffer(ssl)); + + CHECK_OK(esp_mbedtls_reset_add_rx_buffer(ssl)); + + CHECK_OK(__real_mbedtls_ssl_session_reset(ssl)); + + CHECK_OK(esp_mbedtls_reset_free_tx_buffer(ssl)); + + esp_mbedtls_reset_free_rx_buffer(ssl); + + return 0; +} + +int __wrap_mbedtls_ssl_send_alert_message(mbedtls_ssl_context *ssl, unsigned char level, unsigned char message) +{ + int ret; + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, 0)); + + ret = __real_mbedtls_ssl_send_alert_message(ssl, level, message); + + if (tx_done(ssl)) { + CHECK_OK(esp_mbedtls_free_tx_buffer(ssl)); + } + + return ret; +} + +int __wrap_mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl) +{ + int ret; + + CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, 0)); + + ret = __real_mbedtls_ssl_close_notify(ssl); + + if (tx_done(ssl)) { + CHECK_OK(esp_mbedtls_free_tx_buffer(ssl)); + } + + return ret; +} diff --git a/components/mbedtls/mbedtls_v3/port/ecc/ecc_alt.c b/components/mbedtls/mbedtls_v3/port/ecc/ecc_alt.c new file mode 100644 index 000000000..ef0b76fe0 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/ecc/ecc_alt.c @@ -0,0 +1,114 @@ +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "soc/hwcrypto_periph.h" +#include "ecc_impl.h" + +#include "mbedtls/ecp.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_ECP_MUL_ALT) || defined(MBEDTLS_ECP_MUL_ALT_SOFT_FALLBACK) + +#define MAX_SIZE 32 // 256 bits + +static int esp_mbedtls_ecp_point_multiply(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P) +{ + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + uint8_t x_tmp[MAX_SIZE] = {0}; + uint8_t y_tmp[MAX_SIZE] = {0}; + + uint8_t m_le[MAX_SIZE] = {0}; + ecc_point_t p_pt = {0}; + ecc_point_t r_pt = {0}; + + p_pt.len = grp->pbits / 8; + + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(&P->MBEDTLS_PRIVATE(X), p_pt.x, MAX_SIZE)); + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(&P->MBEDTLS_PRIVATE(Y), p_pt.y, MAX_SIZE)); + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(m, m_le, MAX_SIZE)); + + ret = esp_ecc_point_multiply(&p_pt, m_le, &r_pt, false); + + for (int i = 0; i < MAX_SIZE; i++) { + x_tmp[MAX_SIZE - i - 1] = r_pt.x[i]; + y_tmp[MAX_SIZE - i - 1] = r_pt.y[i]; + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&R->MBEDTLS_PRIVATE(X), x_tmp, MAX_SIZE)); + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&R->MBEDTLS_PRIVATE(Y), y_tmp, MAX_SIZE)); + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&R->MBEDTLS_PRIVATE(Z), 1)); + return ret; + +cleanup: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +} + +int ecp_mul_restartable_internal( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + if (grp->id != MBEDTLS_ECP_DP_SECP192R1 && grp->id != MBEDTLS_ECP_DP_SECP256R1) { +#if defined(MBEDTLS_ECP_MUL_ALT_SOFT_FALLBACK) + return ecp_mul_restartable_internal_soft(grp, R, m, P, f_rng, p_rng, rs_ctx); +#else + return ret; +#endif + } + + /* Common sanity checks to conform with mbedTLS return values */ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey(grp, m) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey(grp, P) ); + + MBEDTLS_MPI_CHK( esp_mbedtls_ecp_point_multiply(grp, R, m, P) ); +cleanup: + return( ret ); +} + +#endif /* defined(MBEDTLS_ECP_MUL_ALT) || defined(MBEDTLS_ECP_MUL_ALT_SOFT_FALLBACK) */ + +#if defined(MBEDTLS_ECP_VERIFY_ALT) || defined(MBEDTLS_ECP_VERIFY_ALT_SOFT_FALLBACK) + +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt ) +{ + int res; + ecc_point_t point; + + if (grp->id != MBEDTLS_ECP_DP_SECP192R1 && grp->id != MBEDTLS_ECP_DP_SECP256R1) { +#if defined(MBEDTLS_ECP_VERIFY_ALT_SOFT_FALLBACK) + return mbedtls_ecp_check_pubkey_soft(grp, pt); +#else + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +#endif + } + + if (grp == NULL || pt == NULL) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + /* Must use affine coordinates */ + if( mbedtls_mpi_cmp_int( &pt->MBEDTLS_PRIVATE(Z), 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + mbedtls_platform_zeroize((void *)&point, sizeof(ecc_point_t)); + + memcpy(&point.x, pt->MBEDTLS_PRIVATE(X).MBEDTLS_PRIVATE(p), mbedtls_mpi_size(&pt->MBEDTLS_PRIVATE(X))); + memcpy(&point.y, pt->MBEDTLS_PRIVATE(Y).MBEDTLS_PRIVATE(p), mbedtls_mpi_size(&pt->MBEDTLS_PRIVATE(Y))); + + point.len = grp->pbits / 8; + + res = esp_ecc_point_verify(&point); + if (res == 1) { + return 0; + } else { + return MBEDTLS_ERR_ECP_INVALID_KEY; + } +} +#endif /* defined(MBEDTLS_ECP_VERIFY_ALT) || defined(MBEDTLS_ECP_VERIFY_ALT_SOFT_FALLBACK) */ diff --git a/components/mbedtls/mbedtls_v3/port/ecc/esp_ecc.c b/components/mbedtls/mbedtls_v3/port/ecc/esp_ecc.c new file mode 100644 index 000000000..ecd87a256 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/ecc/esp_ecc.c @@ -0,0 +1,77 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "esp_crypto_lock.h" +#include "esp_private/periph_ctrl.h" +#include "ecc_impl.h" +#include "hal/ecc_hal.h" +#include "hal/ecc_ll.h" + +static void esp_ecc_acquire_hardware(void) +{ + esp_crypto_ecc_lock_acquire(); + + periph_module_enable(PERIPH_ECC_MODULE); + ecc_ll_power_up(); +} + +static void esp_ecc_release_hardware(void) +{ + periph_module_disable(PERIPH_ECC_MODULE); + ecc_ll_power_down(); + + esp_crypto_ecc_lock_release(); +} + +int esp_ecc_point_multiply(const ecc_point_t *point, const uint8_t *scalar, ecc_point_t *result, bool verify_first) +{ + int ret = -1; + uint16_t len = point->len; + ecc_mode_t work_mode = verify_first ? ECC_MODE_VERIFY_THEN_POINT_MUL : ECC_MODE_POINT_MUL; + + esp_ecc_acquire_hardware(); + + ecc_hal_write_mul_param(scalar, point->x, point->y, len); + ecc_hal_set_mode(work_mode); + ecc_hal_start_calc(); + + memset(result, 0, sizeof(ecc_point_t)); + + result->len = len; + + while (!ecc_hal_is_calc_finished()) { + ; + } + + ret = ecc_hal_read_mul_result(result->x, result->y, len); + + esp_ecc_release_hardware(); + + return ret; +} + +int esp_ecc_point_verify(const ecc_point_t *point) +{ + int result; + + esp_ecc_acquire_hardware(); + ecc_hal_write_verify_param(point->x, point->y, point->len); + ecc_hal_set_mode(ECC_MODE_VERIFY); + ecc_hal_start_calc(); + + while (!ecc_hal_is_calc_finished()) { + ; + } + + result = ecc_hal_read_verify_result(); + + esp_ecc_release_hardware(); + + return result; +} diff --git a/components/mbedtls/mbedtls_v3/port/ecdsa/ecdsa_alt.c b/components/mbedtls/mbedtls_v3/port/ecdsa/ecdsa_alt.c new file mode 100644 index 000000000..8f9158c37 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/ecdsa/ecdsa_alt.c @@ -0,0 +1,553 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "hal/ecdsa_hal.h" +#include "esp_crypto_lock.h" +#include "esp_efuse.h" +#include "mbedtls/ecp.h" +#include "mbedtls/error.h" +#include "mbedtls/ecdsa.h" +#include "mbedtls/asn1.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/platform_util.h" +#include "esp_private/periph_ctrl.h" +#include "ecdsa/ecdsa_alt.h" +#include "hal/ecc_ll.h" + +#define ECDSA_KEY_MAGIC (short) 0xECD5A +#define ECDSA_SHA_LEN 32 +#define MAX_ECDSA_COMPONENT_LEN 32 + +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM +#include "esp_timer.h" + +#if CONFIG_ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH +/* + * This is the maximum time (in us) required for performing 1 ECDSA signature + * in this configuration along some additional margin considerations + */ +#define ECDSA_MAX_SIG_TIME 24000 +#else /* CONFIG_ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH */ +#define ECDSA_MAX_SIG_TIME 17500 +#endif /* !CONFIG_ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH */ + +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM +#define DUMMY_OP_COUNT ECDSA_SIGN_MAX_DUMMY_OP_COUNT +#else /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM */ +#define DUMMY_OP_COUNT 0 +#endif /* !CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM */ +#define ECDSA_CM_FIXED_SIG_TIME ECDSA_MAX_SIG_TIME * (DUMMY_OP_COUNT + 1) + +#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM */ + +__attribute__((unused)) static const char *TAG = "ecdsa_alt"; + +static void esp_ecdsa_acquire_hardware(void) +{ + esp_crypto_ecdsa_lock_acquire(); + + periph_module_enable(PERIPH_ECDSA_MODULE); + ecc_ll_power_up(); +} + +static void esp_ecdsa_release_hardware(void) +{ + periph_module_disable(PERIPH_ECDSA_MODULE); + ecc_ll_power_down(); + + esp_crypto_ecdsa_lock_release(); +} + +static void ecdsa_be_to_le(const uint8_t* be_point, uint8_t *le_point, uint8_t len) +{ + /* When the size is 24 bytes, it should be padded with 0 bytes*/ + memset(le_point, 0x0, 32); + + for(int i = 0; i < len; i++) { + le_point[i] = be_point[len - i - 1]; + } +} + +#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN +int esp_ecdsa_privkey_load_mpi(mbedtls_mpi *key, int efuse_blk) +{ + if (!key) { + ESP_LOGE(TAG, "Invalid memory"); + return -1; + } + + if (efuse_blk < EFUSE_BLK_KEY0 || efuse_blk >= EFUSE_BLK_KEY_MAX) { + ESP_LOGE(TAG, "Invalid efuse block"); + return -1; + } + + mbedtls_mpi_init(key); + + /* We use the mbedtls_mpi struct to pass our own context to hardware ECDSA peripheral + * MPI struct expects `s` to be either 1 or -1, by setting it to 0xECD5A, we ensure that it does + * not collide with a valid MPI. This is done to differentiate between using the private key stored in efuse + * or using the private key provided by software + * + * `n` is used to store the efuse block which should be used as key + */ + key->MBEDTLS_PRIVATE(s) = ECDSA_KEY_MAGIC; + key->MBEDTLS_PRIVATE(n) = efuse_blk; + key->MBEDTLS_PRIVATE(p) = NULL; + + return 0; +} + +int esp_ecdsa_privkey_load_pk_context(mbedtls_pk_context *key_ctx, int efuse_blk) +{ + const mbedtls_pk_info_t *pk_info; + mbedtls_ecp_keypair *keypair; + + if (!key_ctx) { + ESP_LOGE(TAG, "Invalid memory"); + return -1; + } + + if (efuse_blk < EFUSE_BLK_KEY0 || efuse_blk >= EFUSE_BLK_KEY_MAX) { + ESP_LOGE(TAG, "Invalid efuse block"); + return -1; + } + + mbedtls_pk_init(key_ctx); + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECDSA); + mbedtls_pk_setup(key_ctx, pk_info); + keypair = mbedtls_pk_ec(*key_ctx); + + return esp_ecdsa_privkey_load_mpi(&(keypair->MBEDTLS_PRIVATE(d)), efuse_blk); +} + +static int esp_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s, + const mbedtls_mpi *d, const unsigned char* msg, size_t msg_len) +{ + ecdsa_curve_t curve; + esp_efuse_block_t blk; + uint16_t len; + uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0}; + uint8_t sha_le[ECDSA_SHA_LEN]; + uint8_t r_le[MAX_ECDSA_COMPONENT_LEN]; + uint8_t s_le[MAX_ECDSA_COMPONENT_LEN]; + + if (!grp || !r || !s || !d || !msg) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (msg_len != ECDSA_SHA_LEN) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (grp->id == MBEDTLS_ECP_DP_SECP192R1) { + curve = ECDSA_CURVE_SECP192R1; + len = 24; + } else if (grp->id == MBEDTLS_ECP_DP_SECP256R1) { + curve = ECDSA_CURVE_SECP256R1; + len = 32; + } else { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (!esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY, &blk)) { + ESP_LOGE(TAG, "No efuse block with purpose ECDSA_KEY found"); + return MBEDTLS_ERR_ECP_INVALID_KEY; + } + + ecdsa_be_to_le(msg, sha_le, len); + + esp_ecdsa_acquire_hardware(); + + bool process_again = false; + + do { + ecdsa_hal_config_t conf = { + .mode = ECDSA_MODE_SIGN_GEN, + .curve = curve, + .sha_mode = ECDSA_Z_USER_PROVIDED, + .efuse_key_blk = d->MBEDTLS_PRIVATE(n), + }; + +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM + uint64_t sig_time = esp_timer_get_time(); +#endif + ecdsa_hal_gen_signature(&conf, sha_le, r_le, s_le, len); +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM + sig_time = esp_timer_get_time() - sig_time; + if (sig_time < ECDSA_CM_FIXED_SIG_TIME) { + esp_rom_delay_us(ECDSA_CM_FIXED_SIG_TIME - sig_time); + } +#endif + process_again = !ecdsa_hal_get_operation_result() + || !memcmp(r_le, zeroes, len) + || !memcmp(s_le, zeroes, len); + + } while (process_again); + + esp_ecdsa_release_hardware(); + + mbedtls_mpi_read_binary_le(r, r_le, len); + mbedtls_mpi_read_binary_le(s, s_le, len); + + return 0; +} + +/* + * Compute ECDSA signature of a hashed message; + */ +extern int __real_mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + +int __wrap_mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + +int __wrap_mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + /* + * Check `d` whether it contains the hardware key + */ + if (d->MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) { + // Use hardware ECDSA peripheral + return esp_ecdsa_sign(grp, r, s, d, buf, blen); + } else { + return __real_mbedtls_ecdsa_sign(grp, r, s, d, buf, blen, f_rng, p_rng); + } +} + +extern int __real_mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx); + +int __wrap_mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx); + +int __wrap_mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx) +{ + /* + * Check `d` whether it contains the hardware key + */ + if (d->MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) { + // Use hardware ECDSA peripheral + return esp_ecdsa_sign(grp, r, s, d, buf, blen); + } else { + return __real_mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen, f_rng, p_rng, f_rng_blind, p_rng_blind, rs_ctx); + } +} + +int __real_mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t sig_size, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx); + +int __wrap_mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t sig_size, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx); + +/* + * Convert a signature (given by context) to ASN.1 + */ +static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s, + unsigned char *sig, size_t sig_size, + size_t *slen) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 }; + // Setting the pointer p to the end of the buffer as the functions used afterwards write in backwards manner in the given buffer. + unsigned char *p = buf + sizeof(buf); + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, s)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, r)); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + + if (len > sig_size) { + return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + } + + memcpy(sig, p, len); + *slen = len; + + return 0; +} + +int __wrap_mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t sig_size, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx) +{ + if (ctx->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(s) != ECDSA_KEY_MAGIC) { + return __real_mbedtls_ecdsa_write_signature_restartable(ctx, md_alg, hash, hlen, sig, sig_size, slen, f_rng, p_rng, rs_ctx); + } + + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi r, s; + + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + /* + * Check `d` whether it contains the hardware key + */ + if (ctx->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) { + // Use hardware ECDSA peripheral + + MBEDTLS_MPI_CHK(esp_ecdsa_sign(&ctx->MBEDTLS_PRIVATE(grp), &r, &s, &ctx->MBEDTLS_PRIVATE(d), hash, hlen)); + } + + MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, sig_size, slen)); + +cleanup: + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); + + return ret; +} + +int __wrap_mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t sig_size, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + +int __wrap_mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t sig_size, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + return __wrap_mbedtls_ecdsa_write_signature_restartable( + ctx, md_alg, hash, hlen, sig, sig_size, slen, + f_rng, p_rng, NULL); +} +#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */ + +#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY +static int esp_ecdsa_verify(mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s) +{ + ecdsa_curve_t curve; + uint16_t len; + uint8_t r_le[MAX_ECDSA_COMPONENT_LEN]; + uint8_t s_le[MAX_ECDSA_COMPONENT_LEN]; + uint8_t qx_le[MAX_ECDSA_COMPONENT_LEN]; + uint8_t qy_le[MAX_ECDSA_COMPONENT_LEN]; + uint8_t sha_le[ECDSA_SHA_LEN]; + + if (!grp || !buf || !Q || !r || !s) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (blen != ECDSA_SHA_LEN) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (grp->id == MBEDTLS_ECP_DP_SECP192R1) { + curve = ECDSA_CURVE_SECP192R1; + len = 24; + } else if (grp->id == MBEDTLS_ECP_DP_SECP256R1) { + curve = ECDSA_CURVE_SECP256R1; + len = 32; + } else { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (mbedtls_mpi_cmp_int(r, 1) < 0 || mbedtls_mpi_cmp_mpi(r, &grp->N) >= 0 || + mbedtls_mpi_cmp_int(s, 1) < 0 || mbedtls_mpi_cmp_mpi(s, &grp->N) >= 0 ) + { + return MBEDTLS_ERR_ECP_VERIFY_FAILED; + } + + ecdsa_be_to_le(buf, sha_le, len); + + mbedtls_mpi_write_binary_le(&Q->MBEDTLS_PRIVATE(X), qx_le, len); + mbedtls_mpi_write_binary_le(&Q->MBEDTLS_PRIVATE(Y), qy_le, len); + mbedtls_mpi_write_binary_le(r, r_le, len); + mbedtls_mpi_write_binary_le(s, s_le, len); + + esp_ecdsa_acquire_hardware(); + + ecdsa_hal_config_t conf = { + .mode = ECDSA_MODE_SIGN_VERIFY, + .curve = curve, + .sha_mode = ECDSA_Z_USER_PROVIDED, + }; + + int ret = ecdsa_hal_verify_signature(&conf, sha_le, r_le, s_le, qx_le, qy_le, len); + + esp_ecdsa_release_hardware(); + + if (ret != 0) { + return MBEDTLS_ERR_ECP_VERIFY_FAILED; + } + + return ret; +} + +/* + * Verify ECDSA signature of hashed message + */ +extern int __real_mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s, + mbedtls_ecdsa_restart_ctx *rs_ctx); + +int __wrap_mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s, + mbedtls_ecdsa_restart_ctx *rs_ctx); + +int __wrap_mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s, + mbedtls_ecdsa_restart_ctx *rs_ctx) +{ + if ((grp->id == MBEDTLS_ECP_DP_SECP192R1 || grp->id == MBEDTLS_ECP_DP_SECP256R1) && blen == ECDSA_SHA_LEN) { + return esp_ecdsa_verify(grp, buf, blen, Q, r, s); + } else { + return __real_mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, rs_ctx); + } +} + +/* + * Verify ECDSA signature of hashed message + */ +extern int __real_mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s); + +int __wrap_mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s); + +int __wrap_mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s) +{ + return __wrap_mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, NULL); +} + + +int __real_mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx); + +int __wrap_mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx); + +int __wrap_mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = (unsigned char *) sig; + const unsigned char *end = sig + slen; + size_t len; + mbedtls_mpi r, s; + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + if (p + len != end) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_ECP_BAD_INPUT_DATA, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + goto cleanup; + } + + if ((ret = mbedtls_asn1_get_mpi(&p, end, &r)) != 0 || + (ret = mbedtls_asn1_get_mpi(&p, end, &s)) != 0) { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + if ((ret = __wrap_mbedtls_ecdsa_verify_restartable(&ctx->MBEDTLS_PRIVATE(grp), hash, hlen, + &ctx->MBEDTLS_PRIVATE(Q), &r, &s, NULL)) != 0) { + goto cleanup; + } + + /* At this point we know that the buffer starts with a valid signature. + * Return 0 if the buffer just contains the signature, and a specific + * error code if the valid signature is followed by more data. */ + if (p != end) { + ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; + } + +cleanup: + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); + + return ret; +} + + +int __real_mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen); + +int __wrap_mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen); + +int __wrap_mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen) +{ + return __wrap_mbedtls_ecdsa_read_signature_restartable( + ctx, hash, hlen, sig, slen, NULL); +} +#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY */ diff --git a/components/mbedtls/mbedtls_v3/port/esp_bignum.c b/components/mbedtls/mbedtls_v3/port/esp_bignum.c new file mode 100644 index 000000000..0fd608a27 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/esp_bignum.c @@ -0,0 +1,461 @@ +/* + * Multi-precision integer library + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +/* + * The following sources were referenced in the design of this Multi-precision + * Integer library: + * + * [1] Handbook of Applied Cryptography - 1997 + * Menezes, van Oorschot and Vanstone + * + * [2] Multi-Precision Math + * Tom St Denis + * https://github.com/libtom/libtommath/blob/develop/tommath.pdf + * + * [3] GNU Multi-Precision Arithmetic Library + * https://gmplib.org/manual/index.html + * + */ + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) + +#include "mbedtls/bignum.h" +#include "bignum_core.h" +#include "bignum_internal.h" +#include "bn_mul.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "constant_time_internal.h" + +#include +#include + +#include "mbedtls/platform.h" + +#if defined(MBEDTLS_MPI_EXP_MOD_ALT) +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) \ + do { \ + if( !(cond) ) \ + { \ + return( ret ); \ + } \ + } while( 0 ) + +/* Internal macro meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE( cond ) \ + do { \ + if( !(cond) ) \ + { \ + return; \ + } \ + } while( 0 ) + +#define MPI_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA ) +#define MPI_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define MULADDC_INIT \ +{ \ + mbedtls_mpi_uint s0, s1, b0, b1; \ + mbedtls_mpi_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) +{ + size_t i; + mbedtls_mpi_uint c, z; + + for( i = c = 0; i < n; i++, s++, d++ ) + { + z = ( *d < c ); *d -= c; + c = ( *d < *s ) + z; *d -= *s; + } + + while( c != 0 ) + { + z = ( *d < c ); *d -= c; + c = z; d++; + } +} + + +void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ); + +void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) +{ + mbedtls_mpi_uint c = 0, t = 0; + +#if defined(MULADDC_HUIT) + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_HUIT + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#else /* MULADDC_HUIT */ + for( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#endif /* MULADDC_HUIT */ + + t++; + + do { + *d += c; c = ( *d < c ); d++; + } + while( c != 0 ); +} +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) +{ + mbedtls_mpi_uint x, m0 = N->p[0]; + unsigned int i; + + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + + for( i = biL; i >= 8; i /= 2 ) + x *= ( 2 - ( m0 * x ) ); + + *mm = ~x + 1; +} + +/* + * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + */ +static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, + const mbedtls_mpi *T ) +{ + size_t i, n, m; + mbedtls_mpi_uint u0, u1, *d; + + if( T->n < N->n + 1 || T->p == NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( T->p, 0, T->n * ciL ); + + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; + + for( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; + + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); + + *d++ = u0; d[n + 1] = 0; + } + + memcpy( A->p, d, ( n + 1 ) * ciL ); + + if( mbedtls_mpi_cmp_abs( A, N ) >= 0 ) + mpi_sub_hlp( n, N->p, A->p ); + else + /* prevent timing attacks */ + mpi_sub_hlp( n, A->p, T->p ); + + return( 0 ); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + */ +static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, + mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +{ + mbedtls_mpi_uint z = 1; + mbedtls_mpi U; + + U.n = U.s = (int) z; + U.p = &z; + + return( mpi_montmul( A, &U, N, mm, T ) ); +} + +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *_RR ) +{ + int ret; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + mbedtls_mpi_uint ei, mm, state; + mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; + int neg; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( E != NULL ); + MPI_VALIDATE_RET( N != NULL ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); + mbedtls_mpi_init( &Apos ); + memset( W, 0, sizeof( W ) ); + + i = mbedtls_mpi_bitlen( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + +#if( MBEDTLS_MPI_WINDOW_SIZE < 6 ) + if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) + wsize = MBEDTLS_MPI_WINDOW_SIZE; +#endif + + j = N->n + 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); + + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + if( neg ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } + + /* + * If 1st call, pre-compute R^2 mod N + */ + if( _RR == NULL || _RR->p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); + + if( _RR != NULL ) + memcpy( _RR, &RR, sizeof( mbedtls_mpi ) ); + } + else + memcpy( &RR, _RR, sizeof( mbedtls_mpi ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); + + MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); + MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); + + if( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = one << ( wsize - 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); + + for( i = 0; i < wsize - 1; i++ ) + MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) ); + + /* + * W[i] = W[i - 1] * W[1] + */ + for( i = j + 1; i < ( one << wsize ); i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); + + MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) ); + } + } + + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; + + while( 1 ) + { + if( bufsize == 0 ) + { + if( nblimbs == 0 ) + break; + + nblimbs--; + + bufsize = sizeof( mbedtls_mpi_uint ) << 3; + } + + bufsize--; + + ei = (E->p[nblimbs] >> bufsize) & 1; + + /* + * skip leading 0s + */ + if( ei == 0 && state == 0 ) + continue; + + if( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= ( ei << ( wsize - nbits ) ); + + if( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for( i = 0; i < wsize; i++ ) + MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for( i = 0; i < nbits; i++ ) + { + MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + + wbits <<= 1; + + if( ( wbits & ( one << wsize ) ) != 0 ) + MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); + + if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) + { + X->s = -1; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); + } + +cleanup: + + for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) + mbedtls_mpi_free( &W[i] ); + + mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); + + if( _RR == NULL || _RR->p == NULL ) + mbedtls_mpi_free( &RR ); + + return( ret ); +} +#endif /* MBEDTLS_MPI_EXP_MOD_ALT */ +#endif /* MBEDTLS_BIGNUM_C */ diff --git a/components/mbedtls/mbedtls_v3/port/esp_ds/esp_rsa_sign_alt.c b/components/mbedtls/mbedtls_v3/port/esp_ds/esp_rsa_sign_alt.c new file mode 100644 index 000000000..023c33671 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/esp_ds/esp_rsa_sign_alt.c @@ -0,0 +1,273 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_ds.h" +#include "rsa_sign_alt.h" +#include "esp_memory_utils.h" + +#ifdef CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/rom/digital_signature.h" +#elif CONFIG_IDF_TARGET_ESP32C3 +#include "esp32c3/rom/digital_signature.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/digital_signature.h" +#elif CONFIG_IDF_TARGET_ESP32C6 +#include "esp32c6/rom/digital_signature.h" +#elif CONFIG_IDF_TARGET_ESP32H2 +#include "esp32h2/rom/digital_signature.h" +#else +#error "Selected target does not support esp_rsa_sign_alt (for DS)" +#endif + +#include "esp_log.h" +#include "esp_heap_caps.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include +static const char *TAG = "ESP_RSA_SIGN_ALT"; +#define SWAP_INT32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | ((x) << 24)) + +#include "mbedtls/rsa.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include + +static hmac_key_id_t s_esp_ds_hmac_key_id; +static esp_ds_data_t *s_ds_data; +static SemaphoreHandle_t s_ds_lock; +static int s_timeout_ms = 0; + +/* key length in bytes = (esp_digital_signature_length_t key + 1 ) * FACTOR_KEYLEN_IN_BYTES */ +#define FACTOR_KEYLEN_IN_BYTES 4 + +/* Lock for the DS session, other TLS connections trying to use the DS peripheral will be blocked + * till this DS session is completed (i.e. TLS handshake for this connection is completed) */ +static void __attribute__((constructor)) esp_ds_conn_lock (void) +{ + if ((s_ds_lock = xSemaphoreCreateMutex()) == NULL) { + ESP_EARLY_LOGE(TAG, "mutex for the DS session lock could not be created"); + } +} + +void esp_ds_set_session_timeout(int timeout) +{ + /* add additional offset of 1000 ms to have enough time for deleting the TLS connection and free the previous ds context after exceeding timeout value (this offset also helps when timeout is set to 0) */ + if (timeout > s_timeout_ms) { + s_timeout_ms = timeout + 1000; + } +} + +esp_err_t esp_ds_init_data_ctx(esp_ds_data_ctx_t *ds_data) +{ + if (ds_data == NULL || ds_data->esp_ds_data == NULL) { + return ESP_ERR_INVALID_ARG; + } + /* mutex is given back when the DS context is freed after the TLS handshake is completed or in case of failure (at cleanup) */ + if ((xSemaphoreTake(s_ds_lock, s_timeout_ms / portTICK_PERIOD_MS) != pdTRUE)) { + ESP_LOGE(TAG, "ds_lock could not be obtained in specified time"); + return ESP_FAIL; + } + s_ds_data = ds_data->esp_ds_data; + ESP_LOGD(TAG, "Using DS with key block %u, RSA length %u", ds_data->efuse_key_id, ds_data->rsa_length_bits); + s_esp_ds_hmac_key_id = (hmac_key_id_t) ds_data->efuse_key_id; + + const unsigned rsa_length_int = (ds_data->rsa_length_bits / 32) - 1; + if (esp_ptr_byte_accessible(s_ds_data)) { + /* calculate the rsa_length in terms of esp_digital_signature_length_t which is required for the internal DS API */ + s_ds_data->rsa_length = rsa_length_int; + } else if (s_ds_data->rsa_length != rsa_length_int) { + /* + * Configuration data is most likely from DROM segment and it + * is not properly formatted for all parameters consideration. + * Moreover, we can not modify as it is read-only and hence + * the error. + */ + ESP_LOGE(TAG, "RSA length mismatch %u, %u", s_ds_data->rsa_length, rsa_length_int); + return ESP_ERR_INVALID_ARG; + } + + return ESP_OK; +} + +void esp_ds_release_ds_lock(void) +{ + if (xSemaphoreGetMutexHolder(s_ds_lock) == xTaskGetCurrentTaskHandle()) { + /* Give back the semaphore (DS lock) */ + xSemaphoreGive(s_ds_lock); + } +} + +size_t esp_ds_get_keylen(void *ctx) +{ + /* calculating the rsa_length in bytes */ + return ((s_ds_data->rsa_length + 1) * FACTOR_KEYLEN_IN_BYTES); +} + +static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + size_t dst_len, + unsigned char *dst ) +{ + size_t oid_size = 0; + size_t nb_pad = dst_len; + unsigned char *p = dst; + const char *oid = NULL; + + /* Are we signing hashed or raw data? */ + if ( md_alg != MBEDTLS_MD_NONE ) { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if ( md_info == NULL ) { + return ( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + if ( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) { + return ( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + hashlen = mbedtls_md_get_size( md_info ); + + /* Double-check that 8 + hashlen + oid_size can be used as a + * 1-byte ASN.1 length encoding and that there's no overflow. */ + if ( 8 + hashlen + oid_size >= 0x80 || + 10 + hashlen < hashlen || + 10 + hashlen + oid_size < 10 + hashlen ) { + return ( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + /* + * Static bounds check: + * - Need 10 bytes for five tag-length pairs. + * (Insist on 1-byte length encodings to protect against variants of + * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification) + * - Need hashlen bytes for hash + * - Need oid_size bytes for hash alg OID. + */ + if ( nb_pad < 10 + hashlen + oid_size ) { + return ( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + nb_pad -= 10 + hashlen + oid_size; + } else { + if ( nb_pad < hashlen ) { + return ( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + nb_pad -= hashlen; + } + + /* Need space for signature header and padding delimiter (3 bytes), + * and 8 bytes for the minimal padding */ + if ( nb_pad < 3 + 8 ) { + return ( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + nb_pad -= 3; + + /* Now nb_pad is the amount of memory to be filled + * with padding, and at least 8 bytes long. */ + + /* Write signature header and padding */ + *p++ = 0; + *p++ = MBEDTLS_RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + + /* Are we signing raw data? */ + if ( md_alg == MBEDTLS_MD_NONE ) { + memcpy( p, hash, hashlen ); + return ( 0 ); + } + + /* Signing hashed data, add corresponding ASN.1 structure + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * Digest ::= OCTET STRING + * + * Schematic: + * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ] + * TAG-NULL + LEN [ NULL ] ] + * TAG-OCTET + LEN [ HASH ] ] + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = (unsigned char) oid_size; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = (unsigned char) hashlen; + memcpy( p, hash, hashlen ); + p += hashlen; + + /* Just a sanity-check, should be automatic + * after the initial bounds check. */ + if ( p != dst + dst_len ) { + mbedtls_platform_zeroize( dst, dst_len ); + return ( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return ( 0 ); +} + + +int esp_ds_rsa_sign( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ) +{ + esp_ds_context_t *esp_ds_ctx; + esp_err_t ds_r; + int ret = -1; + uint32_t *signature = heap_caps_malloc_prefer((s_ds_data->rsa_length + 1) * FACTOR_KEYLEN_IN_BYTES, 2, MALLOC_CAP_32BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL); + if (signature == NULL) { + ESP_LOGE(TAG, "Could not allocate memory for internal DS operations"); + return -1; + } + + if ((ret = (rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, ((s_ds_data->rsa_length + 1) * FACTOR_KEYLEN_IN_BYTES), sig ))) != 0) { + ESP_LOGE(TAG, "Error in pkcs1_v15 encoding, returned %d", ret); + heap_caps_free(signature); + return -1; + } + + for (unsigned int i = 0; i < (s_ds_data->rsa_length + 1); i++) { + signature[i] = SWAP_INT32(((uint32_t *)sig)[(s_ds_data->rsa_length + 1) - (i + 1)]); + } + + ds_r = esp_ds_start_sign((const void *)signature, + s_ds_data, + s_esp_ds_hmac_key_id, + &esp_ds_ctx); + if (ds_r != ESP_OK) { + ESP_LOGE(TAG, "Error in esp_ds_start_sign, returned %d ", ds_r); + heap_caps_free(signature); + return -1; + } + + ds_r = esp_ds_finish_sign((void *)signature, esp_ds_ctx); + if (ds_r != ESP_OK) { + if (ds_r == ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST) { + ESP_LOGE(TAG, "Invalid digest in DS data reported by esp_ds_finish_sign"); + } else { + ESP_LOGE(TAG, "Error in esp_ds_finish_sign, returned %d ", ds_r); + } + heap_caps_free(signature); + return -1; + } + + for (unsigned int i = 0; i < (s_ds_data->rsa_length + 1); i++) { + ((uint32_t *)sig)[i] = SWAP_INT32(((uint32_t *)signature)[(s_ds_data->rsa_length + 1) - (i + 1)]); + } + heap_caps_free(signature); + return 0; +} diff --git a/components/mbedtls/mbedtls_v3/port/esp_hardware.c b/components/mbedtls/mbedtls_v3/port/esp_hardware.c new file mode 100644 index 000000000..c7efea6a6 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/esp_hardware.c @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include +#include +#include + +#include + +#include + +#ifndef MBEDTLS_ENTROPY_HARDWARE_ALT +#error "MBEDTLS_ENTROPY_HARDWARE_ALT should always be set in ESP-IDF" +#endif + +int mbedtls_hardware_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + esp_fill_random(output, len); + *olen = len; + return 0; +} diff --git a/components/mbedtls/mbedtls_v3/port/esp_mem.c b/components/mbedtls/mbedtls_v3/port/esp_mem.c new file mode 100644 index 000000000..a716656b9 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/esp_mem.c @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "esp_mem.h" + +#ifndef CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC + +IRAM_ATTR void *esp_mbedtls_mem_calloc(size_t n, size_t size) +{ + return calloc(n, size); +} + +IRAM_ATTR void esp_mbedtls_mem_free(void *ptr) +{ + return heap_caps_free(ptr); +} + +#endif /* !CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC */ diff --git a/components/mbedtls/mbedtls_v3/port/esp_platform_time.c b/components/mbedtls/mbedtls_v3/port/esp_platform_time.c new file mode 100644 index 000000000..541b664ab --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/esp_platform_time.c @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mbedtls/build_info.h" +#include "mbedtls/platform_time.h" + +#ifdef MBEDTLS_PLATFORM_MS_TIME_ALT +mbedtls_ms_time_t mbedtls_ms_time() +{ + int ret; + struct timespec tv = {}; + mbedtls_ms_time_t current_ms; + + ret = clock_gettime(CLOCK_MONOTONIC, &tv); + if (ret) { + return time(NULL) * 1000L; + } + + current_ms = tv.tv_sec; + return current_ms * 1000L + tv.tv_nsec / 1000000L; +} +#endif // MBEDTLS_PLATFORM_MS_TIME_ALT diff --git a/components/mbedtls/mbedtls_v3/port/esp_timing.c b/components/mbedtls/mbedtls_v3/port/esp_timing.c new file mode 100644 index 000000000..96858f765 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/esp_timing.c @@ -0,0 +1,94 @@ +/* + * Portable interface to the CPU cycle counter + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD + */ +/* + * mbedtls_timing_get_timer()m mbedtls_timing_set_delay() and + * mbedtls_timing_set_delay only abstracted from mbedtls/library/timing.c + * as that does not build on ESP-IDF but these 2 functions are needed for + * DTLS (in particular mbedtls_ssl_set_timer_cb() must be called for DTLS + * which requires these 2 delay functions). + */ + +#include + +#if !defined(MBEDTLS_ESP_TIMING_C) + +#include +#include "mbedtls/timing.h" + +struct _hr_time +{ + struct timeval start; +}; + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + struct _hr_time *t = (struct _hr_time *) val; + + if( reset ) + { + gettimeofday( &t->start, NULL ); + return( 0 ); + } + else + { + unsigned long delta; + struct timeval now; + gettimeofday( &now, NULL ); + delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul + + ( now.tv_usec - t->start.tv_usec ) / 1000; + return( delta ); + } +} + +/* + * Set delays to watch + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + + ctx->MBEDTLS_PRIVATE(int_ms) = int_ms; + ctx->MBEDTLS_PRIVATE(fin_ms) = fin_ms; + + if( fin_ms != 0 ) + (void) mbedtls_timing_get_timer( &ctx->MBEDTLS_PRIVATE(timer), 1 ); +} + +/* + * Get number of delays expired + */ +int mbedtls_timing_get_delay( void *data ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + unsigned long elapsed_ms; + + if( ctx->MBEDTLS_PRIVATE(fin_ms) == 0 ) + return( -1 ); + + elapsed_ms = mbedtls_timing_get_timer( &ctx->MBEDTLS_PRIVATE(timer), 0 ); + + if( elapsed_ms >= ctx->MBEDTLS_PRIVATE(fin_ms) ) + return( 2 ); + + if( elapsed_ms >= ctx->MBEDTLS_PRIVATE(int_ms) ) + return( 1 ); + + return( 0 ); +} + +/* + * Get the final delay. + */ +uint32_t mbedtls_timing_get_final_delay( const mbedtls_timing_delay_context *data ) +{ + return( data->MBEDTLS_PRIVATE(fin_ms) ); +} + +#endif /* MBEDTLS_ESP_TIMING_C */ diff --git a/components/mbedtls/mbedtls_v3/port/include/aes/esp_aes.h b/components/mbedtls/mbedtls_v3/port/include/aes/esp_aes.h new file mode 100644 index 000000000..c9c431696 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/aes/esp_aes.h @@ -0,0 +1,356 @@ +/** + * \brief AES block cipher, ESP hardware accelerated version + * Based on mbedTLS FIPS-197 compliant version. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + */ + +#pragma once + +#include "esp_types.h" +#include "hal/aes_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define ERR_ESP_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define ERR_ESP_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +/** + * \brief AES context structure + * + */ +typedef struct { + uint8_t key_bytes; + volatile uint8_t key_in_hardware; /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */ + uint8_t key[32]; +} esp_aes_context; + +/** + * \brief The AES XTS context-type definition. + */ +typedef struct +{ + esp_aes_context crypt; /*!< The AES context to use for AES block + encryption or decryption. */ + esp_aes_context tweak; /*!< The AES context used for tweak + computation. */ +} esp_aes_xts_context; + + + + +/** + * \brief Lock access to AES hardware unit + * + * AES hardware unit can only be used by one + * consumer at a time. + * + * esp_aes_xxx API calls automatically manage locking & unlocking of + * hardware, this function is only needed if you want to call + * ets_aes_xxx functions directly. + */ +void esp_aes_acquire_hardware( void ); + +/** + * \brief Unlock access to AES hardware unit + * + * esp_aes_xxx API calls automatically manage locking & unlocking of + * hardware, this function is only needed if you want to call + * ets_aes_xxx functions directly. + */ +void esp_aes_release_hardware( void ); + +/** + * \brief Initialize AES context + * + * \param ctx AES context to be initialized + */ +void esp_aes_init( esp_aes_context *ctx ); + +/** + * \brief Clear AES context + * + * \param ctx AES context to be cleared + */ +void esp_aes_free( esp_aes_context *ctx ); + +/** + * \brief This function initializes the specified AES XTS context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES XTS context to initialize. + */ +void esp_aes_xts_init( esp_aes_xts_context *ctx ); + +/** + * \brief This function releases and clears the specified AES XTS context. + * + * \param ctx The AES XTS context to clear. + */ +void esp_aes_xts_free( esp_aes_xts_context *ctx ); + +/** + * \brief AES set key schedule (encryption or decryption) + * + * \param ctx AES context to be initialized + * \param key encryption key + * \param keybits must be 128, 192 or 256 + * + * \return 0 if successful, or ERR_AES_INVALID_KEY_LENGTH + */ +int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits ); + +/** + * \brief AES-ECB block encryption/decryption + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if successful + */ +int esp_aes_crypt_ecb( esp_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16] ); + +/** + * \brief AES-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (16 bytes) + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or ERR_AES_INVALID_INPUT_LENGTH + */ +int esp_aes_crypt_cbc( esp_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + + +/** + * \brief AES-CFB128 buffer encryption/decryption. + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful + */ +int esp_aes_crypt_cfb128( esp_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief AES-CFB8 buffer encryption/decryption. + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful + */ +int esp_aes_crypt_cfb8( esp_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief AES-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * Note: Due to the nature of CTR you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. + * + * \param ctx AES context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int esp_aes_crypt_ctr( esp_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an AES-OFB (Output Feedback Mode) + * encryption or decryption operation. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int esp_aes_crypt_ofb( esp_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function prepares an XTS context for encryption and + * sets the encryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * \param key The encryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function prepares an XTS context for decryption and + * sets the decryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * \param key The decryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); + + +/** + * \brief Internal AES block encryption function + * (Only exposed to allow overriding it, + * see AES_ENCRYPT_ALT) + * + * \param ctx AES context + * \param input Plaintext block + * \param output Output (ciphertext) block + */ +int esp_internal_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ); + +/** + * \brief Internal AES block decryption function + * (Only exposed to allow overriding it, + * see AES_DECRYPT_ALT) + * + * \param ctx AES context + * \param input Ciphertext block + * \param output Output (plaintext) block + */ +int esp_internal_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ); + +/** AES-XTS buffer encryption/decryption */ +int esp_aes_crypt_xts( esp_aes_xts_context *ctx, int mode, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output ); + +/** Deprecated, see esp_aes_internal_decrypt */ +void esp_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated)); + +/** Deprecated, see esp_aes_internal_encrypt */ +void esp_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated)); + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/aes/esp_aes_gcm.h b/components/mbedtls/mbedtls_v3/port/include/aes/esp_aes_gcm.h new file mode 100644 index 000000000..8efb87f40 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/aes/esp_aes_gcm.h @@ -0,0 +1,293 @@ +/* + * GCM block cipher, ESP DMA hardware accelerated version + * Based on mbedTLS FIPS-197 compliant version. + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD + */ +#pragma once + +#include "aes/esp_aes.h" +#include "mbedtls/cipher.h" +#include "soc/lldesc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + ESP_AES_GCM_STATE_INIT, + ESP_AES_GCM_STATE_START, + ESP_AES_GCM_STATE_UPDATE, + ESP_AES_GCM_STATE_FINISH +} esp_aes_gcm_state; +/** + * \brief The GCM context structure. + */ +typedef struct { + uint8_t H[16]; /*!< Initial hash value */ + uint8_t ghash[16]; /*!< GHASH value. */ + uint8_t J0[16]; + uint64_t HL[16]; /*!< Precalculated HTable low. */ + uint64_t HH[16]; /*!< Precalculated HTable high. */ + uint8_t ori_j0[16]; /*!< J0 from first iteration. */ + const uint8_t *iv; + size_t iv_len; /*!< The length of IV. */ + uint64_t aad_len; /*!< The total length of the additional data. */ + size_t data_len; + int mode; + const unsigned char *aad; /*!< The additional data. */ + esp_aes_context aes_ctx; + esp_aes_gcm_state gcm_state; + /* Software context needed for soft fallback for non-AES ciphers */ + void *ctx_soft; +} esp_gcm_context; + + +/** + * \brief This function initializes the specified GCM context + * + * \param ctx The GCM context to initialize. + */ +void esp_aes_gcm_init( esp_gcm_context *ctx); + +/** + * \brief This function associates a GCM context with a + * key. + * + * \param ctx The GCM context to initialize. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. + * \param keybits The key size in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A cipher-specific error code on failure. + */ +int esp_aes_gcm_setkey( esp_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function starts a GCM encryption or decryption + * operation. + * + * \param ctx The GCM context. This must be initialized. + * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or + * #MBEDTLS_GCM_DECRYPT. + * \param iv The initialization vector. This must be a readable buffer of + * at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * + * \return \c 0 on success. + */ +int esp_aes_gcm_starts( esp_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len ); + +/** + * \brief This function feeds an input buffer as associated data + * (authenticated but not encrypted data) in a GCM + * encryption or decryption operation. + * + * Call this function after mbedtls_gcm_starts() to pass + * the associated data. If the associated data is empty, + * you do not need to call this function. You may not + * call this function after calling mbedtls_cipher_update(). + * + * \param ctx The GCM context. This must have been started with + * mbedtls_gcm_starts() and must not have yet received + * any input with mbedtls_gcm_update(). + * \param aad The buffer holding the additional data, or \c NULL + * if \p aad_len is \c 0. + * \param aad_len The length of the additional data. If \c 0, + * \p add may be \c NULL. + * + * \return \c 0 on success. + */ +int esp_aes_gcm_update_ad( esp_gcm_context *ctx, + const unsigned char *aad, + size_t aad_len ); + +/** + * \brief This function feeds an input buffer into an ongoing GCM + * encryption or decryption operation. + * + * You may call this function zero, one or more times + * to pass successive parts of the input: the plaintext to + * encrypt, or the ciphertext (not including the tag) to + * decrypt. After the last part of the input, call + * mbedtls_gcm_finish(). + * + * This function may produce output in one of the following + * ways: + * - Immediate output: the output length is always equal + * to the input length. + * - Buffered output: the output consists of a whole number + * of 16-byte blocks. If the total input length so far + * (not including associated data) is 16 \* *B* + *A* + * with *A* < 16 then the total output length is 16 \* *B*. + * + * In particular: + * - It is always correct to call this function with + * \p output_size >= \p input_length + 15. + * - If \p input_length is a multiple of 16 for all the calls + * to this function during an operation, then it is + * correct to use \p output_size = \p input_length. + * + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. + * + * \param ctx The GCM context. This must be initialized. + * \param input The buffer holding the input data. If \p input_length + * is greater than zero, this must be a readable buffer + * of at least \p input_length bytes. + * \param input_length The length of the input data in bytes. + * \param output The buffer for the output data. If \p output_size + * is greater than zero, this must be a writable buffer of + * of at least \p output_size bytes. + * \param output_size The size of the output buffer in bytes. + * See the function description regarding the output size. + * \param output_length On success, \p *output_length contains the actual + * length of the output written in \p output. + * On failure, the content of \p *output_length is + * unspecified. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure: + * total input length too long, + * unsupported input/output buffer overlap detected, + * or \p output_size too small. + */ +int esp_aes_gcm_update( esp_gcm_context *ctx, + const unsigned char *input, size_t input_length, + unsigned char *output, size_t output_size, + size_t *output_length ); + +/** + * \brief This function finishes the GCM operation and generates + * the authentication tag. + * + * It wraps up the GCM stream, and generates the + * tag. The tag can have a maximum length of 16 Bytes. + * + * \param ctx The GCM context. This must be initialized. + * \param tag The buffer for holding the tag. This must be a writable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to generate. This must be at least + * four. + * \param output The buffer for the final output. + * If \p output_size is nonzero, this must be a writable + * buffer of at least \p output_size bytes. + * \param output_size The size of the \p output buffer in bytes. + * This must be large enough for the output that + * mbedtls_gcm_update() has not produced. In particular: + * - If mbedtls_gcm_update() produces immediate output, + * or if the total input size is a multiple of \c 16, + * then mbedtls_gcm_finish() never produces any output, + * so \p output_size can be \c 0. + * - \p output_size never needs to be more than \c 15. + * \param output_length On success, \p *output_length contains the actual + * length of the output written in \p output. + * On failure, the content of \p *output_length is + * unspecified. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure: + * invalid value of \p tag_len, + * or \p output_size too small. + */ +int esp_aes_gcm_finish( esp_gcm_context *ctx, + unsigned char *output, size_t output_size, + size_t *output_length, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function clears a GCM context + * + * \param ctx The GCM context to clear. + */ +void esp_aes_gcm_free( esp_gcm_context *ctx); + +/** + * \brief This function performs GCM encryption or decryption of a buffer. + * + * \note For encryption, the output buffer can be the same as the + * input buffer. For decryption, the output buffer cannot be + * the same as input buffer. If the buffers overlap, the output + * buffer must trail at least 8 Bytes behind the input buffer. + * + * \param ctx The GCM context to use for encryption or decryption. + * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or + * #MBEDTLS_GCM_DECRYPT. + * \param length The length of the input data. This must be a multiple of + * 16 except in the last call before mbedtls_gcm_finish(). + * \param iv The initialization vector. + * \param iv_len The length of the IV. + * \param aad The buffer holding the additional data. + * \param aad_len The length of the additional data. + * \param input The buffer holding the input data. + * \param output The buffer for holding the output data. + * \param tag_len The length of the tag to generate. + * \param tag The buffer for holding the tag. + * + * \return \c 0 on success. + */ +int esp_aes_gcm_crypt_and_tag( esp_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ); + + +/** + * \brief This function performs a GCM authenticated decryption of a + * buffer. + * + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. + * + * \param ctx The GCM context. + * \param length The length of the input data. This must be a multiple + * of 16 except in the last call before mbedtls_gcm_finish(). + * \param iv The initialization vector. + * \param iv_len The length of the IV. + * \param aad The buffer holding the additional data. + * \param aad_len The length of the additional data. + * \param tag The buffer holding the tag. + * \param tag_len The length of the tag. + * \param input The buffer holding the input data. + * \param output The buffer for holding the output data. + * + * \return 0 if successful and authenticated. + * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. + */ +int esp_aes_gcm_auth_decrypt( esp_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *aad, + size_t aad_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/aes/esp_aes_internal.h b/components/mbedtls/mbedtls_v3/port/include/aes/esp_aes_internal.h new file mode 100644 index 000000000..35a7d3935 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/aes/esp_aes_internal.h @@ -0,0 +1,54 @@ +/** + * \brief AES block cipher, ESP-IDF hardware accelerated version + * Based on mbedTLS FIPS-197 compliant version. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Internal API + */ + +#pragma once + + +#include "aes/esp_aes.h" +#include "aes/esp_aes_gcm.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool valid_key_length(const esp_aes_context *ctx); + + +/** + * @brief Run a AES-GCM conversion using DMA + * + * @param ctx Aes context + * @param input Pointer to input data + * @param output Pointer to output data + * @param len Length of the input data + * @param aad_desc GCM additional data DMA descriptor + * @param aad_len GCM additional data length + * @return int -1 on error + */ +int esp_aes_process_dma_gcm(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, lldesc_t *aad_desc, size_t aad_len); + + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/aes_alt.h b/components/mbedtls/mbedtls_v3/port/include/aes_alt.h new file mode 100644 index 000000000..2f8e958b2 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/aes_alt.h @@ -0,0 +1,69 @@ +/** + * \file aes_alt.h + * + * \brief AES block cipher + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + */ +#ifndef AES_ALT_H +#define AES_ALT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_AES_ALT) +#include "aes/esp_aes.h" + +typedef esp_aes_context mbedtls_aes_context; + +#define mbedtls_aes_init esp_aes_init +#define mbedtls_aes_free esp_aes_free +#define mbedtls_aes_setkey_enc esp_aes_setkey +#define mbedtls_aes_setkey_dec esp_aes_setkey +#define mbedtls_aes_crypt_ecb esp_aes_crypt_ecb +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define mbedtls_aes_crypt_cbc esp_aes_crypt_cbc +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) +#define mbedtls_aes_crypt_cfb128 esp_aes_crypt_cfb128 +#define mbedtls_aes_crypt_cfb8 esp_aes_crypt_cfb8 +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) +#define mbedtls_aes_crypt_ctr esp_aes_crypt_ctr +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) +#define mbedtls_aes_crypt_ofb esp_aes_crypt_ofb +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) +typedef esp_aes_xts_context mbedtls_aes_xts_context; +#define mbedtls_aes_xts_init esp_aes_xts_init +#define mbedtls_aes_xts_free esp_aes_xts_free +#define mbedtls_aes_xts_setkey_enc esp_aes_xts_setkey_enc +#define mbedtls_aes_xts_setkey_dec esp_aes_xts_setkey_dec +#define mbedtls_aes_crypt_xts esp_aes_crypt_xts +#endif +#define mbedtls_internal_aes_encrypt esp_internal_aes_encrypt +#define mbedtls_internal_aes_decrypt esp_internal_aes_decrypt +#endif /* MBEDTLS_AES_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/bignum_impl.h b/components/mbedtls/mbedtls_v3/port/include/bignum_impl.h new file mode 100644 index 000000000..cb208ecb5 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/bignum_impl.h @@ -0,0 +1,96 @@ +#ifndef _ESP_BIGNUM_H_ +#define _ESP_BIGNUM_H_ + +#include +#include + +/* Use montgomery exponentiation (HAC 14.94) for calculating X ^ Y mod M, + this may be faster for some targets. The hardware acceleration support for modular + exponentiation on the ESP32 is slow for public key operations, so use montgomery + exponentiation instead. +*/ +#if CONFIG_IDF_TARGET_ESP32 +#define ESP_MPI_USE_MONT_EXP +#endif + +/** + * @brief Enable the MPI hardware and acquire the lock + * + */ +void esp_mpi_enable_hardware_hw_op( void ); + +/** + * @brief Disable the MPI hardware and release the lock + * + */ +void esp_mpi_disable_hardware_hw_op( void ); + +/** + * @brief Calculate the number of words needed to represent the input word in hardware + * + * @param words The number of words to be represented + * + * @return size_t Number of words required + */ +size_t esp_mpi_hardware_words(size_t words); + +/** + * @brief Starts a (X * Y) Mod M calculation in hardware. Rinv and M_prime needs to be precalculated in software. + * + */ +void esp_mpi_mul_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t hw_words); + +/** + * @brief Starts a (X * Y) calculation in hardware. + * + */ +void esp_mpi_mul_mpi_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words); + +/** + * @brief Special-case of (X * Y), where we use hardware montgomery mod + multiplication to calculate result where either A or B are >2048 bits so + can't use the standard multiplication method. + * + */ +void esp_mpi_mult_mpi_failover_mod_mult_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words); + +/** + * @brief Read out the result from the previous calculation. + * + */ +void esp_mpi_read_result_hw_op(mbedtls_mpi *Z, size_t z_words); + +#ifdef ESP_MPI_USE_MONT_EXP +/** + * @brief Starts a montgomery multiplication calculation in hardware + * + */ +int esp_mont_hw_op(mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi* Y, const mbedtls_mpi* M, + mbedtls_mpi_uint Mprime, + size_t hw_words, + bool again); + +#else + +/** + * @brief Starts a (X ^ Y) Mod M calculation in hardware. Rinv and M_prime needs to be precalculated in software. + * + */ +void esp_mpi_exp_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t hw_words); + +#endif //ESP_MPI_USE_MONT_EXP + +/** + * @brief Enable/disables MPI operation complete interrupt + * + * @param enable true: enable, false: disable + */ +void esp_mpi_interrupt_enable( bool enable ); + +/** + * @brief Clears the MPI operation complete interrupt status + * + */ +void esp_mpi_interrupt_clear( void ); + +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/ecc_impl.h b/components/mbedtls/mbedtls_v3/port/include/ecc_impl.h new file mode 100644 index 000000000..c52c98819 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/ecc_impl.h @@ -0,0 +1,60 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define P256_LEN (256/8) +#define P192_LEN (192/8) + +/* Note: x & y are stored in little endian order (same as CPU byte order, and order used internally by most libraries). + + This is the same order used in hardware + + Note this is opposite to most byte string formats used to represent keys, which are often big endian +*/ +typedef struct { + uint8_t x[P256_LEN]; /* Little endian order */ + uint8_t y[P256_LEN]; /* Little endian order */ + unsigned len; /* P192_LEN or P256_LEN */ +} ecc_point_t; + +/** + * @brief Perform ECC point multiplication (R = K * (Px, Py)) + * + * @param point ECC point (multiplicand) + * @param scalar Integer represented in byte array format (multiplier) + * @param result Result of the multiplication + * @param verify_first Verify that the point is on the curve before performing multiplication + * + * @return - 0 if the multiplication was successful + * - -1 otherwise + * + * @note 'scalar' is expected as a byte array in little endian order. + * Most byte string formats used to represent keys are in big endian order. + */ +int esp_ecc_point_multiply(const ecc_point_t *point, const uint8_t *scalar, ecc_point_t *result, bool verify_first); + +/** + * @brief Perform ECC point verification, + * i.e check whether the point (Px, Py) lies on the curve + * + * @param point ECC point that needs to be verified + * + * @return - 1, if point lies on the curve + * - 0, otherwise + * + */ +int esp_ecc_point_verify(const ecc_point_t *point); + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/ecdsa/ecdsa_alt.h b/components/mbedtls/mbedtls_v3/port/include/ecdsa/ecdsa_alt.h new file mode 100644 index 000000000..f4b7af6a0 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/ecdsa/ecdsa_alt.h @@ -0,0 +1,54 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "sdkconfig.h" +#include "mbedtls/pk.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || __DOXYGEN__ + +/** + * @brief Initialize MPI to notify mbedtls_ecdsa_sign to use the private key in efuse + * We break the MPI struct of the private key in order to + * differentiate between hardware key and software key + * + * @param key The MPI in which this functions stores the hardware context. + * This must be uninitialized + * @param efuse_blk The efuse key block that should be used as the private key. + * The key purpose of this block must be ECDSA_KEY + * + * @return - 0 if successful + * - -1 otherwise + * + */ +int esp_ecdsa_privkey_load_mpi(mbedtls_mpi *key, int efuse_blk); + +/** + * @brief Initialize PK context to notify mbedtls_ecdsa_sign to use the private key in efuse + * We break the MPI struct used to represent the private key `d` in ECP keypair + * in order to differentiate between hardware key and software key + * + * @param key_ctx The context in which this functions stores the hardware context. + * This must be uninitialized + * @param efuse_blk The efuse key block that should be used as the private key. + * The key purpose of this block must be ECDSA_KEY + * + * @return - 0 if successful + * - -1 otherwise + */ +int esp_ecdsa_privkey_load_pk_context(mbedtls_pk_context *key_ctx, int efuse_blk); + +#endif // CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || __DOXYGEN__ + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/entropy_poll.h b/components/mbedtls/mbedtls_v3/port/include/entropy_poll.h new file mode 100644 index 000000000..4bae4d1db --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/entropy_poll.h @@ -0,0 +1,28 @@ +/** + * Mbedtls entropy_poll.h file + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef MBEDTLS_ENTROPY_POLL_H +#define MBEDTLS_ENTROPY_POLL_H +#include "mbedtls/build_info.h" +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Entropy poll callback for a hardware source + * + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_hardware_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); + +#ifdef __cplusplus +} +#endif + +#endif /* entropy_poll.h */ diff --git a/components/mbedtls/mbedtls_v3/port/include/esp_crypto_shared_gdma.h b/components/mbedtls/mbedtls_v3/port/include/esp_crypto_shared_gdma.h new file mode 100644 index 000000000..4e69a5f8e --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/esp_crypto_shared_gdma.h @@ -0,0 +1,47 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "soc/lldesc.h" +#include "esp_private/gdma.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Start a GDMA transfer on the shared crypto DMA channel + * + * @note Will allocate a GDMA channel for AES & SHA if no such channel is already allocated + * + * @param input Input linked list descriptor + * @param output Output linked list descriptor + * @param peripheral Crypto peripheral to connect the DMA to, either GDMA_TRIG_PERIPH_AES or + * GDMA_TRIG_PERIPH_SHA + * @return esp_err_t ESP_FAIL if no GDMA channel available + */ +esp_err_t esp_crypto_shared_gdma_start(const lldesc_t *input, const lldesc_t *output, gdma_trigger_peripheral_t peripheral); + + +/** + * @brief Frees any shared crypto DMA channel, if esp_crypto_shared_gdma_start is called after + * this, new GDMA channels will be allocated. + * + * @note Function is meant to be called from user code, and thus takes AES/SHA lock. + * This means this function should not be called from code which already takes these locks, + * i.e. inside our AES/SHA code. + * + * If you are continously using AES/SHA (e.g. because of a wifi connection) then it's not recommended + * to use this API. Freeing the channel is mainly for use cases where you are finished with the crypto peripherals + * and need the DMA channel for other peripherals. An example would be doing some processing after disconnecting WiFi + */ +void esp_crypto_shared_gdma_free(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/esp_ds/esp_rsa_sign_alt.h b/components/mbedtls/mbedtls_v3/port/include/esp_ds/esp_rsa_sign_alt.h new file mode 100644 index 000000000..7c00ced54 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/esp_ds/esp_rsa_sign_alt.h @@ -0,0 +1,78 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifndef _ESP_RSA_SIGN_ALT_H_ +#define _ESP_RSA_SIGN_ALT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_ds.h" +#include "mbedtls/md.h" + +/** + * @brief ESP-DS data context + * + * @note This structure includes encrypted private key parameters such as ciphertext_c, initialization vector, efuse_key_id, RSA key length, which are obtained when DS peripheral is configured. + */ + +/* Context for encrypted private key data required for DS */ +typedef struct esp_ds_data_ctx { + esp_ds_data_t *esp_ds_data; + uint8_t efuse_key_id; /* efuse block id in which DS_KEY is stored e.g. 0,1*/ + uint16_t rsa_length_bits; /* length of RSA private key in bits e.g. 2048 */ +} esp_ds_data_ctx_t; + +/** + * @brief Initializes internal DS data context + * + * This function allocates and initializes internal ds data context which is used for Digital Signature operation. + * + * @in ds_data ds_data context containing encrypted private key parameters + * @return + * - ESP_OK In case of succees + * - ESP_ERR_NO_MEM In case internal context could not be allocated. + * - ESP_ERR_INVALID_ARG in case input parametrers are NULL + * + */ +esp_err_t esp_ds_init_data_ctx(esp_ds_data_ctx_t *ds_data); + +/** + * + * @brief Release the ds lock acquired for the DS operation (then the DS peripheral can be used for other TLS connection) + * + */ +void esp_ds_release_ds_lock(void); + +/** + * + * @brief Alternate implementation for mbedtls_rsa_rsassa_pkcs1_v15_sign, Internally makes use + * of DS module to perform hardware accelerated RSA sign operation + */ +int esp_ds_rsa_sign( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); + +/* + * @brief Get RSA key length in bytes from internal DS context + * + * @return RSA key length in bytes + */ +size_t esp_ds_get_keylen(void *ctx); + +/* + * @brief Set timeout (equal to TLS session timeout), so that DS module usage can be synchronized in case of multiple TLS connections using DS module, + */ +void esp_ds_set_session_timeout(int timeout); +#ifdef __cplusplus +} +#endif + +#endif /* _ESP_RSA_SIGN_ALT_H_ */ diff --git a/components/mbedtls/mbedtls_v3/port/include/esp_mem.h b/components/mbedtls/mbedtls_v3/port/include/esp_mem.h new file mode 100644 index 000000000..c88b13287 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/esp_mem.h @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +void *esp_mbedtls_mem_calloc(size_t n, size_t size); +void esp_mbedtls_mem_free(void *ptr); diff --git a/components/mbedtls/mbedtls_v3/port/include/gcm_alt.h b/components/mbedtls/mbedtls_v3/port/include/gcm_alt.h new file mode 100644 index 000000000..f76970944 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/gcm_alt.h @@ -0,0 +1,43 @@ +/* + * gcm_alt.h: AES block cipher + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD + */ +#ifndef GCM_ALT_H +#define GCM_ALT_H + +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_GCM_ALT) + + +#include "aes/esp_aes_gcm.h" + + +typedef esp_gcm_context mbedtls_gcm_context; + +#define mbedtls_gcm_init esp_aes_gcm_init +#define mbedtls_gcm_free esp_aes_gcm_free +#define mbedtls_gcm_setkey esp_aes_gcm_setkey +#define mbedtls_gcm_starts esp_aes_gcm_starts +#define mbedtls_gcm_update_ad esp_aes_gcm_update_ad +#define mbedtls_gcm_update esp_aes_gcm_update +#define mbedtls_gcm_finish esp_aes_gcm_finish +#define mbedtls_gcm_auth_decrypt esp_aes_gcm_auth_decrypt +#define mbedtls_gcm_crypt_and_tag esp_aes_gcm_crypt_and_tag + +#endif /* MBEDTLS_GCM_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/mbedtls/bignum.h b/components/mbedtls/mbedtls_v3/port/include/mbedtls/bignum.h new file mode 100644 index 000000000..4f84bed74 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/mbedtls/bignum.h @@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include_next "mbedtls/bignum.h" +#include "sdkconfig.h" + +/** + * This is a wrapper for the main mbedtls/bignum.h. This wrapper + * provides a few additional ESP32-only functions. + * + * This is because we don't set MBEDTLS_BIGNUM_ALT in the same way we + * do for AES, SHA, etc. Because we still use most of the bignum.h + * implementation and just replace a few hardware accelerated + * functions (see MBEDTLS_MPI_EXP_MOD_ALT & MBEDTLS_MPI_MUL_MPI_ALT in + * esp_config.h). + * + * @note Unlike the other hardware accelerator support functions in esp32/hwcrypto, there is no + * generic "hwcrypto/bignum.h" header for using these functions without mbedTLS. The reason for this + * is that all of the function implementations depend strongly upon the mbedTLS MPI implementation. + */ + +/** + * @brief Lock access to RSA Accelerator (MPI/bignum operations) + * + * RSA Accelerator hardware unit can only be used by one + * consumer at a time. + * + * @note This function is non-recursive (do not call it twice from the + * same task.) + * + * @note You do not need to call this if you are using the mbedTLS bignum.h + * API or esp_mpi_xxx functions. This function is only needed if you + * want to call ROM RSA functions or access the registers directly. + * + */ +void esp_mpi_acquire_hardware(void); + +/** + * @brief Unlock access to RSA Accelerator (MPI/bignum operations) + * + * Has to be called once for each call to esp_mpi_acquire_hardware(). + * + * @note You do not need to call this if you are using the mbedTLS bignum.h + * API or esp_mpi_xxx functions. This function is only needed if you + * want to call ROM RSA functions or access the registers directly. + */ +void esp_mpi_release_hardware(void); + +#if CONFIG_MBEDTLS_HARDWARE_MPI + +/* @brief MPI modular mupltiplication function + * + * Calculates Z = (X * Y) mod M using MPI hardware acceleration. + * + * This is not part of the standard mbedTLS bignum API. + * + * @note All of X, Y & Z should be less than 4096 bit long or an error is returned. + * + * @param Z Result bignum, should be pre-initialised with mbedtls_mpi_init(). + * @param X First multiplication argument. + * @param Y Second multiplication argument. + * @param M Modulus value for result. + * + * @return 0 on success, mbedTLS MPI error codes on failure. + */ +int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M); + +#if CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI + +/** + * @brief Perform a sliding-window exponentiation: X = A^E mod N + * + * @param X The destination MPI. This must point to an initialized MPI. + * @param A The base of the exponentiation. + * This must point to an initialized MPI. + * @param E The exponent MPI. This must point to an initialized MPI. + * @param N The base for the modular reduction. This must point to an + * initialized MPI. + * @param _RR A helper MPI depending solely on \p N which can be used to + * speed-up multiple modular exponentiations for the same value + * of \p N. This may be \c NULL. If it is not \c NULL, it must + * point to an initialized MPI. + * + * @return \c 0 if successful. + * @return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * @return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or + * even, or if \c E is negative. + * @return Another negative error code on different kinds of failures. + * + */ +int mbedtls_mpi_exp_mod_soft(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR); + +#endif // CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI + +#endif // CONFIG_MBEDTLS_HARDWARE_MPI diff --git a/components/mbedtls/mbedtls_v3/port/include/mbedtls/certs.h b/components/mbedtls/mbedtls_v3/port/include/mbedtls/certs.h new file mode 100644 index 000000000..be1ec9320 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/mbedtls/certs.h @@ -0,0 +1,28 @@ +/** + * \file certs.h + * + * \brief Sample certificates and DHM parameters for testing + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_CERTS_H +#define MBEDTLS_CERTS_H +// Only for compilation + +#endif /* certs.h */ diff --git a/components/mbedtls/mbedtls_v3/port/include/mbedtls/ecp.h b/components/mbedtls/mbedtls_v3/port/include/mbedtls/ecp.h new file mode 100644 index 000000000..28ccd5c79 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/mbedtls/ecp.h @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include_next "mbedtls/ecp.h" +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_ECP_MUL_ALT) || defined(MBEDTLS_ECP_MUL_ALT_SOFT_FALLBACK) +int ecp_mul_restartable_internal( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ); +#endif + +#if defined(MBEDTLS_ECP_MUL_ALT_SOFT_FALLBACK) +int ecp_mul_restartable_internal_soft( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ); +#endif + +#if defined(MBEDTLS_ECP_VERIFY_ALT_SOFT_FALLBACK) + +int mbedtls_ecp_check_pubkey_soft(const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt ); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/mbedtls/esp_config.h b/components/mbedtls/mbedtls_v3/port/include/mbedtls/esp_config.h new file mode 100644 index 000000000..aa930cb25 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/mbedtls/esp_config.h @@ -0,0 +1,3051 @@ +/** + * + * \brief Default mbedTLS configuration options for ESP-IDF + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ESP_CONFIG_H +#define ESP_CONFIG_H + +#include "sdkconfig.h" +#include "mbedtls/mbedtls_config.h" +// #include "soc/soc_caps.h" + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, + * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and + * MBEDTLS_PLATFORM_STD_TIME. + * + * Comment if your system does not support time functions. + * + * \note If MBEDTLS_TIMING_C is set - to enable the semi-portable timing + * interface - timing.c will include time.h on suitable platforms + * regardless of the setting of MBEDTLS_HAVE_TIME, unless + * MBEDTLS_TIMING_ALT is used. See timing.c for more information. + */ +#ifdef CONFIG_MBEDTLS_HAVE_TIME +#define MBEDTLS_HAVE_TIME +/** + * \def MBEDTLS_PLATFORM_MS_TIME_ALT + * + * Define platform specific function to get time since bootup in milliseconds. + */ +#define MBEDTLS_PLATFORM_MS_TIME_ALT +#else +#undef MBEDTLS_HAVE_TIME +#undef MBEDTLS_PLATFORM_MS_TIME_ALT +#endif + +/** + * \def MBEDTLS_HAVE_TIME_DATE + * + * System has time.h and time(), gmtime() and the clock is correct. + * The time needs to be correct (not necessarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + */ +#ifdef CONFIG_MBEDTLS_HAVE_TIME_DATE +#define MBEDTLS_HAVE_TIME_DATE +#else +#undef MBEDTLS_HAVE_TIME_DATE +#endif + + +/** + * \def MBEDTLS_PLATFORM_TIME_ALT + * + * mbed TLS will provide a function "mbedtls_platform_set_time()" + * that allows you to set an alternative time function pointer. + * + * All these define require MBEDTLS_PLATFORM_C to be defined! + * + * \warning MBEDTLS_PLATFORM_TIME_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_TIME_MACRO! + * + * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME + */ +#ifdef CONFIG_MBEDTLS_PLATFORM_TIME_ALT +#define MBEDTLS_PLATFORM_TIME_ALT +#else +#undef MBEDTLS_PLATFORM_TIME_ALT +#endif + +/** + * \def MBEDTLS_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +#define MBEDTLS_PLATFORM_MEMORY + +/** Override calloc(), free() except for case where memory allocation scheme is not set to custom */ +#ifndef CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC +#include "esp_mem.h" +#define MBEDTLS_PLATFORM_STD_CALLOC esp_mbedtls_mem_calloc +#define MBEDTLS_PLATFORM_STD_FREE esp_mbedtls_mem_free +#endif + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/* The following units have ESP32 hardware support, + uncommenting each _ALT macro will use the + hardware-accelerated implementation. */ +#ifdef CONFIG_MBEDTLS_HARDWARE_AES +#define MBEDTLS_AES_ALT +#else +#undef MBEDTLS_AES_ALT +#endif + +#ifdef CONFIG_MBEDTLS_HARDWARE_AES +#define MBEDTLS_GCM_ALT +#ifdef CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER + /* Prefer hardware and fallback to software */ + #define MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK +#else + #undef MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK +#endif +#endif + +/* MBEDTLS_SHAxx_ALT to enable hardware SHA support + with software fallback. +*/ +#ifdef CONFIG_MBEDTLS_HARDWARE_SHA +#define MBEDTLS_SHA1_ALT +#define MBEDTLS_SHA256_ALT + +#if SOC_SHA_SUPPORT_SHA512 +#define MBEDTLS_SHA512_ALT +#else +#undef MBEDTLS_SHA512_ALT +#endif + +#else +#undef MBEDTLS_SHA1_ALT +#undef MBEDTLS_SHA256_ALT +#undef MBEDTLS_SHA512_ALT +#endif + +/* MBEDTLS_MDx_ALT to enable ROM MD support + with software fallback. +*/ +#ifdef CONFIG_MBEDTLS_ROM_MD5 +#define MBEDTLS_MD5_ALT +#else +#undef MBEDTLS_MD5_ALT +#endif + +/* The following MPI (bignum) functions have hardware support. + * Uncommenting these macros will use the hardware-accelerated + * implementations. + */ +#ifdef CONFIG_MBEDTLS_HARDWARE_MPI +#ifdef CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI + /* Prefer hardware and fallback to software */ + #define MBEDTLS_MPI_EXP_MOD_ALT_FALLBACK +#else + /* Hardware only mode */ + #define MBEDTLS_MPI_EXP_MOD_ALT +#endif +#define MBEDTLS_MPI_MUL_MPI_ALT +#else +#undef MBEDTLS_MPI_EXP_MOD_ALT_FALLBACK +#undef MBEDTLS_MPI_MUL_MPI_ALT +#if defined(CONFIG_MBEDTLS_MPI_EXP_MOD_ALT) +#define MBEDTLS_MPI_EXP_MOD_ALT +#else +#undef MBEDTLS_MPI_EXP_MOD_ALT +#endif +#endif + +#define MBEDTLS_MPI_WINDOW_SIZE 6 + +#ifdef CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN +#define MBEDTLS_ECDSA_SIGN_ALT +#endif + +#ifdef CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY +#define MBEDTLS_ECDSA_VERIFY_ALT +#endif + +#ifdef CONFIG_MBEDTLS_HARDWARE_ECC +#ifdef CONFIG_MBEDTLS_ECC_OTHER_CURVES_SOFT_FALLBACK + /* Use hardware accelerator for SECP192R1 and SECP256R1 curves, + * software implementation for rest of the curves + */ + #define MBEDTLS_ECP_MUL_ALT_SOFT_FALLBACK + #define MBEDTLS_ECP_VERIFY_ALT_SOFT_FALLBACK +#else + /* Only hardware accelerator support */ + #define MBEDTLS_ECP_MUL_ALT + #define MBEDTLS_ECP_VERIFY_ALT +#endif + +#else +#undef MBEDTLS_ECP_MUL_ALT +#undef MBEDTLS_ECP_MUL_ALT_SOFT_FALLBACK +#undef MBEDTLS_ECP_VERIFY_ALT +#undef MBEDTLS_ECP_VERIFY_ALT_SOFT_FALLBACK +#endif + +/** + * \def MBEDTLS_ENTROPY_HARDWARE_ALT + * + * Uncomment this macro to let mbed TLS use your own implementation of a + * hardware entropy collector. + * + * Your function must be called \c mbedtls_hardware_poll(), have the same + * prototype as declared in entropy_poll.h, and accept NULL as first argument. + * + * Uncomment to use your own hardware entropy collector. + */ +#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * \def MBEDTLS_AES_ROM_TABLES + * + * Store the AES tables in ROM. + * + * Uncomment this macro to store the AES tables in ROM. + */ +#define MBEDTLS_AES_ROM_TABLES + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CBC + +/** + * \def MBEDTLS_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CFB + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CTR + +/** + * \def MBEDTLS_CIPHER_MODE_OFB + * + * Enable Output Feedback mode (OFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_OFB + +/** + * \def MBEDTLS_CIPHER_MODE_XTS + * + * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES. + */ +#define MBEDTLS_CIPHER_MODE_XTS + +/** + * \def MBEDTLS_CIPHER_PADDING_PKCS7 + * + * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for + * specific padding modes in the cipher layer with cipher modes that support + * padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define MBEDTLS_CIPHER_PADDING_ZEROS + +/** + * \def MBEDTLS_ECP_RESTARTABLE + * + * Enable "non-blocking" ECC operations that can return early and be resumed. + * + * This allows various functions to pause by returning + * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in + * order to further progress and eventually complete their operation. This is + * controlled through mbedtls_ecp_set_max_ops() which limits the maximum + * number of ECC operations a function may perform before pausing; see + * mbedtls_ecp_set_max_ops() for more information. + * + * This is useful in non-threaded environments if you want to avoid blocking + * for too long on ECC (and, hence, X.509 or SSL/TLS) operations. + * + * This option: + * - Adds xxx_restartable() variants of existing operations in the + * following modules, with corresponding restart context types: + * - ECP (for Short Weierstrass curves only): scalar multiplication (mul), + * linear combination (muladd); + * - ECDSA: signature generation & verification; + * - PK: signature generation & verification; + * - X509: certificate chain verification. + * - Adds mbedtls_ecdh_enable_restart() in the ECDH module. + * - Changes the behaviour of TLS 1.2 clients (not servers) when using the + * ECDHE-ECDSA key exchange (not other key exchanges) to make all ECC + * computations restartable: + * - ECDH operations from the key exchange, only for Short Weierstrass + * curves, only when MBEDTLS_USE_PSA_CRYPTO is not enabled. + * - verification of the server's key exchange signature; + * - verification of the server's certificate chain; + * - generation of the client's signature if client authentication is used, + * with an ECC key/certificate. + * + * \note In the cases above, the usual SSL/TLS functions, such as + * mbedtls_ssl_handshake(), can now return + * MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS. + * + * \note This option only works with the default software implementation of + * elliptic curve functionality. It is incompatible with + * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT, MBEDTLS_ECDSA_XXX_ALT. + * + * Requires: MBEDTLS_ECP_C + * + * Uncomment this macro to enable restartable ECC computations. + */ +#ifdef CONFIG_MBEDTLS_ECP_RESTARTABLE +#define MBEDTLS_ECP_RESTARTABLE +#endif + +/** + * \def MBEDTLS_ECDH_LEGACY_CONTEXT + * + * Use a backward compatible ECDH context. + * + * Mbed TLS supports two formats for ECDH contexts (#mbedtls_ecdh_context + * defined in `ecdh.h`). For most applications, the choice of format makes + * no difference, since all library functions can work with either format, + * except that the new format is incompatible with MBEDTLS_ECP_RESTARTABLE. + + * The new format used when this option is disabled is smaller + * (56 bytes on a 32-bit platform). In future versions of the library, it + * will support alternative implementations of ECDH operations. + * The new format is incompatible with applications that access + * context fields directly and with restartable ECP operations. + * + * Define this macro if you enable MBEDTLS_ECP_RESTARTABLE or if you + * want to access ECDH context fields directly. Otherwise you should + * comment out this macro definition. + * + * This option has no effect if #MBEDTLS_ECDH_C is not enabled. + * + * \note This configuration option is experimental. Future versions of the + * library may modify the way the ECDH context layout is configured + * and may modify the layout of the new context type. + */ +#ifdef CONFIG_MBEDTLS_ECDH_LEGACY_CONTEXT +#define MBEDTLS_ECDH_LEGACY_CONTEXT +#endif + +/** + * \def MBEDTLS_CMAC_C + * + * Enable the CMAC (Cipher-based Message Authentication Code) mode for block + * ciphers. + * + * \note When #MBEDTLS_CMAC_ALT is active, meaning that the underlying + * implementation of the CMAC algorithm is provided by an alternate + * implementation, that alternate implementation may opt to not support + * AES-192 or 3DES as underlying block ciphers for the CMAC operation. + * + * Module: library/cmac.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_AES_C or MBEDTLS_DES_C + * + */ +#ifdef CONFIG_MBEDTLS_CMAC_C +#define MBEDTLS_CMAC_C +#endif + +/** + * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED + * + * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve + * module. By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +/* Short Weierstrass curves (supporting ECP, ECDH, ECDSA) */ +#ifdef CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#else +#undef MBEDTLS_ECP_DP_SECP192R1_ENABLED +#endif +#ifdef CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#else +#undef MBEDTLS_ECP_DP_SECP224R1_ENABLED +#endif +#ifdef CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#else +#undef MBEDTLS_ECP_DP_SECP256R1_ENABLED +#endif +#ifdef CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#else +#undef MBEDTLS_ECP_DP_SECP384R1_ENABLED +#endif +#ifdef CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#else +#undef MBEDTLS_ECP_DP_SECP521R1_ENABLED +#endif +#ifdef CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#else +#undef MBEDTLS_ECP_DP_SECP192K1_ENABLED +#endif +#ifdef CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#else +#undef MBEDTLS_ECP_DP_SECP224K1_ENABLED +#endif +#ifdef CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#else +#undef MBEDTLS_ECP_DP_SECP256K1_ENABLED +#endif +#ifdef CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#else +#undef MBEDTLS_ECP_DP_BP256R1_ENABLED +#endif +#ifdef CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#else +#undef MBEDTLS_ECP_DP_BP384R1_ENABLED +#endif +#ifdef CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#else +#undef MBEDTLS_ECP_DP_BP512R1_ENABLED +#endif +/* Montgomery curves (supporting ECP) */ +#ifdef CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#else +#undef MBEDTLS_ECP_DP_CURVE25519_ENABLED +#endif +#ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED +#undef MBEDTLS_ECP_DP_CURVE448_ENABLED +#endif + +/** + * \def MBEDTLS_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#ifdef CONFIG_MBEDTLS_ECP_NIST_OPTIM +#define MBEDTLS_ECP_NIST_OPTIM +#else +#undef MBEDTLS_ECP_NIST_OPTIM +#endif + +/** + * \def MBEDTLS_ECP_FIXED_POINT_OPTIM + * + * Enable speed up fixed-point multiplication. + * + * Comment this macro to disable FIXED POINT curves optimisation. + */ +#ifdef CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 +#else +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 +#endif + +/** + * \def MBEDTLS_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: MBEDTLS_HMAC_DRBG_C, MBEDTLS_ECDSA_C + * + * Comment this macro to disable deterministic ECDSA. + */ +#ifdef CONFIG_MBEDTLS_ECDSA_DETERMINISTIC +#define MBEDTLS_ECDSA_DETERMINISTIC +#else +#undef MBEDTLS_ECDSA_DETERMINISTIC +#endif + +/** + * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + */ +#ifdef CONFIG_MBEDTLS_KEY_EXCHANGE_PSK +#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#else +#undef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#endif + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + */ +#ifdef CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK +#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#else +#undef MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#endif + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + */ +#ifdef CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK +#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#else +#undef MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#endif + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + */ +#ifdef CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK +#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#else +#undef MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#endif + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + */ +#ifdef CONFIG_MBEDTLS_KEY_EXCHANGE_RSA +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#else +#undef MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#endif + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + */ +#ifdef CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA +#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#else +#undef MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#endif + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + */ +#ifdef CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA +#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#else +#undef MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#endif + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + */ +#ifdef CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#else +#undef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#endif + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#ifdef CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA +#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#else +#undef MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#endif + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#ifdef CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA +#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#else +#undef MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#endif + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + * + * Enable the ECJPAKE based ciphersuite modes in SSL / TLS. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Requires: MBEDTLS_ECJPAKE_C + * MBEDTLS_SHA256_C + * MBEDTLS_ECP_DP_SECP256R1_ENABLED + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + */ +#ifdef CONFIG_MBEDTLS_KEY_EXCHANGE_ECJPAKE +#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED +#else +#undef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED +#endif + +/** + * \def MBEDTLS_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +#define MBEDTLS_PK_PARSE_EC_EXTENDED + +/** + * \def MBEDTLS_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of mbedtls_strerror() in + * third party libraries easier when MBEDTLS_ERROR_C is disabled + * (no effect when MBEDTLS_ERROR_C is enabled). + * + * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're + * not using mbedtls_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * mbedtls_strerror() + */ +#define MBEDTLS_ERROR_STRERROR_DUMMY + +/** + * \def MBEDTLS_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: MBEDTLS_BIGNUM_C + */ +#define MBEDTLS_GENPRIME + +/** + * \def MBEDTLS_FS_IO + * + * Enable functions that use the filesystem. + */ +#define MBEDTLS_FS_IO + +/** + * \def MBEDTLS_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +#define MBEDTLS_NO_PLATFORM_ENTROPY + +/** + * \def MBEDTLS_PK_RSA_ALT_SUPPORT + * + * Support external private RSA keys (eg from a HSM) in the PK layer. + * + * Comment this macro to disable support for external private RSA keys. + */ +#define MBEDTLS_PK_RSA_ALT_SUPPORT + +/** + * \def MBEDTLS_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: MBEDTLS_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define MBEDTLS_PKCS1_V15 + +/** + * \def MBEDTLS_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#define MBEDTLS_PKCS1_V21 + +/** + * \def MBEDTLS_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +#define MBEDTLS_SELF_TEST + +/** + * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, mbed TLS can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define MBEDTLS_SSL_ALL_ALERT_MESSAGES + +/** + * \def MBEDTLS_SSL_DTLS_CONNECTION_ID + * + * Enable support for the DTLS Connection ID (CID) extension, + * which allows to identify DTLS connections across changes + * in the underlying transport. The CID functionality is described + * in RFC 9146. + * + * Setting this option enables the SSL APIs `mbedtls_ssl_set_cid()`, + * mbedtls_ssl_get_own_cid()`, `mbedtls_ssl_get_peer_cid()` and + * `mbedtls_ssl_conf_cid()`. See the corresponding documentation for + * more information. + * + * The maximum lengths of outgoing and incoming CIDs can be configured + * through the options + * - MBEDTLS_SSL_CID_OUT_LEN_MAX + * - MBEDTLS_SSL_CID_IN_LEN_MAX. + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Uncomment to enable the Connection ID extension. + */ +#ifdef CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID +#define MBEDTLS_SSL_DTLS_CONNECTION_ID +#else +#undef MBEDTLS_SSL_DTLS_CONNECTION_ID +#endif + +/** + * \def MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT + * + * Defines whether RFC 9146 (default) or the legacy version + * (version draft-ietf-tls-dtls-connection-id-05, + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05) + * is used. + * + * Set the value to 0 for the standard version, and + * 1 for the legacy draft version. + * + * \deprecated Support for the legacy version of the DTLS + * Connection ID feature is deprecated. Please + * switch to the standardized version defined + * in RFC 9146 enabled by utilizing + * MBEDTLS_SSL_DTLS_CONNECTION_ID without use + * of MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT. + * + * Requires: MBEDTLS_SSL_DTLS_CONNECTION_ID + */ +#undef MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT + +/** + * \def MBEDTLS_SSL_CONTEXT_SERIALIZATION + * + * Enable serialization of the TLS context structures, through use of the + * functions mbedtls_ssl_context_save() and mbedtls_ssl_context_load(). + * + * This pair of functions allows one side of a connection to serialize the + * context associated with the connection, then free or reuse that context + * while the serialized state is persisted elsewhere, and finally deserialize + * that state to a live context for resuming read/write operations on the + * connection. From a protocol perspective, the state of the connection is + * unaffected, in particular this is entirely transparent to the peer. + * + * Note: this is distinct from TLS session resumption, which is part of the + * protocol and fully visible by the peer. TLS session resumption enables + * establishing new connections associated to a saved session with shorter, + * lighter handshakes, while context serialization is a local optimization in + * handling a single, potentially long-lived connection. + * + * Enabling these APIs makes some SSL structures larger, as 64 extra bytes are + * saved after the handshake to allow for more efficient serialization, so if + * you don't need this feature you'll save RAM by disabling it. + * + * Requires: MBEDTLS_GCM_C or MBEDTLS_CCM_C or MBEDTLS_CHACHAPOLY_C + * + * Comment to disable the context serialization APIs. + */ +#ifdef CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION +#define MBEDTLS_SSL_CONTEXT_SERIALIZATION +#else +#undef MBEDTLS_SSL_CONTEXT_SERIALIZATION +#endif + +/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC + * + * Enable support for Encrypt-then-MAC, RFC 7366. + * + * This allows peers that both support it to use a more robust protection for + * ciphersuites using CBC, providing deep resistance against timing attacks + * on the padding or underlying cipher. + * + * This only affects CBC ciphersuites, and is useless if none is defined. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ +#ifdef CONFIG_MBEDTLS_TLS_ENABLED +#define MBEDTLS_SSL_ENCRYPT_THEN_MAC +#else +#undef MBEDTLS_SSL_ENCRYPT_THEN_MAC +#endif + +/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for RFC 7627: Session Hash and Extended Master Secret + * Extension. + * + * This was introduced as "the proper fix" to the Triple Handshake family of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ +#ifdef CONFIG_MBEDTLS_TLS_ENABLED +#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#else +#undef MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#endif + +/** + * \def MBEDTLS_SSL_FALLBACK_SCSV + * + * Enable support for RFC 7507: Fallback Signaling Cipher Suite Value (SCSV) + * for Preventing Protocol Downgrade Attacks. + * + * For servers, it is recommended to always enable this, unless you support + * only one version of TLS, or know for sure that none of your clients + * implements a fallback strategy. + * + * For clients, you only need this if you're using a fallback strategy, which + * is not recommended in the first place, unless you absolutely need it to + * interoperate with buggy (version-intolerant) servers. + * + * Comment this macro to disable support for FALLBACK_SCSV + */ +#define MBEDTLS_SSL_FALLBACK_SCSV + +/** + * \def MBEDTLS_SSL_KEEP_PEER_CERTIFICATE + * + * This option controls the availability of the API mbedtls_ssl_get_peer_cert() + * giving access to the peer's certificate after completion of the handshake. + * + * Unless you need mbedtls_ssl_peer_cert() in your application, it is + * recommended to disable this option for reduced RAM usage. + * + * \note If this option is disabled, mbedtls_ssl_get_peer_cert() is still + * defined, but always returns \c NULL. + * + * \note This option has no influence on the protection against the + * triple handshake attack. Even if it is disabled, Mbed TLS will + * still ensure that certificates do not change during renegotiation, + * for example by keeping a hash of the peer's certificate. + * + * \note This option is required if MBEDTLS_SSL_PROTO_TLS1_3 is set. + * + * Comment this macro to disable storing the peer's certificate + * after the handshake. + */ +#ifdef CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE +#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE +#else +#undef MBEDTLS_SSL_KEEP_PEER_CERTIFICATE +#endif + +/** + * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING + * + * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0. + * + * This is a countermeasure to the BEAST attack, which also minimizes the risk + * of interoperability issues compared to sending 0-length records. + * + * Comment this macro to disable 1/n-1 record splitting. + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING +#else +#undef MBEDTLS_SSL_CBC_RECORD_SPLITTING +#endif + +/** + * \def MBEDTLS_SSL_RENEGOTIATION + * + * Enable support for TLS renegotiation. + * + * The two main uses of renegotiation are (1) refresh keys on long-lived + * connections and (2) client authentication after the initial handshake. + * If you don't need renegotiation, it's probably better to disable it, since + * it has been associated with security issues in the past and is easy to + * misuse/misunderstand. + * + * Comment this to disable support for renegotiation. + * + * \note Even if this option is disabled, both client and server are aware + * of the Renegotiation Indication Extension (RFC 5746) used to + * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). + * (See \c mbedtls_ssl_conf_legacy_renegotiation for the + * configuration of this extension). + * + */ +#ifdef CONFIG_MBEDTLS_SSL_RENEGOTIATION +#define MBEDTLS_SSL_RENEGOTIATION +#else +#undef MBEDTLS_SSL_RENEGOTIATION +#endif + +/** + * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def MBEDTLS_SSL_RECORD_SIZE_LIMIT + * + * Enable support for RFC 8449 record_size_limit extension in SSL (TLS 1.3 only). + * + * \warning This extension is currently in development and must NOT be used except + * for testing purposes. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_3 + * + * Uncomment this macro to enable support for the record_size_limit extension + */ +//#define MBEDTLS_SSL_RECORD_SIZE_LIMIT + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 + */ +#ifdef CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 +#define MBEDTLS_SSL_PROTO_TLS1_2 +#else +#undef MBEDTLS_SSL_PROTO_TLS1_2 +#endif + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_3 + * + * Enable support for TLS 1.3. + * + * \note The support for TLS 1.3 is not comprehensive yet, in particular + * pre-shared keys are not supported. + * See docs/architecture/tls13-support.md for a description of the TLS + * 1.3 support that this option enables. + * + * Requires: MBEDTLS_SSL_KEEP_PEER_CERTIFICATE + * + * Uncomment this macro to enable the support for TLS 1.3. + * + */ +#ifdef CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 +#define MBEDTLS_SSL_PROTO_TLS1_3 +#else +#undef MBEDTLS_SSL_PROTO_TLS1_3 +#endif + +/** + * \def MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE + * + * Enable TLS 1.3 middlebox compatibility mode. + * + * As specified in Section D.4 of RFC 8446, TLS 1.3 offers a compatibility + * mode to make a TLS 1.3 connection more likely to pass through middle boxes + * expecting TLS 1.2 traffic. + * + * Turning on the compatibility mode comes at the cost of a few added bytes + * on the wire, but it doesn't affect compatibility with TLS 1.3 implementations + * that don't use it. Therefore, unless transmission bandwidth is critical and + * you know that middlebox compatibility issues won't occur, it is therefore + * recommended to set this option. + * + * Comment to disable compatibility mode for TLS 1.3. If + * MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not have any + * effect on the build. + * + */ +#ifdef CONFIG_MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE +#define MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE +#else +#undef MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE +#endif + +/** + * \def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED + * + * Enable TLS 1.3 PSK key exchange mode. + * + * Comment to disable support for the PSK key exchange mode in TLS 1.3. If + * MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not have any + * effect on the build. + * + */ +#ifdef CONFIG_MBEDTLS_SSL_TLS1_3_KEXM_PSK +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED +#else +#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED +#endif + +/** + * \def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED + * + * Enable TLS 1.3 ephemeral key exchange mode. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C, MBEDTLS_ECDSA_C or + * MBEDTLS_PKCS1_V21 + * + * Comment to disable support for the ephemeral key exchange mode in TLS 1.3. + * If MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not have any + * effect on the build. + * + */ +#ifdef CONFIG_MBEDTLS_SSL_TLS1_3_KEXM_EPHEMERAL +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED +#else +#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED +#endif + +/** + * \def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED + * + * Enable TLS 1.3 PSK ephemeral key exchange mode. + * + * Requires: MBEDTLS_ECDH_C + * + * Comment to disable support for the PSK ephemeral key exchange mode in + * TLS 1.3. If MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not + * have any effect on the build. + * + */ +#ifdef CONFIG_MBEDTLS_SSL_TLS1_3_KEXM_PSK_EPHEMERAL +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED +#else +#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED +#endif + +/** + * \def MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE + * + * Maximum time difference in milliseconds tolerated between the age of a + * ticket from the server and client point of view. + * From the client point of view, the age of a ticket is the time difference + * between the time when the client proposes to the server to use the ticket + * (time of writing of the Pre-Shared Key Extension including the ticket) and + * the time the client received the ticket from the server. + * From the server point of view, the age of a ticket is the time difference + * between the time when the server receives a proposition from the client + * to use the ticket and the time when the ticket was created by the server. + * The server age is expected to be always greater than the client one and + * MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE defines the + * maximum difference tolerated for the server to accept the ticket. + * This is not used in TLS 1.2. + * + */ +#define MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE 6000 + +/** + * \def MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH + * + * Size in bytes of a ticket nonce. This is not used in TLS 1.2. + * + * This must be less than 256. + */ +#define MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH 32 + +/** + * \def MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS + * + * Default number of NewSessionTicket messages to be sent by a TLS 1.3 server + * after handshake completion. This is not used in TLS 1.2 and relevant only if + * the MBEDTLS_SSL_SESSION_TICKETS option is enabled. + * + */ +#define MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS 1 + +/** + * \def MBEDTLS_SSL_EARLY_DATA + * + * Enable support for RFC 8446 TLS 1.3 early data. + * + * Requires: MBEDTLS_SSL_SESSION_TICKETS and either + * MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED or + * MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED + * + * Comment this to disable support for early data. If MBEDTLS_SSL_PROTO_TLS1_3 + * is not enabled, this option does not have any effect on the build. + * + * This feature is experimental, not completed and thus not ready for + * production. + * + */ +//#define MBEDTLS_SSL_EARLY_DATA + +/** + * \def MBEDTLS_SSL_MAX_EARLY_DATA_SIZE + * + * The default maximum amount of 0-RTT data. See the documentation of + * \c mbedtls_ssl_tls13_conf_max_early_data_size() for more information. + * + * It must be positive and smaller than UINT32_MAX. + * + * If MBEDTLS_SSL_EARLY_DATA is not defined, this default value does not + * have any impact on the build. + * + * This feature is experimental, not completed and thus not ready for + * production. + * + */ +#define MBEDTLS_SSL_MAX_EARLY_DATA_SIZE 1024 + + +/** + * \def MBEDTLS_SSL_PROTO_DTLS + * + * Enable support for DTLS (all available versions). + * + * Enable this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for DTLS + */ +#ifdef CONFIG_MBEDTLS_SSL_PROTO_DTLS +#define MBEDTLS_SSL_PROTO_DTLS +#else +#undef MBEDTLS_SSL_PROTO_DTLS +#endif + +/** + * \def MBEDTLS_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ +#ifdef CONFIG_MBEDTLS_SSL_ALPN +#define MBEDTLS_SSL_ALPN +#else +#undef MBEDTLS_SSL_ALPN +#endif + +/** + * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY + * + * Enable support for the anti-replay mechanism in DTLS. + * + * Requires: MBEDTLS_SSL_TLS_C + * MBEDTLS_SSL_PROTO_DTLS + * + * \warning Disabling this is often a security risk! + * See mbedtls_ssl_conf_dtls_anti_replay() for details. + * + * Comment this to disable anti-replay in DTLS. + */ +#ifdef CONFIG_MBEDTLS_SSL_PROTO_DTLS +#define MBEDTLS_SSL_DTLS_ANTI_REPLAY +#else +#undef MBEDTLS_SSL_DTLS_ANTI_REPLAY +#endif + +/** + * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Enable support for HelloVerifyRequest on DTLS servers. + * + * This feature is highly recommended to prevent DTLS servers being used as + * amplifiers in DoS attacks against other hosts. It should always be enabled + * unless you know for sure amplification cannot be a problem in the + * environment in which your server operates. + * + * \warning Disabling this can ba a security risk! (see above) + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Comment this to disable support for HelloVerifyRequest. + */ +#ifdef CONFIG_MBEDTLS_SSL_PROTO_DTLS +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY +#else +#undef MBEDTLS_SSL_DTLS_HELLO_VERIFY +#endif + +/** + * \def MBEDTLS_SSL_DTLS_SRTP + * + * Enable support for negotiation of DTLS-SRTP (RFC 5764) + * through the use_srtp extension. + * + * \note This feature provides the minimum functionality required + * to negotiate the use of DTLS-SRTP and to allow the derivation of + * the associated SRTP packet protection key material. + * In particular, the SRTP packet protection itself, as well as the + * demultiplexing of RTP and DTLS packets at the datagram layer + * (see Section 5 of RFC 5764), are not handled by this feature. + * Instead, after successful completion of a handshake negotiating + * the use of DTLS-SRTP, the extended key exporter API + * mbedtls_ssl_conf_export_keys_ext_cb() should be used to implement + * the key exporter described in Section 4.2 of RFC 5764 and RFC 5705 + * (this is implemented in the SSL example programs). + * The resulting key should then be passed to an SRTP stack. + * + * Setting this option enables the runtime API + * mbedtls_ssl_conf_dtls_srtp_protection_profiles() + * through which the supported DTLS-SRTP protection + * profiles can be configured. You must call this API at + * runtime if you wish to negotiate the use of DTLS-SRTP. + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Uncomment this to enable support for use_srtp extension. + */ +#ifdef CONFIG_MBEDTLS_SSL_PROTO_DTLS +#define MBEDTLS_SSL_DTLS_SRTP +#else +#undef MBEDTLS_SSL_DTLS_SRTP +#endif + +/** + * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + * + * Enable server-side support for clients that reconnect from the same port. + * + * Some clients unexpectedly close the connection and try to reconnect using the + * same source port. This needs special support from the server to handle the + * new connection securely, as described in section 4.2.8 of RFC 6347. This + * flag enables that support. + * + * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Comment this to disable support for clients reusing the source port. + */ +#ifdef CONFIG_MBEDTLS_SSL_PROTO_DTLS +#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE +#else +#undef MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE +#endif + +/** + * \def MBEDTLS_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * Client-side, provides full support for session tickets (maintenance of a + * session store remains the responsibility of the application, though). + * Server-side, you also need to provide callbacks for writing and parsing + * tickets, including authenticated encryption and key management. Example + * callbacks are provided by MBEDTLS_SSL_TICKET_C. + * + * Comment this macro to disable support for SSL session tickets + */ +#ifdef CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS +#define MBEDTLS_SSL_SESSION_TICKETS +#else +#undef MBEDTLS_SSL_SESSION_TICKETS +#endif + +/** + * \def MBEDTLS_SSL_EXPORT_KEYS + * + * Enable support for exporting key block and master secret. + * This is required for certain users of TLS, e.g. EAP-TLS. + * + * Comment this macro to disable support for key export + */ +#define MBEDTLS_SSL_EXPORT_KEYS + +/** + * \def MBEDTLS_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: MBEDTLS_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ +#define MBEDTLS_SSL_SERVER_NAME_INDICATION + + +/** + * \def MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH + * + * When this option is enabled, the SSL buffer will be resized automatically + * based on the negotiated maximum fragment length in each direction. + * + * Requires: MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + */ +#ifdef CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH +#define MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH +#else +#undef MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH +#endif + +/** + * + * \def MBEDTLS_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via mbedtls_version_check_feature(). + * + * Requires: MBEDTLS_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +#define MBEDTLS_VERSION_FEATURES + + +/** + * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ +#define MBEDTLS_X509_RSASSA_PSS_SUPPORT + + +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def MBEDTLS_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +#define MBEDTLS_AESNI_C + +/** + * \def MBEDTLS_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/ssl_tls.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#ifdef CONFIG_MBEDTLS_AES_C +#define MBEDTLS_AES_C +#else +#undef MBEDTLS_AES_C +#endif + +/** + * \def MBEDTLS_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define MBEDTLS_ASN1_PARSE_C + +/** + * \def MBEDTLS_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/mbedtls_x509write_csr.c + */ +#define MBEDTLS_ASN1_WRITE_C + +/** + * \def MBEDTLS_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define MBEDTLS_BASE64_C + +/** + * \def MBEDTLS_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * library/bignum_core.c + * library/bignum_mod.c + * library/bignum_mod_raw.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/rsa_alt_helpers.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define MBEDTLS_BIGNUM_C + +/** + * \def MBEDTLS_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +#ifdef CONFIG_MBEDTLS_BLOWFISH_C +#define MBEDTLS_BLOWFISH_C +#else +#undef MBEDTLS_BLOWFISH_C +#endif + +/** + * \def MBEDTLS_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +#ifdef CONFIG_MBEDTLS_CAMELLIA_C +#define MBEDTLS_CAMELLIA_C +#else +#undef MBEDTLS_CAMELLIA_C +#endif + +/** + * \def MBEDTLS_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or + * MBEDTLS_ARIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +#ifdef CONFIG_MBEDTLS_CCM_C +#define MBEDTLS_CCM_C +#else +#undef MBEDTLS_CCM_C +#endif + +/** + * \def MBEDTLS_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +#define MBEDTLS_CERTS_C + +/** + * \def MBEDTLS_CHACHA20_C + * + * Enable the ChaCha20 stream cipher. + * + * Module: library/chacha20.c + */ +#ifdef CONFIG_MBEDTLS_CHACHA20_C +#define MBEDTLS_CHACHA20_C +#else +#undef MBEDTLS_CHACHA20_C +#endif + +/** + * \def MBEDTLS_CHACHAPOLY_C + * + * Enable the ChaCha20-Poly1305 AEAD algorithm. + * + * Module: library/chachapoly.c + * + * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C + */ +#ifdef CONFIG_MBEDTLS_CHACHAPOLY_C +#define MBEDTLS_CHACHAPOLY_C +#else +#undef MBEDTLS_CHACHAPOLY_C +#endif + +/** + * \def MBEDTLS_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ccm.c + * library/cmac.c + * library/gcm.c + * library/nist_kw.c + * library/pkcs12.c + * library/pkcs5.c + * library/psa_crypto_aead.c + * library/psa_crypto_mac.c + * library/ssl_ciphersuites.c + * library/ssl_msg.c + * library/ssl_ticket.c (unless MBEDTLS_USE_PSA_CRYPTO is enabled) + * + * Uncomment to enable generic cipher wrappers. + */ +#define MBEDTLS_CIPHER_C + +/** + * \def MBEDTLS_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: MBEDTLS_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +#define MBEDTLS_CTR_DRBG_C + +/** + * \def MBEDTLS_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_msg.c + * library/ssl_tls.c + * library/ssl_tls12_*.c + * library/ssl_tls13_*.c + * + * This module provides debugging functions. + */ +#if CONFIG_MBEDTLS_DEBUG +#define MBEDTLS_DEBUG_C +#else +#undef MBEDTLS_DEBUG_C +#endif + +/** + * \def MBEDTLS_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + */ +#ifdef CONFIG_MBEDTLS_DES_C +#define MBEDTLS_DES_C +#else +#undef MBEDTLS_DES_C +#endif + +/** + * \def MBEDTLS_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_tls.c + * library/ssl*_client.c + * library/ssl*_server.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + */ +#ifdef CONFIG_MBEDTLS_DHM_C +#define MBEDTLS_DHM_C +#else +#undef MBEDTLS_DHM_C +#endif + +/** + * \def MBEDTLS_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/psa_crypto.c + * library/ssl_tls.c + * library/ssl*_client.c + * library/ssl*_server.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: MBEDTLS_ECP_C + */ +#ifdef CONFIG_MBEDTLS_ECDH_C +#define MBEDTLS_ECDH_C +#else +#undef MBEDTLS_ECDH_C +#endif + +/** + * \def MBEDTLS_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C, + * and at least one MBEDTLS_ECP_DP_XXX_ENABLED for a + * short Weierstrass curve. + */ +#ifdef CONFIG_MBEDTLS_ECDSA_C +#define MBEDTLS_ECDSA_C +#else +#undef MBEDTLS_ECDSA_C +#endif + +/** + * \def MBEDTLS_ECJPAKE_C + * + * Enable the elliptic curve J-PAKE library. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Module: library/ecjpake.c + * Caller: + * + * This module is used by the following key exchanges: + * ECJPAKE + * + * Requires: MBEDTLS_ECP_C and MBEDTLS_MD_C + * + */ +#ifdef CONFIG_MBEDTLS_ECJPAKE_C +#define MBEDTLS_ECJPAKE_C +#else +#undef MBEDTLS_ECJPAKE_C +#endif + +/** + * \def MBEDTLS_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +#ifdef CONFIG_MBEDTLS_ECP_C +#define MBEDTLS_ECP_C +#else +#undef MBEDTLS_ECP_C +#endif + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +#define MBEDTLS_ENTROPY_C + +/** + * \def MBEDTLS_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +#if CONFIG_MBEDTLS_ERROR_STRINGS +#define MBEDTLS_ERROR_C +#else +#undef MBEDTLS_ERROR_C +#endif + +/** + * \def MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME + * + * Caller: library/ssl_tls.c + * + * Allow weak certificate verification without a hostname. + * This option is not recommended for production use. + */ + +#if CONFIG_MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION +#define MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME +#else +#undef MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME +#endif + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM). + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or + * MBEDTLS_ARIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +#ifdef CONFIG_MBEDTLS_GCM_C +#define MBEDTLS_GCM_C +#else +#undef MBEDTLS_GCM_C +#endif + +/** + * \def MBEDTLS_HKDF_C + * + * Enable the HKDF algorithm (RFC 5869). + * + * Module: library/hkdf.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * This module enables support for the Hashed Message Authentication Code + * (HMAC)-based key derivation function (HKDF). + */ +#ifdef CONFIG_MBEDTLS_HKDF_C +#define MBEDTLS_HKDF_C +#else +#undef MBEDTLS_HKDF_C +#endif + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number generator. + */ +#define MBEDTLS_HMAC_DRBG_C + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Requires: one of: MBEDTLS_MD5_C, MBEDTLS_RIPEMD160_C, MBEDTLS_SHA1_C, + * MBEDTLS_SHA224_C, MBEDTLS_SHA256_C, MBEDTLS_SHA384_C, + * MBEDTLS_SHA512_C. + * + * Module: library/md.c + * Caller: library/constant_time.c + * library/ecdsa.c + * library/ecjpake.c + * library/hkdf.c + * library/hmac_drbg.c + * library/pk.c + * library/pkcs5.c + * library/pkcs12.c + * library/psa_crypto_ecp.c + * library/psa_crypto_rsa.c + * library/rsa.c + * library/ssl_cookie.c + * library/ssl_msg.c + * library/ssl_tls.c + * library/x509.c + * library/x509_crt.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Uncomment to enable generic message digest wrappers. + */ +#define MBEDTLS_MD_C + +/** + * \def MBEDTLS_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/mbedtls_md5.c + * Caller: library/mbedtls_md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS and X.509. + * PEM_PARSE uses MD5 for decrypting encrypted keys. + */ +#define MBEDTLS_MD5_C + +/** + * \def MBEDTLS_NET_C + * + * Enable the TCP and UDP over IPv6/IPv4 networking routines. + * + * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) + * and Windows. For other platforms, you'll want to disable it, and write your + * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/net_sockets.c + * + * This module provides networking routines. + */ +#ifdef MBEDTLS_NET_C +#undef MBEDTLS_NET_C +#endif + +/** + * \def MBEDTLS_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/mbedtls_x509_crl.c + * library/mbedtls_x509_crt.c + * library/mbedtls_x509_csr.c + * library/x509write_crt.c + * library/mbedtls_x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define MBEDTLS_OID_C + +/** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +#define MBEDTLS_PADLOCK_C + +/** + * \def MBEDTLS_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/mbedtls_x509_crl.c + * library/mbedtls_x509_crt.c + * library/mbedtls_x509_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#ifdef CONFIG_MBEDTLS_PEM_PARSE_C +#define MBEDTLS_PEM_PARSE_C +#else +#undef MBEDTLS_PEM_PARSE_C +#endif + +/** + * \def MBEDTLS_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/mbedtls_x509write_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +#ifdef CONFIG_MBEDTLS_PEM_WRITE_C +#define MBEDTLS_PEM_WRITE_C +#else +#undef MBEDTLS_PEM_WRITE_C +#endif + +/** + * \def MBEDTLS_PK_C + * + * Enable the generic public (asymmetric) key layer. + * + * Module: library/pk.c + * Caller: library/psa_crypto_rsa.c + * library/ssl_tls.c + * library/ssl*_client.c + * library/ssl*_server.c + * library/x509.c + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define MBEDTLS_PK_C + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymmetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/mbedtls_x509_crt.c + * library/mbedtls_x509_csr.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define MBEDTLS_PK_PARSE_C + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymmetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +#define MBEDTLS_PK_WRITE_C + +/** + * \def MBEDTLS_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: MBEDTLS_CIPHER_C and MBEDTLS_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +#define MBEDTLS_PKCS5_C + +/** + * \def MBEDTLS_PKCS7_C + * + * This feature is a work in progress and not ready for production. Testing and + * validation is incomplete, and handling of malformed inputs may not be robust. + * The API may change. + * + * Enable PKCS7 core for using PKCS7 formatted signatures. + * RFC Link - https://tools.ietf.org/html/rfc2315 + * + * Module: library/pkcs7.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_OID_C, MBEDTLS_PK_PARSE_C, + * MBEDTLS_X509_CRT_PARSE_C MBEDTLS_X509_CRL_PARSE_C, + * MBEDTLS_BIGNUM_C, MBEDTLS_MD_C + * + * This module is required for the PKCS #7 parsing modules. + */ +#ifdef CONFIG_MBEDTLS_PKCS7_C +#define MBEDTLS_PKCS7_C +#else +#undef MBEDTLS_PKCS7_C +#endif + +/** + * \def MBEDTLS_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * + * This module enables PKCS#12 functions. + */ +#define MBEDTLS_PKCS12_C + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other modules rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define MBEDTLS_PLATFORM_C + +/** + * \def MBEDTLS_POLY1305_C + * + * Enable the Poly1305 MAC algorithm. + * + * Module: library/poly1305.c + * Caller: library/chachapoly.c + */ +#ifdef CONFIG_MBEDTLS_POLY1305_C +#define MBEDTLS_POLY1305_C +#else +#undef MBEDTLS_POLY1305_C +#endif + +/** + * \def MBEDTLS_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/mbedtls_ripemd160.c + * Caller: library/mbedtls_md.c + * + */ +#ifdef CONFIG_MBEDTLS_RIPEMD160_C +#define MBEDTLS_RIPEMD160_C +#else +#undef MBEDTLS_RIPEMD160_C +#endif + +/** + * \def MBEDTLS_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * library/rsa_alt_helpers.c + * Caller: library/pk.c + * library/psa_crypto.c + * library/ssl_tls.c + * library/ssl*_client.c + * library/ssl*_server.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C + */ +#define MBEDTLS_RSA_C + +/** + * \def MBEDTLS_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/psa_crypto_hash.c + * + * This module is required for TLS 1.2 depending on the handshake parameters, + * and for SHA1-signed certificates. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_SHA224_C + * + * Enable the SHA-224 cryptographic hash algorithm. + * + * Requires: MBEDTLS_SHA256_C. The library does not currently support enabling + * SHA-224 without SHA-256. + * + * Module: library/sha256.c + * Caller: library/md.c + * library/ssl_cookie.c + * + * This module adds support for SHA-224. + */ +#define MBEDTLS_SHA224_C + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/mbedtls_sha256.c + * Caller: library/entropy.c + * library/mbedtls_md.c + * library/ssl_tls.c + * library/ssl*_client.c + * library/ssl*_server.c= + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_tls.c + * library/ssl_cookie.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#ifdef CONFIG_MBEDTLS_SHA512_C +#define MBEDTLS_SHA384_C +#define MBEDTLS_SHA512_C +#else +#undef MBEDTLS_SHA384_C +#undef MBEDTLS_SHA512_C +#endif + +/** + * \def MBEDTLS_SHA3_C + * + * Enable the SHA3 cryptographic hash algorithm. + * + * Module: library/sha3.c + * + * This module adds support for SHA3. + */ +#ifdef CONFIG_MBEDTLS_SHA3_C +#define MBEDTLS_SHA3_C +#else +#undef MBEDTLS_SHA3_C +#endif + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +#define MBEDTLS_SSL_CACHE_C + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +#define MBEDTLS_SSL_COOKIE_C + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: (MBEDTLS_CIPHER_C) && + * (MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C) + */ +#ifdef CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS +#define MBEDTLS_SSL_TICKET_C +#else +#undef MBEDTLS_SSL_TICKET_C +#endif + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl*_client.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#ifdef CONFIG_MBEDTLS_TLS_CLIENT +#define MBEDTLS_SSL_CLI_C +#else +#undef MBEDTLS_SSL_CLI_C +#endif + +/** + * \def MBEDTLS_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +#ifdef CONFIG_MBEDTLS_TLS_SERVER +#define MBEDTLS_SSL_SRV_C +#else +#undef MBEDTLS_SSL_SRV_C +#endif + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl*_client.c + * library/ssl*_server.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +#ifdef CONFIG_MBEDTLS_TLS_ENABLED +#define MBEDTLS_SSL_TLS_C +#else +#undef MBEDTLS_SSL_TLS_C +#endif + +/** + * \def MBEDTLS_TIMING_C + * + * Enable the semi-portable timing interface. + * + * \note The provided implementation only works on POSIX/Unix (including Linux, + * BSD and OS X) and Windows. On other platforms, you can either disable that + * module and provide your own implementations of the callbacks needed by + * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide + * your own implementation of the whole module by setting + * \c MBEDTLS_TIMING_ALT in the current file. + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +#ifdef MBEDTLS_TIMING_C +#undef MBEDTLS_TIMING_C +#endif + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define MBEDTLS_VERSION_C + +/** + * \def MBEDTLS_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/mbedtls_x509_crl.c + * library/mbedtls_x509_crt.c + * library/mbedtls_x509_csr.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, + * MBEDTLS_PK_PARSE_C, MBEDTLS_MD_C + * + * This module is required for the X.509 parsing modules. + */ +#define MBEDTLS_X509_USE_C + +/** + * \def MBEDTLS_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/mbedtls_x509_crt.c + * Caller: library/ssl_tls.c + * library/ssl*_client.c + * library/ssl*_server.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define MBEDTLS_X509_CRT_PARSE_C + +/** + * \def MBEDTLS_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/mbedtls_x509_crl.c + * Caller: library/mbedtls_x509_crt.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +#ifdef CONFIG_MBEDTLS_X509_CRL_PARSE_C +#define MBEDTLS_X509_CRL_PARSE_C +#else +#undef MBEDTLS_X509_CRL_PARSE_C +#endif + +/** + * \def MBEDTLS_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/mbedtls_x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +#ifdef CONFIG_MBEDTLS_X509_CSR_PARSE_C +#define MBEDTLS_X509_CSR_PARSE_C +#else +#undef MBEDTLS_X509_CSR_PARSE_C +#endif + +/** + * \def MBEDTLS_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C, + * MBEDTLS_MD_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +#define MBEDTLS_X509_CREATE_C + +/** + * \def MBEDTLS_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +#define MBEDTLS_X509_CRT_WRITE_C + +/** + * \def MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK + * + * If set, this enables the X.509 API `mbedtls_x509_crt_verify_with_ca_cb()` + * and the SSL API `mbedtls_ssl_conf_ca_cb()` which allow users to configure + * the set of trusted certificates through a callback instead of a linked + * list. + * + * This is useful for example in environments where a large number of trusted + * certificates is present and storing them in a linked list isn't efficient + * enough, or when the set of trusted certificates changes frequently. + * + * See the documentation of `mbedtls_x509_crt_verify_with_ca_cb()` and + * `mbedtls_ssl_conf_ca_cb()` for more information. + * + * Uncomment to enable trusted certificate callbacks. + */ +#ifdef CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK +#define MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +#else +#undef MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +#endif + +/** + * \def MBEDTLS_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +#define MBEDTLS_X509_CSR_WRITE_C + +/** + * \def MBEDTLS_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +#ifdef CONFIG_MBEDTLS_XTEA_C +#define MBEDTLS_XTEA_C +#else +#undef MBEDTLS_XTEA_C +#endif + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* SSL options */ +#ifndef CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN + +#define MBEDTLS_SSL_MAX_CONTENT_LEN CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN /**< Maximum fragment length in bytes, determines the size of each of the two internal I/O buffers */ + +#else + +/** \def MBEDTLS_SSL_IN_CONTENT_LEN + * + * Maximum incoming fragment length in bytes. + * + * Uncomment to set the size of the inward TLS buffer independently of the + * outward buffer. + */ +#define MBEDTLS_SSL_IN_CONTENT_LEN CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN + +/** \def MBEDTLS_SSL_CID_IN_LEN_MAX + * + * The maximum length of CIDs used for incoming DTLS messages. + * + */ +#ifdef CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID +#define MBEDTLS_SSL_CID_IN_LEN_MAX CONFIG_MBEDTLS_SSL_CID_IN_LEN_MAX +#else +#undef MBEDTLS_SSL_CID_IN_LEN_MAX +#endif + + +/** \def MBEDTLS_SSL_CID_OUT_LEN_MAX + * + * The maximum length of CIDs used for outgoing DTLS messages. + * + */ +#ifdef CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID +#define MBEDTLS_SSL_CID_OUT_LEN_MAX CONFIG_MBEDTLS_SSL_CID_OUT_LEN_MAX +#else +#undef MBEDTLS_SSL_CID_OUT_LEN_MAX +#endif + +/** \def MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY + * + * This option controls the use of record plaintext padding + * in TLS 1.3 and when using the Connection ID extension in DTLS 1.2. + * + * The padding will always be chosen so that the length of the + * padded plaintext is a multiple of the value of this option. + * + * Note: A value of \c 1 means that no padding will be used + * for outgoing records. + * + * Note: On systems lacking division instructions, + * a power of two should be preferred. + * + */ +#ifdef CONFIG_MBEDTLS_SSL_CID_PADDING_GRANULARITY +#define MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY CONFIG_MBEDTLS_SSL_CID_PADDING_GRANULARITY +#else +#undef MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY +#endif + + +/** \def MBEDTLS_SSL_OUT_CONTENT_LEN + * + * Maximum outgoing fragment length in bytes. + * + * Uncomment to set the size of the outward TLS buffer independently of the + * inward buffer. + * + * It is possible to save RAM by setting a smaller outward buffer, while keeping + * the default inward 16384 byte buffer to conform to the TLS specification. + * + * The minimum required outward buffer size is determined by the handshake + * protocol's usage. Handshaking will fail if the outward buffer is too small. + * The specific size requirement depends on the configured ciphers and any + * certificate data which is sent during the handshake. + * + * For absolute minimum RAM usage, it's best to enable + * MBEDTLS_SSL_MAX_FRAGMENT_LENGTH and reduce MBEDTLS_SSL_MAX_CONTENT_LEN. This + * reduces both incoming and outgoing buffer sizes. However this is only + * guaranteed if the other end of the connection also supports the TLS + * max_fragment_len extension. Otherwise the connection may fail. + */ +#define MBEDTLS_SSL_OUT_CONTENT_LEN CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN + +#endif /* !CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN */ + +/** + * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake + * signature and ciphersuite selection. Without this build-time option, SHA-1 + * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. + * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by + * default. At the time of writing, there is no practical attack on the use + * of SHA-1 in handshake signatures, hence this option is turned on by default + * for compatibility with existing peers. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + */ +#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE + +/** + * \def MBEDTLS_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. See also our Knowledge Base article about threading: + * https://mbed-tls.readthedocs.io/en/latest/kb/development/thread-safety-and-multi-threading + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +#ifdef CONFIG_MBEDTLS_THREADING_C +#define MBEDTLS_THREADING_C +#else +#undef MBEDTLS_THREADING_C +#endif + +/** + * \def MBEDTLS_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +#ifdef CONFIG_MBEDTLS_THREADING_ALT +#define MBEDTLS_THREADING_ALT +#else +#undef MBEDTLS_THREADING_ALT +#endif + +/** + * \def MBEDTLS_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +#ifdef CONFIG_MBEDTLS_THREADING_PTHREAD +#define MBEDTLS_THREADING_PTHREAD +#else +#undef MBEDTLS_THREADING_PTHREAD +#endif + +/** + * \def MBEDTLS_NIST_KW_C + * + * Enable AES key wrapping as per NIST + * + * Requires: MBEDTLS_AES_C + * + * Uncomment this to enable aes key wrap. + */ +#ifdef CONFIG_MBEDTLS_NIST_KW_C +#define MBEDTLS_NIST_KW_C +#else +#undef MBEDTLS_NIST_KW_C +#endif + +/* \} name SECTION: Module configuration options */ + +#if defined(TARGET_LIKE_MBED) +#include "mbedtls/target_config.h" +#endif + +/* + * Allow user to override any previous default. + * + * Use two macro names for that, as: + * - with yotta the prefix YOTTA_CFG_ is forced + * - without yotta is looks weird to have a YOTTA prefix. + */ +#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE) +#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE +#elif defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +/* This flag makes sure that we are not using + * any functino that is deprecated by mbedtls */ +// #define MBEDTLS_DEPRECATED_REMOVED + +#include "mbedtls/compat-2.x.h" + +#endif /* ESP_CONFIG_H */ diff --git a/components/mbedtls/mbedtls_v3/port/include/mbedtls/esp_debug.h b/components/mbedtls/mbedtls_v3/port/include/mbedtls/esp_debug.h new file mode 100644 index 000000000..ecd4688f9 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/mbedtls/esp_debug.h @@ -0,0 +1,59 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _ESP_DEBUG_H_ +#define _ESP_DEBUG_H_ + +#include "mbedtls/ssl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sdkconfig.h" +#ifdef CONFIG_MBEDTLS_DEBUG + +/** @brief Enable mbedTLS debug logging via the esp_log mechanism. + * + * mbedTLS internal debugging is filtered from a specified mbedTLS + * threshold level to esp_log level at runtime: + * + * - 1 - Warning + * - 2 - Info + * - 3 - Debug + * - 4 - Verbose + * + * (Note that mbedTLS debug thresholds are not always consistently used.) + * + * This function will set the esp log level for "mbedtls" to the specified mbedTLS + * threshold level that matches. However, the overall max ESP log level must be set high + * enough in menuconfig, or some messages may be filtered at compile time. + * + * @param conf mbedtls_ssl_config structure + * @param mbedTLS debug threshold, 0-4. Messages are filtered at runtime. + */ +void mbedtls_esp_enable_debug_log(mbedtls_ssl_config *conf, int threshold); + +/** @brief Disable mbedTLS debug logging via the esp_log mechanism. + * + */ +void mbedtls_esp_disable_debug_log(mbedtls_ssl_config *conf); + + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __ESP_DEBUG_H__ */ diff --git a/components/mbedtls/mbedtls_v3/port/include/mbedtls/gcm.h b/components/mbedtls/mbedtls_v3/port/include/mbedtls/gcm.h new file mode 100644 index 000000000..d50527d4d --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/mbedtls/gcm.h @@ -0,0 +1,81 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include_next "mbedtls/gcm.h" +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_GCM_ALT) && defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK) + +/** + * When the MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK is defined, for non-AES GCM + * operations we need to fallback to the software function definitions of the + * mbedtls GCM layer. + * Thus in this case we need declarations for the software funtions. + * Please refer mbedtls/include/mbedtls/gcm.h for function documentations + */ + +void mbedtls_gcm_init_soft(mbedtls_gcm_context_soft *ctx); + + +int mbedtls_gcm_setkey_soft(mbedtls_gcm_context_soft *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits); + +int mbedtls_gcm_starts_soft(mbedtls_gcm_context_soft *ctx, + int mode, + const unsigned char *iv, size_t iv_len); + +int mbedtls_gcm_update_ad_soft(mbedtls_gcm_context_soft *ctx, + const unsigned char *add, size_t add_len); + +int mbedtls_gcm_update_soft(mbedtls_gcm_context_soft *ctx, + const unsigned char *input, size_t input_length, + unsigned char *output, size_t output_size, + size_t *output_length); + +int mbedtls_gcm_finish_soft(mbedtls_gcm_context_soft *ctx, + unsigned char *output, size_t output_size, + size_t *output_length, + unsigned char *tag, size_t tag_len); + + +int mbedtls_gcm_crypt_and_tag_soft(mbedtls_gcm_context_soft *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag); + + +int mbedtls_gcm_auth_decrypt_soft(mbedtls_gcm_context_soft *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output); + +void mbedtls_gcm_free_soft(mbedtls_gcm_context_soft *ctx); + +#endif /* MBEDTLS_GCM_ALT && MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK*/ + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/mbedtls/ssl_internal.h b/components/mbedtls/mbedtls_v3/port/include/mbedtls/ssl_internal.h new file mode 100644 index 000000000..52b1a515a --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/mbedtls/ssl_internal.h @@ -0,0 +1,28 @@ +/** + * \file ssl_internal.h + * + * \brief Internal functions shared by the SSL modules + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SSL_INTERNAL_H +#define MBEDTLS_SSL_INTERNAL_H +// Only for compilation + +#endif /* ssl_internal.h */ diff --git a/components/mbedtls/mbedtls_v3/port/include/md/esp_md.h b/components/mbedtls/mbedtls_v3/port/include/md/esp_md.h new file mode 100644 index 000000000..5f4d175c1 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/md/esp_md.h @@ -0,0 +1,119 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +// #include "esp_rom_md5.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if CONFIG_IDF_TARGET_ESP32C2 +typedef struct mbedtls_md5_context mbedtls_md5_context; +#else +typedef struct MD5Context mbedtls_md5_context; +#endif + +/** + * \brief Initialize MD5 context + * + * \param ctx MD5 context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void esp_md5_init( mbedtls_md5_context *ctx ); + +/** + * \brief Clear MD5 context + * + * \param ctx MD5 context to be cleared + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void esp_md5_free( mbedtls_md5_context *ctx ); + +/** + * \brief Clone (the state of) an MD5 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void esp_md5_clone( mbedtls_md5_context *dst, const mbedtls_md5_context *src ); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_starts( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int esp_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int esp_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int esp_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/md5_alt.h b/components/mbedtls/mbedtls_v3/port/include/md5_alt.h new file mode 100644 index 000000000..788c6554e --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/md5_alt.h @@ -0,0 +1,35 @@ +/* + * md5_alt.h: MD5 block cipher + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD + */ +#ifndef MD5_ALT_H +#define MD5_ALT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_MD5_ALT) +#include "md/esp_md.h" + +#define mbedtls_md5_init esp_md5_init +#define mbedtls_md5_update esp_md5_update +#define mbedtls_md5_finish esp_md5_finish +#define mbedtls_md5_starts esp_md5_starts + +#define mbedtls_md5_free esp_md5_free +#define mbedtls_md5_clone esp_md5_clone +#define mbedtls_internal_md5_process esp_md5_process + +#endif /* MBEDTLS_MD5_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/rsa_sign_alt.h b/components/mbedtls/mbedtls_v3/port/include/rsa_sign_alt.h new file mode 100644 index 000000000..bd299cfc3 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/rsa_sign_alt.h @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifndef _RSA_SIGN_ALT_H_ +#define _RSA_SIGN_ALT_H_ + +#ifdef __cpluscplus +extern "C" { +#endif + +#ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL +#include "esp_ds/esp_rsa_sign_alt.h" +#else + +#error "DS configuration flags not activated, please enable required menuconfig flags" + +#endif + +#ifdef __cpluscplus +} +#endif + +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/sha/sha_block.h b/components/mbedtls/mbedtls_v3/port/include/sha/sha_block.h new file mode 100644 index 000000000..d1752e772 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/sha/sha_block.h @@ -0,0 +1,113 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#include "hal/sha_types.h" + +/** @brief Low-level support functions for the hardware SHA engine + * + * @note If you're looking for a SHA API to use, try mbedtls component + * mbedtls/shaXX.h. That API supports hardware acceleration. + * + * The API in this header provides some building blocks for implementing a + * full SHA API such as the one in mbedtls, and also a basic SHA function esp_sha(). + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @brief Calculate SHA1 or SHA2 sum of some data, using hardware SHA engine + * + * @note For more versatile SHA calculations, where data doesn't need + * to be passed all at once, try the mbedTLS mbedtls/shaX.h APIs. + * + * @note It is not necessary to lock any SHA hardware before calling + * this function, thread safety is managed internally. + * + * @param sha_type SHA algorithm to use. + * + * @param input Input data buffer. + * + * @param ilen Length of input data in bytes. + * + * @param output Buffer for output SHA digest. Output is 20 bytes for + * sha_type SHA1, 32 bytes for sha_type SHA2_256, 48 bytes for + * sha_type SHA2_384, 64 bytes for sha_type SHA2_512. + */ +void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output); + +/** @brief Execute SHA block operation + * + * @note This is a piece of a SHA algorithm, rather than an entire SHA + * algorithm. + * + * @note Call esp_sha_acquire_hardware() before calling this + * function. + * + * @param sha_type SHA algorithm to use. + * + * @param data_block Pointer to the input data. Block size is + * determined by algorithm (SHA1/SHA2_256 = 64 bytes, + * SHA2_384/SHA2_512 = 128 bytes) + * + * @param is_first_block If this parameter is true, the SHA state will + * be initialised (with the initial state of the given SHA algorithm) + * before the block is calculated. If false, the existing state of the + * SHA engine will be used. + * + */ +void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block); + +/** + * @brief Read out the current state of the SHA digest + * + * @note This is a piece of a SHA algorithm, rather than an entire SHA algorithm. + * + * @note Call esp_sha_aquire_hardware() before calling this + * function. + * + * If the SHA suffix padding block has been executed already, the + * value that is read is the SHA digest. + * Otherwise, the value that is read is an interim SHA state. + * + * @param sha_type SHA algorithm in use. + * @param digest_state Pointer to a memory buffer to hold the SHA state. Size + * is 20 bytes (SHA1), 32 bytes (SHA2_256), or 64 bytes (SHA2_384, SHA2_512). + */ +void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state); + +/** + * @brief Set the current state of the SHA digest + * + * @note Call esp_sha_aquire_hardware() before calling this + * function. + * + * @param sha_type SHA algorithm in use. + * @param digest_state Digest state to write to hardware + */ +void esp_sha_write_digest_state(esp_sha_type sha_type, void *digest_state); + + +/** + * @brief Enables the SHA peripheral and takes the lock. + */ +void esp_sha_acquire_hardware(void); + +/** + * @brief Disables the SHA peripheral and releases the lock. + */ +void esp_sha_release_hardware(void); + + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/sha/sha_dma.h b/components/mbedtls/mbedtls_v3/port/include/sha/sha_dma.h new file mode 100644 index 000000000..af12f23a5 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/sha/sha_dma.h @@ -0,0 +1,159 @@ +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "hal/sha_types.h" + +/** @brief Low-level support functions for the hardware SHA engine using DMA + * + * @note If you're looking for a SHA API to use, try mbedtls component + * mbedtls/shaXX.h. That API supports hardware acceleration. + * + * The API in this header provides some building blocks for implementing a + * full SHA API such as the one in mbedtls, and also a basic SHA function esp_sha(). + * + * Some technical details about the hardware SHA engine: + * + * - The crypto DMA is shared between the SHA and AES engine, it is not + * possible for them to run calcalutions in parallel. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @brief Calculate SHA1 or SHA2 sum of some data, using hardware SHA engine + * + * @note For more versatile SHA calculations, where data doesn't need + * to be passed all at once, try the mbedTLS mbedtls/shaX.h APIs. + * + * @note It is not necessary to lock any SHA hardware before calling + * this function, thread safety is managed internally. + * + * @param sha_type SHA algorithm to use. + * + * @param input Input data buffer. + * + * @param ilen Length of input data in bytes. + * + * @param output Buffer for output SHA digest. Output is 20 bytes for + * sha_type SHA1, 32 bytes for sha_type SHA2_256, 48 bytes for + * sha_type SHA2_384, 64 bytes for sha_type SHA2_512. + */ +void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output); + +/** @brief Execute SHA block operation using DMA + * + * @note This is a piece of a SHA algorithm, rather than an entire SHA + * algorithm. + * + * @note Call esp_sha_aquire_hardware() before calling this + * function. + * + * @param sha_type SHA algorithm to use. + * + * @param input Pointer to the input data. Block size is + * determined by algorithm (SHA1/SHA2_256 = 64 bytes, + * SHA2_384/SHA2_512 = 128 bytes) + * + * @param ilen length of input data should be multiple of block length. + * + * @param buf Pointer to blocks of data that will be prepended + * to data_block before hashing. Useful when there is two sources of + * data that need to be efficiently calculated in a single SHA DMA + * operation. + * + * @param buf_len length of buf data should be multiple of block length. + * Should not be longer than the maximum amount of bytes in a single block + * (128 bytes) + * + * @param is_first_block If this parameter is true, the SHA state will + * be initialised (with the initial state of the given SHA algorithm) + * before the block is calculated. If false, the existing state of the + * SHA engine will be used. + * + * @param t The number of bits for the SHA512/t hash function, with + * output truncated to t bits. Used for calculating the inital hash. + * t is any positive integer between 1 and 512, except 384. + * + * @return 0 if successful + */ +int esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen, + const void *buf, uint32_t buf_len, bool is_first_block); + +/** + * @brief Read out the current state of the SHA digest + * + * @note This is a piece of a SHA algorithm, rather than an entire SHA algorithm. + * + * @note Call esp_sha_aquire_hardware() before calling this + * function. + * + * If the SHA suffix padding block has been executed already, the + * value that is read is the SHA digest. + * Otherwise, the value that is read is an interim SHA state. + * + * @param sha_type SHA algorithm in use. + * @param digest_state Pointer to a memory buffer to hold the SHA state. Size + * is 20 bytes (SHA1), 32 bytes (SHA2_256), or 64 bytes (SHA2_384, SHA2_512). + */ +void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state); + +/** + * @brief Set the current state of the SHA digest + * + * @note Call esp_sha_aquire_hardware() before calling this + * function. + * + * When resuming a + * + * @param sha_type SHA algorithm in use. + * @param digest_state + */ +void esp_sha_write_digest_state(esp_sha_type sha_type, void *digest_state); + + +/** + * @brief Enables the SHA and crypto DMA peripheral and takes the + * locks for both of them. + */ +void esp_sha_acquire_hardware(void); + +/** + * @brief Disables the SHA and crypto DMA peripheral and releases the + * locks. + */ +void esp_sha_release_hardware(void); + +/** + * @brief Sets the initial hash value for SHA512/t. + * + * @note Is generated according to the algorithm described in the TRM, + * chapter SHA-Accelerator + * + * @note The engine must be locked until the value is used for an operation + * or read out. Else you risk another operation overwriting it. + * + * @param t + * + * @return 0 if successful + */ +int esp_sha_512_t_init_hash(uint16_t t); + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/sha/sha_parallel_engine.h b/components/mbedtls/mbedtls_v3/port/include/sha/sha_parallel_engine.h new file mode 100644 index 000000000..cf6f0607d --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/sha/sha_parallel_engine.h @@ -0,0 +1,205 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include "hal/sha_types.h" +#include "esp_types.h" + +/** @brief Low-level support functions for the hardware SHA engine + * + * @note If you're looking for a SHA API to use, try mbedtls component + * mbedtls/shaXX.h. That API supports hardware acceleration. + * + * The API in this header provides some building blocks for implementing a + * full SHA API such as the one in mbedtls, and also a basic SHA function esp_sha(). + * + * Some technical details about the hardware SHA engine: + * + * - SHA accelerator engine calculates one digest at a time, per SHA + * algorithm type. It initialises and maintains the digest state + * internally. It is possible to read out an in-progress SHA digest + * state, but it is not possible to restore a SHA digest state + * into the engine. + * + * - The memory block SHA_TEXT_BASE is shared between all SHA digest + * engines, so all engines must be idle before this memory block is + * modified. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @brief Calculate SHA1 or SHA2 sum of some data, using hardware SHA engine + * + * @note For more versatile SHA calculations, where data doesn't need + * to be passed all at once, try the mbedTLS mbedtls/shaX.h APIs. The + * hardware-accelerated mbedTLS implementation is also faster when + * hashing large amounts of data. + * + * @note It is not necessary to lock any SHA hardware before calling + * this function, thread safety is managed internally. + * + * @note If a TLS connection is open then this function may block + * indefinitely waiting for a SHA engine to become available. Use the + * mbedTLS SHA API to avoid this problem. + * + * @param sha_type SHA algorithm to use. + * + * @param input Input data buffer. + * + * @param ilen Length of input data in bytes. + * + * @param output Buffer for output SHA digest. Output is 20 bytes for + * sha_type SHA1, 32 bytes for sha_type SHA2_256, 48 bytes for + * sha_type SHA2_384, 64 bytes for sha_type SHA2_512. + */ +void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output); + +/* @brief Begin to execute a single SHA block operation + * + * @note This is a piece of a SHA algorithm, rather than an entire SHA + * algorithm. + * + * @note Call esp_sha_try_lock_engine() before calling this + * function. Do not call esp_sha_lock_memory_block() beforehand, this + * is done inside the function. + * + * @param sha_type SHA algorithm to use. + * + * @param data_block Pointer to block of data. Block size is + * determined by algorithm (SHA1/SHA2_256 = 64 bytes, + * SHA2_384/SHA2_512 = 128 bytes) + * + * @param is_first_block If this parameter is true, the SHA state will + * be initialised (with the initial state of the given SHA algorithm) + * before the block is calculated. If false, the existing state of the + * SHA engine will be used. + * + * @return As a performance optimisation, this function returns before + * the SHA block operation is complete. Both this function and + * esp_sha_read_state() will automatically wait for any previous + * operation to complete before they begin. If using the SHA registers + * directly in another way, call esp_sha_wait_idle() after calling this + * function but before accessing the SHA registers. + */ +void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block); + +/** @brief Read out the current state of the SHA digest loaded in the engine. + * + * @note This is a piece of a SHA algorithm, rather than an entire SHA algorithm. + * + * @note Call esp_sha_try_lock_engine() before calling this + * function. Do not call esp_sha_lock_memory_block() beforehand, this + * is done inside the function. + * + * If the SHA suffix padding block has been executed already, the + * value that is read is the SHA digest (in big endian + * format). Otherwise, the value that is read is an interim SHA state. + * + * @note If sha_type is SHA2_384, only 48 bytes of state will be read. + * This is enough for the final SHA2_384 digest, but if you want the + * interim SHA-384 state (to continue digesting) then pass SHA2_512 instead. + * + * @param sha_type SHA algorithm in use. + * + * @param state Pointer to a memory buffer to hold the SHA state. Size + * is 20 bytes (SHA1), 32 bytes (SHA2_256), 48 bytes (SHA2_384) or 64 bytes (SHA2_512). + * + */ +void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state); + +/** + * @brief Obtain exclusive access to a particular SHA engine + * + * @param sha_type Type of SHA engine to use. + * + * Blocks until engine is available. Note: Can block indefinitely + * while a TLS connection is open, suggest using + * esp_sha_try_lock_engine() and failing over to software SHA. + */ +void esp_sha_lock_engine(esp_sha_type sha_type); + +/** + * @brief Try and obtain exclusive access to a particular SHA engine + * + * @param sha_type Type of SHA engine to use. + * + * @return Returns true if the SHA engine is locked for exclusive + * use. Call esp_sha_unlock_sha_engine() when done. Returns false if + * the SHA engine is already in use, caller should use software SHA + * algorithm for this digest. + */ +bool esp_sha_try_lock_engine(esp_sha_type sha_type); + +/** + * @brief Unlock an engine previously locked with esp_sha_lock_engine() or esp_sha_try_lock_engine() + * + * @param sha_type Type of engine to release. + */ +void esp_sha_unlock_engine(esp_sha_type sha_type); + +/** + * @brief Acquire exclusive access to the SHA shared memory block at SHA_TEXT_BASE + * + * This memory block is shared across all the SHA algorithm types. + * + * Caller should have already locked a SHA engine before calling this function. + * + * Note that it is possible to obtain exclusive access to the memory block even + * while it is in use by the SHA engine. Caller should use esp_sha_wait_idle() + * to ensure the SHA engine is not reading from the memory block in hardware. + * + * @note This function enters a critical section. Do not block while holding this lock. + * + * @note You do not need to lock the memory block before calling esp_sha_block() or esp_sha_read_digest_state(), these functions handle memory block locking internally. + * + * Call esp_sha_unlock_memory_block() when done. + */ +void esp_sha_lock_memory_block(void); + +/** + * @brief Release exclusive access to the SHA register memory block at SHA_TEXT_BASE + * + * Caller should have already locked a SHA engine before calling this function. + * + * This function releases the critical section entered by esp_sha_lock_memory_block(). + * + * Call following esp_sha_lock_memory_block(). + */ +void esp_sha_unlock_memory_block(void); + +/** @brief Wait for the SHA engine to finish any current operation + * + * @note This function does not ensure exclusive access to any SHA + * engine. Caller should use esp_sha_try_lock_engine() and + * esp_sha_lock_memory_block() as required. + * + * @note Functions declared in this header file wait for SHA engine + * completion automatically, so you don't need to use this API for + * these. However if accessing SHA registers directly, you will need + * to call this before accessing SHA registers if using the + * esp_sha_block() function. + * + * @note This function busy-waits, so wastes CPU resources. + * Best to delay calling until you are about to need it. + * + */ +void esp_sha_wait_idle(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/sha1_alt.h b/components/mbedtls/mbedtls_v3/port/include/sha1_alt.h new file mode 100644 index 000000000..26039378b --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/sha1_alt.h @@ -0,0 +1,98 @@ +/* + * SHA-1 implementation with hardware ESP32 support added. + * Uses mbedTLS software implementation for failover when concurrent + * SHA operations are in use. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE LTD + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef _SHA1_ALT_H_ +#define _SHA1_ALT_H_ + +#if defined(MBEDTLS_SHA1_ALT) + +#include "hal/sha_types.h" +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if SOC_SHA_SUPPORT_PARALLEL_ENG + +typedef enum { + ESP_MBEDTLS_SHA1_UNUSED, /* first block hasn't been processed yet */ + ESP_MBEDTLS_SHA1_HARDWARE, /* using hardware SHA engine */ + ESP_MBEDTLS_SHA1_SOFTWARE, /* using software SHA */ +} esp_mbedtls_sha1_mode; + +/** + * \brief SHA-1 context structure + */ +typedef struct { + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + esp_mbedtls_sha1_mode mode; +} mbedtls_sha1_context; + +/** + * \brief Set the SHA-1 mode for a mbedtls_sha1_context. + * + * \param ctx The SHA-1 context structure. + * \param mode The SHA-1 mode to be set. It can be one of the following: + * - ESP_MBEDTLS_SHA1_UNUSED: Indicates that the first block hasn't been processed yet. + * - ESP_MBEDTLS_SHA1_HARDWARE: Specifies the use of hardware SHA engine for SHA-1 calculations. + * - ESP_MBEDTLS_SHA1_SOFTWARE: Specifies the use of software-based SHA-1 calculations. + * + * \return None. + */ +static inline void esp_mbedtls_set_sha1_mode(mbedtls_sha1_context *ctx, esp_mbedtls_sha1_mode mode) +{ + if (ctx) { + ctx->mode = mode; + } +} + +#elif SOC_SHA_SUPPORT_DMA || SOC_SHA_SUPPORT_RESUME + +typedef enum { + ESP_SHA1_STATE_INIT, + ESP_SHA1_STATE_IN_PROCESS +} esp_sha1_state; + +/** + * \brief SHA-1 context structure + */ +typedef struct { + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + int first_block; /*!< if first then true else false */ + esp_sha_type mode; + esp_sha1_state sha_state; +} mbedtls_sha1_context; + +#endif + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/sha256_alt.h b/components/mbedtls/mbedtls_v3/port/include/sha256_alt.h new file mode 100644 index 000000000..641f5e893 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/sha256_alt.h @@ -0,0 +1,79 @@ +/* + * SHA-256 implementation with hardware ESP32 support added. + * Uses mbedTLS software implementation for failover when concurrent + * SHA operations are in use. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE LTD + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef _SHA256_ALT_H_ +#define _SHA256_ALT_H_ + +#if defined(MBEDTLS_SHA256_ALT) + +#include "hal/sha_types.h" +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if SOC_SHA_SUPPORT_PARALLEL_ENG +typedef enum { + ESP_MBEDTLS_SHA256_UNUSED, /* first block hasn't been processed yet */ + ESP_MBEDTLS_SHA256_HARDWARE, /* using hardware SHA engine */ + ESP_MBEDTLS_SHA256_SOFTWARE, /* using software SHA */ +} esp_mbedtls_sha256_mode; + +/** + * \brief SHA-256 context structure + */ +typedef struct { + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[8]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + int is224; /*!< 0 => SHA-256, else SHA-224 */ + esp_mbedtls_sha256_mode mode; +} mbedtls_sha256_context; + +#elif SOC_SHA_SUPPORT_DMA || SOC_SHA_SUPPORT_RESUME +typedef enum { + ESP_SHA256_STATE_INIT, + ESP_SHA256_STATE_IN_PROCESS +} esp_sha256_state; + +/** + * \brief SHA-256 context structure + */ +typedef struct { + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[8]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + int first_block; /*!< if first then true, else false */ + esp_sha_type mode; + esp_sha256_state sha_state; +} mbedtls_sha256_context; + +#endif + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/mbedtls/mbedtls_v3/port/include/sha512_alt.h b/components/mbedtls/mbedtls_v3/port/include/sha512_alt.h new file mode 100644 index 000000000..d0de4623e --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/include/sha512_alt.h @@ -0,0 +1,97 @@ +/* + * SHA-512 implementation with hardware ESP32 support added. + * Uses mbedTLS software implementation for failover when concurrent + * SHA operations are in use. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE LTD + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef _SHA512_ALT_H_ +#define _SHA512_ALT_H_ + +#if defined(MBEDTLS_SHA512_ALT) + +#include "hal/sha_types.h" +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if SOC_SHA_SUPPORT_PARALLEL_ENG + +typedef enum { + ESP_MBEDTLS_SHA512_UNUSED, /* first block hasn't been processed yet */ + ESP_MBEDTLS_SHA512_HARDWARE, /* using hardware SHA engine */ + ESP_MBEDTLS_SHA512_SOFTWARE, /* using software SHA */ +} esp_mbedtls_sha512_mode; + +/** + * \brief SHA-512 context structure + */ +typedef struct { + uint64_t total[2]; /*!< number of bytes processed */ + uint64_t state[8]; /*!< intermediate digest state */ + unsigned char buffer[128]; /*!< data block being processed */ + int is384; /*!< 0 => SHA-512, else SHA-384 */ + esp_mbedtls_sha512_mode mode; +} mbedtls_sha512_context; + +#elif SOC_SHA_SUPPORT_DMA || SOC_SHA_SUPPORT_RESUME + +typedef enum { + ESP_SHA512_STATE_INIT, + ESP_SHA512_STATE_IN_PROCESS +} esp_sha512_state; + +/** + * \brief SHA-512 context structure + */ +typedef struct { + uint64_t total[2]; /*!< number of bytes processed */ + uint64_t state[8]; /*!< intermediate digest state */ + unsigned char buffer[128]; /*!< data block being processed */ + int first_block; + esp_sha_type mode; + uint32_t t_val; /*!< t_val for 512/t mode */ + esp_sha512_state sha_state; +} mbedtls_sha512_context; + +/** + * @brief Sets the specfic algorithm for SHA512 + * + * @param ctx The mbedtls sha512 context + * + * @param type The mode, used for setting SHA2_512224 and SHA2_512256: + * + */ +void esp_sha512_set_mode(mbedtls_sha512_context *ctx, esp_sha_type type); + +/* For SHA512/t mode the intial hash value will depend on t */ +void esp_sha512_set_t( mbedtls_sha512_context *ctx, uint16_t t_val); + + +#endif + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/mbedtls/mbedtls_v3/port/mbedtls_debug.c b/components/mbedtls/mbedtls_v3/port/mbedtls_debug.c new file mode 100644 index 000000000..23f7eab10 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/mbedtls_debug.c @@ -0,0 +1,86 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "esp_log.h" +#include "mbedtls/platform.h" +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/esp_debug.h" + +#ifdef CONFIG_MBEDTLS_DEBUG +static const char *TAG = "mbedtls"; + +static void mbedtls_esp_debug(void *ctx, int level, + const char *file, int line, + const char *str); + +void mbedtls_esp_enable_debug_log(mbedtls_ssl_config *conf, int threshold) +{ + esp_log_level_t level = ESP_LOG_NONE; + mbedtls_debug_set_threshold(threshold); + mbedtls_ssl_conf_dbg(conf, mbedtls_esp_debug, NULL); + switch(threshold) { + case 1: + level = ESP_LOG_WARN; + break; + case 2: + level = ESP_LOG_INFO; + break; + case 3: + level = ESP_LOG_DEBUG; + break; + case 4: + level = ESP_LOG_VERBOSE; + break; + } + esp_log_level_set(TAG, level); +} + +void mbedtls_esp_disable_debug_log(mbedtls_ssl_config *conf) +{ + mbedtls_ssl_conf_dbg(conf, NULL, NULL); +} + + +/* Default mbedtls debug function that translates mbedTLS debug output + to ESP_LOGx debug output. +*/ +static void mbedtls_esp_debug(void *ctx, int level, + const char *file, int line, + const char *str) +{ + char *file_sep; + + /* Shorten 'file' from the whole file path to just the filename + + This is a bit wasteful because the macros are compiled in with + the full _FILE_ path in each case. + */ + file_sep = rindex(file, '/'); + if(file_sep) + file = file_sep+1; + + switch(level) { + case 1: + ESP_LOGW(TAG, "%s:%d %s", file, line, str); + break; + case 2: + ESP_LOGI(TAG, "%s:%d %s", file, line, str); + break; + case 3: + ESP_LOGD(TAG, "%s:%d %s", file, line, str); + break; + case 4: + ESP_LOGV(TAG, "%s:%d %s", file, line, str); + break; + default: + ESP_LOGE(TAG, "Unexpected log level %d: %s", level, str); + break; + } +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/mbedtls_rom/mbedtls_rom_osi.c b/components/mbedtls/mbedtls_v3/port/mbedtls_rom/mbedtls_rom_osi.c new file mode 100644 index 000000000..d29d03e96 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/mbedtls_rom/mbedtls_rom_osi.c @@ -0,0 +1,468 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "soc/chip_revision.h" +#include "hal/efuse_hal.h" +#include "mbedtls/platform.h" +#include "mbedtls_rom_osi.h" + +void mbedtls_rom_osi_functions_init(void); + +static void mbedtls_rom_mutex_init( mbedtls_threading_mutex_t *mutex ) +{ + if (mutex == NULL) { + return; + } + +#if defined(MBEDTLS_THREADING_ALT) + mutex->mutex = xSemaphoreCreateMutex(); + assert(mutex->mutex != NULL); +#else + mbedtls_mutex_init(mutex); +#endif +} + +static void mbedtls_rom_mutex_free( mbedtls_threading_mutex_t *mutex ) +{ + if (mutex == NULL) { + return; + } + +#if defined(MBEDTLS_THREADING_ALT) + vSemaphoreDelete(mutex->mutex); +#else + mbedtls_mutex_free(mutex); +#endif +} + +static int mbedtls_rom_mutex_lock( mbedtls_threading_mutex_t *mutex ) +{ + if (mutex == NULL) { + return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; + } + +#if defined(MBEDTLS_THREADING_ALT) + if (xSemaphoreTake(mutex->mutex, portMAX_DELAY) != pdTRUE) { + return MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } + return 0; +#else + return mbedtls_mutex_lock(mutex); +#endif +} + +static int mbedtls_rom_mutex_unlock( mbedtls_threading_mutex_t *mutex ) +{ + if (mutex == NULL) { + return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; + } + +#if defined(MBEDTLS_THREADING_ALT) + if (xSemaphoreGive(mutex->mutex) != pdTRUE) { + return MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } + return 0; +#else + return mbedtls_mutex_unlock(mutex); +#endif +} + +/* This structure can be automatically generated by the script with rom.mbedtls.ld. */ +static const mbedtls_rom_funcs_t mbedtls_rom_funcs_table = { + /* Fill the ROM functions into mbedtls rom function table. */ + /* aes module */ + ._rom_mbedtls_aes_init = mbedtls_aes_init, + ._rom_mbedtls_aes_free = mbedtls_aes_free, + ._rom_mbedtls_aes_setkey_enc = mbedtls_aes_setkey_enc, + ._rom_mbedtls_aes_setkey_dec = mbedtls_aes_setkey_dec, + ._rom_mbedtls_aes_crypt_ecb = mbedtls_aes_crypt_ecb, + ._rom_mbedtls_aes_crypt_cbc = mbedtls_aes_crypt_cbc, + ._rom_mbedtls_internal_aes_encrypt = mbedtls_internal_aes_encrypt, + ._rom_mbedtls_internal_aes_decrypt = mbedtls_internal_aes_decrypt, + /* asn1 module */ + ._rom_mbedtls_asn1_get_len = mbedtls_asn1_get_len, + ._rom_mbedtls_asn1_get_tag = mbedtls_asn1_get_tag, + ._rom_mbedtls_asn1_get_bool = mbedtls_asn1_get_bool, + ._rom_mbedtls_asn1_get_int = mbedtls_asn1_get_int, + ._rom_mbedtls_asn1_get_bitstring = mbedtls_asn1_get_bitstring, + ._rom_mbedtls_asn1_get_bitstring_null = mbedtls_asn1_get_bitstring_null, + ._rom_mbedtls_asn1_get_sequence_of = mbedtls_asn1_get_sequence_of, + ._rom_mbedtls_asn1_get_mpi = mbedtls_asn1_get_mpi, + ._rom_mbedtls_asn1_get_alg = mbedtls_asn1_get_alg, + ._rom_mbedtls_asn1_get_alg_null = mbedtls_asn1_get_alg_null, + ._rom_mbedtls_asn1_write_len = mbedtls_asn1_write_len, + ._rom_mbedtls_asn1_write_tag = mbedtls_asn1_write_tag, + ._rom_mbedtls_asn1_write_mpi = mbedtls_asn1_write_mpi, + /* base64 module */ + ._rom_mbedtls_base64_decode = mbedtls_base64_decode, + /* bignum module */ + ._rom_mbedtls_mpi_init = mbedtls_mpi_init, + ._rom_mbedtls_mpi_free = mbedtls_mpi_free, + ._rom_mbedtls_mpi_grow = mbedtls_mpi_grow, + ._rom_mbedtls_mpi_shrink = mbedtls_mpi_shrink, + ._rom_mbedtls_mpi_copy = mbedtls_mpi_copy, + ._rom_mbedtls_mpi_safe_cond_assign = mbedtls_mpi_safe_cond_assign, + ._rom_mbedtls_mpi_safe_cond_swap = mbedtls_mpi_safe_cond_swap, + ._rom_mbedtls_mpi_lset = mbedtls_mpi_lset, + ._rom_mbedtls_mpi_get_bit = mbedtls_mpi_get_bit, + ._rom_mbedtls_mpi_set_bit = mbedtls_mpi_set_bit, + ._rom_mbedtls_mpi_lsb = mbedtls_mpi_lsb, + ._rom_mbedtls_mpi_bitlen = mbedtls_mpi_bitlen, + ._rom_mbedtls_mpi_size = mbedtls_mpi_size, + ._rom_mbedtls_mpi_read_binary = mbedtls_mpi_read_binary, + ._rom_mbedtls_mpi_write_binary = mbedtls_mpi_write_binary, + ._rom_mbedtls_mpi_shift_l = mbedtls_mpi_shift_l, + ._rom_mbedtls_mpi_shift_r = mbedtls_mpi_shift_r, + ._rom_mbedtls_mpi_cmp_abs = mbedtls_mpi_cmp_abs, + ._rom_mbedtls_mpi_cmp_mpi = mbedtls_mpi_cmp_mpi, + ._rom_mbedtls_mpi_lt_mpi_ct = mbedtls_mpi_lt_mpi_ct, + ._rom_mbedtls_mpi_cmp_int = mbedtls_mpi_cmp_int, + ._rom_mbedtls_mpi_add_abs = mbedtls_mpi_add_abs, + ._rom_mbedtls_mpi_sub_abs = mbedtls_mpi_sub_abs, + ._rom_mbedtls_mpi_add_mpi = mbedtls_mpi_add_mpi, + ._rom_mbedtls_mpi_sub_mpi = mbedtls_mpi_sub_mpi, + ._rom_mbedtls_mpi_add_int = mbedtls_mpi_add_int, + ._rom_mbedtls_mpi_sub_int = mbedtls_mpi_sub_int, + ._rom_mbedtls_mpi_mul_mpi = mbedtls_mpi_mul_mpi, + ._rom_mbedtls_mpi_mul_int = mbedtls_mpi_mul_int, + ._rom_mbedtls_mpi_div_mpi = mbedtls_mpi_div_mpi, + ._rom_mbedtls_mpi_div_int = mbedtls_mpi_div_int, + ._rom_mbedtls_mpi_mod_mpi = mbedtls_mpi_mod_mpi, + ._rom_mbedtls_mpi_mod_int = mbedtls_mpi_mod_int, + ._rom_mbedtls_mpi_exp_mod = mbedtls_mpi_exp_mod, + ._rom_mbedtls_mpi_fill_random = mbedtls_mpi_fill_random, + ._rom_mbedtls_mpi_gcd = mbedtls_mpi_gcd, + ._rom_mbedtls_mpi_inv_mod = mbedtls_mpi_inv_mod, + ._rom_mbedtls_mpi_is_prime_ext = mbedtls_mpi_is_prime_ext, + /* ccm module */ + ._rom_mbedtls_ccm_star_encrypt_and_tag = mbedtls_ccm_star_encrypt_and_tag, + ._rom_mbedtls_ccm_star_auth_decrypt = mbedtls_ccm_star_auth_decrypt, + /* cipher module */ + ._rom_mbedtls_cipher_init = mbedtls_cipher_init, + ._rom_mbedtls_cipher_set_padding_mode = mbedtls_cipher_set_padding_mode, + ._rom_mbedtls_cipher_reset = mbedtls_cipher_reset, + ._rom_mbedtls_cipher_finish = mbedtls_cipher_finish, + ._rom_mbedtls_cipher_crypt = mbedtls_cipher_crypt, + ._rom_mbedtls_cipher_cmac_starts = mbedtls_cipher_cmac_starts, + ._rom_mbedtls_cipher_cmac_update = mbedtls_cipher_cmac_update, + ._rom_mbedtls_cipher_cmac_finish = mbedtls_cipher_cmac_finish, + /* ctr drbg module */ + ._rom_mbedtls_ctr_drbg_init = mbedtls_ctr_drbg_init, + ._rom_mbedtls_ctr_drbg_seed = mbedtls_ctr_drbg_seed, + ._rom_mbedtls_ctr_drbg_free = mbedtls_ctr_drbg_free, + ._rom_mbedtls_ctr_drbg_reseed = mbedtls_ctr_drbg_reseed, + ._rom_mbedtls_ctr_drbg_random_with_add = mbedtls_ctr_drbg_random_with_add, + ._rom_mbedtls_ctr_drbg_random = mbedtls_ctr_drbg_random, + /* sha1 module */ + ._rom_mbedtls_sha1_init = mbedtls_sha1_init, + ._rom_mbedtls_sha1_free = mbedtls_sha1_free, + ._rom_mbedtls_sha1_clone = mbedtls_sha1_clone, + ._rom_mbedtls_sha1_starts = mbedtls_sha1_starts, + ._rom_mbedtls_sha1_finish = mbedtls_sha1_finish, + /* sha256 module */ + ._rom_mbedtls_sha256_init = mbedtls_sha256_init, + ._rom_mbedtls_sha256_free = mbedtls_sha256_free, + ._rom_mbedtls_sha256_clone = mbedtls_sha256_clone, + ._rom_mbedtls_sha256_starts = mbedtls_sha256_starts, + ._rom_mbedtls_sha256_finish = mbedtls_sha256_finish, + ._rom_mbedtls_sha256 = mbedtls_sha256, + /* sha512 module */ + ._rom_mbedtls_sha512_init = mbedtls_sha512_init, + ._rom_mbedtls_sha512_free = mbedtls_sha512_free, + ._rom_mbedtls_sha512_clone = mbedtls_sha512_clone, + ._rom_mbedtls_sha512_starts = mbedtls_sha512_starts, + ._rom_mbedtls_sha512_update = mbedtls_sha512_update, + ._rom_mbedtls_sha512_finish = mbedtls_sha512_finish, + ._rom_mbedtls_internal_sha512_process = mbedtls_internal_sha512_process, + ._rom_mbedtls_sha512 = mbedtls_sha512, + + /* Fill the platform functions into mbedtls rom function table. */ + ._mbedtls_mutex_init = mbedtls_rom_mutex_init, + ._mbedtls_mutex_free = mbedtls_rom_mutex_free, + ._mbedtls_mutex_lock = mbedtls_rom_mutex_lock, + ._mbedtls_mutex_unlock = mbedtls_rom_mutex_unlock, + ._mbedtls_calloc = MBEDTLS_PLATFORM_STD_CALLOC, + ._mbedtls_free = MBEDTLS_PLATFORM_STD_FREE, + + /* Fill the SHA functions into mbedtls rom function table, since these functions are not exported in the ROM interface. */ + ._mbedtls_sha1_update = mbedtls_sha1_update, + ._mbedtls_internal_sha1_process = mbedtls_internal_sha1_process, + ._mbedtls_sha256_update = mbedtls_sha256_update, + ._mbedtls_internal_sha256_process = mbedtls_internal_sha256_process, +}; + +/* This structure can be automatically generated by the script with rom.mbedtls.ld. */ +static const mbedtls_rom_eco4_funcs_t mbedtls_rom_eco4_funcs_table = { + /* Fill the ROM functions into mbedtls rom function table. */ + /* aes module */ + ._rom_mbedtls_aes_init = mbedtls_aes_init, + ._rom_mbedtls_aes_free = mbedtls_aes_free, + ._rom_mbedtls_aes_setkey_enc = mbedtls_aes_setkey_enc, + ._rom_mbedtls_aes_setkey_dec = mbedtls_aes_setkey_dec, + ._rom_mbedtls_aes_crypt_ecb = mbedtls_aes_crypt_ecb, + ._rom_mbedtls_aes_crypt_cbc = mbedtls_aes_crypt_cbc, + ._rom_mbedtls_internal_aes_encrypt = mbedtls_internal_aes_encrypt, + ._rom_mbedtls_internal_aes_decrypt = mbedtls_internal_aes_decrypt, + /* asn1 module */ + ._rom_mbedtls_asn1_get_len = mbedtls_asn1_get_len, + ._rom_mbedtls_asn1_get_tag = mbedtls_asn1_get_tag, + ._rom_mbedtls_asn1_get_bool = mbedtls_asn1_get_bool, + ._rom_mbedtls_asn1_get_int = mbedtls_asn1_get_int, + ._rom_mbedtls_asn1_get_bitstring = mbedtls_asn1_get_bitstring, + ._rom_mbedtls_asn1_get_bitstring_null = mbedtls_asn1_get_bitstring_null, + ._rom_mbedtls_asn1_get_sequence_of = mbedtls_asn1_get_sequence_of, + ._rom_mbedtls_asn1_get_mpi = mbedtls_asn1_get_mpi, + ._rom_mbedtls_asn1_get_alg = mbedtls_asn1_get_alg, + ._rom_mbedtls_asn1_get_alg_null = mbedtls_asn1_get_alg_null, + ._rom_mbedtls_asn1_write_len = mbedtls_asn1_write_len, + ._rom_mbedtls_asn1_write_tag = mbedtls_asn1_write_tag, + ._rom_mbedtls_asn1_write_mpi = mbedtls_asn1_write_mpi, + /* base64 module */ + ._rom_mbedtls_base64_decode = mbedtls_base64_decode, + /* bignum module */ + ._rom_mbedtls_mpi_init = mbedtls_mpi_init, + ._rom_mbedtls_mpi_free = mbedtls_mpi_free, + ._rom_mbedtls_mpi_grow = mbedtls_mpi_grow, + ._rom_mbedtls_mpi_shrink = mbedtls_mpi_shrink, + ._rom_mbedtls_mpi_copy = mbedtls_mpi_copy, + ._rom_mbedtls_mpi_safe_cond_assign = mbedtls_mpi_safe_cond_assign, + ._rom_mbedtls_mpi_safe_cond_swap = mbedtls_mpi_safe_cond_swap, + ._rom_mbedtls_mpi_lset = mbedtls_mpi_lset, + ._rom_mbedtls_mpi_get_bit = mbedtls_mpi_get_bit, + ._rom_mbedtls_mpi_set_bit = mbedtls_mpi_set_bit, + ._rom_mbedtls_mpi_lsb = mbedtls_mpi_lsb, + ._rom_mbedtls_mpi_bitlen = mbedtls_mpi_bitlen, + ._rom_mbedtls_mpi_size = mbedtls_mpi_size, + ._rom_mbedtls_mpi_read_binary = mbedtls_mpi_read_binary, + ._rom_mbedtls_mpi_write_binary = mbedtls_mpi_write_binary, + ._rom_mbedtls_mpi_shift_l = mbedtls_mpi_shift_l, + ._rom_mbedtls_mpi_shift_r = mbedtls_mpi_shift_r, + ._rom_mbedtls_mpi_cmp_abs = mbedtls_mpi_cmp_abs, + ._rom_mbedtls_mpi_cmp_mpi = mbedtls_mpi_cmp_mpi, + ._rom_mbedtls_mpi_lt_mpi_ct = mbedtls_mpi_lt_mpi_ct, + ._rom_mbedtls_mpi_cmp_int = mbedtls_mpi_cmp_int, + ._rom_mbedtls_mpi_add_abs = mbedtls_mpi_add_abs, + ._rom_mbedtls_mpi_sub_abs = mbedtls_mpi_sub_abs, + ._rom_mbedtls_mpi_add_mpi = mbedtls_mpi_add_mpi, + ._rom_mbedtls_mpi_sub_mpi = mbedtls_mpi_sub_mpi, + ._rom_mbedtls_mpi_add_int = mbedtls_mpi_add_int, + ._rom_mbedtls_mpi_sub_int = mbedtls_mpi_sub_int, + ._rom_mbedtls_mpi_mul_mpi = mbedtls_mpi_mul_mpi, + ._rom_mbedtls_mpi_mul_int = mbedtls_mpi_mul_int, + ._rom_mbedtls_mpi_div_mpi = mbedtls_mpi_div_mpi, + ._rom_mbedtls_mpi_div_int = mbedtls_mpi_div_int, + ._rom_mbedtls_mpi_mod_mpi = mbedtls_mpi_mod_mpi, + ._rom_mbedtls_mpi_mod_int = mbedtls_mpi_mod_int, + ._rom_mbedtls_mpi_exp_mod = mbedtls_mpi_exp_mod, + ._rom_mbedtls_mpi_fill_random = mbedtls_mpi_fill_random, + ._rom_mbedtls_mpi_gcd = mbedtls_mpi_gcd, + ._rom_mbedtls_mpi_inv_mod = mbedtls_mpi_inv_mod, + ._rom_mbedtls_mpi_is_prime_ext = mbedtls_mpi_is_prime_ext, + /* ccm module */ + ._rom_mbedtls_ccm_star_encrypt_and_tag = mbedtls_ccm_star_encrypt_and_tag, + ._rom_mbedtls_ccm_star_auth_decrypt = mbedtls_ccm_star_auth_decrypt, + /* cipher module */ + ._rom_mbedtls_cipher_init = mbedtls_cipher_init, + ._rom_mbedtls_cipher_set_padding_mode = mbedtls_cipher_set_padding_mode, + ._rom_mbedtls_cipher_reset = mbedtls_cipher_reset, + ._rom_mbedtls_cipher_finish = mbedtls_cipher_finish, + ._rom_mbedtls_cipher_crypt = mbedtls_cipher_crypt, + ._rom_mbedtls_cipher_cmac_starts = mbedtls_cipher_cmac_starts, + ._rom_mbedtls_cipher_cmac_update = mbedtls_cipher_cmac_update, + ._rom_mbedtls_cipher_cmac_finish = mbedtls_cipher_cmac_finish, + /* ctr drbg module */ + ._rom_mbedtls_ctr_drbg_init = mbedtls_ctr_drbg_init, + ._rom_mbedtls_ctr_drbg_seed = mbedtls_ctr_drbg_seed, + ._rom_mbedtls_ctr_drbg_free = mbedtls_ctr_drbg_free, + ._rom_mbedtls_ctr_drbg_reseed = mbedtls_ctr_drbg_reseed, + ._rom_mbedtls_ctr_drbg_random_with_add = mbedtls_ctr_drbg_random_with_add, + ._rom_mbedtls_ctr_drbg_random = mbedtls_ctr_drbg_random, + /* sha1 module */ + ._rom_mbedtls_sha1_init = mbedtls_sha1_init, + ._rom_mbedtls_sha1_free = mbedtls_sha1_free, + ._rom_mbedtls_sha1_clone = mbedtls_sha1_clone, + ._rom_mbedtls_sha1_starts = mbedtls_sha1_starts, + ._rom_mbedtls_sha1_finish = mbedtls_sha1_finish, + /* sha256 module */ + ._rom_mbedtls_sha256_init = mbedtls_sha256_init, + ._rom_mbedtls_sha256_free = mbedtls_sha256_free, + ._rom_mbedtls_sha256_clone = mbedtls_sha256_clone, + ._rom_mbedtls_sha256_starts = mbedtls_sha256_starts, + ._rom_mbedtls_sha256_finish = mbedtls_sha256_finish, + ._rom_mbedtls_sha256 = mbedtls_sha256, + /* sha512 module */ + ._rom_mbedtls_sha512_init = mbedtls_sha512_init, + ._rom_mbedtls_sha512_free = mbedtls_sha512_free, + ._rom_mbedtls_sha512_clone = mbedtls_sha512_clone, + ._rom_mbedtls_sha512_starts = mbedtls_sha512_starts, + ._rom_mbedtls_sha512_update = mbedtls_sha512_update, + ._rom_mbedtls_sha512_finish = mbedtls_sha512_finish, + //._rom_mbedtls_internal_sha512_process = mbedtls_internal_sha512_process, + ._rom_mbedtls_sha512 = mbedtls_sha512, + + ._rom_mbedtls_aes_xts_init = mbedtls_aes_xts_init, + ._rom_mbedtls_aes_xts_free = mbedtls_aes_xts_free, + ._rom_mbedtls_aes_xts_setkey_enc = mbedtls_aes_xts_setkey_enc, + ._rom_mbedtls_aes_xts_setkey_dec = mbedtls_aes_xts_setkey_dec, + ._rom_mbedtls_aes_crypt_xts = mbedtls_aes_crypt_xts, + ._rom_mbedtls_aes_crypt_cfb128 = mbedtls_aes_crypt_cfb128, + ._rom_mbedtls_aes_crypt_ofb = mbedtls_aes_crypt_ofb, + ._rom_mbedtls_aes_crypt_ctr = mbedtls_aes_crypt_ctr, + ._rom_mbedtls_ccm_init = mbedtls_ccm_init, + ._rom_mbedtls_ccm_setkey = mbedtls_ccm_setkey, + ._rom_mbedtls_ccm_free = mbedtls_ccm_free, + ._rom_mbedtls_ccm_encrypt_and_tag = mbedtls_ccm_encrypt_and_tag, + ._rom_mbedtls_ccm_auth_decrypt = mbedtls_ccm_auth_decrypt, + ._rom_mbedtls_md5_init = mbedtls_md5_init, + ._rom_mbedtls_md5_free = mbedtls_md5_free, + ._rom_mbedtls_md5_clone = mbedtls_md5_clone, + ._rom_mbedtls_md5_starts = mbedtls_md5_starts, + ._rom_mbedtls_md5_update = mbedtls_md5_update, + ._rom_mbedtls_md5_finish = mbedtls_md5_finish, + ._rom_mbedtls_md5 = mbedtls_md5, + ._rom_mbedtls_sha1 = mbedtls_sha1, + + // eco4 rom mbedtls functions + ._rom_mbedtls_aes_crypt_cfb8 = mbedtls_aes_crypt_cfb8, + ._rom_mbedtls_mpi_swap = mbedtls_mpi_swap, + ._rom_mbedtls_mpi_read_string = mbedtls_mpi_read_string, + ._rom_mbedtls_mpi_write_string = mbedtls_mpi_write_string, + ._rom_mbedtls_mpi_read_binary_le = mbedtls_mpi_read_binary_le, + ._rom_mbedtls_mpi_write_binary_le = mbedtls_mpi_write_binary_le, + ._rom_mbedtls_mpi_random = mbedtls_mpi_random, + ._rom_mbedtls_mpi_gen_prime = mbedtls_mpi_gen_prime, + ._rom_mbedtls_ecp_check_budget = mbedtls_ecp_check_budget, + ._rom_mbedtls_ecp_set_max_ops = mbedtls_ecp_set_max_ops, + ._rom_mbedtls_ecp_restart_is_enabled = mbedtls_ecp_restart_is_enabled, + ._rom_mbedtls_ecp_get_type = mbedtls_ecp_get_type, + ._rom_mbedtls_ecp_curve_list = mbedtls_ecp_curve_list, + ._rom_mbedtls_ecp_grp_id_list = mbedtls_ecp_grp_id_list, + ._rom_mbedtls_ecp_curve_info_from_grp_id = mbedtls_ecp_curve_info_from_grp_id, + ._rom_mbedtls_ecp_curve_info_from_tls_id = mbedtls_ecp_curve_info_from_tls_id, + ._rom_mbedtls_ecp_curve_info_from_name = mbedtls_ecp_curve_info_from_name, + ._rom_mbedtls_ecp_point_init = mbedtls_ecp_point_init, + ._rom_mbedtls_ecp_group_init = mbedtls_ecp_group_init, + ._rom_mbedtls_ecp_keypair_init = mbedtls_ecp_keypair_init, + ._rom_mbedtls_ecp_point_free = mbedtls_ecp_point_free, + ._rom_mbedtls_ecp_group_free = mbedtls_ecp_group_free, + ._rom_mbedtls_ecp_keypair_free = mbedtls_ecp_keypair_free, + ._rom_mbedtls_ecp_restart_init = mbedtls_ecp_restart_init, + ._rom_mbedtls_ecp_restart_free = mbedtls_ecp_restart_free, + ._rom_mbedtls_ecp_copy = mbedtls_ecp_copy, + ._rom_mbedtls_ecp_group_copy = mbedtls_ecp_group_copy, + ._rom_mbedtls_ecp_set_zero = mbedtls_ecp_set_zero, + ._rom_mbedtls_ecp_is_zero = mbedtls_ecp_is_zero, + ._rom_mbedtls_ecp_point_cmp = mbedtls_ecp_point_cmp, + ._rom_mbedtls_ecp_point_read_string = mbedtls_ecp_point_read_string, + ._rom_mbedtls_ecp_point_write_binary = mbedtls_ecp_point_write_binary, + ._rom_mbedtls_ecp_point_read_binary = mbedtls_ecp_point_read_binary, + ._rom_mbedtls_ecp_tls_read_point = mbedtls_ecp_tls_read_point, + ._rom_mbedtls_ecp_tls_write_point = mbedtls_ecp_tls_write_point, + ._rom_mbedtls_ecp_group_load = mbedtls_ecp_group_load, + ._rom_mbedtls_ecp_tls_read_group = mbedtls_ecp_tls_read_group, + ._rom_mbedtls_ecp_tls_read_group_id = mbedtls_ecp_tls_read_group_id, + ._rom_mbedtls_ecp_tls_write_group = mbedtls_ecp_tls_write_group, + ._rom_mbedtls_ecp_mul = mbedtls_ecp_mul, + ._rom_mbedtls_ecp_mul_restartable = mbedtls_ecp_mul_restartable, + ._rom_mbedtls_ecp_muladd = mbedtls_ecp_muladd, + ._rom_mbedtls_ecp_muladd_restartable = mbedtls_ecp_muladd_restartable, + ._rom_mbedtls_ecp_check_pubkey = mbedtls_ecp_check_pubkey, + ._rom_mbedtls_ecp_check_privkey = mbedtls_ecp_check_privkey, + ._rom_mbedtls_ecp_gen_privkey = mbedtls_ecp_gen_privkey, + ._rom_mbedtls_ecp_gen_keypair_base = mbedtls_ecp_gen_keypair_base, + ._rom_mbedtls_ecp_gen_keypair = mbedtls_ecp_gen_keypair, + ._rom_mbedtls_ecp_gen_key = mbedtls_ecp_gen_key, + ._rom_mbedtls_ecp_read_key = mbedtls_ecp_read_key, + ._rom_mbedtls_ecp_write_key_ext = mbedtls_ecp_write_key_ext, + ._rom_mbedtls_ecp_check_pub_priv = mbedtls_ecp_check_pub_priv, + ._rom_mbedtls_ecp_export = mbedtls_ecp_export, + ._rom_mbedtls_asn1_get_enum = mbedtls_asn1_get_enum, + ._rom_mbedtls_asn1_sequence_free = mbedtls_asn1_sequence_free, + ._rom_mbedtls_asn1_traverse_sequence_of = mbedtls_asn1_traverse_sequence_of, + ._rom_mbedtls_asn1_find_named_data = mbedtls_asn1_find_named_data, + ._rom_mbedtls_asn1_free_named_data_list = mbedtls_asn1_free_named_data_list, + ._rom_mbedtls_asn1_free_named_data_list_shallow = mbedtls_asn1_free_named_data_list_shallow, + ._rom_mbedtls_asn1_write_raw_buffer = mbedtls_asn1_write_raw_buffer, + ._rom_mbedtls_asn1_write_null = mbedtls_asn1_write_null, + ._rom_mbedtls_asn1_write_oid = mbedtls_asn1_write_oid, + ._rom_mbedtls_asn1_write_algorithm_identifier = mbedtls_asn1_write_algorithm_identifier, + ._rom_mbedtls_asn1_write_bool = mbedtls_asn1_write_bool, + ._rom_mbedtls_asn1_write_int = mbedtls_asn1_write_int, + ._rom_mbedtls_asn1_write_enum = mbedtls_asn1_write_enum, + ._rom_mbedtls_asn1_write_tagged_string = mbedtls_asn1_write_tagged_string, + ._rom_mbedtls_asn1_write_printable_string = mbedtls_asn1_write_printable_string, + ._rom_mbedtls_asn1_write_utf8_string = mbedtls_asn1_write_utf8_string, + ._rom_mbedtls_asn1_write_ia5_string = mbedtls_asn1_write_ia5_string, + ._rom_mbedtls_asn1_write_bitstring = mbedtls_asn1_write_bitstring, + ._rom_mbedtls_asn1_write_named_bitstring = mbedtls_asn1_write_named_bitstring, + ._rom_mbedtls_asn1_write_octet_string = mbedtls_asn1_write_octet_string, + ._rom_mbedtls_asn1_store_named_data = mbedtls_asn1_store_named_data, + ._rom_mbedtls_ccm_starts = mbedtls_ccm_starts, + ._rom_mbedtls_ccm_set_lengths = mbedtls_ccm_set_lengths, + ._rom_mbedtls_ccm_update_ad = mbedtls_ccm_update_ad, + ._rom_mbedtls_ccm_update = mbedtls_ccm_update, + ._rom_mbedtls_ccm_finish = mbedtls_ccm_finish, + ._rom_mbedtls_cipher_list = mbedtls_cipher_list, + ._rom_mbedtls_cipher_info_from_string = mbedtls_cipher_info_from_string, + ._rom_mbedtls_cipher_info_from_type = mbedtls_cipher_info_from_type, + ._rom_mbedtls_cipher_info_from_values = mbedtls_cipher_info_from_values, + ._rom_mbedtls_cipher_free = mbedtls_cipher_free, + ._rom_mbedtls_cipher_setup = mbedtls_cipher_setup, + ._rom_mbedtls_cipher_setkey = mbedtls_cipher_setkey, + ._rom_mbedtls_cipher_set_iv = mbedtls_cipher_set_iv, + ._rom_mbedtls_cipher_update_ad = mbedtls_cipher_update_ad, + ._rom_mbedtls_cipher_update = mbedtls_cipher_update, + ._rom_mbedtls_cipher_write_tag = mbedtls_cipher_write_tag, + ._rom_mbedtls_cipher_check_tag = mbedtls_cipher_check_tag, + ._rom_mbedtls_cipher_auth_encrypt_ext = mbedtls_cipher_auth_encrypt_ext, + ._rom_mbedtls_cipher_auth_decrypt_ext = mbedtls_cipher_auth_decrypt_ext, + ._rom_mbedtls_cipher_cmac_reset = mbedtls_cipher_cmac_reset, + ._rom_mbedtls_cipher_cmac = mbedtls_cipher_cmac, + ._rom_mbedtls_aes_cmac_prf_128 = mbedtls_aes_cmac_prf_128, + ._rom_mbedtls_ctr_drbg_set_prediction_resistance = mbedtls_ctr_drbg_set_prediction_resistance, + ._rom_mbedtls_ctr_drbg_set_entropy_len = mbedtls_ctr_drbg_set_entropy_len, + ._rom_mbedtls_ctr_drbg_set_nonce_len = mbedtls_ctr_drbg_set_nonce_len, + ._rom_mbedtls_ctr_drbg_set_reseed_interval = mbedtls_ctr_drbg_set_reseed_interval, + ._rom_mbedtls_ctr_drbg_update = mbedtls_ctr_drbg_update, + ._rom_mbedtls_base64_encode = mbedtls_base64_encode, + + /* Fill the SHA hardware functions into mbedtls rom function table */ + ._rom_mbedtls_sha1_update = mbedtls_sha1_update, + ._rom_mbedtls_sha256_update = mbedtls_sha256_update, + + //memory calloc free + ._rom_mbedtls_mem_calloc = MBEDTLS_PLATFORM_STD_CALLOC, + ._rom_mbedtls_mem_free = MBEDTLS_PLATFORM_STD_FREE, +}; + +__attribute__((constructor)) void mbedtls_rom_osi_functions_init(void) +{ + /* Export the rom mbedtls functions table pointer */ + extern void *mbedtls_rom_osi_funcs_ptr; + +#if defined(MBEDTLS_THREADING_ALT) + mbedtls_threading_set_alt(mbedtls_rom_mutex_init, mbedtls_rom_mutex_free, mbedtls_rom_mutex_lock, mbedtls_rom_mutex_unlock); +#endif + + unsigned chip_version = efuse_hal_chip_revision(); + if ( ESP_CHIP_REV_ABOVE(chip_version, 200) ) { + /* Initialize the rom function mbedtls_threading_set_alt on chip rev2.0 with rom eco4 */ + _rom_mbedtls_threading_set_alt_t rom_mbedtls_threading_set_alt = (_rom_mbedtls_threading_set_alt_t)0x40002c0c; + rom_mbedtls_threading_set_alt(mbedtls_rom_mutex_init, mbedtls_rom_mutex_free, mbedtls_rom_mutex_lock, mbedtls_rom_mutex_unlock); + + /* Initialize the pointer of rom eco4 mbedtls functions table. */ + mbedtls_rom_osi_funcs_ptr = (mbedtls_rom_eco4_funcs_t *)&mbedtls_rom_eco4_funcs_table; + } else { + /* Initialize the pointer of rom mbedtls functions table. */ + mbedtls_rom_osi_funcs_ptr = (mbedtls_rom_funcs_t *)&mbedtls_rom_funcs_table; + } +} diff --git a/components/mbedtls/mbedtls_v3/port/mbedtls_rom/mbedtls_rom_osi.h b/components/mbedtls/mbedtls_v3/port/mbedtls_rom/mbedtls_rom_osi.h new file mode 100644 index 000000000..b612adfa5 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/mbedtls_rom/mbedtls_rom_osi.h @@ -0,0 +1,794 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "mbedtls/aes.h" +#include "mbedtls/asn1.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/base64.h" +#include "mbedtls/bignum.h" +#include "mbedtls/ccm.h" +#include "mbedtls/cipher.h" +#include "mbedtls/cmac.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/dhm.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/ecdsa.h" +#include "mbedtls/ecjpake.h" +#include "mbedtls/ecp.h" +#include "mbedtls/entropy.h" +#include "mbedtls/hmac_drbg.h" +#include "mbedtls/md.h" +#include "mbedtls/md5.h" +#include "mbedtls/oid.h" +#include "mbedtls/pem.h" +#include "mbedtls/pkcs12.h" +#include "mbedtls/pkcs5.h" +#include "mbedtls/pk.h" +#include "mbedtls/platform.h" +#include "mbedtls/rsa.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +#include "mbedtls/ssl_ciphersuites.h" +#include "mbedtls/ssl.h" +#include "mbedtls/x509_crt.h" +#include "mbedtls/x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if (!defined(CONFIG_MBEDTLS_THREADING_C)) +#error CONFIG_MBEDTLS_THREADING_C +#endif + +typedef void (*_rom_mbedtls_threading_set_alt_t)(void (*mutex_init)(mbedtls_threading_mutex_t *), + void (*mutex_free)(mbedtls_threading_mutex_t *), + int (*mutex_lock)(mbedtls_threading_mutex_t *), + int (*mutex_unlock)(mbedtls_threading_mutex_t *)); + +typedef struct mbedtls_rom_funcs { + void (*_rom_mbedtls_aes_init)( mbedtls_aes_context *ctx ); + int (*_rom_ssl_write_client_hello)( mbedtls_ssl_context *ssl ); + int (*_rom_ssl_parse_server_hello)( mbedtls_ssl_context *ssl ); + int (*_rom_ssl_parse_server_key_exchange)( mbedtls_ssl_context *ssl ); + int (*_rom_ssl_parse_certificate_request)( mbedtls_ssl_context *ssl ); + int (*_rom_ssl_parse_server_hello_done)( mbedtls_ssl_context *ssl ); + int (*_rom_ssl_write_client_key_exchange)( mbedtls_ssl_context *ssl ); + int (*_rom_ssl_write_certificate_verify)( mbedtls_ssl_context *ssl ); + int (*_rom_ssl_parse_new_session_ticket)( mbedtls_ssl_context *ssl ); + void (*_rom_mbedtls_aes_free)( mbedtls_aes_context *ctx ); + int (*_rom_mbedtls_aes_setkey_enc)( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits ); + int (*_rom_mbedtls_aes_setkey_dec)( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits ); + int (*_rom_mbedtls_aes_crypt_ecb)( mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16] ); + int (*_rom_mbedtls_aes_crypt_cbc)( mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output ); + int (*_rom_mbedtls_internal_aes_encrypt)( mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ); + int (*_rom_mbedtls_internal_aes_decrypt)( mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ); + int (*_rom_mbedtls_asn1_get_len)( unsigned char **p, const unsigned char *end, size_t *len ); + int (*_rom_mbedtls_asn1_get_tag)( unsigned char **p, const unsigned char *end, size_t *len, int tag ); + int (*_rom_mbedtls_asn1_get_bool)( unsigned char **p, const unsigned char *end, int *val ); + int (*_rom_mbedtls_asn1_get_int)( unsigned char **p, const unsigned char *end, int *val ); + int (*_rom_mbedtls_asn1_get_bitstring)( unsigned char **p, const unsigned char *end, mbedtls_asn1_bitstring *bs); + int (*_rom_mbedtls_asn1_get_bitstring_null)( unsigned char **p, const unsigned char *end, size_t *len ); + int (*_rom_mbedtls_asn1_get_sequence_of)( unsigned char **p, const unsigned char *end, mbedtls_asn1_sequence *cur, int tag); + int (*_rom_mbedtls_asn1_get_mpi)( unsigned char **p, const unsigned char *end, mbedtls_mpi *X ); + int (*_rom_mbedtls_asn1_get_alg)( unsigned char **p, const unsigned char *end, mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ); + int (*_rom_mbedtls_asn1_get_alg_null)( unsigned char **p, const unsigned char *end, mbedtls_asn1_buf *alg ); + int (*_rom_mbedtls_asn1_write_len)( unsigned char **p, const unsigned char *start, size_t len ); + int (*_rom_mbedtls_asn1_write_tag)( unsigned char **p, const unsigned char *start, unsigned char tag ); + int (*_rom_mbedtls_asn1_write_mpi)( unsigned char **p, const unsigned char *start, const mbedtls_mpi *X ); + int (*_rom_mbedtls_base64_decode)( unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen ); + void (*_rom_mbedtls_mpi_init)( mbedtls_mpi *X ); + void (*_rom_mbedtls_mpi_free)( mbedtls_mpi *X ); + int (*_rom_mbedtls_mpi_grow)( mbedtls_mpi *X, size_t nblimbs ); + int (*_rom_mbedtls_mpi_shrink)( mbedtls_mpi *X, size_t nblimbs ); + int (*_rom_mbedtls_mpi_copy)( mbedtls_mpi *X, const mbedtls_mpi *Y ); + int (*_rom_mbedtls_mpi_safe_cond_assign)( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); + int (*_rom_mbedtls_mpi_safe_cond_swap)( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); + int (*_rom_mbedtls_mpi_lset)( mbedtls_mpi *X, mbedtls_mpi_sint z ); + int (*_rom_mbedtls_mpi_get_bit)( const mbedtls_mpi *X, size_t pos ); + int (*_rom_mbedtls_mpi_set_bit)( mbedtls_mpi *X, size_t pos, unsigned char val ); + size_t (*_rom_mbedtls_mpi_lsb)( const mbedtls_mpi *X ); + size_t (*_rom_mbedtls_mpi_bitlen)( const mbedtls_mpi *X ); + size_t (*_rom_mbedtls_mpi_size)( const mbedtls_mpi *X ); + int (*_rom_mbedtls_mpi_read_binary)( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ); + int (*_rom_mbedtls_mpi_write_binary)( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ); + int (*_rom_mbedtls_mpi_shift_l)( mbedtls_mpi *X, size_t count ); + int (*_rom_mbedtls_mpi_shift_r)( mbedtls_mpi *X, size_t count ); + int (*_rom_mbedtls_mpi_cmp_abs)( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + int (*_rom_mbedtls_mpi_cmp_mpi)( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + int (*_rom_mbedtls_mpi_lt_mpi_ct)( const mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned *ret ); + int (*_rom_mbedtls_mpi_cmp_int)( const mbedtls_mpi *X, mbedtls_mpi_sint z ); + int (*_rom_mbedtls_mpi_add_abs)( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + int (*_rom_mbedtls_mpi_sub_abs)( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + int (*_rom_mbedtls_mpi_add_mpi)( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + int (*_rom_mbedtls_mpi_sub_mpi)( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + int (*_rom_mbedtls_mpi_add_int)( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + int (*_rom_mbedtls_mpi_sub_int)( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + int (*_rom_mbedtls_mpi_mul_mpi)( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + int (*_rom_mbedtls_mpi_mul_int)( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ); + int (*_rom_mbedtls_mpi_div_mpi)( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); + int (*_rom_mbedtls_mpi_div_int)( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + int (*_rom_mbedtls_mpi_mod_mpi)( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); + int (*_rom_mbedtls_mpi_mod_int)( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + int (*_rom_mbedtls_mpi_exp_mod)( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ); + int (*_rom_mbedtls_mpi_fill_random)( mbedtls_mpi *X, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + int (*_rom_mbedtls_mpi_gcd)( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ); + int (*_rom_mbedtls_mpi_inv_mod)( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ); + int (*_rom_mbedtls_mpi_is_prime_ext)( const mbedtls_mpi *X, int rounds, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + int (*_rom_mbedtls_ccm_star_encrypt_and_tag)( mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len ); + int (*_rom_mbedtls_ccm_star_auth_decrypt)( mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len ); + void (*_rom_mbedtls_cipher_init)( mbedtls_cipher_context_t *ctx ); + int (*_rom_mbedtls_cipher_set_padding_mode)( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ); + int (*_rom_mbedtls_cipher_reset)( mbedtls_cipher_context_t *ctx ); + int (*_rom_mbedtls_cipher_finish)( mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen ); + int (*_rom_mbedtls_cipher_crypt)( mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen ); + int (*_rom_mbedtls_cipher_cmac_starts)( mbedtls_cipher_context_t *ctx, const unsigned char *key, size_t keybits ); + int (*_rom_mbedtls_cipher_cmac_update)( mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen ); + int (*_rom_mbedtls_cipher_cmac_finish)( mbedtls_cipher_context_t *ctx, unsigned char *output ); + void (*_rom_mbedtls_ctr_drbg_init)( mbedtls_ctr_drbg_context *ctx ); + int (*_rom_mbedtls_ctr_drbg_seed)( mbedtls_ctr_drbg_context *ctx, int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, const unsigned char *custom, size_t len ); + void (*_rom_mbedtls_ctr_drbg_free)( mbedtls_ctr_drbg_context *ctx ); + int (*_rom_mbedtls_ctr_drbg_reseed)( mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t len ); + int (*_rom_mbedtls_ctr_drbg_random_with_add)( void *p_rng, unsigned char *output, size_t output_len, const unsigned char *additional, size_t add_len ); + int (*_rom_mbedtls_ctr_drbg_random)( void *p_rng, unsigned char *output, size_t output_len ); + void (*_rom_mbedtls_dhm_init)( mbedtls_dhm_context *ctx ); + int (*_rom_mbedtls_dhm_read_params)( mbedtls_dhm_context *ctx, unsigned char **p, const unsigned char *end ); + int (*_rom_mbedtls_dhm_make_public)( mbedtls_dhm_context *ctx, int x_size, unsigned char *output, size_t olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + int (*_rom_mbedtls_dhm_calc_secret)( mbedtls_dhm_context *ctx, unsigned char *output, size_t output_size, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + void (*_rom_mbedtls_dhm_free)( mbedtls_dhm_context *ctx ); + void (*_rom_mbedtls_ecdh_init)( mbedtls_ecdh_context *ctx ); + int (*_rom_mbedtls_ecdh_setup)( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id ); + void (*_rom_mbedtls_ecdh_free)( mbedtls_ecdh_context *ctx ); + int (*_rom_mbedtls_ecdh_read_params)( mbedtls_ecdh_context *ctx, const unsigned char **buf, const unsigned char *end ); + int (*_rom_mbedtls_ecdh_get_params)( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, mbedtls_ecdh_side side ); + int (*_rom_mbedtls_ecdh_make_public)( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + int (*_rom_mbedtls_ecdh_calc_secret)( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + void (*_rom_mbedtls_ecdh_enable_restart)( mbedtls_ecdh_context *ctx ); + int (*_rom_mbedtls_ecdsa_write_signature)( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + int (*_rom_mbedtls_ecdsa_write_signature_restartable)( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecdsa_restart_ctx *rs_ctx ); + int (*_rom_mbedtls_ecdsa_read_signature)( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen ); + int (*_rom_mbedtls_ecdsa_read_signature_restartable)( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen, mbedtls_ecdsa_restart_ctx *rs_ctx ); + int (*_rom_mbedtls_ecdsa_from_keypair)( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ); + void (*_rom_mbedtls_ecdsa_init)( mbedtls_ecdsa_context *ctx ); + void (*_rom_mbedtls_ecdsa_free)( mbedtls_ecdsa_context *ctx ); + void (*_rom_mbedtls_ecdsa_restart_init)( mbedtls_ecdsa_restart_ctx *ctx ); + void (*_rom_mbedtls_ecdsa_restart_free)( mbedtls_ecdsa_restart_ctx *ctx ); + void (*_rom_mbedtls_ecjpake_init)( mbedtls_ecjpake_context *ctx ); + int (*_rom_mbedtls_ecjpake_check)( const mbedtls_ecjpake_context *ctx ); + int (*_rom_mbedtls_ecjpake_write_round_one)( mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + int (*_rom_mbedtls_ecjpake_read_round_one)( mbedtls_ecjpake_context *ctx, const unsigned char *buf, size_t len ); + int (*_rom_mbedtls_ecjpake_write_round_two)( mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + int (*_rom_mbedtls_ecjpake_read_round_two)( mbedtls_ecjpake_context *ctx, const unsigned char *buf, size_t len ); + int (*_rom_mbedtls_ecjpake_derive_secret)( mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + void (*_rom_mbedtls_ecjpake_free)( mbedtls_ecjpake_context *ctx ); + int (*_rom_mbedtls_ecp_check_budget)( const mbedtls_ecp_group *grp, mbedtls_ecp_restart_ctx *rs_ctx, unsigned ops ); + int (*_rom_mbedtls_ecp_restart_is_enabled)( void ); + const mbedtls_ecp_curve_info *(*_rom_mbedtls_ecp_curve_list)( void ); + const mbedtls_ecp_group_id *(*_rom_mbedtls_ecp_grp_id_list)( void ); + const mbedtls_ecp_curve_info *(*_rom_mbedtls_ecp_curve_info_from_grp_id)( mbedtls_ecp_group_id grp_id ); + const mbedtls_ecp_curve_info *(*_rom_mbedtls_ecp_curve_info_from_tls_id)( uint16_t tls_id ); + void (*_rom_mbedtls_ecp_point_init)( mbedtls_ecp_point *pt ); + void (*_rom_mbedtls_ecp_group_init)( mbedtls_ecp_group *grp ); + void (*_rom_mbedtls_ecp_keypair_init)( mbedtls_ecp_keypair *key ); + void (*_rom_mbedtls_ecp_point_free)( mbedtls_ecp_point *pt ); + void (*_rom_mbedtls_ecp_group_free)( mbedtls_ecp_group *grp ); + void (*_rom_mbedtls_ecp_keypair_free)( mbedtls_ecp_keypair *key ); + void (*_rom_mbedtls_ecp_restart_init)( mbedtls_ecp_restart_ctx *ctx ); + void (*_rom_mbedtls_ecp_restart_free)( mbedtls_ecp_restart_ctx *ctx ); + int (*_rom_mbedtls_ecp_copy)( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); + int (*_rom_mbedtls_ecp_group_copy)( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ); + int (*_rom_mbedtls_ecp_set_zero)( mbedtls_ecp_point *pt ); + int (*_rom_mbedtls_ecp_is_zero)( mbedtls_ecp_point *pt ); + int (*_rom_mbedtls_ecp_point_cmp)( const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); + int (*_rom_mbedtls_ecp_point_write_binary)( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, int format, size_t *olen, unsigned char *buf, size_t buflen ); + int (*_rom_mbedtls_ecp_point_read_binary)( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, const unsigned char *buf, size_t ilen ); + int (*_rom_mbedtls_ecp_tls_read_point)( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, const unsigned char **buf, size_t len ); + int (*_rom_mbedtls_ecp_tls_write_point)( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, int format, size_t *olen, unsigned char *buf, size_t blen ); + int (*_rom_mbedtls_ecp_group_load)( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ); + int (*_rom_mbedtls_ecp_tls_read_group)( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ); + int (*_rom_mbedtls_ecp_tls_read_group_id)( mbedtls_ecp_group_id *grp, const unsigned char **buf, size_t len ); + int (*_rom_mbedtls_ecp_tls_write_group)( const mbedtls_ecp_group *grp, size_t *olen, unsigned char *buf, size_t blen ); + int (*_rom_mbedtls_ecp_mul)( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + int (*_rom_mbedtls_ecp_mul_restartable)( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx ); + int (*_rom_mbedtls_ecp_muladd)( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); + int (*_rom_mbedtls_ecp_muladd_restartable)( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q, mbedtls_ecp_restart_ctx *rs_ctx ); + int (*_rom_mbedtls_ecp_check_pubkey)( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ); + int (*_rom_mbedtls_ecp_check_privkey)( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ); + int (*_rom_mbedtls_ecp_gen_privkey)( const mbedtls_ecp_group *grp, mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + int (*_rom_mbedtls_ecp_gen_keypair_base)( mbedtls_ecp_group *grp, const mbedtls_ecp_point *G, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + int (*_rom_mbedtls_ecp_check_pub_priv)( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ); + int (*_rom_mbedtls_reserved0)(void); + int (*_rom_mbedtls_reserved1)(void); + int (*_rom_mbedtls_gcm_crypt_and_tag)( mbedtls_gcm_context *ctx, int mode, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, size_t tag_len, unsigned char *tag ); + int (*_rom_mbedtls_gcm_starts)( mbedtls_gcm_context *ctx, int mode, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len ); + int (*_rom_mbedtls_gcm_update)( mbedtls_gcm_context *ctx, size_t length, const unsigned char *input, unsigned char *output ); + int (*_rom_mbedtls_gcm_finish)( mbedtls_gcm_context *ctx, unsigned char *tag, size_t tag_len ); + void (*_rom_mbedtls_hmac_drbg_init)( mbedtls_hmac_drbg_context *ctx ); + int (*_rom_mbedtls_hmac_drbg_seed_buf)( mbedtls_hmac_drbg_context *ctx, const mbedtls_md_info_t * md_info, const unsigned char *data, size_t data_len ); + int (*_rom_mbedtls_hmac_drbg_update_ret)( mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t add_len ); + int (*_rom_mbedtls_hmac_drbg_reseed)( mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t len ); + int (*_rom_mbedtls_hmac_drbg_random_with_add)( void *p_rng, unsigned char *output, size_t output_len, const unsigned char *additional, size_t add_len ); + int (*_rom_mbedtls_hmac_drbg_random)( void *p_rng, unsigned char *output, size_t out_len ); + void (*_rom_mbedtls_hmac_drbg_free)( mbedtls_hmac_drbg_context *ctx ); + const int *(*_rom_mbedtls_md_list)( void ); + void (*_rom_mbedtls_md_init)( mbedtls_md_context_t *ctx ); + void (*_rom_mbedtls_md_free)( mbedtls_md_context_t *ctx ); + int (*_rom_mbedtls_md_setup)( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); + int (*_rom_mbedtls_md_clone)( mbedtls_md_context_t *dst, const mbedtls_md_context_t *src ); + unsigned char (*_rom_mbedtls_md_get_size)( const mbedtls_md_info_t *md_info ); + mbedtls_md_type_t (*_rom_mbedtls_md_get_type)( const mbedtls_md_info_t *md_info ); + int (*_rom_mbedtls_md_starts)( mbedtls_md_context_t *ctx ); + int (*_rom_mbedtls_md_update)( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); + int (*_rom_mbedtls_md_finish)( mbedtls_md_context_t *ctx, unsigned char *output ); + int (*_rom_mbedtls_md)( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, unsigned char *output ); + int (*_rom_mbedtls_md_hmac_starts)( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ); + int (*_rom_mbedtls_md_hmac_update)( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); + int (*_rom_mbedtls_md_hmac_finish)( mbedtls_md_context_t *ctx, unsigned char *output); + int (*_rom_mbedtls_md_hmac_reset)( mbedtls_md_context_t *ctx ); + int (*_rom_mbedtls_oid_get_x509_ext_type)( const mbedtls_asn1_buf *oid, int *ext_type ); + int (*_rom_mbedtls_oid_get_pk_alg)( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg ); + int (*_rom_mbedtls_oid_get_ec_grp)( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id ); + int (*_rom_mbedtls_oid_get_sig_alg)( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg ); + int (*_rom_mbedtls_oid_get_md_alg)( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg ); + int (*_rom_mbedtls_oid_get_md_hmac)( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac ); + int (*_rom_mbedtls_oid_get_oid_by_md)( mbedtls_md_type_t md_alg, const char **oid, size_t *olen ); + int (*_rom_mbedtls_oid_get_cipher_alg)( const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg ); + int (*_rom_mbedtls_oid_get_pkcs12_pbe_alg)( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, mbedtls_cipher_type_t *cipher_alg ); + void (*_rom_mbedtls_pem_init)( void *ctx ); + void (*_rom_mbedtls_pem_free)( void *ctx ); + int (*_rom_mbedtls_pkcs12_pbe_sha1_rc4_128)( mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *input, size_t len, unsigned char *output ); + int (*_rom_mbedtls_pkcs12_pbe)( mbedtls_asn1_buf *pbe_params, int mode, mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, const unsigned char *pwd, size_t pwdlen, const unsigned char *input, size_t len, unsigned char *output ); + int (*_rom_mbedtls_pkcs12_derivation)( unsigned char *data, size_t datalen, const unsigned char *pwd, size_t pwdlen, const unsigned char *salt, size_t saltlen, mbedtls_md_type_t mbedtls_md, int id, int iterations ); + int (*_rom_mbedtls_pkcs5_pbes2)( const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t datalen, unsigned char *output ); + int (*_rom_mbedtls_pkcs5_pbkdf2_hmac)( mbedtls_md_context_t *ctx, const unsigned char *password, size_t plen, const unsigned char *salt, size_t slen, unsigned int iteration_count, uint32_t key_length, unsigned char *output ); + const mbedtls_pk_info_t *(*_rom_mbedtls_pk_info_from_type)( mbedtls_pk_type_t pk_type ); + void (*_rom_mbedtls_pk_init)( mbedtls_pk_context *ctx ); + void (*_rom_mbedtls_pk_free)( mbedtls_pk_context *ctx ); + void (*_rom_mbedtls_pk_restart_init)( mbedtls_pk_restart_ctx *ctx ); + void (*_rom_mbedtls_pk_restart_free)( mbedtls_pk_restart_ctx *ctx ); + int (*_rom_mbedtls_pk_setup)( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); + int (*_rom_mbedtls_pk_can_do)( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); + int (*_rom_mbedtls_pk_verify)( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len ); + int (*_rom_mbedtls_pk_verify_restartable)( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, mbedtls_pk_restart_ctx *rs_ctx ); + int (*_rom_mbedtls_pk_verify_ext)( mbedtls_pk_type_t type, const void *options, mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len ); + int (*_rom_mbedtls_pk_sign_restartable)( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_pk_restart_ctx *rs_ctx ); + int (*_rom_mbedtls_pk_encrypt)( mbedtls_pk_context *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + mbedtls_pk_type_t (*_rom_mbedtls_pk_get_type)( const mbedtls_pk_context *ctx ); + int (*_rom_mbedtls_pk_parse_subpubkey)( unsigned char **p, const unsigned char *end, mbedtls_pk_context *pk ); + void (*_rom_mbedtls_rsa_init)( mbedtls_rsa_context *ctx ); + int (*_rom_mbedtls_rsa_import)( mbedtls_rsa_context *ctx, const mbedtls_mpi *N, const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *E ); + int (*_rom_mbedtls_rsa_import_raw)( mbedtls_rsa_context *ctx, unsigned char const *N, size_t N_len, unsigned char const *P, size_t P_len, unsigned char const *Q, size_t Q_len, unsigned char const *D, size_t D_len, unsigned char const *E, size_t E_len ); + int (*_rom_mbedtls_rsa_complete)( mbedtls_rsa_context *ctx ); + int (*_rom_mbedtls_rsa_set_padding)( mbedtls_rsa_context *ctx, int padding, mbedtls_md_type_t hash_id ); + size_t (*_rom_mbedtls_rsa_get_len)( const mbedtls_rsa_context *ctx ); + int (*_rom_mbedtls_rsa_check_pubkey)( const mbedtls_rsa_context *ctx ); + int (*_rom_mbedtls_rsa_check_privkey)( const mbedtls_rsa_context *ctx ); + int (*_rom_mbedtls_rsa_check_pub_priv)( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv ); + int (*_rom_mbedtls_rsa_public)( mbedtls_rsa_context *ctx, const unsigned char *input, unsigned char *output ); + int (*_rom_mbedtls_rsa_private)( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *input, unsigned char *output ); + int (*_rom_mbedtls_rsa_pkcs1_encrypt)( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, size_t ilen, const unsigned char *input, unsigned char *output ); + int (*_rom_mbedtls_rsa_rsaes_pkcs1_v15_encrypt)( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, size_t ilen, const unsigned char *input, unsigned char *output ); + int (*_rom_mbedtls_rsa_rsaes_oaep_encrypt)( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, const unsigned char *label, size_t label_len, size_t ilen, const unsigned char *input, unsigned char *output ); + int (*_rom_mbedtls_rsa_pkcs1_decrypt)( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len ); + int (*_rom_mbedtls_rsa_rsaes_pkcs1_v15_decrypt)( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len ); + int (*_rom_mbedtls_rsa_rsaes_oaep_decrypt)( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, const unsigned char *label, size_t label_len, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len ); + int (*_rom_mbedtls_rsa_pkcs1_sign)( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig ); + int (*_rom_mbedtls_rsa_rsassa_pkcs1_v15_sign)( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig ); + int (*_rom_mbedtls_rsa_rsassa_pss_sign)( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig ); + int (*_rom_mbedtls_rsa_pkcs1_verify)( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig ); + int (*_rom_mbedtls_rsa_rsassa_pkcs1_v15_verify)( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig ); + int (*_rom_mbedtls_rsa_rsassa_pss_verify)( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig ); + int (*_rom_mbedtls_rsa_rsassa_pss_verify_ext)( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, mbedtls_md_type_t mgf1_hash_id, int expected_salt_len, const unsigned char *sig ); + void (*_rom_mbedtls_rsa_free)( mbedtls_rsa_context *ctx ); + int (*_rom_mbedtls_rsa_deduce_primes)( mbedtls_mpi const *N, mbedtls_mpi const *E, mbedtls_mpi const *D, mbedtls_mpi *P, mbedtls_mpi *Q ); + int (*_rom_mbedtls_rsa_deduce_private_exponent)( mbedtls_mpi const *P, mbedtls_mpi const *Q, mbedtls_mpi const *E, mbedtls_mpi *D ); + int (*_rom_mbedtls_rsa_deduce_crt)( const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ); + int (*_rom_mbedtls_rsa_validate_params)( const mbedtls_mpi *N, const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *E, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + int (*_rom_mbedtls_rsa_validate_crt)( const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *DP, const mbedtls_mpi *DQ, const mbedtls_mpi *QP ); + void (*_rom_mbedtls_sha1_init)( mbedtls_sha1_context *ctx ); + void (*_rom_mbedtls_sha1_free)( mbedtls_sha1_context *ctx ); + void (*_rom_mbedtls_sha1_clone)( mbedtls_sha1_context *dst, const mbedtls_sha1_context *src ); + int (*_rom_mbedtls_sha1_starts)( mbedtls_sha1_context *ctx ); + int (*_rom_mbedtls_sha1_finish)( mbedtls_sha1_context *ctx, unsigned char output[20] ); + void (*_rom_mbedtls_sha256_init)( mbedtls_sha256_context *ctx ); + void (*_rom_mbedtls_sha256_free)( mbedtls_sha256_context *ctx ); + void (*_rom_mbedtls_sha256_clone)( mbedtls_sha256_context *dst, const mbedtls_sha256_context *src ); + int (*_rom_mbedtls_sha256_starts)( mbedtls_sha256_context *ctx, int is224 ); + int (*_rom_mbedtls_sha256_finish)( mbedtls_sha256_context *ctx, unsigned char output[32] ); + int (*_rom_mbedtls_sha256)( const unsigned char *input, size_t ilen, unsigned char output[32], int is224 ); + void (*_rom_mbedtls_sha512_init)( mbedtls_sha512_context *ctx ); + void (*_rom_mbedtls_sha512_free)( mbedtls_sha512_context *ctx ); + void (*_rom_mbedtls_sha512_clone)( mbedtls_sha512_context *dst, const mbedtls_sha512_context *src ); + int (*_rom_mbedtls_sha512_starts)( mbedtls_sha512_context *ctx, int is384 ); + int (*_rom_mbedtls_sha512_update)( mbedtls_sha512_context *ctx, const unsigned char *input, size_t ilen ); + int (*_rom_mbedtls_sha512_finish)( mbedtls_sha512_context *ctx, unsigned char output[64] ); + int (*_rom_mbedtls_internal_sha512_process)( mbedtls_sha512_context *ctx, const unsigned char data[128] ); + int (*_rom_mbedtls_sha512)( const unsigned char *input, size_t ilen, unsigned char output[64], int is384 ); + void (*_rom_mbedtls_ssl_conf_endpoint)( mbedtls_ssl_config *conf, int endpoint ); + void (*_rom_mbedtls_ssl_conf_transport)( mbedtls_ssl_config *conf, int transport ); + void (*_rom_mbedtls_ssl_set_bio)( mbedtls_ssl_context *ssl, void *p_bio, mbedtls_ssl_send_t *f_send, mbedtls_ssl_recv_t *f_recv, mbedtls_ssl_recv_timeout_t *f_recv_timeout ); + int (*_rom_mbedtls_ssl_conf_dh_param_bin)( mbedtls_ssl_config *conf, const unsigned char *dhm_P, size_t P_len, const unsigned char *dhm_G, size_t G_len ); + size_t (*_rom_mbedtls_ssl_get_max_frag_len)( const mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_get_max_out_record_payload)( const mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_handshake)( mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_handshake_step)( mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_renegotiate)( mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_send_alert_message)( mbedtls_ssl_context *ssl, unsigned char level, unsigned char message ); + int (*_rom_mbedtls_ssl_config_defaults)( mbedtls_ssl_config *conf, int endpoint, int transport, int preset ); + void (*_rom_mbedtls_ssl_session_init)( mbedtls_ssl_session *session ); + void (*_rom_mbedtls_ssl_session_free)( mbedtls_ssl_session *session ); + void (*_rom_mbedtls_ssl_transform_free)( mbedtls_ssl_transform *transform ); + void (*_rom_mbedtls_ssl_handshake_free)( mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_handshake_client_step)( mbedtls_ssl_context *ssl ); + void (*_rom_mbedtls_ssl_handshake_wrapup)( mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_derive_keys)( mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_handle_message_type)( mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_prepare_handshake_record)( mbedtls_ssl_context *ssl ); + void (*_rom_mbedtls_ssl_update_handshake_status)( mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_read_record)( mbedtls_ssl_context *ssl, unsigned update_hs_digest ); + int (*_rom_mbedtls_ssl_fetch_input)( mbedtls_ssl_context *ssl, size_t nb_want ); + int (*_rom_mbedtls_ssl_write_handshake_msg)( mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_write_record)( mbedtls_ssl_context *ssl, uint8_t force_flush ); + int (*_rom_mbedtls_ssl_flush_output)( mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_parse_certificate)( mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_write_certificate)( mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_parse_change_cipher_spec)( mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_write_change_cipher_spec)( mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_parse_finished)( mbedtls_ssl_context *ssl ); + int (*_rom_mbedtls_ssl_write_finished)( mbedtls_ssl_context *ssl ); + void (*_rom_mbedtls_ssl_optimize_checksum)( mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *ciphersuite_info ); + int (*_rom_mbedtls_ssl_psk_derive_premaster)( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ); + unsigned char (*_rom_mbedtls_ssl_sig_from_pk)( mbedtls_pk_context *pk ); + mbedtls_pk_type_t (*_rom_mbedtls_ssl_pk_alg_from_sig)( unsigned char sig ); + mbedtls_md_type_t (*_rom_mbedtls_ssl_md_alg_from_hash)( unsigned char hash ); + unsigned char (*_rom_mbedtls_ssl_hash_from_md_alg)( int md ); + int (*_rom_mbedtls_ssl_check_curve)( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ); + int (*_rom_mbedtls_ssl_check_sig_hash)( const mbedtls_ssl_context *ssl, mbedtls_md_type_t md ); + void (*_rom_mbedtls_ssl_write_version)( int major, int minor, int transport, unsigned char ver[2] ); + void (*_rom_mbedtls_ssl_read_version)( int *major, int *minor, int transport, const unsigned char ver[2] ); + int (*_rom_mbedtls_ssl_get_key_exchange_md_ssl_tls)( mbedtls_ssl_context *ssl, unsigned char *output, unsigned char *data, size_t data_len ); + int (*_rom_mbedtls_ssl_get_key_exchange_md_tls1_2)( mbedtls_ssl_context *ssl, unsigned char *hash, size_t *hashlen, unsigned char *data, size_t data_len, mbedtls_md_type_t md_alg ); + int (*_rom_mbedtls_ssl_cf_hmac)( mbedtls_md_context_t *ctx, const unsigned char *add_data, size_t add_data_len, const unsigned char *data, size_t data_len_secret, size_t min_data_len, size_t max_data_len, unsigned char *output ); + void (*_rom_mbedtls_ssl_cf_memcpy_offset)( unsigned char *dst, const unsigned char *src_base, size_t offset_secret, size_t offset_min, size_t offset_max, size_t len ); + int (*_rom_mbedtls_x509_crt_parse_der)( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); + int (*_rom_mbedtls_x509_crt_verify_restartable)( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy, mbedtls_x509_crt_restart_ctx *rs_ctx ); + int (*_rom_mbedtls_x509_crt_check_key_usage)( const mbedtls_x509_crt *crt, unsigned int usage ); + int (*_rom_mbedtls_x509_crt_check_extended_key_usage)( const mbedtls_x509_crt *crt, const char *usage_oid, size_t usage_len ); + int (*_rom_mbedtls_x509_crt_is_revoked)( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ); + void (*_rom_mbedtls_x509_crt_init)( mbedtls_x509_crt *crt ); + void (*_rom_mbedtls_x509_crt_free)( mbedtls_x509_crt *crt ); + void (*_rom_mbedtls_x509_crt_restart_init)( mbedtls_x509_crt_restart_ctx *ctx ); + void (*_rom_mbedtls_x509_crt_restart_free)( mbedtls_x509_crt_restart_ctx *ctx ); + int (*_rom_mbedtls_x509_get_name)( unsigned char **p, const unsigned char *end, mbedtls_x509_name *cur ); + int (*_rom_mbedtls_x509_get_alg_null)( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *alg ); + int (*_rom_mbedtls_x509_get_alg)( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *alg, mbedtls_x509_buf *params ); + int (*_rom_mbedtls_x509_get_rsassa_pss_params)( const mbedtls_x509_buf *params, mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, int *salt_len ); + int (*_rom_mbedtls_x509_get_sig)( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ); + int (*_rom_mbedtls_x509_get_sig_alg)( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, void **sig_opts ); + int (*_rom_mbedtls_x509_get_time)( unsigned char **p, const unsigned char *end, mbedtls_x509_time *t ); + int (*_rom_mbedtls_x509_get_serial)( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *serial ); + int (*_rom_mbedtls_x509_get_ext)( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *ext, int tag ); + void (*_mbedtls_mutex_init)( mbedtls_threading_mutex_t *mutex ); + void (*_mbedtls_mutex_free)( mbedtls_threading_mutex_t *mutex ); + int (*_mbedtls_mutex_lock)( mbedtls_threading_mutex_t *mutex ); + int (*_mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); + bool (*_mbedtls_allow_unsupported_critical_ext)( void ); + const mbedtls_cipher_info_t *(*_mbedtls_cipher_info_from_type)( const mbedtls_cipher_type_t cipher_type ); + const mbedtls_cipher_info_t *(*_mbedtls_cipher_info_from_values)( const mbedtls_cipher_id_t cipher_id, int key_bitlen, const mbedtls_cipher_mode_t mode ); + void (*_mbedtls_cipher_free)( mbedtls_cipher_context_t *ctx ); + int (*_mbedtls_cipher_setup)( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ); + int (*_mbedtls_cipher_setkey)( mbedtls_cipher_context_t *ctx, const unsigned char *key, int key_bitlen, const mbedtls_operation_t operation ); + int (*_mbedtls_cipher_set_iv)( mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len ); + int (*_mbedtls_cipher_update)( mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen ); + int (*_mbedtls_cipher_auth_encrypt)( mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, unsigned char *tag, size_t tag_len ); + int (*_mbedtls_cipher_auth_decrypt)( mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, const unsigned char *tag, size_t tag_len ); + int (*_mbedtls_hardware_poll)( void *data, unsigned char *output, size_t len, size_t *olen ); + const mbedtls_md_info_t *(*_mbedtls_md_info_from_type)( mbedtls_md_type_t md_type ); + int (*_mbedtls_pem_read_buffer)( void *ctx, const char *header, const char *footer, const unsigned char *data, const unsigned char *pwd, size_t pwdlen, size_t *use_len ); + void *(*_mbedtls_calloc)( size_t n, size_t size ); + void (*_mbedtls_free)( void *ptr ); + int (*_mbedtls_sha1_update)( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ); + int (*_mbedtls_internal_sha1_process)( mbedtls_sha1_context *ctx, const unsigned char data[64] ); + int (*_mbedtls_sha256_update)( mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen ); + int (*_mbedtls_internal_sha256_process)( mbedtls_sha256_context *ctx, const unsigned char data[64] ); + const int *(*_mbedtls_ssl_list_ciphersuites)( void ); + const mbedtls_ssl_ciphersuite_t *(*_mbedtls_ssl_ciphersuite_from_id)( int ciphersuite_id ); + mbedtls_pk_type_t (*_mbedtls_ssl_get_ciphersuite_sig_pk_alg)( const mbedtls_ssl_ciphersuite_t *info ); + int (*_mbedtls_ssl_ciphersuite_uses_ec)( const mbedtls_ssl_ciphersuite_t *info ); + int (*_mbedtls_ssl_ciphersuite_uses_psk)( const mbedtls_ssl_ciphersuite_t *info ); + int (*_mbedtls_ssl_handshake_server_step)( mbedtls_ssl_context *ssl ); + int (*_mbedtls_ssl_check_cert_usage)( const mbedtls_x509_crt *cert, const mbedtls_ssl_ciphersuite_t *ciphersuite, int cert_endpoint, uint32_t *flags ); + int (*_mbedtls_x509_time_is_past)( const mbedtls_x509_time *to ); + int (*_mbedtls_x509_time_is_future)( const mbedtls_x509_time *from ); +} mbedtls_rom_funcs_t; + +typedef struct mbedtls_rom_eco4_funcs { + // aes module + void (*_rom_mbedtls_aes_init)(mbedtls_aes_context *ctx); + void (*_rom_mbedtls_aes_free)(mbedtls_aes_context *ctx); + void (*_rom_mbedtls_aes_xts_init)(mbedtls_aes_xts_context *ctx); + void (*_rom_mbedtls_aes_xts_free)(mbedtls_aes_xts_context *ctx); + int (*_rom_mbedtls_aes_setkey_enc)(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits); + int (*_rom_mbedtls_aes_setkey_dec)(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits); + int (*_rom_mbedtls_aes_xts_setkey_enc)(mbedtls_aes_xts_context *ctx, const unsigned char *key, unsigned int keybits); + int (*_rom_mbedtls_aes_xts_setkey_dec)(mbedtls_aes_xts_context *ctx, const unsigned char *key, unsigned int keybits); + int (*_rom_mbedtls_aes_crypt_ecb)(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]); + int (*_rom_mbedtls_aes_crypt_cbc)(mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output); + int (*_rom_mbedtls_aes_crypt_xts)(mbedtls_aes_xts_context *ctx, int mode, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output); + int (*_rom_mbedtls_aes_crypt_cfb128)(mbedtls_aes_context *ctx, int mode, size_t length, size_t *iv_off, unsigned char iv[16], const unsigned char *input, unsigned char *output); + int (*_rom_mbedtls_aes_crypt_ofb)(mbedtls_aes_context *ctx, size_t length, size_t *iv_off, unsigned char iv[16], const unsigned char *input, unsigned char *output); + int (*_rom_mbedtls_aes_crypt_ctr)(mbedtls_aes_context *ctx, size_t length, size_t *nc_off, unsigned char nonce_counter[16], unsigned char stream_block[16], const unsigned char *input, unsigned char *output); + int (*_rom_mbedtls_internal_aes_encrypt)(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]); + int (*_rom_mbedtls_internal_aes_decrypt)(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]); + // md5 module + void (*_rom_mbedtls_md5_init)(mbedtls_md5_context *ctx); + void (*_rom_mbedtls_md5_free)(mbedtls_md5_context *ctx); + void (*_rom_mbedtls_md5_clone)(mbedtls_md5_context *dst, const mbedtls_md5_context *src); + int (*_rom_mbedtls_md5_starts)(mbedtls_md5_context *ctx); + int (*_rom_mbedtls_md5_update)(mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen); + int (*_rom_mbedtls_md5_finish)(mbedtls_md5_context *ctx, unsigned char output[16]); + int (*_rom_mbedtls_md5)(const unsigned char *input, size_t ilen, unsigned char output[16]); + // bignum module + void (*_rom_mbedtls_mpi_init)(mbedtls_mpi *X); + void (*_rom_mbedtls_mpi_free)(mbedtls_mpi *X); + int (*_rom_mbedtls_mpi_grow)(mbedtls_mpi *X, size_t nblimbs); + int (*_rom_mbedtls_mpi_shrink)(mbedtls_mpi *X, size_t nblimbs); + int (*_rom_mbedtls_mpi_copy)(mbedtls_mpi *X, const mbedtls_mpi *Y); + int (*_rom_mbedtls_mpi_safe_cond_assign)(mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign); + int (*_rom_mbedtls_mpi_safe_cond_swap)(mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap); + int (*_rom_mbedtls_mpi_lset)(mbedtls_mpi *X, mbedtls_mpi_sint z); + int (*_rom_mbedtls_mpi_get_bit)(const mbedtls_mpi *X, size_t pos); + int (*_rom_mbedtls_mpi_set_bit)(mbedtls_mpi *X, size_t pos, unsigned char val); + size_t (*_rom_mbedtls_mpi_lsb)(const mbedtls_mpi *X); + size_t (*_rom_mbedtls_mpi_bitlen)(const mbedtls_mpi *X); + size_t (*_rom_mbedtls_mpi_size)(const mbedtls_mpi *X); + int (*_rom_mbedtls_mpi_read_binary)(mbedtls_mpi *X, const unsigned char *buf, size_t buflen); + int (*_rom_mbedtls_mpi_write_binary)(const mbedtls_mpi *X, unsigned char *buf, size_t buflen); + int (*_rom_mbedtls_mpi_shift_l)(mbedtls_mpi *X, size_t count); + int (*_rom_mbedtls_mpi_shift_r)(mbedtls_mpi *X, size_t count); + int (*_rom_mbedtls_mpi_cmp_abs)(const mbedtls_mpi *X, const mbedtls_mpi *Y); + int (*_rom_mbedtls_mpi_cmp_mpi)(const mbedtls_mpi *X, const mbedtls_mpi *Y); + int (*_rom_mbedtls_mpi_lt_mpi_ct)(const mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned *ret); + int (*_rom_mbedtls_mpi_cmp_int)(const mbedtls_mpi *X, mbedtls_mpi_sint z); + int (*_rom_mbedtls_mpi_add_abs)(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); + int (*_rom_mbedtls_mpi_sub_abs)(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); + int (*_rom_mbedtls_mpi_add_mpi)(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); + int (*_rom_mbedtls_mpi_sub_mpi)(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); + int (*_rom_mbedtls_mpi_add_int)(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b); + int (*_rom_mbedtls_mpi_sub_int)(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b); + int (*_rom_mbedtls_mpi_mul_mpi)(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); + int (*_rom_mbedtls_mpi_mul_int)(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b); + int (*_rom_mbedtls_mpi_div_mpi)(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B); + int (*_rom_mbedtls_mpi_div_int)(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b); + int (*_rom_mbedtls_mpi_mod_mpi)(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B); + int (*_rom_mbedtls_mpi_mod_int)(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b); + int (*_rom_mbedtls_mpi_exp_mod)(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *prec_RR); + int (*_rom_mbedtls_mpi_fill_random)(mbedtls_mpi *X, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + int (*_rom_mbedtls_mpi_gcd)(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B); + int (*_rom_mbedtls_mpi_inv_mod)(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N); + int (*_rom_mbedtls_mpi_is_prime_ext)(const mbedtls_mpi *X, int rounds, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + // sha1 sha256 sha512 module + void (*_rom_mbedtls_sha1_init)(mbedtls_sha1_context *ctx); + void (*_rom_mbedtls_sha1_free)(mbedtls_sha1_context *ctx); + void (*_rom_mbedtls_sha1_clone)(mbedtls_sha1_context *dst, const mbedtls_sha1_context *src); + int (*_rom_mbedtls_sha1_starts)(mbedtls_sha1_context *ctx); + int (*_rom_mbedtls_sha1_finish)(mbedtls_sha1_context *ctx, unsigned char output[20]); + int (*_rom_mbedtls_sha1)(const unsigned char *input, size_t ilen, unsigned char output[20]); + void (*_rom_mbedtls_sha256_init)(mbedtls_sha256_context *ctx); + void (*_rom_mbedtls_sha256_free)(mbedtls_sha256_context *ctx); + void (*_rom_mbedtls_sha256_clone)(mbedtls_sha256_context *dst, const mbedtls_sha256_context *src); + int (*_rom_mbedtls_sha256_starts)(mbedtls_sha256_context *ctx, int is224); + int (*_rom_mbedtls_sha256_finish)(mbedtls_sha256_context *ctx, unsigned char *output); + int (*_rom_mbedtls_sha256)(const unsigned char *input, size_t ilen, unsigned char *output, int is224); + void (*_rom_mbedtls_sha512_init)(mbedtls_sha512_context *ctx); + void (*_rom_mbedtls_sha512_free)(mbedtls_sha512_context *ctx); + void (*_rom_mbedtls_sha512_clone)(mbedtls_sha512_context *dst, const mbedtls_sha512_context *src); + int (*_rom_mbedtls_sha512_starts)(mbedtls_sha512_context *ctx, int is384); + int (*_rom_mbedtls_sha512_update)(mbedtls_sha512_context *ctx, const unsigned char *input, size_t ilen); + int (*_rom_mbedtls_sha512_finish)(mbedtls_sha512_context *ctx, unsigned char *output); + int (*_rom_mbedtls_sha512)(const unsigned char *input, size_t ilen, unsigned char *output, int is384); + // ecp module + // asn1 module + int (*_rom_mbedtls_asn1_get_len)(unsigned char **p, const unsigned char *end, size_t *len); + int (*_rom_mbedtls_asn1_get_tag)(unsigned char **p, const unsigned char *end, size_t *len, int tag); + int (*_rom_mbedtls_asn1_get_bool)(unsigned char **p, const unsigned char *end, int *val); + int (*_rom_mbedtls_asn1_get_int)(unsigned char **p, const unsigned char *end, int *val); + int (*_rom_mbedtls_asn1_get_bitstring)(unsigned char **p, const unsigned char *end, mbedtls_asn1_bitstring *bs); + int (*_rom_mbedtls_asn1_get_bitstring_null)(unsigned char **p, const unsigned char *end, size_t *len); + int (*_rom_mbedtls_asn1_get_sequence_of)(unsigned char **p, const unsigned char *end, mbedtls_asn1_sequence *cur, int tag); + int (*_rom_mbedtls_asn1_get_mpi)(unsigned char **p, const unsigned char *end, mbedtls_mpi *X); + int (*_rom_mbedtls_asn1_get_alg)(unsigned char **p, const unsigned char *end, mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params); + int (*_rom_mbedtls_asn1_get_alg_null)(unsigned char **p, const unsigned char *end, mbedtls_asn1_buf *alg); + // asn1write module + int (*_rom_mbedtls_asn1_write_len)(unsigned char **p, const unsigned char *start, size_t len); + int (*_rom_mbedtls_asn1_write_tag)(unsigned char **p, const unsigned char *start, unsigned char tag); + int (*_rom_mbedtls_asn1_write_mpi)(unsigned char **p, const unsigned char *start, const mbedtls_mpi *X); + // ccm module + void (*_rom_mbedtls_ccm_init)(mbedtls_ccm_context *ctx); + int (*_rom_mbedtls_ccm_setkey)(mbedtls_ccm_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, unsigned int keybits); + void (*_rom_mbedtls_ccm_free)(mbedtls_ccm_context *ctx); + int (*_rom_mbedtls_ccm_encrypt_and_tag)(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len); + int (*_rom_mbedtls_ccm_star_encrypt_and_tag)(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len); + int (*_rom_mbedtls_ccm_auth_decrypt)(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len); + int (*_rom_mbedtls_ccm_star_auth_decrypt)(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len); + // cipher module + void (*_rom_mbedtls_cipher_init)(mbedtls_cipher_context_t *ctx); + int (*_rom_mbedtls_cipher_set_padding_mode)(mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode); + int (*_rom_mbedtls_cipher_reset)(mbedtls_cipher_context_t *ctx); + int (*_rom_mbedtls_cipher_finish)(mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen); + int (*_rom_mbedtls_cipher_crypt)(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen); + int (*_rom_mbedtls_cipher_cmac_starts)(mbedtls_cipher_context_t *ctx, const unsigned char *key, size_t keybits); + int (*_rom_mbedtls_cipher_cmac_update)(mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen); + int (*_rom_mbedtls_cipher_cmac_finish)(mbedtls_cipher_context_t *ctx, unsigned char *output); + // ctr drbg module + void (*_rom_mbedtls_ctr_drbg_init)(mbedtls_ctr_drbg_context *ctx); + int (*_rom_mbedtls_ctr_drbg_seed)(mbedtls_ctr_drbg_context *ctx, int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, const unsigned char *custom, size_t len); + void (*_rom_mbedtls_ctr_drbg_free)(mbedtls_ctr_drbg_context *ctx); + int (*_rom_mbedtls_ctr_drbg_reseed)(mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t len); + int (*_rom_mbedtls_ctr_drbg_random_with_add)(void *p_rng, unsigned char *output, size_t output_len, const unsigned char *additional, size_t add_len); + int (*_rom_mbedtls_ctr_drbg_random)(void *p_rng, unsigned char *output, size_t output_len); + // base64 module + int (*_rom_mbedtls_base64_decode)(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen); + //*******************************************************************************************************************************************************************// + // aes module + int (*_rom_mbedtls_aes_crypt_cfb8)(mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output); + // md5 module + // bignum module + void (*_rom_mbedtls_mpi_swap)(mbedtls_mpi *X, mbedtls_mpi *Y); + int (*_rom_mbedtls_mpi_read_string)(mbedtls_mpi *X, int radix, const char *s); + int (*_rom_mbedtls_mpi_write_string)(const mbedtls_mpi *X, int radix, char *buf, size_t buflen, size_t *olen); + int (*_rom_mbedtls_mpi_read_binary_le)(mbedtls_mpi *X, const unsigned char *buf, size_t buflen); + int (*_rom_mbedtls_mpi_write_binary_le)(const mbedtls_mpi *X, unsigned char *buf, size_t buflen); + int (*_rom_mbedtls_mpi_random)(mbedtls_mpi *X, mbedtls_mpi_sint min, const mbedtls_mpi *N, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + int (*_rom_mbedtls_mpi_gen_prime)(mbedtls_mpi *X, size_t nbits, int flags, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + // ecp module + int (*_rom_mbedtls_ecp_check_budget)(const mbedtls_ecp_group *grp, mbedtls_ecp_restart_ctx *rs_ctx, unsigned ops); + void (*_rom_mbedtls_ecp_set_max_ops)(unsigned max_ops); + int (*_rom_mbedtls_ecp_restart_is_enabled)(void); + mbedtls_ecp_curve_type (*_rom_mbedtls_ecp_get_type)(const mbedtls_ecp_group *grp); + const mbedtls_ecp_curve_info *(*_rom_mbedtls_ecp_curve_list)(void); + const mbedtls_ecp_group_id *(*_rom_mbedtls_ecp_grp_id_list)(void); + const mbedtls_ecp_curve_info *(*_rom_mbedtls_ecp_curve_info_from_grp_id)(mbedtls_ecp_group_id grp_id); + const mbedtls_ecp_curve_info *(*_rom_mbedtls_ecp_curve_info_from_tls_id)(uint16_t tls_id); + const mbedtls_ecp_curve_info *(*_rom_mbedtls_ecp_curve_info_from_name)(const char *name); + void (*_rom_mbedtls_ecp_point_init)(mbedtls_ecp_point *pt); + void (*_rom_mbedtls_ecp_group_init)(mbedtls_ecp_group *grp); + void (*_rom_mbedtls_ecp_keypair_init)(mbedtls_ecp_keypair *key); + void (*_rom_mbedtls_ecp_point_free)(mbedtls_ecp_point *pt); + void (*_rom_mbedtls_ecp_group_free)(mbedtls_ecp_group *grp); + void (*_rom_mbedtls_ecp_keypair_free)(mbedtls_ecp_keypair *key); + void (*_rom_mbedtls_ecp_restart_init)(mbedtls_ecp_restart_ctx *ctx); + void (*_rom_mbedtls_ecp_restart_free)(mbedtls_ecp_restart_ctx *ctx); + int (*_rom_mbedtls_ecp_copy)(mbedtls_ecp_point *P, const mbedtls_ecp_point *Q); + int (*_rom_mbedtls_ecp_group_copy)(mbedtls_ecp_group *dst, const mbedtls_ecp_group *src); + int (*_rom_mbedtls_ecp_set_zero)(mbedtls_ecp_point *pt); + int (*_rom_mbedtls_ecp_is_zero)(mbedtls_ecp_point *pt); + int (*_rom_mbedtls_ecp_point_cmp)(const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q); + int (*_rom_mbedtls_ecp_point_read_string)(mbedtls_ecp_point *P, int radix, const char *x, const char *y); + int (*_rom_mbedtls_ecp_point_write_binary)(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, int format, size_t *olen, unsigned char *buf, size_t buflen); + int (*_rom_mbedtls_ecp_point_read_binary)(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, const unsigned char *buf, size_t ilen); + int (*_rom_mbedtls_ecp_tls_read_point)(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, const unsigned char **buf, size_t len); + int (*_rom_mbedtls_ecp_tls_write_point)(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, int format, size_t *olen, unsigned char *buf, size_t blen); + int (*_rom_mbedtls_ecp_group_load)(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id); + int (*_rom_mbedtls_ecp_tls_read_group)(mbedtls_ecp_group *grp, const unsigned char **buf, size_t len); + int (*_rom_mbedtls_ecp_tls_read_group_id)(mbedtls_ecp_group_id *grp, const unsigned char **buf, size_t len); + int (*_rom_mbedtls_ecp_tls_write_group)(const mbedtls_ecp_group *grp, size_t *olen, unsigned char *buf, size_t blen); + int (*_rom_mbedtls_ecp_mul)(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + int (*_rom_mbedtls_ecp_mul_restartable)(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx); + int (*_rom_mbedtls_ecp_muladd)(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q); + int (*_rom_mbedtls_ecp_muladd_restartable)( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q, mbedtls_ecp_restart_ctx *rs_ctx); + int (*_rom_mbedtls_ecp_check_pubkey)(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt); + int (*_rom_mbedtls_ecp_check_privkey)(const mbedtls_ecp_group *grp, const mbedtls_mpi *d); + int (*_rom_mbedtls_ecp_gen_privkey)(const mbedtls_ecp_group *grp, mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + int (*_rom_mbedtls_ecp_gen_keypair_base)(mbedtls_ecp_group *grp, const mbedtls_ecp_point *G, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + int (*_rom_mbedtls_ecp_gen_keypair)(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + int (*_rom_mbedtls_ecp_gen_key)(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + int (*_rom_mbedtls_ecp_read_key)(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, const unsigned char *buf, size_t buflen); + int (*_rom_mbedtls_ecp_write_key_ext)(const mbedtls_ecp_keypair *key, size_t *olen, unsigned char *buf, size_t buflen); + int (*_rom_mbedtls_ecp_check_pub_priv)( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + int (*_rom_mbedtls_ecp_export)(const mbedtls_ecp_keypair *key, mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q); + // asn1 module + int (*_rom_mbedtls_asn1_get_enum)(unsigned char **p, const unsigned char *end, int *val); + void (*_rom_mbedtls_asn1_sequence_free)(mbedtls_asn1_sequence *seq); + int (*_rom_mbedtls_asn1_traverse_sequence_of)( unsigned char **p, const unsigned char *end, unsigned char tag_must_mask, unsigned char tag_must_val, unsigned char tag_may_mask, unsigned char tag_may_val, int (*cb)(void *ctx, int tag, unsigned char *start, size_t len), void *ctx); + const mbedtls_asn1_named_data *(*_rom_mbedtls_asn1_find_named_data)(const mbedtls_asn1_named_data *list, const char *oid, size_t len); + void (*_rom_mbedtls_asn1_free_named_data_list)(mbedtls_asn1_named_data **head); + void (*_rom_mbedtls_asn1_free_named_data_list_shallow)(mbedtls_asn1_named_data *name); + // asn1write module + int (*_rom_mbedtls_asn1_write_raw_buffer)(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t size); + int (*_rom_mbedtls_asn1_write_null)(unsigned char **p, const unsigned char *start); + int (*_rom_mbedtls_asn1_write_oid)(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len); + int (*_rom_mbedtls_asn1_write_algorithm_identifier)(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len, size_t par_len); + int (*_rom_mbedtls_asn1_write_bool)(unsigned char **p, const unsigned char *start, int boolean); + int (*_rom_mbedtls_asn1_write_int)(unsigned char **p, const unsigned char *start, int val); + int (*_rom_mbedtls_asn1_write_enum)(unsigned char **p, const unsigned char *start, int val); + int (*_rom_mbedtls_asn1_write_tagged_string)(unsigned char **p, const unsigned char *start, int tag, const char *text, size_t text_len); + int (*_rom_mbedtls_asn1_write_printable_string)(unsigned char **p, const unsigned char *start, const char *text, size_t text_len); + int (*_rom_mbedtls_asn1_write_utf8_string)(unsigned char **p, const unsigned char *start, const char *text, size_t text_len); + int (*_rom_mbedtls_asn1_write_ia5_string)(unsigned char **p, const unsigned char *start, const char *text, size_t text_len); + int (*_rom_mbedtls_asn1_write_bitstring)(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t bits); + int (*_rom_mbedtls_asn1_write_named_bitstring)(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t bits); + int (*_rom_mbedtls_asn1_write_octet_string)(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t size); + mbedtls_asn1_named_data *(*_rom_mbedtls_asn1_store_named_data)(mbedtls_asn1_named_data **list, const char *oid, size_t oid_len, const unsigned char *val, size_t val_len); + // ccm module + int (*_rom_mbedtls_ccm_starts)(mbedtls_ccm_context *ctx, int mode, const unsigned char *iv, size_t iv_len); + int (*_rom_mbedtls_ccm_set_lengths)(mbedtls_ccm_context *ctx, size_t total_ad_len, size_t plaintext_len, size_t tag_len); + int (*_rom_mbedtls_ccm_update_ad)(mbedtls_ccm_context *ctx, const unsigned char *ad, size_t ad_len); + int (*_rom_mbedtls_ccm_update)(mbedtls_ccm_context *ctx, const unsigned char *input, size_t input_len, unsigned char *output, size_t output_size, size_t *output_len); + int (*_rom_mbedtls_ccm_finish)(mbedtls_ccm_context *ctx, unsigned char *tag, size_t tag_len); + // cipher module + const int *(*_rom_mbedtls_cipher_list)(void); + const mbedtls_cipher_info_t *(*_rom_mbedtls_cipher_info_from_string)(const char *cipher_name); + const mbedtls_cipher_info_t *(*_rom_mbedtls_cipher_info_from_type)(const mbedtls_cipher_type_t cipher_type); + const mbedtls_cipher_info_t *(*_rom_mbedtls_cipher_info_from_values)(const mbedtls_cipher_id_t cipher_id, int key_bitlen, const mbedtls_cipher_mode_t mode); + void (*_rom_mbedtls_cipher_free)(mbedtls_cipher_context_t *ctx); + int (*_rom_mbedtls_cipher_setup)(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info); + int (*_rom_mbedtls_cipher_setkey)(mbedtls_cipher_context_t *ctx, const unsigned char *key, int key_bitlen, const mbedtls_operation_t operation); + int (*_rom_mbedtls_cipher_set_iv)(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len); + int (*_rom_mbedtls_cipher_update_ad)(mbedtls_cipher_context_t *ctx, const unsigned char *ad, size_t ad_len); + int (*_rom_mbedtls_cipher_update)(mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen); + int (*_rom_mbedtls_cipher_write_tag)(mbedtls_cipher_context_t *ctx, unsigned char *tag, size_t tag_len); + int (*_rom_mbedtls_cipher_check_tag)(mbedtls_cipher_context_t *ctx, const unsigned char *tag, size_t tag_len); + int (*_rom_mbedtls_cipher_auth_encrypt_ext)(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t output_len, size_t *olen, size_t tag_len); + int (*_rom_mbedtls_cipher_auth_decrypt_ext)(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t output_len, size_t *olen, size_t tag_len); + int (*_rom_mbedtls_cipher_cmac_reset)(mbedtls_cipher_context_t *ctx); + int (*_rom_mbedtls_cipher_cmac)(const mbedtls_cipher_info_t *cipher_info, const unsigned char *key, size_t keylen, const unsigned char *input, size_t ilen, unsigned char *output); + int (*_rom_mbedtls_aes_cmac_prf_128)(const unsigned char *key, size_t key_len, const unsigned char *input, size_t in_len, unsigned char output[16]); + // ctr drbg module + void (*_rom_mbedtls_ctr_drbg_set_prediction_resistance)(mbedtls_ctr_drbg_context *ctx, int resistance); + void (*_rom_mbedtls_ctr_drbg_set_entropy_len)(mbedtls_ctr_drbg_context *ctx, size_t len); + int (*_rom_mbedtls_ctr_drbg_set_nonce_len)(mbedtls_ctr_drbg_context *ctx, size_t len); + void (*_rom_mbedtls_ctr_drbg_set_reseed_interval)(mbedtls_ctr_drbg_context *ctx, int interval); + int (*_rom_mbedtls_ctr_drbg_update)(mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t add_len); + // base64 module + int (*_rom_mbedtls_base64_encode)(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen); + // sha1 sha256 sha512 module + int (*_rom_mbedtls_sha1_update)(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen); + int (*_rom_mbedtls_sha256_update)(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen); + // memory calloc free + void *(*_rom_mbedtls_mem_calloc)(size_t n, size_t size); + void (*_rom_mbedtls_mem_free)(void *ptr); +} mbedtls_rom_eco4_funcs_t; + +#define STRUCT_OFFSET_CHECK(x, y, z) _Static_assert((offsetof(x,y)==(z)), "The variables type of "#x" before "#y" should be "#z) +#define STRUCT_SIZE_CHECK(x, y) _Static_assert((sizeof(x)==(y)), "The sizeof "#x" should be "#y) + +#if (!defined(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL)) +#error "CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL" +#endif + +/* platform_util.c */ +#if (defined(MBEDTLS_PLATFORM_ZEROIZE_ALT)) +#error "MBEDTLS_PLATFORM_ZEROIZE_ALT" +#endif + +/* sha1.c */ +STRUCT_OFFSET_CHECK(mbedtls_sha1_context, total, 0); +STRUCT_OFFSET_CHECK(mbedtls_sha1_context, state, 8); +STRUCT_OFFSET_CHECK(mbedtls_sha1_context, buffer, 28); +STRUCT_OFFSET_CHECK(mbedtls_sha1_context, first_block, 92); +STRUCT_OFFSET_CHECK(mbedtls_sha1_context, mode, 96); +STRUCT_OFFSET_CHECK(mbedtls_sha1_context, sha_state, 100); +STRUCT_SIZE_CHECK(mbedtls_sha1_context, 104); +#if (!defined(MBEDTLS_SHA1_C)) || \ + (!defined(MBEDTLS_SHA1_ALT)) || \ + (defined(MBEDTLS_SHA1_PROCESS_ALT)) +#error "MBEDTLS_SHA1_C" +#endif + +/* sha256.c */ +STRUCT_OFFSET_CHECK(mbedtls_sha256_context, total, 0); +STRUCT_OFFSET_CHECK(mbedtls_sha256_context, state, 8); +STRUCT_OFFSET_CHECK(mbedtls_sha256_context, buffer, 40); +STRUCT_OFFSET_CHECK(mbedtls_sha256_context, first_block, 104); +STRUCT_OFFSET_CHECK(mbedtls_sha256_context, mode, 108); +STRUCT_OFFSET_CHECK(mbedtls_sha256_context, sha_state, 112); +STRUCT_SIZE_CHECK(mbedtls_sha256_context, 116); +#if (!defined(MBEDTLS_SHA256_C)) || \ + (!defined(MBEDTLS_SHA256_ALT)) || \ + (defined(MBEDTLS_SHA256_PROCESS_ALT)) || \ + (defined(MBEDTLS_SHA256_SMALLER)) +#error "!MBEDTLS_SHA256_C" +#endif + +/* sha512.c */ +STRUCT_OFFSET_CHECK(mbedtls_sha512_context, MBEDTLS_PRIVATE(total), 0); +STRUCT_OFFSET_CHECK(mbedtls_sha512_context, MBEDTLS_PRIVATE(state), 16); +STRUCT_OFFSET_CHECK(mbedtls_sha512_context, MBEDTLS_PRIVATE(buffer), 80); +STRUCT_OFFSET_CHECK(mbedtls_sha512_context, MBEDTLS_PRIVATE(is384), 208); +STRUCT_SIZE_CHECK(mbedtls_sha512_context, 216); +#if (!defined(MBEDTLS_SHA512_C)) || \ + (defined(MBEDTLS_SHA512_ALT)) || \ + (defined(MBEDTLS_SHA512_PROCESS_ALT)) +#error "MBEDTLS_SHA256_C" +#endif + +/* aes.c */ +STRUCT_OFFSET_CHECK(mbedtls_aes_context, MBEDTLS_PRIVATE(nr), 0); +STRUCT_OFFSET_CHECK(mbedtls_aes_context, MBEDTLS_PRIVATE(rk_offset), 4); +STRUCT_OFFSET_CHECK(mbedtls_aes_context, MBEDTLS_PRIVATE(buf), 8); +STRUCT_SIZE_CHECK(mbedtls_aes_context, 280); +STRUCT_OFFSET_CHECK(mbedtls_aes_xts_context, MBEDTLS_PRIVATE(crypt), 0); +STRUCT_OFFSET_CHECK(mbedtls_aes_xts_context, MBEDTLS_PRIVATE(tweak), 280); +STRUCT_SIZE_CHECK(mbedtls_aes_xts_context, 560); +#if (defined(MBEDTLS_HAVE_X86)) || \ + (defined(MBEDTLS_HAVE_X86_64)) +#error "MBEDTLS_HAVE_X86" +#endif +#if (!defined(MBEDTLS_AES_C)) || \ + (defined(MBEDTLS_AES_ALT)) || \ + (defined(MBEDTLS_AES_ENCRYPT_ALT)) || \ + (defined(MBEDTLS_AES_DECRYPT_ALT)) || \ + (defined(MBEDTLS_AES_SETKEY_ENC_ALT)) || \ + (defined(MBEDTLS_AES_SETKEY_DEC_ALT)) +#error "MBEDTLS_AES_C" +#endif +#if (!defined(MBEDTLS_AES_ROM_TABLES)) || \ + (defined(MBEDTLS_AES_FEWER_TABLES)) +#error "MBEDTLS_AES_ROM_TABLES" +#endif +#if (!defined(MBEDTLS_CIPHER_MODE_XTS)) || \ + (!defined(MBEDTLS_CIPHER_MODE_CBC)) || \ + (!defined(MBEDTLS_CIPHER_MODE_CFB)) || \ + (!defined(MBEDTLS_CIPHER_MODE_OFB)) || \ + (!defined(MBEDTLS_CIPHER_MODE_CTR)) +#error "MBEDTLS_CIPHER_MODE" +#endif + +/* asn1parse.c asn1write.c */ +STRUCT_OFFSET_CHECK(mbedtls_asn1_buf, tag, 0); +STRUCT_OFFSET_CHECK(mbedtls_asn1_buf, len, 4); +STRUCT_OFFSET_CHECK(mbedtls_asn1_buf, p, 8); +STRUCT_SIZE_CHECK(mbedtls_asn1_buf, 12); +STRUCT_OFFSET_CHECK(mbedtls_asn1_bitstring, len, 0); +STRUCT_OFFSET_CHECK(mbedtls_asn1_bitstring, unused_bits, 4); +STRUCT_OFFSET_CHECK(mbedtls_asn1_bitstring, p, 8); +STRUCT_SIZE_CHECK(mbedtls_asn1_bitstring, 12); +STRUCT_OFFSET_CHECK(mbedtls_asn1_sequence, buf, 0); +STRUCT_OFFSET_CHECK(mbedtls_asn1_sequence, next, 12); +STRUCT_SIZE_CHECK(mbedtls_asn1_sequence, 16); +STRUCT_OFFSET_CHECK(mbedtls_asn1_named_data, oid, 0); +STRUCT_OFFSET_CHECK(mbedtls_asn1_named_data, val, 12); +STRUCT_OFFSET_CHECK(mbedtls_asn1_named_data, next, 24); +STRUCT_OFFSET_CHECK(mbedtls_asn1_named_data, MBEDTLS_PRIVATE(next_merged), 28); +STRUCT_SIZE_CHECK(mbedtls_asn1_named_data, 32); +#if (!defined(MBEDTLS_ASN1_PARSE_C)) +#error "MBEDTLS_ASN1_PARSE_C" +#endif +#if (!defined(MBEDTLS_ASN1_WRITE_C)) +#error "MBEDTLS_ASN1_PARSE_C" +#endif + +/* base64.c */ +#if (!defined(MBEDTLS_BASE64_C)) +#error "MBEDTLS_BASE64_C" +#endif + +/* md5.c */ +#if (defined(MBEDTLS_MD2_C)) || \ + (defined(MBEDTLS_MD4_C)) || \ + (!defined(MBEDTLS_MD5_C)) /* || \ + (defined(MBEDTLS_MD5_ALT)) */ +#error "MBEDTLS_MD_C" +#endif +#ifdef CONFIG_MBEDTLS_ROM_MD5 +STRUCT_OFFSET_CHECK(mbedtls_md5_context, total, 0); +STRUCT_OFFSET_CHECK(mbedtls_md5_context, state, 8); +STRUCT_OFFSET_CHECK(mbedtls_md5_context, buffer, 24); +STRUCT_SIZE_CHECK(mbedtls_md5_context, 88); +#else +STRUCT_OFFSET_CHECK(mbedtls_md5_context, MBEDTLS_PRIVATE(total), 0); +STRUCT_OFFSET_CHECK(mbedtls_md5_context, MBEDTLS_PRIVATE(state), 8); +STRUCT_OFFSET_CHECK(mbedtls_md5_context, MBEDTLS_PRIVATE(buffer), 24); +STRUCT_SIZE_CHECK(mbedtls_md5_context, 88); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/mbedtls_rom/threading_alt.h b/components/mbedtls/mbedtls_v3/port/mbedtls_rom/threading_alt.h new file mode 100644 index 000000000..6dc3349da --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/mbedtls_rom/threading_alt.h @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +typedef struct mbedtls_threading_mutex_t { + SemaphoreHandle_t mutex; + /* is_valid is 0 after a failed init or a free, and nonzero after a + * successful init. This field is not considered part of the public + * API of Mbed TLS and may change without notice. */ + char is_valid; +} mbedtls_threading_mutex_t; + +extern void mbedtls_threading_set_alt(void (*mutex_init)(mbedtls_threading_mutex_t *), + void (*mutex_free)(mbedtls_threading_mutex_t *), + int (*mutex_lock)(mbedtls_threading_mutex_t *), + int (*mutex_unlock)(mbedtls_threading_mutex_t *)); diff --git a/components/mbedtls/mbedtls_v3/port/md/esp_md.c b/components/mbedtls/mbedtls_v3/port/md/esp_md.c new file mode 100644 index 000000000..eb54b5d85 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/md/esp_md.c @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "mbedtls/md5.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_MD5_ALT) +#include "md/esp_md.h" + +int esp_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ) +{ + esp_rom_md5_final(output, ctx); + + + return 0; +} + +int esp_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ) +{ + esp_rom_md5_update(ctx, input, ilen); + + + return 0; +} + +void esp_md5_init( mbedtls_md5_context *ctx ) +{ + esp_rom_md5_init(ctx); +} + +int esp_md5_starts( mbedtls_md5_context *ctx ) +{ + esp_md5_init(ctx); + return 0; +} + +void esp_md5_free( mbedtls_md5_context *ctx ) +{ + if (ctx == NULL) { + return; + } + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) ); +} + +int esp_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ) +{ + esp_md5_update(ctx, data, 64); + + return 0; +} + +void esp_md5_clone( mbedtls_md5_context *dst, const mbedtls_md5_context *src ) +{ + *dst = *src; +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/net_sockets.c b/components/mbedtls/mbedtls_v3/port/net_sockets.c new file mode 100644 index 000000000..956a48c16 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/net_sockets.c @@ -0,0 +1,458 @@ +/* + * TCP/IP or UDP/IP networking functions + * modified for LWIP support on ESP32 + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2015 Angus Gratton + */ + +#include +#if !defined(MBEDTLS_NET_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#define mbedtls_time time +#define mbedtls_time_t time_t +#endif + +#include "mbedtls/net_sockets.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Prepare for using the sockets interface + */ +static int net_prepare( void ) +{ + return ( 0 ); +} + +/* + * Initialize a context + */ +void mbedtls_net_init( mbedtls_net_context *ctx ) +{ + ctx->fd = -1; +} + +/* + * Initiate a TCP connection with host:port and the given protocol + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ) +{ + int ret; + struct addrinfo hints, *addr_list, *cur; + + if ( ( ret = net_prepare() ) != 0 ) { + return ( ret ); + } + + /* Do name resolution with both IPv6 and IPv4 */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + + if ( getaddrinfo( host, port, &hints, &addr_list ) != 0 ) { + return ( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + } + + /* Try the sockaddrs until a connection succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for ( cur = addr_list; cur != NULL; cur = cur->ai_next ) { + int fd = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol ); + + if ( fd < 0 ) { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if ( connect( fd, cur->ai_addr, cur->ai_addrlen ) == 0 ) { + ctx->fd = fd; // connected! + ret = 0; + break; + } + + close( fd ); + ret = MBEDTLS_ERR_NET_CONNECT_FAILED; + } + + freeaddrinfo( addr_list ); + + return ( ret ); +} + +/* + * Create a listening socket on bind_ip:port + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ) +{ + int ret; + struct addrinfo hints, *addr_list, *cur; + struct sockaddr_storage *serv_addr = NULL; +#if SO_REUSE + int n = 1; +#endif + + if ( ( ret = net_prepare() ) != 0 ) { + return ( ret ); + } + + /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + + if ( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) { + return ( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + } + + /* Try the sockaddrs until a binding succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for ( cur = addr_list; cur != NULL; cur = cur->ai_next ) { + int fd = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol ); + if ( fd < 0 ) { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + /*SO_REUSEADDR option dafault is disable in source code(lwip)*/ +#if SO_REUSE + if ( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &n, sizeof( n ) ) != 0 ) { + close( fd ); + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } +#endif + serv_addr = (struct sockaddr_storage *) cur->ai_addr; +#if CONFIG_LWIP_IPV4 + if (cur->ai_family == AF_INET) { + /*bind interface dafault don't process the addr is 0xffffffff for TCP Protocol*/ + struct sockaddr_in *p = (struct sockaddr_in *)serv_addr; + p->sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */ + } +#endif // CONFIG_LWIP_IPV4 +#if CONFIG_LWIP_IPV6 + if (cur->ai_family == AF_INET6) { + struct sockaddr_in6 *p = (struct sockaddr_in6 *) serv_addr; + struct in6_addr inaddr_any = IN6ADDR_ANY_INIT; + p->sin6_addr = inaddr_any; + } +#endif // CONFIG_LWIP_IPV6 + + if ( bind( fd, (struct sockaddr *)serv_addr, cur->ai_addrlen ) != 0 ) { + close( fd ); + ret = MBEDTLS_ERR_NET_BIND_FAILED; + continue; + } + + /* Listen only makes sense for TCP */ + if ( proto == MBEDTLS_NET_PROTO_TCP ) { + if ( listen( fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) { + close( fd ); + ret = MBEDTLS_ERR_NET_LISTEN_FAILED; + continue; + } + } + + /* I we ever get there, it's a success */ + ctx->fd = fd; + ret = 0; + break; + } + + freeaddrinfo( addr_list ); + + return ( ret ); + +} + +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + * + * Note: on a blocking socket this function always returns 0! + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + int error = errno; + + switch ( errno = error ) { +#if defined EAGAIN + case EAGAIN: +#endif +#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif + return ( 1 ); + } + return ( 0 ); +} + +/* + * Accept a connection from a remote client + */ +int mbedtls_net_accept( mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len ) +{ + int ret; + int type; + + struct sockaddr_storage client_addr; + + socklen_t n = (socklen_t) sizeof( client_addr ); + socklen_t type_len = (socklen_t) sizeof( type ); + + /* Is this a TCP or UDP socket? */ + if ( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE, + (void *) &type, (socklen_t *) &type_len ) != 0 || + ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) { + return ( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + if ( type == SOCK_STREAM ) { + /* TCP: actual accept() */ + ret = client_ctx->fd = (int) accept( bind_ctx->fd, + (struct sockaddr *) &client_addr, &n ); + } else { + /* UDP: wait for a message, but keep it in the queue */ + char buf[1] = { 0 }; + + ret = recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, + (struct sockaddr *) &client_addr, &n ); + + } + + if ( ret < 0 ) { + if ( net_would_block( bind_ctx ) != 0 ) { + return ( MBEDTLS_ERR_SSL_WANT_READ ); + } + + return ( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + /* UDP: hijack the listening socket to communicate with the client, + * then bind a new socket to accept new connections */ + if ( type != SOCK_STREAM ) { + struct sockaddr_storage local_addr; + int one = 1; + + if ( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) { + return ( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + client_ctx->fd = bind_ctx->fd; + bind_ctx->fd = -1; /* In case we exit early */ + + n = sizeof( struct sockaddr_storage ); + if ( getsockname( client_ctx->fd, + (struct sockaddr *) &local_addr, &n ) != 0 || + ( bind_ctx->fd = (int) socket( local_addr.ss_family, + SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || + setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &one, sizeof( one ) ) != 0 ) { + return ( MBEDTLS_ERR_NET_SOCKET_FAILED ); + } + + if ( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) { + return ( MBEDTLS_ERR_NET_BIND_FAILED ); + } + } + + if ( client_ip != NULL ) { +#ifdef CONFIG_LWIP_IPV4 + if( client_addr.ss_family == AF_INET ) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; + *ip_len = sizeof( addr4->sin_addr.s_addr ); + + if ( buf_size < *ip_len ) { + return ( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + } + + memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len ); + } +#endif // CONFIG_LWIP_IPV4 +#ifdef CONFIG_LWIP_IPV6 + if( client_addr.ss_family == AF_INET6 ) + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; + *ip_len = sizeof( addr6->sin6_addr.s6_addr ); + + if( buf_size < *ip_len ) { + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + } + + memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len); + } +#endif // CONFIG_LWIP_IPV6 + } + + return ( 0 ); +} + +/* + * Set the socket blocking or non-blocking + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ) +{ + return ( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL, 0 ) & ~O_NONBLOCK ) ); +} + +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) +{ + return ( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL, 0 ) | O_NONBLOCK ) ); +} + +/* + * Portable usleep helper + */ +void mbedtls_net_usleep( unsigned long usec ) +{ + struct timeval tv; + tv.tv_sec = usec / 1000000; + tv.tv_usec = usec % 1000000; + select( 0, NULL, NULL, NULL, &tv ); +} + +/* + * Read at most 'len' characters + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) +{ + int ret; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if ( fd < 0 ) { + return ( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + } + + ret = (int) read( fd, buf, len ); + + if ( ret < 0 ) { + if ( net_would_block( ctx ) != 0 ) { + return ( MBEDTLS_ERR_SSL_WANT_READ ); + } + + if ( errno == EPIPE || errno == ECONNRESET ) { + return ( MBEDTLS_ERR_NET_CONN_RESET ); + } + + if ( errno == EINTR ) { + return ( MBEDTLS_ERR_SSL_WANT_READ ); + } + + return ( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + return ( ret ); +} + +/* + * Read at most 'len' characters, blocking for at most 'timeout' ms + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, + uint32_t timeout ) +{ + int ret; + struct timeval tv; + fd_set read_fds; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if ( fd < 0 ) { + return ( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + } + + FD_ZERO( &read_fds ); + FD_SET( fd, &read_fds ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv ); + + /* Zero fds ready means we timed out */ + if ( ret == 0 ) { + return ( MBEDTLS_ERR_SSL_TIMEOUT ); + } + + if ( ret < 0 ) { + if ( errno == EINTR ) { + return ( MBEDTLS_ERR_SSL_WANT_READ ); + } + + return ( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + /* This call will not block */ + return ( mbedtls_net_recv( ctx, buf, len ) ); +} + +/* + * Write at most 'len' characters + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) +{ + int ret; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if ( fd < 0 ) { + return ( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + } + + ret = (int) write( fd, buf, len ); + + if ( ret < 0 ) { + if ( net_would_block( ctx ) != 0 ) { + return ( MBEDTLS_ERR_SSL_WANT_WRITE ); + } + + if ( errno == EPIPE || errno == ECONNRESET ) { + return ( MBEDTLS_ERR_NET_CONN_RESET ); + } + + if ( errno == EINTR ) { + return ( MBEDTLS_ERR_SSL_WANT_WRITE ); + } + + return ( MBEDTLS_ERR_NET_SEND_FAILED ); + } + + return ( ret ); +} + +/* + * Gracefully close the connection + */ +void mbedtls_net_free( mbedtls_net_context *ctx ) +{ + if ( ctx->fd == -1) { + return; + } + + shutdown( ctx->fd, 2); + close(ctx->fd); + + ctx->fd = -1; +} + +#endif /* MBEDTLS_NET_C */ diff --git a/components/mbedtls/mbedtls_v3/port/sha/block/esp_sha1.c b/components/mbedtls/mbedtls_v3/port/sha/block/esp_sha1.c new file mode 100644 index 000000000..1e73fe5d9 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/block/esp_sha1.c @@ -0,0 +1,220 @@ +/* + * SHA-1 implementation with hardware ESP support added. + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include + +#if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_SHA1_ALT) + +#include "mbedtls/sha1.h" + +#include +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#include "sha/sha_block.h" + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) +{ + volatile unsigned char *p = (unsigned char *)v; + while ( n-- ) { + *p++ = 0; + } +} + +/* + * 32-bit integer manipulation macros (big endian) + */ + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) +{ + assert(ctx != NULL); + + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) +{ + if ( ctx == NULL ) { + return; + } + mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ) +{ + memcpy(dst, src, sizeof(mbedtls_sha1_context)); +} + +/* + * SHA-1 context setup + */ +int mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); + ctx->mode = SHA1; + + return 0; +} + +static void esp_internal_sha_update_state(mbedtls_sha1_context *ctx) +{ + if (ctx->sha_state == ESP_SHA1_STATE_INIT) { + ctx->first_block = true; + ctx->sha_state = ESP_SHA1_STATE_IN_PROCESS; + } else if (ctx->sha_state == ESP_SHA1_STATE_IN_PROCESS) { + ctx->first_block = false; + esp_sha_write_digest_state(ctx->mode, ctx->state); + } +} + +static void esp_internal_sha1_block_process(mbedtls_sha1_context *ctx, const uint8_t *data) +{ + esp_sha_block(SHA1, data, ctx->first_block); + + if (ctx->first_block) { + ctx->first_block = false; + } +} + +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) +{ + esp_sha_acquire_hardware(); + esp_internal_sha_update_state(ctx); + esp_sha_block(ctx->mode, data, ctx->first_block); + esp_sha_read_digest_state(ctx->mode, ctx->state); + esp_sha_release_hardware(); + return 0; +} + +int mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + uint32_t left, local_len = 0; + + if ( !ilen || (input == NULL)) { + return 0; + } + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if ( ctx->total[0] < (uint32_t) ilen ) { + ctx->total[1]++; + } + + if ( left && ilen >= fill ) { + memcpy( (void *) (ctx->buffer + left), input, fill ); + input += fill; + ilen -= fill; + left = 0; + local_len = 64; + } + + if ( (ilen >= 64) || local_len) { + + esp_sha_acquire_hardware(); + + esp_internal_sha_update_state(ctx); + + /* First process buffered block, if any */ + if ( local_len ) { + esp_internal_sha1_block_process(ctx, ctx->buffer); + } + + while ( ilen >= 64 ) { + esp_internal_sha1_block_process(ctx, input); + + input += 64; + ilen -= 64; + } + + esp_sha_read_digest_state(SHA1, ctx->state); + + esp_sha_release_hardware(); + + } + + if ( ilen > 0 ) { + memcpy( (void *) (ctx->buffer + left), input, ilen); + } + return 0; +} + +static const unsigned char sha1_padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* +* SHA-1 final digest + */ +int mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ) +{ + int ret = -1; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, msglen, 0 ); + PUT_UINT32_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + + if ( ( ret = mbedtls_sha1_update( ctx, sha1_padding, padn ) ) != 0 ) { + return ret; + } + if ( ( ret = mbedtls_sha1_update( ctx, msglen, 8 ) ) != 0 ) { + return ret; + } + + memcpy(output, ctx->state, 20); + + return ret; +} + +#endif /* MBEDTLS_SHA1_C && MBEDTLS_SHA1_ALT */ diff --git a/components/mbedtls/mbedtls_v3/port/sha/block/esp_sha256.c b/components/mbedtls/mbedtls_v3/port/sha/block/esp_sha256.c new file mode 100644 index 000000000..eb456afda --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/block/esp_sha256.c @@ -0,0 +1,239 @@ +/* + * SHA-256 implementation with hardware ESP support added. + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD + */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include + +#if defined(MBEDTLS_SHA256_C) && defined(MBEDTLS_SHA256_ALT) + +#include "mbedtls/sha256.h" + +#include +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#include "sha/sha_block.h" + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) +{ + volatile unsigned char *p = v; + while ( n-- ) { + *p++ = 0; + } +} + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +do { \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} while( 0 ) +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +do { \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} while( 0 ) +#endif + +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) +{ + assert(ctx != NULL); + + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) +{ + if ( ctx == NULL ) { + return; + } + + mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ) +{ + *dst = *src; +} + +/* + * SHA-256 context setup + */ +int mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) +{ + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); + + if ( is224 ) { + ctx->mode = SHA2_224; + } else { + ctx->mode = SHA2_256; + } + + return 0; +} + +static void esp_internal_sha_update_state(mbedtls_sha256_context *ctx) +{ + if (ctx->sha_state == ESP_SHA256_STATE_INIT) { + ctx->first_block = true; + ctx->sha_state = ESP_SHA256_STATE_IN_PROCESS; + } else if (ctx->sha_state == ESP_SHA256_STATE_IN_PROCESS) { + ctx->first_block = false; + esp_sha_write_digest_state(ctx->mode, ctx->state); + } +} + +static void esp_internal_sha256_block_process(mbedtls_sha256_context *ctx, const uint8_t *data) +{ + esp_sha_block(ctx->mode, data, ctx->first_block); + + if (ctx->first_block) { + ctx->first_block = false; + } +} + +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) +{ + esp_sha_acquire_hardware(); + esp_internal_sha_update_state(ctx); + esp_sha_block(ctx->mode, data, ctx->first_block); + esp_sha_read_digest_state(ctx->mode, ctx->state); + esp_sha_release_hardware(); + return 0; +} + +/* + * SHA-256 process buffer + */ +int mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, + size_t ilen ) +{ + size_t fill; + uint32_t left, local_len = 0; + + if ( ilen == 0 ) { + return 0; + } + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if ( ctx->total[0] < (uint32_t) ilen ) { + ctx->total[1]++; + } + + /* Check if any data pending from previous call to this API */ + if ( left && ilen >= fill ) { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + input += fill; + ilen -= fill; + left = 0; + local_len = 64; + } + + if ( (ilen >= 64) || local_len) { + + esp_sha_acquire_hardware(); + + esp_internal_sha_update_state(ctx); + + /* First process buffered block, if any */ + if ( local_len ) { + esp_internal_sha256_block_process(ctx, ctx->buffer); + } + + while ( ilen >= 64 ) { + esp_internal_sha256_block_process(ctx, input); + + input += 64; + ilen -= 64; + } + esp_sha_read_digest_state(ctx->mode, ctx->state); + + esp_sha_release_hardware(); + + } + + if ( ilen > 0 ) { + memcpy( (void *) (ctx->buffer + left), input, ilen); + } + + return 0; +} + +static const unsigned char sha256_padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-256 final digest + */ +int mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char *output ) +{ + int ret = -1; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, msglen, 0 ); + PUT_UINT32_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + if ( ( ret = mbedtls_sha256_update( ctx, sha256_padding, padn ) ) != 0 ) { + return ret; + } + + if ( ( ret = mbedtls_sha256_update( ctx, msglen, 8 ) ) != 0 ) { + return ret; + } + + memcpy(output, ctx->state, 32); + + return ret; +} + +#endif /* MBEDTLS_SHA256_C && MBEDTLS_SHA256_ALT */ diff --git a/components/mbedtls/mbedtls_v3/port/sha/block/esp_sha512.c b/components/mbedtls/mbedtls_v3/port/sha/block/esp_sha512.c new file mode 100644 index 000000000..c36e01dfa --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/block/esp_sha512.c @@ -0,0 +1,290 @@ +/* + * SHA-512 implementation with hardware ESP support added. + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD + */ +/* + * The SHA-512 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include + +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_SHA512_ALT) + +#include "mbedtls/sha512.h" + +#if defined(_MSC_VER) || defined(__WATCOMC__) +#define UL64(x) x##ui64 +#else +#define UL64(x) x##ULL +#endif + +#include +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#include "sha/sha_block.h" + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) +{ + volatile unsigned char *p = v; + while ( n-- ) { + *p++ = 0; + } +} + +/* + * 64-bit integer manipulation macros (big endian) + */ +#ifndef PUT_UINT64_BE +#define PUT_UINT64_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 7] = (unsigned char) ( (n) ); \ +} +#endif /* PUT_UINT64_BE */ + +void esp_sha512_set_mode(mbedtls_sha512_context *ctx, esp_sha_type type) +{ + switch (type) { + case SHA2_384: + case SHA2_512224: + case SHA2_512256: + case SHA2_512T: + ctx->mode = type; + break; + default: + ctx->mode = SHA2_512; + break; + } +} + + +/* For SHA512/t mode the intial hash value will depend on t */ +void esp_sha512_set_t( mbedtls_sha512_context *ctx, uint16_t t_val) +{ + ctx->t_val = t_val; +} + +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) +{ + assert(ctx != NULL); + + memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) +{ + if ( ctx == NULL ) { + return; + } + + mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ) +{ + memcpy(dst, src, sizeof(mbedtls_sha512_context)); +} + +/* + * SHA-512 context setup + */ +int mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ) +{ + mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); + + if ( is384 ) { + ctx->mode = SHA2_384; + } else { + ctx->mode = SHA2_512; + } + + return 0; +} + +static int esp_internal_sha_update_state(mbedtls_sha512_context *ctx) +{ + if (ctx->sha_state == ESP_SHA512_STATE_INIT) { + if (ctx->mode == SHA2_512T) { + int ret = -1; + if ((ret = esp_sha_512_t_init_hash(ctx->t_val)) != 0) { + return ret; + } + ctx->first_block = false; + } else { + ctx->first_block = true; + } + ctx->sha_state = ESP_SHA512_STATE_IN_PROCESS; + + } else if (ctx->sha_state == ESP_SHA512_STATE_IN_PROCESS) { + ctx->first_block = false; + esp_sha_write_digest_state(ctx->mode, ctx->state); + } + return 0; +} + +static void esp_internal_sha512_block_process(mbedtls_sha512_context *ctx, const uint8_t *data) +{ + esp_sha_block(ctx->mode, data, ctx->first_block); + + if (ctx->first_block) { + ctx->first_block = false; + } +} + +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) +{ + int ret = -1; + esp_sha_acquire_hardware(); + + ret = esp_internal_sha_update_state(ctx); + if (ret != 0) { + esp_sha_release_hardware(); + return ret; + } + + esp_sha_block(ctx->mode, data, ctx->first_block); + esp_sha_read_digest_state(ctx->mode, ctx->state); + esp_sha_release_hardware(); + return ret; +} + +/* + * SHA-512 process buffer + */ +int mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + unsigned int left, len, local_len = 0; + + if ( ilen == 0 ) { + return 0; + } + + left = (unsigned int) (ctx->total[0] & 0x7F); + fill = 128 - left; + + ctx->total[0] += (uint64_t) ilen; + + if ( ctx->total[0] < (uint64_t) ilen ) { + ctx->total[1]++; + } + + if ( left && ilen >= fill ) { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + input += fill; + ilen -= fill; + left = 0; + local_len = 128; + } + + + if ( len || local_len) { + + esp_sha_acquire_hardware(); + + int ret = esp_internal_sha_update_state(ctx); + + if (ret != 0) { + esp_sha_release_hardware(); + return ret; + } + + /* First process buffered block, if any */ + if ( local_len ) { + esp_internal_sha256_block_process(ctx, ctx->buffer); + } + + while ( ilen >= 128 ) { + esp_internal_sha256_block_process(ctx, input); + + input += 64; + ilen -= 64; + } + esp_sha_read_digest_state(ctx->mode, ctx->state); + + esp_sha_release_hardware(); + } + + if ( ilen > 0 ) { + memcpy( (void *) (ctx->buffer + left), input, ilen); + } + + return 0; +} + +static const unsigned char sha512_padding[128] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-512 final digest + */ +int mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char *output ) +{ + int ret = -1; + size_t last, padn; + uint64_t high, low; + unsigned char msglen[16]; + + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT64_BE( high, msglen, 0 ); + PUT_UINT64_BE( low, msglen, 8 ); + + last = (size_t)( ctx->total[0] & 0x7F ); + padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); + + if ( ( ret = mbedtls_sha512_update( ctx, sha512_padding, padn ) ) != 0 ) { + return ret; + } + + if ( ( ret = mbedtls_sha512_update( ctx, msglen, 16 ) ) != 0 ) { + return ret; + } + + if (ctx->mode == SHA2_384) { + memcpy(output, ctx->state, 48); + } else { + memcpy(output, ctx->state, 64); + } + + return ret; +} + +#endif /* MBEDTLS_SHA512_C && MBEDTLS_SHA512_ALT */ diff --git a/components/mbedtls/mbedtls_v3/port/sha/block/sha.c b/components/mbedtls/mbedtls_v3/port/sha/block/sha.c new file mode 100644 index 000000000..9cffe5e89 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/block/sha.c @@ -0,0 +1,73 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +#include "soc/soc_caps.h" +#include "soc/periph_defs.h" +#include "esp_private/periph_ctrl.h" + +#include "sha/sha_block.h" +#include "hal/sha_hal.h" + + +static _lock_t s_sha_lock; + +void esp_sha_write_digest_state(esp_sha_type sha_type, void *digest_state) +{ + sha_hal_write_digest(sha_type, digest_state); +} + +void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state) +{ + sha_hal_read_digest(sha_type, digest_state); +} + +/* Return block size (in bytes) for a given SHA type */ +inline static size_t block_length(esp_sha_type type) +{ + switch (type) { + case SHA1: + case SHA2_224: + case SHA2_256: + return 64; +#if SOC_SHA_SUPPORT_SHA384 + case SHA2_384: +#endif +#if SOC_SHA_SUPPORT_SHA512 + case SHA2_512: +#endif +#if SOC_SHA_SUPPORT_SHA512_T + case SHA2_512224: + case SHA2_512256: + case SHA2_512T: +#endif + return 128; + default: + return 0; + } +} + + +/* Lock the SHA peripheral and then enable it */ +void esp_sha_acquire_hardware() +{ + _lock_acquire(&s_sha_lock); /* Released when releasing hw with esp_sha_release_hardware() */ + periph_module_enable(PERIPH_SHA_MODULE); +} + +/* Disable SHA peripheral block and then release it */ +void esp_sha_release_hardware() +{ + periph_module_disable(PERIPH_SHA_MODULE); + _lock_release(&s_sha_lock); +} + + +void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block) +{ + sha_hal_hash_block(sha_type, data_block, block_length(sha_type) / 4, is_first_block); +} diff --git a/components/mbedtls/mbedtls_v3/port/sha/dma/esp_sha1.c b/components/mbedtls/mbedtls_v3/port/sha/dma/esp_sha1.c new file mode 100644 index 000000000..409a1d1d5 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/dma/esp_sha1.c @@ -0,0 +1,220 @@ +/* + * SHA-1 implementation with hardware ESP support added. + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include + +#if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_SHA1_ALT) + +#include "mbedtls/sha1.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#include "sha/sha_dma.h" + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) +{ + volatile unsigned char *p = (unsigned char *)v; + while ( n-- ) { + *p++ = 0; + } +} + +/* + * 32-bit integer manipulation macros (big endian) + */ + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) +{ + if ( ctx == NULL ) { + return; + } + mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ) +{ + memcpy(dst, src, sizeof(mbedtls_sha1_context)); +} + +/* + * SHA-1 context setup + */ +int mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); + ctx->mode = SHA1; + + return 0; +} + +static void esp_internal_sha_update_state(mbedtls_sha1_context *ctx) +{ + if (ctx->sha_state == ESP_SHA1_STATE_INIT) { + ctx->first_block = true; + ctx->sha_state = ESP_SHA1_STATE_IN_PROCESS; + } else if (ctx->sha_state == ESP_SHA1_STATE_IN_PROCESS) { + ctx->first_block = false; + esp_sha_write_digest_state(ctx->mode, ctx->state); + } +} + +static int esp_internal_sha1_dma_process(mbedtls_sha1_context *ctx, + const uint8_t *data, size_t len, + uint8_t *buf, size_t buf_len) +{ + return esp_sha_dma(SHA1, data, len, buf, buf_len, ctx->first_block); +} + +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) +{ + int ret = -1; + esp_sha_acquire_hardware(); + esp_internal_sha_update_state(ctx); + + ret = esp_sha_dma(ctx->mode, data, 64, 0, 0, ctx->first_block); + if (ret != 0) { + esp_sha_release_hardware(); + return ret; + } + + esp_sha_read_digest_state(ctx->mode, ctx->state); + esp_sha_release_hardware(); + return ret; +} + +int mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + uint32_t left, len, local_len = 0; + + if ( !ilen || (input == NULL)) { + return 0; + } + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if ( ctx->total[0] < (uint32_t) ilen ) { + ctx->total[1]++; + } + + if ( left && ilen >= fill ) { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + input += fill; + ilen -= fill; + left = 0; + local_len = 64; + } + + len = (ilen / 64) * 64; + if ( len || local_len) { + + esp_sha_acquire_hardware(); + + esp_internal_sha_update_state(ctx); + + int ret = esp_internal_sha1_dma_process(ctx, input, len, ctx->buffer, local_len); + if (ret != 0) { + esp_sha_release_hardware(); + return ret; + } + + esp_sha_read_digest_state(SHA1, ctx->state); + + esp_sha_release_hardware(); + + } + + if ( ilen > 0 ) { + memcpy( (void *) (ctx->buffer + left), input + len, ilen - len ); + } + + return 0; +} + +static const unsigned char sha1_padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* +* SHA-1 final digest + */ +int mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ) +{ + int ret = -1; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, msglen, 0 ); + PUT_UINT32_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + + if ( ( ret = mbedtls_sha1_update( ctx, sha1_padding, padn ) ) != 0 ) { + return ret; + } + if ( ( ret = mbedtls_sha1_update( ctx, msglen, 8 ) ) != 0 ) { + return ret; + } + + memcpy(output, ctx->state, 20); + + return ret; +} + +#endif /* MBEDTLS_SHA1_C && MBEDTLS_SHA1_ALT */ diff --git a/components/mbedtls/mbedtls_v3/port/sha/dma/esp_sha256.c b/components/mbedtls/mbedtls_v3/port/sha/dma/esp_sha256.c new file mode 100644 index 000000000..b2d33b04a --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/dma/esp_sha256.c @@ -0,0 +1,230 @@ +/* + * SHA-256 implementation with hardware ESP support added. + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD + */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include + +#if defined(MBEDTLS_SHA256_C) && defined(MBEDTLS_SHA256_ALT) + +#include "mbedtls/sha256.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#include "sha/sha_dma.h" + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) +{ + volatile unsigned char *p = v; + while ( n-- ) { + *p++ = 0; + } +} + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +do { \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} while( 0 ) +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +do { \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} while( 0 ) +#endif + +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) +{ + if ( ctx == NULL ) { + return; + } + + mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ) +{ + *dst = *src; +} + +/* + * SHA-256 context setup + */ +int mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) +{ + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); + + if ( is224 ) { + ctx->mode = SHA2_224; + } else { + ctx->mode = SHA2_256; + } + + return 0; +} + +static void esp_internal_sha_update_state(mbedtls_sha256_context *ctx) +{ + if (ctx->sha_state == ESP_SHA256_STATE_INIT) { + ctx->first_block = true; + ctx->sha_state = ESP_SHA256_STATE_IN_PROCESS; + } else if (ctx->sha_state == ESP_SHA256_STATE_IN_PROCESS) { + ctx->first_block = false; + esp_sha_write_digest_state(ctx->mode, ctx->state); + } +} + +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) +{ + int ret = -1; + esp_sha_acquire_hardware(); + esp_internal_sha_update_state(ctx); + + ret = esp_sha_dma(ctx->mode, data, 64, 0, 0, ctx->first_block); + if (ret != 0) { + esp_sha_release_hardware(); + return ret; + } + + esp_sha_read_digest_state(ctx->mode, ctx->state); + esp_sha_release_hardware(); + + return ret; +} + +/* + * SHA-256 process buffer + */ +int mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, + size_t ilen ) +{ + size_t fill; + uint32_t left, len, local_len = 0; + + if ( ilen == 0 ) { + return 0; + } + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if ( ctx->total[0] < (uint32_t) ilen ) { + ctx->total[1]++; + } + + /* Check if any data pending from previous call to this API */ + if ( left && ilen >= fill ) { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + input += fill; + ilen -= fill; + left = 0; + local_len = 64; + } + + len = (ilen / 64) * 64; + + if ( len || local_len) { + esp_sha_acquire_hardware(); + esp_internal_sha_update_state(ctx); + + int ret = esp_sha_dma(ctx->mode, input, len, ctx->buffer, local_len, ctx->first_block); + + if (ret != 0) { + esp_sha_release_hardware(); + return ret; + } + + esp_sha_read_digest_state(ctx->mode, ctx->state); + + esp_sha_release_hardware(); + } + + if ( ilen > 0 ) { + memcpy( (void *) (ctx->buffer + left), input + len, ilen - len ); + } + + return 0; +} + +static const unsigned char sha256_padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-256 final digest + */ +int mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char *output ) +{ + int ret = -1; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, msglen, 0 ); + PUT_UINT32_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + if ( ( ret = mbedtls_sha256_update( ctx, sha256_padding, padn ) ) != 0 ) { + return ret; + } + + if ( ( ret = mbedtls_sha256_update( ctx, msglen, 8 ) ) != 0 ) { + return ret; + } + + memcpy(output, ctx->state, 32); + + return ret; +} + +#endif /* MBEDTLS_SHA256_C && MBEDTLS_SHA256_ALT */ diff --git a/components/mbedtls/mbedtls_v3/port/sha/dma/esp_sha512.c b/components/mbedtls/mbedtls_v3/port/sha/dma/esp_sha512.c new file mode 100644 index 000000000..4e5bfa003 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/dma/esp_sha512.c @@ -0,0 +1,293 @@ +/* + * SHA-512 implementation with hardware ESP support added. + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD + */ +/* + * The SHA-512 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include + +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_SHA512_ALT) + +#include "mbedtls/sha512.h" + +#if defined(_MSC_VER) || defined(__WATCOMC__) +#define UL64(x) x##ui64 +#else +#define UL64(x) x##ULL +#endif + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#include "sha/sha_dma.h" + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) +{ + volatile unsigned char *p = v; + while ( n-- ) { + *p++ = 0; + } +} + +/* + * 64-bit integer manipulation macros (big endian) + */ +#ifndef PUT_UINT64_BE +#define PUT_UINT64_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 7] = (unsigned char) ( (n) ); \ +} +#endif /* PUT_UINT64_BE */ + +void esp_sha512_set_mode(mbedtls_sha512_context *ctx, esp_sha_type type) +{ + switch (type) { + case SHA2_384: + case SHA2_512224: + case SHA2_512256: + case SHA2_512T: + ctx->mode = type; + break; + default: + ctx->mode = SHA2_512; + break; + } +} + + +/* For SHA512/t mode the intial hash value will depend on t */ +void esp_sha512_set_t( mbedtls_sha512_context *ctx, uint16_t t_val) +{ + ctx->t_val = t_val; +} + +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) +{ + if ( ctx == NULL ) { + return; + } + + mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ) +{ + memcpy(dst, src, sizeof(mbedtls_sha512_context)); +} + +/* + * SHA-512 context setup + */ +int mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ) +{ + mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); + + if ( is384 ) { + ctx->mode = SHA2_384; + } else { + ctx->mode = SHA2_512; + } + + return 0; +} + +static int esp_internal_sha_update_state(mbedtls_sha512_context *ctx) +{ + if (ctx->sha_state == ESP_SHA512_STATE_INIT) { + if (ctx->mode == SHA2_512T) { + int ret = -1; + if ((ret = esp_sha_512_t_init_hash(ctx->t_val)) != 0) { + return ret; + } + ctx->first_block = false; + } else { + ctx->first_block = true; + } + ctx->sha_state = ESP_SHA512_STATE_IN_PROCESS; + } else if (ctx->sha_state == ESP_SHA512_STATE_IN_PROCESS) { + ctx->first_block = false; + esp_sha_write_digest_state(ctx->mode, ctx->state); + } + return 0; +} + +static int esp_internal_sha512_dma_process(mbedtls_sha512_context *ctx, + const uint8_t *data, size_t len, + uint8_t *buf, size_t buf_len) +{ + + + return esp_sha_dma(ctx->mode, data, len, buf, buf_len, ctx->first_block); + + +} + +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) +{ + int ret = -1; + esp_sha_acquire_hardware(); + + ret = esp_internal_sha_update_state(ctx); + if (ret != 0) { + esp_sha_release_hardware(); + return ret; + } + + ret = esp_internal_sha512_dma_process(ctx, data, 128, 0, 0); + if (ret != 0) { + esp_sha_release_hardware(); + return ret; + } + + esp_sha_read_digest_state(ctx->mode, ctx->state); + esp_sha_release_hardware(); + + return ret; + +} + +/* + * SHA-512 process buffer + */ +int mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, + size_t ilen ) +{ + size_t fill; + unsigned int left, len, local_len = 0; + + if ( ilen == 0 ) { + return 0; + } + + left = (unsigned int) (ctx->total[0] & 0x7F); + fill = 128 - left; + + ctx->total[0] += (uint64_t) ilen; + + if ( ctx->total[0] < (uint64_t) ilen ) { + ctx->total[1]++; + } + + if ( left && ilen >= fill ) { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + input += fill; + ilen -= fill; + left = 0; + local_len = 128; + } + + len = (ilen / 128) * 128; + + if ( len || local_len) { + + esp_sha_acquire_hardware(); + + int ret = esp_internal_sha_update_state(ctx); + + if (ret != 0) { + esp_sha_release_hardware(); + return ret; + } + + ret = esp_internal_sha512_dma_process(ctx, input, len, ctx->buffer, local_len); + + if (ret != 0) { + esp_sha_release_hardware(); + return ret; + } + + esp_sha_read_digest_state(ctx->mode, ctx->state); + + esp_sha_release_hardware(); + + } + + + if ( ilen > 0 ) { + memcpy( (void *) (ctx->buffer + left), input + len, ilen - len ); + } + + return 0; +} + +static const unsigned char sha512_padding[128] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-512 final digest + */ +int mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char *output ) +{ + int ret = -1; + size_t last, padn; + uint64_t high, low; + unsigned char msglen[16]; + + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT64_BE( high, msglen, 0 ); + PUT_UINT64_BE( low, msglen, 8 ); + + last = (size_t)( ctx->total[0] & 0x7F ); + padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); + + if ( ( ret = mbedtls_sha512_update( ctx, sha512_padding, padn ) ) != 0 ) { + return ret; + } + + if ( ( ret = mbedtls_sha512_update( ctx, msglen, 16 ) ) != 0 ) { + return ret; + } + + if (ctx->mode == SHA2_384) { + memcpy(output, ctx->state, 48); + } else { + memcpy(output, ctx->state, 64); + } + + return ret; +} + +#endif /* MBEDTLS_SHA512_C && MBEDTLS_SHA512_ALT */ diff --git a/components/mbedtls/mbedtls_v3/port/sha/dma/esp_sha_crypto_dma_impl.c b/components/mbedtls/mbedtls_v3/port/sha/dma/esp_sha_crypto_dma_impl.c new file mode 100644 index 000000000..331751f95 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/dma/esp_sha_crypto_dma_impl.c @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include "esp_sha_dma_priv.h" + +#include "soc/soc_caps.h" +#include "soc/crypto_dma_reg.h" +#include "hal/crypto_dma_ll.h" + + +esp_err_t esp_sha_dma_start(const lldesc_t *input) +{ + crypto_dma_ll_set_mode(CRYPTO_DMA_SHA); + crypto_dma_ll_reset(); + + crypto_dma_ll_outlink_set((intptr_t)input); + crypto_dma_ll_outlink_start(); + + return ESP_OK; +} diff --git a/components/mbedtls/mbedtls_v3/port/sha/dma/esp_sha_gdma_impl.c b/components/mbedtls/mbedtls_v3/port/sha/dma/esp_sha_gdma_impl.c new file mode 100644 index 000000000..bf6528304 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/dma/esp_sha_gdma_impl.c @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_sha_dma_priv.h" +#include "esp_crypto_shared_gdma.h" + +esp_err_t esp_sha_dma_start(const lldesc_t *input) +{ + return esp_crypto_shared_gdma_start(input, NULL, GDMA_TRIG_PERIPH_SHA); +} diff --git a/components/mbedtls/mbedtls_v3/port/sha/dma/include/esp_sha_dma_priv.h b/components/mbedtls/mbedtls_v3/port/sha/dma/include/esp_sha_dma_priv.h new file mode 100644 index 000000000..fdb758fc3 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/dma/include/esp_sha_dma_priv.h @@ -0,0 +1,38 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "soc/lldesc.h" +#include "soc/soc_caps.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Start the DMA engine + * + * @param input SHA input descriptor (outlink) + * @return + * - ESP_OK: Successfully started the DMA + * - ESP_ERR_INVALID_STATE: No DMA channel available + */ +esp_err_t esp_sha_dma_start(const lldesc_t *input); + + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/mbedtls_v3/port/sha/dma/sha.c b/components/mbedtls/mbedtls_v3/port/sha/dma/sha.c new file mode 100644 index 000000000..0e0977168 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/dma/sha.c @@ -0,0 +1,348 @@ +/* + * ESP hardware accelerated SHA1/256/512 implementation + * based on mbedTLS FIPS-197 compliant version. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE Ltd + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include +#include +#include + +#include "esp_log.h" +#include "esp_memory_utils.h" +#include "esp_crypto_lock.h" +#include "esp_attr.h" +#include "soc/lldesc.h" +#include "soc/ext_mem_defs.h" +#include "soc/periph_defs.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +#include "esp_private/periph_ctrl.h" +#include "sys/param.h" + +#include "sha/sha_dma.h" +#include "hal/sha_hal.h" +#include "soc/soc_caps.h" +#include "esp_sha_dma_priv.h" + +#if CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/rom/cache.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/cache.h" +#elif CONFIG_IDF_TARGET_ESP32C3 +#include "esp32s3/rom/cache.h" +#elif CONFIG_IDF_TARGET_ESP32C2 +#include "esp32c2/rom/cache.h" +#endif + +#if SOC_SHA_GDMA +#define SHA_LOCK() esp_crypto_sha_aes_lock_acquire() +#define SHA_RELEASE() esp_crypto_sha_aes_lock_release() +#elif SOC_SHA_CRYPTO_DMA +#define SHA_LOCK() esp_crypto_dma_lock_acquire() +#define SHA_RELEASE() esp_crypto_dma_lock_release() +#endif + +const static char *TAG = "esp-sha"; +static bool s_check_dma_capable(const void *p); + +/* These are static due to: + * * Must be in DMA capable memory, so stack is not a safe place to put them + * * To avoid having to malloc/free them for every DMA operation + */ +static DRAM_ATTR lldesc_t s_dma_descr_input; +static DRAM_ATTR lldesc_t s_dma_descr_buf; + +void esp_sha_write_digest_state(esp_sha_type sha_type, void *digest_state) +{ + sha_hal_write_digest(sha_type, digest_state); +} + +void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state) +{ + sha_hal_read_digest(sha_type, digest_state); +} + +/* Return block size (in bytes) for a given SHA type */ +inline static size_t block_length(esp_sha_type type) +{ + switch (type) { + case SHA1: + case SHA2_224: + case SHA2_256: + return 64; +#if SOC_SHA_SUPPORT_SHA384 + case SHA2_384: +#endif +#if SOC_SHA_SUPPORT_SHA512 + case SHA2_512: +#endif +#if SOC_SHA_SUPPORT_SHA512_T + case SHA2_512224: + case SHA2_512256: + case SHA2_512T: +#endif + return 128; + default: + return 0; + } +} + + +/* Enable SHA peripheral and then lock it */ +void esp_sha_acquire_hardware() +{ + SHA_LOCK(); /* Released when releasing hw with esp_sha_release_hardware() */ + + /* Enable SHA and DMA hardware */ +#if SOC_SHA_CRYPTO_DMA + periph_module_enable(PERIPH_SHA_DMA_MODULE); +#elif SOC_SHA_GDMA + periph_module_enable(PERIPH_SHA_MODULE); +#endif +} + +/* Disable SHA peripheral block and then release it */ +void esp_sha_release_hardware() +{ + /* Disable SHA and DMA hardware */ +#if SOC_SHA_CRYPTO_DMA + periph_module_disable(PERIPH_SHA_DMA_MODULE); +#elif SOC_SHA_GDMA + periph_module_disable(PERIPH_SHA_MODULE); +#endif + + SHA_RELEASE(); +} + +#if SOC_SHA_SUPPORT_SHA512_T +/* The initial hash value for SHA512/t is generated according to the + algorithm described in the TRM, chapter SHA-Accelerator +*/ +int esp_sha_512_t_init_hash(uint16_t t) +{ + uint32_t t_string = 0; + uint8_t t0, t1, t2, t_len; + + if (t == 384) { + ESP_LOGE(TAG, "Invalid t for SHA512/t, t = %u,cannot be 384", t); + return -1; + } + + if (t <= 9) { + t_string = (uint32_t)((1 << 23) | ((0x30 + t) << 24)); + t_len = 0x48; + } else if (t <= 99) { + t0 = t % 10; + t1 = (t / 10) % 10; + t_string = (uint32_t)((1 << 15) | ((0x30 + t0) << 16) | + (((0x30 + t1) << 24))); + t_len = 0x50; + } else if (t <= 512) { + t0 = t % 10; + t1 = (t / 10) % 10; + t2 = t / 100; + t_string = (uint32_t)((1 << 7) | ((0x30 + t0) << 8) | + (((0x30 + t1) << 16) + ((0x30 + t2) << 24))); + t_len = 0x58; + } else { + ESP_LOGE(TAG, "Invalid t for SHA512/t, t = %u, must equal or less than 512", t); + return -1; + } + + sha_hal_sha512_init_hash(t_string, t_len); + + return 0; +} + +#endif //SOC_SHA_SUPPORT_SHA512_T + + +/* Hash the input block by block, using non-DMA mode */ +static void esp_sha_block_mode(esp_sha_type sha_type, const uint8_t *input, uint32_t ilen, + const uint8_t *buf, uint32_t buf_len, bool is_first_block) +{ + size_t blk_len = 0; + size_t blk_word_len = 0; + int num_block = 0; + + blk_len = block_length(sha_type); + blk_word_len = blk_len / 4; + num_block = ilen / blk_len; + + if (buf_len != 0) { + sha_hal_hash_block(sha_type, buf, blk_word_len, is_first_block); + is_first_block = false; + } + + for (int i = 0; i < num_block; i++) { + sha_hal_hash_block(sha_type, input + blk_len * i, blk_word_len, is_first_block); + is_first_block = false; + } +} + + + +static int esp_sha_dma_process(esp_sha_type sha_type, const void *input, uint32_t ilen, + const void *buf, uint32_t buf_len, bool is_first_block); + +/* Performs SHA on multiple blocks at a time using DMA + splits up into smaller operations for inputs that exceed a single DMA list + */ +int esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen, + const void *buf, uint32_t buf_len, bool is_first_block) +{ + int ret = 0; + unsigned char *dma_cap_buf = NULL; + + if (buf_len > block_length(sha_type)) { + ESP_LOGE(TAG, "SHA DMA buf_len cannot exceed max size for a single block"); + return -1; + } + + /* DMA cannot access memory in flash, hash block by block instead of using DMA */ + if (!s_check_dma_capable(input) && (ilen != 0)) { + esp_sha_block_mode(sha_type, input, ilen, buf, buf_len, is_first_block); + return 0; + } + +#if (CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE) + if (esp_ptr_external_ram(input)) { + Cache_WriteBack_Addr((uint32_t)input, ilen); + } + if (esp_ptr_external_ram(buf)) { + Cache_WriteBack_Addr((uint32_t)buf, buf_len); + } +#endif + + /* Copy to internal buf if buf is in non DMA capable memory */ + if (!s_check_dma_capable(buf) && (buf_len != 0)) { + dma_cap_buf = heap_caps_malloc(sizeof(unsigned char) * buf_len, MALLOC_CAP_8BIT|MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL); + if (dma_cap_buf == NULL) { + ESP_LOGE(TAG, "Failed to allocate buf memory"); + ret = -1; + goto cleanup; + } + memcpy(dma_cap_buf, buf, buf_len); + buf = dma_cap_buf; + } + + uint32_t dma_op_num; + + if (ilen > 0) { + /* Number of DMA operations based on maximum chunk size in single operation */ + dma_op_num = (ilen + SOC_SHA_DMA_MAX_BUFFER_SIZE - 1) / SOC_SHA_DMA_MAX_BUFFER_SIZE; + } else { + /* For zero input length, we must allow at-least 1 DMA operation to see + * if there is any pending data that is yet to be copied out */ + dma_op_num = 1; + } + + /* The max amount of blocks in a single hardware operation is 2^6 - 1 = 63 + Thus we only do a single DMA input list + dma buf list, + which is max 3968/64 + 64/64 = 63 blocks */ + for (int i = 0; i < dma_op_num; i++) { + + int dma_chunk_len = MIN(ilen, SOC_SHA_DMA_MAX_BUFFER_SIZE); + + ret = esp_sha_dma_process(sha_type, input, dma_chunk_len, buf, buf_len, is_first_block); + + if (ret != 0) { + goto cleanup; + } + + ilen -= dma_chunk_len; + input = (uint8_t *)input + dma_chunk_len; + + // Only append buf to the first operation + buf_len = 0; + is_first_block = false; + } + +cleanup: + free(dma_cap_buf); + return ret; +} + + +/* Performs SHA on multiple blocks at a time */ +static esp_err_t esp_sha_dma_process(esp_sha_type sha_type, const void *input, uint32_t ilen, + const void *buf, uint32_t buf_len, bool is_first_block) +{ + int ret = 0; + lldesc_t *dma_descr_head; + size_t num_blks = (ilen + buf_len) / block_length(sha_type); + + memset(&s_dma_descr_input, 0, sizeof(lldesc_t)); + memset(&s_dma_descr_buf, 0, sizeof(lldesc_t)); + + /* DMA descriptor for Memory to DMA-SHA transfer */ + if (ilen) { + s_dma_descr_input.length = ilen; + s_dma_descr_input.size = ilen; + s_dma_descr_input.owner = 1; + s_dma_descr_input.eof = 1; + s_dma_descr_input.buf = (uint8_t *)input; + dma_descr_head = &s_dma_descr_input; + } + /* Check after input to overide head if there is any buf*/ + if (buf_len) { + s_dma_descr_buf.length = buf_len; + s_dma_descr_buf.size = buf_len; + s_dma_descr_buf.owner = 1; + s_dma_descr_buf.eof = 1; + s_dma_descr_buf.buf = (uint8_t *)buf; + dma_descr_head = &s_dma_descr_buf; + } + + /* Link DMA lists */ + if (buf_len && ilen) { + s_dma_descr_buf.eof = 0; + s_dma_descr_buf.empty = (uint32_t)(&s_dma_descr_input); + } + + if (esp_sha_dma_start(dma_descr_head) != ESP_OK) { + ESP_LOGE(TAG, "esp_sha_dma_start failed, no DMA channel available"); + return -1; + } + + sha_hal_hash_dma(sha_type, num_blks, is_first_block); + + sha_hal_wait_idle(); + + return ret; +} + +static bool s_check_dma_capable(const void *p) +{ + bool is_capable = false; +#if CONFIG_SPIRAM + is_capable |= esp_ptr_dma_ext_capable(p); +#endif + is_capable |= esp_ptr_dma_capable(p); + + return is_capable; +} diff --git a/components/mbedtls/mbedtls_v3/port/sha/esp_sha.c b/components/mbedtls/mbedtls_v3/port/sha/esp_sha.c new file mode 100644 index 000000000..4648e4afc --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/esp_sha.c @@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "hal/sha_types.h" +#include "soc/soc_caps.h" +#include "esp_log.h" + +#include +#include +#include + +#if SOC_SHA_SUPPORT_PARALLEL_ENG +#include "sha/sha_parallel_engine.h" +#elif SOC_SHA_SUPPORT_DMA +#include "sha/sha_dma.h" +#else +#include "sha/sha_block.h" +#endif + +static const char *TAG = "esp_sha"; + +void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output) +{ + union { +#if SOC_SHA_SUPPORT_SHA1 + mbedtls_sha1_context sha1; +#endif +#if SOC_SHA_SUPPORT_SHA256 + mbedtls_sha256_context sha256; +#endif +#if SOC_SHA_SUPPORT_SHA384 || SOC_SHA_SUPPORT_SHA512 + mbedtls_sha512_context sha512; +#endif + } ctx; + + int ret __attribute__((unused)); + assert(input != NULL && output != NULL); + +#if SOC_SHA_SUPPORT_SHA1 + if (sha_type == SHA1) { + mbedtls_sha1_init(&ctx.sha1); + mbedtls_sha1_starts(&ctx.sha1); + ret = mbedtls_sha1_update(&ctx.sha1, input, ilen); + assert(ret == 0); + ret = mbedtls_sha1_finish(&ctx.sha1, output); + assert(ret == 0); + mbedtls_sha1_free(&ctx.sha1); + return; + } +#endif //SOC_SHA_SUPPORT_SHA1 + +#if SOC_SHA_SUPPORT_SHA256 + if (sha_type == SHA2_256) { + mbedtls_sha256_init(&ctx.sha256); + mbedtls_sha256_starts(&ctx.sha256, 0); + ret = mbedtls_sha256_update(&ctx.sha256, input, ilen); + assert(ret == 0); + ret = mbedtls_sha256_finish(&ctx.sha256, output); + assert(ret == 0); + mbedtls_sha256_free(&ctx.sha256); + return; + } +#endif //SOC_SHA_SUPPORT_SHA256 + +#if SOC_SHA_SUPPORT_SHA384 + if (sha_type == SHA2_384) { + mbedtls_sha512_init(&ctx.sha512); + mbedtls_sha512_starts(&ctx.sha512, 1); + ret = mbedtls_sha512_update(&ctx.sha512, input, ilen); + assert(ret == 0); + ret = mbedtls_sha512_finish(&ctx.sha512, output); + assert(ret == 0); + mbedtls_sha512_free(&ctx.sha512); + return; + } +#endif //SOC_SHA_SUPPORT_SHA384 + +#if SOC_SHA_SUPPORT_SHA512 + if (sha_type == SHA2_512) { + mbedtls_sha512_init(&ctx.sha512); + mbedtls_sha512_starts(&ctx.sha512, 0); + ret = mbedtls_sha512_update(&ctx.sha512, input, ilen); + assert(ret == 0); + ret = mbedtls_sha512_finish(&ctx.sha512, output); + assert(ret == 0); + mbedtls_sha512_free(&ctx.sha512); + return; + } +#endif //SOC_SHA_SUPPORT_SHA512 + + ESP_LOGE(TAG, "SHA type %d not supported", (int)sha_type); + abort(); +} diff --git a/components/mbedtls/mbedtls_v3/port/sha/parallel_engine/esp_sha1.c b/components/mbedtls/mbedtls_v3/port/sha/parallel_engine/esp_sha1.c new file mode 100644 index 000000000..9790a7273 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/parallel_engine/esp_sha1.c @@ -0,0 +1,423 @@ +/* + * SHA-1 implementation with hardware ESP32 support added. + * Uses mbedTLS software implementation for failover when concurrent + * SHA operations are in use. + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include + +#if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_SHA1_ALT) + +#include "mbedtls/sha1.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#include "sha/sha_parallel_engine.h" + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) +{ + volatile unsigned char *p = (unsigned char *)v; + while ( n-- ) { + *p++ = 0; + } +} + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) +{ + if ( ctx == NULL ) { + return; + } + + if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) { + esp_sha_unlock_engine(SHA1); + } + mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ) +{ + *dst = *src; + + if (src->mode == ESP_MBEDTLS_SHA1_HARDWARE) { + /* Copy hardware digest state out to cloned state, + which will be a software digest. + */ + esp_sha_read_digest_state(SHA1, dst->state); + dst->mode = ESP_MBEDTLS_SHA1_SOFTWARE; + } +} + + +/* + * SHA-1 context setup + */ +int mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) { + esp_sha_unlock_engine(SHA1); + } + ctx->mode = ESP_MBEDTLS_SHA1_UNUSED; + + return 0; +} + + +static void mbedtls_sha1_software_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) +{ + uint32_t temp, W[16], A, B, C, D, E; + + GET_UINT32_BE( W[ 0], data, 0 ); + GET_UINT32_BE( W[ 1], data, 4 ); + GET_UINT32_BE( W[ 2], data, 8 ); + GET_UINT32_BE( W[ 3], data, 12 ); + GET_UINT32_BE( W[ 4], data, 16 ); + GET_UINT32_BE( W[ 5], data, 20 ); + GET_UINT32_BE( W[ 6], data, 24 ); + GET_UINT32_BE( W[ 7], data, 28 ); + GET_UINT32_BE( W[ 8], data, 32 ); + GET_UINT32_BE( W[ 9], data, 36 ); + GET_UINT32_BE( W[10], data, 40 ); + GET_UINT32_BE( W[11], data, 44 ); + GET_UINT32_BE( W[12], data, 48 ); + GET_UINT32_BE( W[13], data, 52 ); + GET_UINT32_BE( W[14], data, 56 ); + GET_UINT32_BE( W[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define R(t) \ +( \ + temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \ + W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \ + ( W[t & 0x0F] = S(temp,1) ) \ +) + +#define P(a,b,c,d,e,x) \ +{ \ + e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P( A, B, C, D, E, W[0] ); + P( E, A, B, C, D, W[1] ); + P( D, E, A, B, C, W[2] ); + P( C, D, E, A, B, W[3] ); + P( B, C, D, E, A, W[4] ); + P( A, B, C, D, E, W[5] ); + P( E, A, B, C, D, W[6] ); + P( D, E, A, B, C, W[7] ); + P( C, D, E, A, B, W[8] ); + P( B, C, D, E, A, W[9] ); + P( A, B, C, D, E, W[10] ); + P( E, A, B, C, D, W[11] ); + P( D, E, A, B, C, W[12] ); + P( C, D, E, A, B, W[13] ); + P( B, C, D, E, A, W[14] ); + P( A, B, C, D, E, W[15] ); + P( E, A, B, C, D, R(16) ); + P( D, E, A, B, C, R(17) ); + P( C, D, E, A, B, R(18) ); + P( B, C, D, E, A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P( A, B, C, D, E, R(20) ); + P( E, A, B, C, D, R(21) ); + P( D, E, A, B, C, R(22) ); + P( C, D, E, A, B, R(23) ); + P( B, C, D, E, A, R(24) ); + P( A, B, C, D, E, R(25) ); + P( E, A, B, C, D, R(26) ); + P( D, E, A, B, C, R(27) ); + P( C, D, E, A, B, R(28) ); + P( B, C, D, E, A, R(29) ); + P( A, B, C, D, E, R(30) ); + P( E, A, B, C, D, R(31) ); + P( D, E, A, B, C, R(32) ); + P( C, D, E, A, B, R(33) ); + P( B, C, D, E, A, R(34) ); + P( A, B, C, D, E, R(35) ); + P( E, A, B, C, D, R(36) ); + P( D, E, A, B, C, R(37) ); + P( C, D, E, A, B, R(38) ); + P( B, C, D, E, A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P( A, B, C, D, E, R(40) ); + P( E, A, B, C, D, R(41) ); + P( D, E, A, B, C, R(42) ); + P( C, D, E, A, B, R(43) ); + P( B, C, D, E, A, R(44) ); + P( A, B, C, D, E, R(45) ); + P( E, A, B, C, D, R(46) ); + P( D, E, A, B, C, R(47) ); + P( C, D, E, A, B, R(48) ); + P( B, C, D, E, A, R(49) ); + P( A, B, C, D, E, R(50) ); + P( E, A, B, C, D, R(51) ); + P( D, E, A, B, C, R(52) ); + P( C, D, E, A, B, R(53) ); + P( B, C, D, E, A, R(54) ); + P( A, B, C, D, E, R(55) ); + P( E, A, B, C, D, R(56) ); + P( D, E, A, B, C, R(57) ); + P( C, D, E, A, B, R(58) ); + P( B, C, D, E, A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P( A, B, C, D, E, R(60) ); + P( E, A, B, C, D, R(61) ); + P( D, E, A, B, C, R(62) ); + P( C, D, E, A, B, R(63) ); + P( B, C, D, E, A, R(64) ); + P( A, B, C, D, E, R(65) ); + P( E, A, B, C, D, R(66) ); + P( D, E, A, B, C, R(67) ); + P( C, D, E, A, B, R(68) ); + P( B, C, D, E, A, R(69) ); + P( A, B, C, D, E, R(70) ); + P( E, A, B, C, D, R(71) ); + P( D, E, A, B, C, R(72) ); + P( C, D, E, A, B, R(73) ); + P( B, C, D, E, A, R(74) ); + P( A, B, C, D, E, R(75) ); + P( E, A, B, C, D, R(76) ); + P( D, E, A, B, C, R(77) ); + P( C, D, E, A, B, R(78) ); + P( B, C, D, E, A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} + + +static int esp_internal_sha1_parallel_engine_process( mbedtls_sha1_context *ctx, const unsigned char data[64], bool read_digest ) +{ + bool first_block = false; + + if (ctx->mode == ESP_MBEDTLS_SHA1_UNUSED) { + /* try to use hardware for this digest */ + if (esp_sha_try_lock_engine(SHA1)) { + ctx->mode = ESP_MBEDTLS_SHA1_HARDWARE; + first_block = true; + } else { + ctx->mode = ESP_MBEDTLS_SHA1_SOFTWARE; + } + } + + if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) { + esp_sha_block(SHA1, data, first_block); + if (read_digest) { + esp_sha_read_digest_state(SHA1, ctx->state); + } + } else { + mbedtls_sha1_software_process(ctx, data); + } + + return 0; +} + + +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) +{ + return esp_internal_sha1_parallel_engine_process(ctx, data, true); +} + + +/* + * SHA-1 process buffer + */ +int mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ) +{ + int ret = -1; + size_t fill; + uint32_t left; + + if ( ilen == 0 ) { + return 0; + } + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if ( ctx->total[0] < (uint32_t) ilen ) { + ctx->total[1]++; + } + + if ( left && ilen >= fill ) { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if ( ( ret = esp_internal_sha1_parallel_engine_process( ctx, ctx->buffer, false ) ) != 0 ) { + return ret; + } + + input += fill; + ilen -= fill; + left = 0; + } + + while ( ilen >= 64 ) { + if ( ( ret = esp_internal_sha1_parallel_engine_process( ctx, input, false ) ) != 0 ) { + return ret; + } + + input += 64; + ilen -= 64; + } + + if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) { + esp_sha_read_digest_state(SHA1, ctx->state); + } + + if ( ilen > 0 ) { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return 0; +} + +static const unsigned char sha1_padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* +* SHA-1 final digest + */ +int mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ) +{ + int ret = -1; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, msglen, 0 ); + PUT_UINT32_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + if ( ( ret = mbedtls_sha1_update( ctx, sha1_padding, padn ) ) != 0 ) { + goto out; + } + if ( ( ret = mbedtls_sha1_update( ctx, msglen, 8 ) ) != 0 ) { + goto out; + } + + /* if state is in hardware, read it out */ + if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) { + esp_sha_read_digest_state(SHA1, ctx->state); + } + + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); + +out: + if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) { + esp_sha_unlock_engine(SHA1); + ctx->mode = ESP_MBEDTLS_SHA1_SOFTWARE; + } + + return ret; +} + +#endif /* MBEDTLS_SHA1_C && MBEDTLS_SHA1_ALT */ diff --git a/components/mbedtls/mbedtls_v3/port/sha/parallel_engine/esp_sha256.c b/components/mbedtls/mbedtls_v3/port/sha/parallel_engine/esp_sha256.c new file mode 100644 index 000000000..10f6f22fe --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/parallel_engine/esp_sha256.c @@ -0,0 +1,390 @@ +/* + * SHA-256 implementation with hardware ESP32 support added. + * Uses mbedTLS software implementation for failover when concurrent + * SHA operations are in use. + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD + */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include + +#if defined(MBEDTLS_SHA256_C) && defined(MBEDTLS_SHA256_ALT) + +#include "mbedtls/sha256.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#include "sha/sha_parallel_engine.h" + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) +{ + volatile unsigned char *p = v; + while ( n-- ) { + *p++ = 0; + } +} + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +do { \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} while( 0 ) +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +do { \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} while( 0 ) +#endif + +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) +{ + if ( ctx == NULL ) { + return; + } + + if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) { + esp_sha_unlock_engine(SHA2_256); + } + mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ) +{ + *dst = *src; + + if (src->mode == ESP_MBEDTLS_SHA256_HARDWARE) { + /* Copy hardware digest state out to cloned state, + which will become a software digest. + */ + esp_sha_read_digest_state(SHA2_256, dst->state); + dst->mode = ESP_MBEDTLS_SHA256_SOFTWARE; + } +} + +/* + * SHA-256 context setup + */ +int mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + if ( is224 == 0 ) { + /* SHA-256 */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; + } else { + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; + } + + ctx->is224 = is224; + if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) { + esp_sha_unlock_engine(SHA2_256); + } + ctx->mode = ESP_MBEDTLS_SHA256_UNUSED; + return 0; +} + +static const uint32_t K[] = { + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, +}; + +#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) +#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) + +#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) + +#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) + +#define F0(x,y,z) ((x & y) | (z & (x | y))) +#define F1(x,y,z) (z ^ (x & (y ^ z))) + +#define R(t) \ +( \ + W[t] = S1(W[t - 2]) + W[t - 7] + \ + S0(W[t - 15]) + W[t - 16] \ +) + +#define P(a,b,c,d,e,f,g,h,x,K) \ +{ \ + temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + temp2 = S2(a) + F0(a,b,c); \ + d += temp1; h = temp1 + temp2; \ +} + + +static void mbedtls_sha256_software_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) +{ + uint32_t temp1, temp2, W[64]; + uint32_t A[8]; + unsigned int i; + + for ( i = 0; i < 8; i++ ) { + A[i] = ctx->state[i]; + } + +#if defined(MBEDTLS_SHA256_SMALLER) + for ( i = 0; i < 64; i++ ) { + if ( i < 16 ) { + GET_UINT32_BE( W[i], data, 4 * i ); + } else { + R( i ); + } + + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); + + temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3]; + A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1; + } +#else /* MBEDTLS_SHA256_SMALLER */ + for ( i = 0; i < 16; i++ ) { + GET_UINT32_BE( W[i], data, 4 * i ); + } + + for ( i = 0; i < 16; i += 8 ) { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i + 0], K[i + 0] ); + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i + 1], K[i + 1] ); + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i + 2], K[i + 2] ); + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i + 3], K[i + 3] ); + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i + 4], K[i + 4] ); + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i + 5], K[i + 5] ); + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i + 6], K[i + 6] ); + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i + 7], K[i + 7] ); + } + + for ( i = 16; i < 64; i += 8 ) { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i + 0), K[i + 0] ); + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i + 1), K[i + 1] ); + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i + 2), K[i + 2] ); + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i + 3), K[i + 3] ); + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i + 4), K[i + 4] ); + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i + 5), K[i + 5] ); + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i + 6), K[i + 6] ); + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i + 7), K[i + 7] ); + } +#endif /* MBEDTLS_SHA256_SMALLER */ + + for ( i = 0; i < 8; i++ ) { + ctx->state[i] += A[i]; + } +} + + +static int esp_internal_sha256_parallel_engine_process( mbedtls_sha256_context *ctx, const unsigned char data[64], bool read_digest ) +{ + bool first_block = false; + + if (ctx->mode == ESP_MBEDTLS_SHA256_UNUSED) { + /* try to use hardware for this digest */ + if (!ctx->is224 && esp_sha_try_lock_engine(SHA2_256)) { + ctx->mode = ESP_MBEDTLS_SHA256_HARDWARE; + first_block = true; + } else { + ctx->mode = ESP_MBEDTLS_SHA256_SOFTWARE; + } + } + + if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) { + esp_sha_block(SHA2_256, data, first_block); + if (read_digest) { + esp_sha_read_digest_state(SHA2_256, ctx->state); + } + } else { + mbedtls_sha256_software_process(ctx, data); + } + + return 0; +} + + +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) +{ + return esp_internal_sha256_parallel_engine_process(ctx, data, true); +} + + +/* + * SHA-256 process buffer + */ +int mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, + size_t ilen ) +{ + int ret = -1; + size_t fill; + uint32_t left; + + if ( ilen == 0 ) { + return 0; + } + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if ( ctx->total[0] < (uint32_t) ilen ) { + ctx->total[1]++; + } + + if ( left && ilen >= fill ) { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if ( ( ret = esp_internal_sha256_parallel_engine_process( ctx, ctx->buffer, false ) ) != 0 ) { + return ret; + } + + input += fill; + ilen -= fill; + left = 0; + } + + while ( ilen >= 64 ) { + if ( ( ret = esp_internal_sha256_parallel_engine_process( ctx, input, false ) ) != 0 ) { + return ret; + } + + input += 64; + ilen -= 64; + } + + if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) { + esp_sha_read_digest_state(SHA2_256, ctx->state); + } + + if ( ilen > 0 ) { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return 0; +} + +static const unsigned char sha256_padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-256 final digest + */ +int mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char *output ) +{ + int ret = -1; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, msglen, 0 ); + PUT_UINT32_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + if ( ( ret = mbedtls_sha256_update( ctx, sha256_padding, padn ) ) != 0 ) { + goto out; + } + + if ( ( ret = mbedtls_sha256_update( ctx, msglen, 8 ) ) != 0 ) { + goto out; + } + + /* if state is in hardware, read it out */ + if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) { + esp_sha_read_digest_state(SHA2_256, ctx->state); + } + + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); + PUT_UINT32_BE( ctx->state[5], output, 20 ); + PUT_UINT32_BE( ctx->state[6], output, 24 ); + + if ( ctx->is224 == 0 ) { + PUT_UINT32_BE( ctx->state[7], output, 28 ); + } + +out: + if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) { + esp_sha_unlock_engine(SHA2_256); + ctx->mode = ESP_MBEDTLS_SHA256_SOFTWARE; + } + + return ret; +} + +#endif /* MBEDTLS_SHA256_C && MBEDTLS_SHA256_ALT */ diff --git a/components/mbedtls/mbedtls_v3/port/sha/parallel_engine/esp_sha512.c b/components/mbedtls/mbedtls_v3/port/sha/parallel_engine/esp_sha512.c new file mode 100644 index 000000000..b305cdf16 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/parallel_engine/esp_sha512.c @@ -0,0 +1,428 @@ +/* + * SHA-512 implementation with hardware ESP32 support added. + * Uses mbedTLS software implementation for failover when concurrent + * SHA operations are in use. + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD + */ +/* + * The SHA-512 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include + +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_SHA512_ALT) + +#include "mbedtls/sha512.h" + +#if defined(_MSC_VER) || defined(__WATCOMC__) +#define UL64(x) x##ui64 +#else +#define UL64(x) x##ULL +#endif + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#include "sha/sha_parallel_engine.h" + +inline static esp_sha_type sha_type(const mbedtls_sha512_context *ctx) +{ + return ctx->is384 ? SHA2_384 : SHA2_512; +} + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) +{ + volatile unsigned char *p = v; + while ( n-- ) { + *p++ = 0; + } +} + +/* + * 64-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT64_BE +#define GET_UINT64_BE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) ] << 56 ) \ + | ( (uint64_t) (b)[(i) + 1] << 48 ) \ + | ( (uint64_t) (b)[(i) + 2] << 40 ) \ + | ( (uint64_t) (b)[(i) + 3] << 32 ) \ + | ( (uint64_t) (b)[(i) + 4] << 24 ) \ + | ( (uint64_t) (b)[(i) + 5] << 16 ) \ + | ( (uint64_t) (b)[(i) + 6] << 8 ) \ + | ( (uint64_t) (b)[(i) + 7] ); \ +} +#endif /* GET_UINT64_BE */ + +#ifndef PUT_UINT64_BE +#define PUT_UINT64_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 7] = (unsigned char) ( (n) ); \ +} +#endif /* PUT_UINT64_BE */ + +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) +{ + if ( ctx == NULL ) { + return; + } + + if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) { + esp_sha_unlock_engine(sha_type(ctx)); + } + mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ) +{ + *dst = *src; + + if (src->mode == ESP_MBEDTLS_SHA512_HARDWARE) { + /* Copy hardware digest state out to cloned state, + which will be a software digest. + + Always read 512 bits of state, even for SHA-384 + (SHA-384 state is identical to SHA-512, only + digest is truncated.) + */ + esp_sha_read_digest_state(SHA2_512, dst->state); + dst->mode = ESP_MBEDTLS_SHA512_SOFTWARE; + } +} + + +/* + * SHA-512 context setup + */ +int mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + if ( is384 == 0 ) { + /* SHA-512 */ + ctx->state[0] = UL64(0x6A09E667F3BCC908); + ctx->state[1] = UL64(0xBB67AE8584CAA73B); + ctx->state[2] = UL64(0x3C6EF372FE94F82B); + ctx->state[3] = UL64(0xA54FF53A5F1D36F1); + ctx->state[4] = UL64(0x510E527FADE682D1); + ctx->state[5] = UL64(0x9B05688C2B3E6C1F); + ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); + ctx->state[7] = UL64(0x5BE0CD19137E2179); + } else { + /* SHA-384 */ + ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); + ctx->state[1] = UL64(0x629A292A367CD507); + ctx->state[2] = UL64(0x9159015A3070DD17); + ctx->state[3] = UL64(0x152FECD8F70E5939); + ctx->state[4] = UL64(0x67332667FFC00B31); + ctx->state[5] = UL64(0x8EB44A8768581511); + ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); + ctx->state[7] = UL64(0x47B5481DBEFA4FA4); + } + + ctx->is384 = is384; + if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) { + esp_sha_unlock_engine(sha_type(ctx)); + } + ctx->mode = ESP_MBEDTLS_SHA512_UNUSED; + + return 0; +} + +/* + * Round constants + */ +static const uint64_t K[80] = { + UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), + UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), + UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), + UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), + UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), + UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), + UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), + UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), + UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), + UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), + UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), + UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), + UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), + UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), + UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), + UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), + UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), + UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), + UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), + UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), + UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), + UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), + UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), + UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), + UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), + UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), + UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), + UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), + UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), + UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), + UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), + UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), + UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), + UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), + UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), + UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), + UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), + UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), + UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), + UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) +}; + + +static void mbedtls_sha512_software_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) +{ + int i; + uint64_t temp1, temp2, W[80]; + uint64_t A, B, C, D, E, F, G, H; + +#define SHR(x,n) (x >> n) +#define ROTR(x,n) (SHR(x,n) | (x << (64 - n))) + +#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) +#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) + +#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) +#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) + +#define F0(x,y,z) ((x & y) | (z & (x | y))) +#define F1(x,y,z) (z ^ (x & (y ^ z))) + +#define P(a,b,c,d,e,f,g,h,x,K) \ +{ \ + temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + temp2 = S2(a) + F0(a,b,c); \ + d += temp1; h = temp1 + temp2; \ +} + + for ( i = 0; i < 16; i++ ) { + GET_UINT64_BE( W[i], data, i << 3 ); + } + + for ( ; i < 80; i++ ) { + W[i] = S1(W[i - 2]) + W[i - 7] + + S0(W[i - 15]) + W[i - 16]; + } + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + F = ctx->state[5]; + G = ctx->state[6]; + H = ctx->state[7]; + i = 0; + + do { + P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++; + P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++; + P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++; + P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++; + P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++; + P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++; + P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++; + P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++; + } while ( i < 80 ); + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + ctx->state[5] += F; + ctx->state[6] += G; + ctx->state[7] += H; +} + + +static int esp_internal_sha512_parallel_engine_process( mbedtls_sha512_context *ctx, const unsigned char data[128], bool read_digest ) +{ + bool first_block = false; + + if (ctx->mode == ESP_MBEDTLS_SHA512_UNUSED) { + /* try to use hardware for this digest */ + if (esp_sha_try_lock_engine(sha_type(ctx))) { + ctx->mode = ESP_MBEDTLS_SHA512_HARDWARE; + first_block = true; + } else { + ctx->mode = ESP_MBEDTLS_SHA512_SOFTWARE; + } + } + + if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) { + esp_sha_block(sha_type(ctx), data, first_block); + if (read_digest) { + esp_sha_read_digest_state(sha_type(ctx), ctx->state); + } + } else { + mbedtls_sha512_software_process(ctx, data); + } + + return 0; +} + + +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) +{ + return esp_internal_sha512_parallel_engine_process(ctx, data, true); +} + + +/* + * SHA-512 process buffer + */ +int mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, + size_t ilen ) +{ + int ret = -1; + size_t fill; + unsigned int left; + + if ( ilen == 0 ) { + return 0; + } + + left = (unsigned int) (ctx->total[0] & 0x7F); + fill = 128 - left; + + ctx->total[0] += (uint64_t) ilen; + + if ( ctx->total[0] < (uint64_t) ilen ) { + ctx->total[1]++; + } + + if ( left && ilen >= fill ) { + memcpy( (void *) (ctx->buffer + left), input, fill ); + if ( ( ret = esp_internal_sha512_parallel_engine_process( ctx, ctx->buffer, false ) ) != 0 ) { + return ret; + } + + input += fill; + ilen -= fill; + left = 0; + } + + while ( ilen >= 128 ) { + if ( ( ret = esp_internal_sha512_parallel_engine_process( ctx, input, false ) ) != 0 ) { + return ret; + } + + input += 128; + ilen -= 128; + } + + if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) { + esp_sha_read_digest_state(sha_type(ctx), ctx->state); + } + + if ( ilen > 0 ) { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return 0; +} + +static const unsigned char sha512_padding[128] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-512 final digest + */ +int mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char *output ) +{ + int ret = -1; + size_t last, padn; + uint64_t high, low; + unsigned char msglen[16]; + + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT64_BE( high, msglen, 0 ); + PUT_UINT64_BE( low, msglen, 8 ); + + last = (size_t)( ctx->total[0] & 0x7F ); + padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); + + if ( ( ret = mbedtls_sha512_update( ctx, sha512_padding, padn ) ) != 0 ) { + goto out; + } + + if ( ( ret = mbedtls_sha512_update( ctx, msglen, 16 ) ) != 0 ) { + goto out; + } + + /* if state is in hardware, read it out */ + if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) { + esp_sha_read_digest_state(sha_type(ctx), ctx->state); + } + + PUT_UINT64_BE( ctx->state[0], output, 0 ); + PUT_UINT64_BE( ctx->state[1], output, 8 ); + PUT_UINT64_BE( ctx->state[2], output, 16 ); + PUT_UINT64_BE( ctx->state[3], output, 24 ); + PUT_UINT64_BE( ctx->state[4], output, 32 ); + PUT_UINT64_BE( ctx->state[5], output, 40 ); + + if ( ctx->is384 == 0 ) { + PUT_UINT64_BE( ctx->state[6], output, 48 ); + PUT_UINT64_BE( ctx->state[7], output, 56 ); + } + +out: + if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) { + esp_sha_unlock_engine(sha_type(ctx)); + ctx->mode = ESP_MBEDTLS_SHA512_SOFTWARE; + } + + return ret; +} + +#endif /* MBEDTLS_SHA512_C && MBEDTLS_SHA512_ALT */ diff --git a/components/mbedtls/mbedtls_v3/port/sha/parallel_engine/sha.c b/components/mbedtls/mbedtls_v3/port/sha/parallel_engine/sha.c new file mode 100644 index 000000000..8c025d707 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/port/sha/parallel_engine/sha.c @@ -0,0 +1,222 @@ +/* + * ESP32 hardware accelerated SHA1/256/512 implementation + * based on mbedTLS FIPS-197 compliant version. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "esp_cpu.h" + +#include "hal/sha_hal.h" +#include "hal/sha_types.h" +#include "sha/sha_parallel_engine.h" +#include "soc/hwcrypto_periph.h" +#include "esp_private/periph_ctrl.h" + +/* + Single spinlock for SHA engine memory block +*/ +static portMUX_TYPE memory_block_lock = portMUX_INITIALIZER_UNLOCKED; + + +/* Binary semaphore managing the state of each concurrent SHA engine. + + Available = noone is using this SHA engine + Taken = a SHA session is running on this SHA engine + + Indexes: + 0 = SHA1 + 1 = SHA2_256 + 2 = SHA2_384 or SHA2_512 +*/ +static SemaphoreHandle_t engine_states[3]; + +static uint8_t engines_in_use; + +/* Spinlock for engines_in_use counter +*/ +static portMUX_TYPE engines_in_use_lock = portMUX_INITIALIZER_UNLOCKED; + +/* Return block size (in words) for a given SHA type */ +inline static size_t block_length(esp_sha_type type) +{ + switch (type) { + case SHA1: + case SHA2_256: + return 64 / 4; + case SHA2_384: + case SHA2_512: + return 128 / 4; + default: + return 0; + } +} + +/* Index into the engine_states array */ +inline static size_t sha_engine_index(esp_sha_type type) +{ + switch (type) { + case SHA1: + return 0; + case SHA2_256: + return 1; + default: + return 2; + } +} + +void esp_sha_lock_memory_block(void) +{ + portENTER_CRITICAL(&memory_block_lock); +} + +void esp_sha_unlock_memory_block(void) +{ + portEXIT_CRITICAL(&memory_block_lock); +} + +static SemaphoreHandle_t sha_get_engine_state(esp_sha_type sha_type) +{ + unsigned idx = sha_engine_index(sha_type); + volatile SemaphoreHandle_t *engine = &engine_states[idx]; + SemaphoreHandle_t result = *engine; + + if (result == NULL) { + // Create a new semaphore for 'in use' flag + SemaphoreHandle_t new_engine = xSemaphoreCreateBinary(); + assert(new_engine != NULL); + xSemaphoreGive(new_engine); // start available + + // try to atomically set the previously NULL *engine to new_engine + if (!esp_cpu_compare_and_set((volatile uint32_t *)engine, 0, (uint32_t)new_engine)) { + // we lost a race setting *engine + vSemaphoreDelete(new_engine); + } + result = *engine; + } + return result; +} + +static bool esp_sha_lock_engine_common(esp_sha_type sha_type, TickType_t ticks_to_wait); + +bool esp_sha_try_lock_engine(esp_sha_type sha_type) +{ + return esp_sha_lock_engine_common(sha_type, 0); +} + +void esp_sha_lock_engine(esp_sha_type sha_type) +{ + esp_sha_lock_engine_common(sha_type, portMAX_DELAY); +} + +static bool esp_sha_lock_engine_common(esp_sha_type sha_type, TickType_t ticks_to_wait) +{ + SemaphoreHandle_t engine_state = sha_get_engine_state(sha_type); + BaseType_t result = xSemaphoreTake(engine_state, ticks_to_wait); + + if (result == pdFALSE) { + // failed to take semaphore + return false; + } + + portENTER_CRITICAL(&engines_in_use_lock); + + if (engines_in_use == 0) { + /* Just locked first engine, + so enable SHA hardware */ + periph_module_enable(PERIPH_SHA_MODULE); + } + + engines_in_use++; + assert(engines_in_use <= 3); + + portEXIT_CRITICAL(&engines_in_use_lock); + + return true; +} + + +void esp_sha_unlock_engine(esp_sha_type sha_type) +{ + SemaphoreHandle_t engine_state = sha_get_engine_state(sha_type); + + portENTER_CRITICAL(&engines_in_use_lock); + + engines_in_use--; + + if (engines_in_use == 0) { + /* About to release last engine, so + disable SHA hardware */ + periph_module_disable(PERIPH_SHA_MODULE); + } + + portEXIT_CRITICAL(&engines_in_use_lock); + + xSemaphoreGive(engine_state); +} + +void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state) +{ +#ifndef NDEBUG + { + SemaphoreHandle_t engine_state = sha_get_engine_state(sha_type); + assert(uxSemaphoreGetCount(engine_state) == 0 && + "SHA engine should be locked" ); + } +#endif + + // preemptively do this before entering the critical section, then re-check once in it + sha_hal_wait_idle(); + + esp_sha_lock_memory_block(); + + sha_hal_read_digest(sha_type, digest_state); + + esp_sha_unlock_memory_block(); +} + +void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool first_block) +{ +#ifndef NDEBUG + { + SemaphoreHandle_t engine_state = sha_get_engine_state(sha_type); + assert(uxSemaphoreGetCount(engine_state) == 0 && + "SHA engine should be locked" ); + } +#endif + + // preemptively do this before entering the critical section, then re-check once in it + sha_hal_wait_idle(); + esp_sha_lock_memory_block(); + + sha_hal_hash_block(sha_type, data_block, block_length(sha_type), first_block); + + esp_sha_unlock_memory_block(); +} diff --git a/components/mbedtls/mbedtls_v3/test_apps/CMakeLists.txt b/components/mbedtls/mbedtls_v3/test_apps/CMakeLists.txt new file mode 100644 index 000000000..16481610b --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/CMakeLists.txt @@ -0,0 +1,7 @@ +#This is the project CMakeLists.txt file for the test subproject +cmake_minimum_required(VERSION 3.16) + +set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components") + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(mbedtls_test) diff --git a/components/mbedtls/mbedtls_v3/test_apps/README.md b/components/mbedtls/mbedtls_v3/test_apps/README.md new file mode 100644 index 000000000..a8b7833fa --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/README.md @@ -0,0 +1,2 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | diff --git a/components/mbedtls/mbedtls_v3/test_apps/ecdsa_key_p192.pem b/components/mbedtls/mbedtls_v3/test_apps/ecdsa_key_p192.pem new file mode 100644 index 000000000..a0ca456b8 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/ecdsa_key_p192.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MF8CAQEEGNav/J4c/nx4R+a30zxRJ2e7l15YTyZlkqAKBggqhkjOPQMBAaE0AzIA +BIhHJTy0t4ckXgfhx/x2D2uD9oF9m1/EuZz8qu3vugLDHApVF+CdEMsjrn4PH01p +1Q== +-----END EC PRIVATE KEY----- diff --git a/components/mbedtls/mbedtls_v3/test_apps/ecdsa_key_p256.pem b/components/mbedtls/mbedtls_v3/test_apps/ecdsa_key_p256.pem new file mode 100644 index 000000000..3f6b70853 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/ecdsa_key_p256.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIBElYzI+FTYu0axLSDoANj0kfm1/oxBzMCDLx89MK0fzoAoGCCqGSM49 +AwEHoUQDQgAEoo9SYCCbVDwTL1Gxib/H+oRcVpYqAGfdfIwPY4t2f7n2TIdbWptZ +CsRTBHINfN6sfq1JjPdcwxwegfJHAXQF1Q== +-----END EC PRIVATE KEY----- diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/CMakeLists.txt b/components/mbedtls/mbedtls_v3/test_apps/main/CMakeLists.txt new file mode 100644 index 000000000..1017c93a5 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/CMakeLists.txt @@ -0,0 +1,18 @@ +set(TEST_CRTS "crts/server_cert_chain.pem" + "crts/prvtkey.pem" + "crts/server_cert_bundle" + "crts/bad_md_crt.pem" + "crts/wrong_sig_crt_esp32_com.pem" + "crts/correct_sig_crt_esp32_com.pem") + +idf_component_register(SRC_DIRS "." + PRIV_INCLUDE_DIRS "." + PRIV_REQUIRES cmock test_utils mbedtls esp_timer unity spi_flash + EMBED_TXTFILES ${TEST_CRTS} + WHOLE_ARCHIVE) + +idf_component_get_property(mbedtls mbedtls COMPONENT_LIB) +target_compile_definitions(${mbedtls} INTERFACE "-DMBEDTLS_DEPRECATED_WARNING") +target_compile_definitions(mbedtls PUBLIC "-DMBEDTLS_DEPRECATED_WARNING") +target_compile_definitions(mbedcrypto PUBLIC "-DMBEDTLS_DEPRECATED_WARNING") +target_compile_definitions(mbedx509 PUBLIC "-DMBEDTLS_DEPRECATED_WARNING") diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/app_main.c b/components/mbedtls/mbedtls_v3/test_apps/main/app_main.c new file mode 100644 index 000000000..27735fb98 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/app_main.c @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "unity.h" +#include "mbedtls/aes.h" +#include "memory_checks.h" +#include "soc/soc_caps.h" + +/* setUp runs before every test */ +void setUp(void) +{ + // Execute mbedtls_aes_init operation to allocate AES interrupt + // allocation memory which is considered as leak otherwise +#if SOC_AES_SUPPORTED + mbedtls_aes_context ctx; + mbedtls_aes_init(&ctx); +#endif // SOC_AES_SUPPORTED + + test_utils_record_free_mem(); + test_utils_set_leak_level(CONFIG_UNITY_CRITICAL_LEAK_LEVEL_GENERAL, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL); + test_utils_set_leak_level(CONFIG_UNITY_WARN_LEAK_LEVEL_GENERAL, ESP_LEAK_TYPE_WARNING, ESP_COMP_LEAK_GENERAL); + test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_LWIP); +} + +/* tearDown runs after every test */ +void tearDown(void) +{ + /* some FreeRTOS stuff is cleaned up by idle task */ + vTaskDelay(5); + + /* clean up some of the newlib's lazy allocations */ + esp_reent_cleanup(); + + /* check if unit test has caused heap corruption in any heap */ + TEST_ASSERT_MESSAGE( heap_caps_check_integrity(MALLOC_CAP_INVALID, true), "The test has corrupted the heap"); + + test_utils_finish_and_evaluate_leaks(test_utils_get_leak_level(ESP_LEAK_TYPE_WARNING, ESP_COMP_LEAK_ALL), + test_utils_get_leak_level(ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_ALL)); + +} + +static void test_task(void *pvParameters) +{ + vTaskDelay(2); /* Delay a bit to let the main task be deleted */ + unity_run_menu(); +} + +void app_main(void) +{ + xTaskCreatePinnedToCore(test_task, "testTask", CONFIG_UNITY_FREERTOS_STACK_SIZE, NULL, CONFIG_UNITY_FREERTOS_PRIORITY, NULL, CONFIG_UNITY_FREERTOS_CPU); +} diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/crts/bad_md_crt.pem b/components/mbedtls/mbedtls_v3/test_apps/main/crts/bad_md_crt.pem new file mode 100644 index 000000000..e1a1d307b --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/crts/bad_md_crt.pem @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE----- +MIIGijCCBXKgAwIBAgIQAfUXR/1IrnlbCX0+CKqtnDANBgkqhkiG9w0BAQsFADBeMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMR0wGwYDVQQDExRHZW9UcnVzdCBSU0EgQ0EgMjAxODAeFw0yMDA2MTgwMDAwMDBaFw0yMjA5MDExMjAwMDBaMG4xCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazERMA8GA1UEBxMITmV3IFlvcmsxIDAeBgNVBAoTF0FkYWZydWl0IEluZHVzdHJpZXMgTExDMRcwFQYDVQQDDA4qLmFkYWZydWl0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbW8pXtrCk9RpHdtHRfKx7AgQjH6KMalaUOjeMxI2mqk5oyF/399FQWky/10oeLohivyIv5uror1w0TVon/H946LlTKhT3sbYrpAVDZsfybZF3qD/Sld6kAb0rdb5/TADc0Qy3J0ciCZ6oM3FSDyS7GYnsQ1scw5z82H0unA4ZQQJ1uwa0uIWkpCXyRyb6pidyAj06V7q03EtIQgn8iufV4uncONkp0HVQcuS3uk6RRP26QcdYqBl3OOYHgHeIbANLXgEUDm6cihhPqYRvIFi5jZlmFfEFLvnTgC88iMijCQopaLhWIBos+1lvQT5wzIU/Wj+aqvpWRT05FW4pH/zkCAwEAAaOCAzIwggMuMB8GA1UdIwQYMBaAFJBY/7CcdahRVHex7fKjQxY4nmzFMB0GA1UdDgQWBBTPR/O8QzK2xZ7BH/rN1NLmMNtyizAnBgNVHREEIDAegg4qLmFkYWZydWl0LmNvbYIMYWRhZnJ1aXQuY29tMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwPgYDVR0fBDcwNTAzoDGgL4YtaHR0cDovL2NkcC5nZW90cnVzdC5jb20vR2VvVHJ1c3RSU0FDQTIwMTguY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQICMHUGCCsGAQUFBwEBBGkwZzAmBggrBgEFBQcwAYYaaHR0cDovL3N0YXR1cy5nZW90cnVzdC5jb20wPQYIKwYBBQUHMAKGMWh0dHA6Ly9jYWNlcnRzLmdlb3RydXN0LmNvbS9HZW9UcnVzdFJTQUNBMjAxOC5jcnQwDAYDVR0TAQH/BAIwADCCAX8GCisGAQQB1nkCBAIEggFvBIIBawFpAHcAKXm+8J45OSHwVnOfY6V35b5XfZxgCvj5TV0mXCVdx4QAAAFyyKMnsAAABAMASDBGAiEApqsw2Iokda11fM2fTA+H4ofSYCaBRUVm4L+DXaldU6ACIQC550v/HYDLUp6a9gugs+tajI/S/9bnSDtfF05IROsOAAB2ACJFRQdZVSRWlj+hL/H3bYbgIyZjrcBLf13Gg1xu4g8CAAABcsijJ6AAAAQDAEcwRQIgJRF0L+7t63eMG/e3kgVKU5rpEZ+A0WUh4A1Wuo8frvoCIQCXj00F2+sTmK1BKo/I1nqOYeaQHeMtlKCJkunJKGannwB2AFGjsPX9AXmcVm24N3iPDKR6zBsny/eeiEKaDf7UiwXlAAABcsijJ+cAAAQDAEcwRQIgItT1DYXAx2uyz1NToQOFqJ2UIL+Dm0nVG40QHL/GVJsCIQCLiBO9MS2PLM/wmufSomt/SDhbLwKFBU9RP8O1qbtV9TANBgkqhkiG9w0BAQsFAAOCAQEANfsWhI00ONyqz5DtuFRxxx4iApmyW7PbQr+9lZuNzkqieNIt/VuCyNIKZEBJ3PA/2QfwvXdIpjE6M7yz+9kh9WdRRg6qj6hPp2gvSQQrk361RY/sTtueAh4re8yyJDebH3B60kUwzNmMms7zcxQ0Ctvg/BDPVBd1VFF/tsoYO4P5iMar1YCl8BNozu6q4JP2E0HRygZD0U7vY2Gsi1wHdm5hVZnLJq6SRTbYUWY3tryEp2lJYQFiSoVfu5icebrLUVRmSl05PyYstjFekb9DCNyyLIBZsjmaFJoJCGo1y5cSqBYfwSsrq1aD9hn5LFeEVG+PEa10IlVv7l+33mLWZA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEizCCA3OgAwIBAgIQBUb+GCP34ZQdo5/OFMRhczANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0xNzExMDYxMjIzNDVaFw0yNzExMDYxMjIzNDVaMF4xCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xHTAbBgNVBAMTFEdlb1RydXN0IFJTQSBDQSAyMDE4MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv4rRY03hGOqHXegWPI9/tr6HFzekDPgxP59FVEAh150Hm8oDI0q9m+2FAmM/n4W57Cjv8oYi2/hNVEHFtEJ/zzMXAQ6CkFLTxzSkwaEB2jKgQK0fWeQz/KDDlqxobNPomXOMJhB3y7c/OTLo0lko7geG4gk7hfiqafapa59YrXLIW4dmrgjgdPstU0Nigz2PhUwRl9we/FAwuIMIMl5cXMThdSBK66XWdS3cLX184ND+fHWhTkAChJrZDVouoKzzNYoq6tZaWmyOLKv23v14RyZ5eqoi6qnmcRID0/i6U9J5nL1krPYbY7tNjzgC+PBXXcWqJVoMXcUw/iBTGWzpwwIDAQABo4IBQDCCATwwHQYDVR0OBBYEFJBY/7CcdahRVHex7fKjQxY4nmzFMB8GA1UdIwQYMBaAFAPeUDVW0Uy7ZvCj4hsbw5eyPdFVMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBCBgNVHR8EOzA5MDegNaAzhjFodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRHbG9iYWxSb290Q0EuY3JsMD0GA1UdIAQ2MDQwMgYEVR0gADAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMA0GCSqGSIb3DQEBCwUAA4IBAQAw8YdVPYQI/C5earp80s3VLOO+AtpdiXft9OlWwJLwKlUtRfccKj8QW/Pp4b7h6QAlufejwQMb455OjpIbCZVS+awY/R8pAYsXCnM09GcSVe4ivMswyoCZP/vPEn/LPRhHhdgUPk8MlD979RGoUWz7qGAwqJChi28uRds3thx+vRZZIbEyZ62No0tJPzsSGSz8nQ//jP8BIwrzBAUH5WcBAbmvgWfrKcuv+PyGPqRcc4T55TlzrBnzAzZ3oClo9fTvO9PuiHMKrC6V6mgi0s2sa/gbXlPCD9Z24XUMxJElwIVTDuKB0Q4YMMlnpN/QChJ4B0AFsQ+DU0NCO+f78Xf7 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQkCAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/crts/correct_sig_crt_esp32_com.pem b/components/mbedtls/mbedtls_v3/test_apps/main/crts/correct_sig_crt_esp32_com.pem new file mode 100644 index 000000000..2b7c6e2fa --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/crts/correct_sig_crt_esp32_com.pem @@ -0,0 +1,6 @@ +-----BEGIN CERTIFICATE----- +MIIFXDCCBESgAwIBAgISA9EyvtMwECvtdhru9l2xnEOgMA0GCSqGSIb3DQEBCwUAMEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0yMDEwMjMxODE2MDFaFw0yMTAxMjExODE2MDFaMBgxFjAUBgNVBAMTDXd3dy5lc3AzMi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGvklnzfCVCwTwNFr9+W263qTDSOK8cS6azwirKQl+62Z4E/fvhxvvmp02xiuWoeDpmqsQQCoZMiR77ziqBEDnf80J1S9ZSX3PRWsAYuDGMajTwiywMa7ttvs4Cm3BmXhSQpYEDTIrT7EVgOljSfkGAStKWK5fbkxMJ11eIQdA5KCLKOOPEofq4I5pgwk/4PGGjPSDA51w/XJyNX85hIMLdwXIrWBukrW+B/GFe7a/gdWZCUY2QMBsFPqwGYKZ41S1xtM4VnpZyMu9bvVmS9fvoYIyYUQ6zlktkLawIo56PIEO7wGu4tSNm62dQW23g7jxRwfLCQ7vUSSxOy35LyplAgMBAAGjggJsMIICaDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFHiCm41V5UtbkbDidxwrRbN1Bn58MB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMG8GCCsGAQUFBwEBBGMwYTAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNyeXB0Lm9yZzAvBggrBgEFBQcwAoYjaHR0cDovL2NlcnQuaW50LXgzLmxldHNlbmNyeXB0Lm9yZy8wIwYDVR0RBBwwGoIJZXNwMzIuY29tgg13d3cuZXNwMzIuY29tMEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcGCysGAQQBgt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5cHQub3JnMIIBAwYKKwYBBAHWeQIEAgSB9ASB8QDvAHUAXNxDkv7mq0VEsV6a1FbmEDf71fpH3KFzlLJe5vbHDsoAAAF1VuOmWgAABAMARjBEAiAn6M8aTEpBZ+jZgPV67cuNCzuBfa0cXSmntpONtT0ZXAIgYP2ZEZmwkNrkLmYYrhDsPlNlMikj/Y+sObK31z8k30QAdgB9PvL4j/+IVWgkwsDKnlKJeSvFDngJfy5ql2iZfiLw1wAAAXVW46acAAAEAwBHMEUCIF9duaNUkko6siaTN1qY0Jqep7KQ5l/c9bhxkXLvwOLPAiEAlf6Zn/EaXCVCubM1ouKBaYXggKhWWDVRlfPclyDqmHgwDQYJKoZIhvcNAQELBQADggEBAFjhZtXgJTgDc8x19LWE3LVlPsQBNmO1WIuFaTSOShmXHocIy1pR80TWBa905EB0gdVqw7Ez7e84DkIJlczH+1fPUZs8K1TUtte7iR/NfpExrbFXDiGM7kkq9FzVU2xDzLIvlYPFkIfcY1fiaYcnlsS3F3p+vfVidVel61mtBQ7mM2Mf0Vg3emGcw7uuNq5Q1QWs6ILM+JRePDnOD9JQBbK3XZ8imIXr4ewW2VG85NHTyRXRCEP9PwEsMmpqmsYk8vonNz9GeFEPusQ5BWvLvlpC/lprhgpFdxyPQ8iTqBjG5m36J+6TaQdyFi2kpTdnHzV6uvBgyTEUz/Zw3rjlxT8= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0NlowSjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMTGkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EFq6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWAa6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIGCCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNvbTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9kc3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAwVAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcCARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwuY3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsFAAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJouM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwuX4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlGPfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== +-----END CERTIFICATE----- diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/crts/prvtkey.pem b/components/mbedtls/mbedtls_v3/test_apps/main/crts/prvtkey.pem new file mode 100644 index 000000000..bb0a510a7 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/crts/prvtkey.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAySb2QFrQZjQ1EhfN7I+raKrWSWWeYGppqPk3E1sV2y6LSE3M +7cVZyXxcpnP4mcKos3D9k8sbkt05oKcHR2THpWdz5mJn8A7TfJYWnYRHcRuR85th +XC8Pjf3f+JfjXgr/2a2JqHb4fttxoDRwWP1+kbTHa4iERqTFOIhYB9wD8uzbBHJq +IlIGbBHO9J+JxZKVkgDWZfc7zik3YzvkuWju/PmF73BagGxxRDzodzfxhHq1f96J +w10YS9pkhVFLxzOz3O+buwL8plCQplVnpj6J+2MaY4JlUvCcosDkT0EORAtrYGwZ +KJBKn4dRftk8Wbtns7zoJ2SNUL5TZ2oyAb2dwQIDAQABAoIBAQCRmE3tTs5A69Du +A6TdcTAUVnM8NP1ptBw+XgRrUiaDuzC9aPLHt2zB1e4J3S83vBn3p/UjIIQYzV+E +1OED4AJRyoutWdT5gQG6z7gW00QSrm358aGK49VSZUvT17yOuU9u85kMAvDigVvB +JbOb9f/C3yLoxqtXprPJs4ZkSe/hyB0JtRzauDYZnK4JmtgDfGds1cykohbUaeCW +ExUSbi/EPuroowmjEPFmN4tH/C3GtQonwGfjP76GXm8u5Fg8VXYUmb5pnxYcFdvv +shoasbK5lksgK50VP2vA9Y3mIrThRvkWgcv0TZaQWAF/JtdSXIID5WzfsgLbtDQF +hZLk1dDxAoGBAPfAjPAqapNVl4GqSkUWofUHMzZG85fHoPN3INSA0aMr4X9wHFfQ +pQ0ACxuimQj66Vk4rWww+HrsjPfiNMZzoi1exS1tjbQVyTBffrHj8sSdWt8Gw6MB +Pp5ubnCy9pl4lWNHlJZJp2SwAd10LzrizzAQALeEtRmg8meYGZElVUy7AoGBAM/Z +REXLJgaad5V3A2xehrSnknKUwab4LFIrgirZ6h0RXYo+wEHGJpDvM5Vw3sZT+UaJ +Jdlb3cXbqOxWrKlqjKe/S2vNScP7V2Na8l/ySO93PYE0V1Q+EeuNGi41xWC4Dh7o +D7BX2nDm9YBZzNVxM/30/dTzFM+CKrCARsLIXvWzAoGBAOQ4GRv61qXVyHSHO1cd +HB+sfD5ZaXa9S8Q6TqGx8GrQty4/RbyW1BN/oLvaMgKVr3KixQ3OpnYFhW2qkFbm +mdQVYqkQK+Jh1yyaKwkPI8h98wFTJ8/2C4rByzZBhOumqmYDwBoYyvvzLiSjLAag +e56YfzCOLIzpN6K594M+0q6VAoGBALWR5D1gKRjNqbetHxV1QhHg7WMhJkaZOAaU +MYMDmKvJ9sAE72jGE/y6qYJb9pCk3PdMaf8GbKciq9/CG9Vn2fXUe6txy4XkNEP8 +OA2vFx3yOY18Tumty3PNcNh7arCCOPuw17vCE3ZbnI2CZRj0amnosjFsJHreCDLl +7GrOJX5XAoGASZXbGykpYJTTr5PGPL/eX0koU1RZ9f6fvVdkfeWNGZfJ4oGkxDcO +fJnzq9wC9YREy6f3eoMrix95RPv4Qo1Wwi2PmtyMFvUdsYckFEhxSN3p4Iqn/nQg +6I7VB0yNqw8ZdP1vBkRcg3kk+QO2tci+OTdpDSKmO5nGjuqpsdBM5/o= +-----END RSA PRIVATE KEY----- diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/crts/server_cert_bundle b/components/mbedtls/mbedtls_v3/test_apps/main/crts/server_cert_bundle new file mode 100644 index 000000000..0b7f09aa0 Binary files /dev/null and b/components/mbedtls/mbedtls_v3/test_apps/main/crts/server_cert_bundle differ diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/crts/server_cert_chain.pem b/components/mbedtls/mbedtls_v3/test_apps/main/crts/server_cert_chain.pem new file mode 100644 index 000000000..afc99a9e3 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/crts/server_cert_chain.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDVTCCAj0CFG5WO5Ukqd/0PnrSPIlQnXNjrCUUMA0GCSqGSIb3DQEBCwUAMGIx +CzAJBgNVBAYTAkNOMRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQHDAhTaGFu +Z2hhaTESMBAGA1UECgwJRXNwcmVzc2lmMRcwFQYDVQQDDA5Fc3ByZXNzaWYgUm9v +dDAeFw0yMDAzMjYwNjQxMTlaFw0yMTAzMjEwNjQxMTlaMGwxCzAJBgNVBAYTAkNO +MRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQHDAhTaGFuZ2hhaTEhMB8GA1UE +CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAlsb2NhbGhvc3Qw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJJvZAWtBmNDUSF83sj6to +qtZJZZ5gammo+TcTWxXbLotITcztxVnJfFymc/iZwqizcP2TyxuS3TmgpwdHZMel +Z3PmYmfwDtN8lhadhEdxG5Hzm2FcLw+N/d/4l+NeCv/ZrYmodvh+23GgNHBY/X6R +tMdriIRGpMU4iFgH3APy7NsEcmoiUgZsEc70n4nFkpWSANZl9zvOKTdjO+S5aO78 ++YXvcFqAbHFEPOh3N/GEerV/3onDXRhL2mSFUUvHM7Pc75u7AvymUJCmVWemPon7 +YxpjgmVS8JyiwORPQQ5EC2tgbBkokEqfh1F+2TxZu2ezvOgnZI1QvlNnajIBvZ3B +AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAI2RzAwx1IiyWYPbSQOMjATKG1hiqNJF +fkkqJrSfu93iQyye3Umb/pdUf7v5xgN2NrW5VnRow19VR7uCU4VCCBfx77f0Zp2e +UA13qhT5zljoqgtkU9bHbRfTW/Hq30joKqQz8+Z0Yom6qZA7XjAhXXiHt7I4Noq6 +y+HwH08Xr1nII1c6Zc0cDqK9UV02w2v1RJrnGlq3v/CBpanA/nz4LdP5Jqbh79WW +bCe8+Y7WEYR7K4dKSkDugf8ROAaGuCYAbhRMU3tFjNlMRR/5HcBpy7MfUvX6GcI0 +QCfe4ugnHXQXNxS0rb2uM6yCHOTiQ5MJjBPh9tRYV9bSko5u/NmwsFU= +-----END CERTIFICATE----- diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/crts/server_root.pem b/components/mbedtls/mbedtls_v3/test_apps/main/crts/server_root.pem new file mode 100644 index 000000000..5854747f9 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/crts/server_root.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDpTCCAo2gAwIBAgIUduK+lv/MILT278PPIYz8HkFzhFUwDQYJKoZIhvcNAQEL +BQAwYjELMAkGA1UEBhMCQ04xEzARBgNVBAgMClNvbWUtU3RhdGUxETAPBgNVBAcM +CFNoYW5naGFpMRIwEAYDVQQKDAlFc3ByZXNzaWYxFzAVBgNVBAMMDkVzcHJlc3Np +ZiBSb290MB4XDTIwMDMyNjA2NDAxMFoXDTI1MDMyNjA2NDAxMFowYjELMAkGA1UE +BhMCQ04xEzARBgNVBAgMClNvbWUtU3RhdGUxETAPBgNVBAcMCFNoYW5naGFpMRIw +EAYDVQQKDAlFc3ByZXNzaWYxFzAVBgNVBAMMDkVzcHJlc3NpZiBSb290MIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp9ILzOjsz7dZbABUIoDCBat3MPsv +qd20Jsk3GzkLjY/HjTCMBweq2zt0sRsa+YwCPtQyAsYPtgt/VzRY4TF8jqmSj7Ko +DKOWkbim0O0XDAT8DfkQ32pZC7DnAw/374Vmm/ZmN/yE4zNUjNbjO2weswczcSdL +B3ITsa+OquKYK8J2Pe5gZh/tC0f0I9ks3UplcLyEex8TQZivAK3RL4QWj4j4NJWn +wH5qdizuKStwWEo3FvTP4g95SQItw31HTA8mJcBzCZC0NOZyMckRSmK51XljQ0iU +G7KwK8GNbDC+VUZEt5aGB5QZhCFC2wo5An7u20UHRUWbv4MEgddPDoQ4EwIDAQAB +o1MwUTAdBgNVHQ4EFgQU3inIjbdXp/DgSnVAiJmTlAtKH08wHwYDVR0jBBgwFoAU +3inIjbdXp/DgSnVAiJmTlAtKH08wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B +AQsFAAOCAQEAOpLjyXj2e0IaUgJK3lGuJ9u6piehYK1WqPoCR7K7pUnFGyNLu0mq +yfTqNoXV8a7NmM8Vn8ZJ1Gep20JqgvR27o3OE87bT7E/JPUsvbu7MNdfiVxpFWi1 +HxdBrzHr+mcakbhRxI38s3GVNT9Y89Y7FZbE+dqT8SxILk2pVUExfZR/ItazDTxl +95ARCOj/bQPCEN+oLYzS31ORmkJfY2AuJAcJUTCyO4UfpKVFmQeAKlNmTq9Q0a6C +0RlbzZ/PJoB3d265A9fTjlANQ7XzE8GgIJVR7cz5OJzZVxfEr9ME9VfgNrjKyXS3 +FcFQvif6JqX6IbmTenEKi7IfgX2zu1nxtQ== +-----END CERTIFICATE----- diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/crts/wrong_sig_crt_esp32_com.pem b/components/mbedtls/mbedtls_v3/test_apps/main/crts/wrong_sig_crt_esp32_com.pem new file mode 100644 index 000000000..0d6b8b720 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/crts/wrong_sig_crt_esp32_com.pem @@ -0,0 +1,6 @@ +-----BEGIN CERTIFICATE----- +MIIFXDCCBESgAwIBAgISA9EyvtMwECvtdhru9l2xnEOgMA0GCSqGSIb3DQEBCwUAMEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0yMDEwMjMxODE2MDFaFw0yMTAxMjExODE2MDFaMBgxFjAUBgNVBAMTDXd3dy5lc3AzMi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGvklnzfCVCwTwNFr9+W263qTDSOK8cS6azwirKQl+62Z4E/fvhxvvmp02xiuWoeDpmqsQQCoZMiR77ziqBEDnf80J1S9ZSX3PRWsAYuDGMajTwiywMa7ttvs4Cm3BmXhSQpYEDTIrT7EVgOljSfkGAStKWK5fbkxMJ11eIQdA5KCLKOOPEofq4I5pgwk/4PGGjPSDA51w/XJyNX85hIMLdwXIrWBukrW+B/GFe7a/gdWZCUY2QMBsFPqwGYKZ41S1xtM4VnpZyMu9bvVmS9fvoYIyYUQ6zlktkLawIo56PIEO7wGu4tSNm62dQW23g7jxRwfLCQ7vUSSxOy35LyplAgMBAAGjggJsMIICaDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFHiCm41V5UtbkbDidxwrRbN1Bn58MB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMG8GCCsGAQUFBwEBBGMwYTAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNyeXB0Lm9yZzAvBggrBgEFBQcwAoYjaHR0cDovL2NlcnQuaW50LXgzLmxldHNlbmNyeXB0Lm9yZy8wIwYDVR0RBBwwGoIJZXNwMzIuY29tgg13d3cuZXNwMzIuY29tMEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcGCysGAQQBgt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5cHQub3JnMIIBAwYKKwYBBAHWeQIEAgSB9ASB8QDvAHUAXNxDkv7mq0VEsV6a1FbmEDf71fpH3KFzlLJe5vbHDsoAAAF1VuOmWgAABAMARjBEAiAn6M8aTEpBZ+jZgPV67cuNCzuBfa0cXSmntpONtT0ZXAIgYP2ZEZmwkNrkLmYYrhDsPlNlMikj/Y+sObK31z8k30QAdgB9PvL4j/+IVWgkwsDKnlKJeSvFDngJfy5ql2iZfiLw1wAAAXVW46acAAAEAwBHMEUCIF9duaNUkko6siaTN1qY0Jqep7KQ5l/c9bhxkXLvwOLPAiEAlf6Zn/EaXCVCubM1ouKBaYXggKhWWDVRlfPclyDqmHgwDQYJKoZIhvcNAQELBQADggEBAFjhZtXgJTgDc8x19LWE3LVlPsQBNmO1WIuFaTSOShmXHocIy1pR80TWBa905EB0gdVqw7Ez7e84DkIJlczH+1fPUZs8K1TUtte7iR/NfpExrbFXDiGM7kkq9FzVU2xDzLIvlYPFkIfcY1fiaYcnlsS3F3p+vfVidVel61mtBQ7mM2Mf0Vg3emGcw7uuNq5Q1QWs6ILM+JRePDnOD9JQBbK3XZ8imIXr4ewW2VG85NHTyRXRCEP9PwEsMmpqmsYk8vonNz9GeFEPusQ5BWvLvlpC/lprhgpFdxyPQ8iTqBjG5m36J+6TaQdyFi2kpTdnHzV6uvBgyTEUz/Zw3rjlxT8= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0NlowSjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMTGkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EFq6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWAa6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIGCCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNvbTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9kc3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAwVAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcCARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwuY3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsFAAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJouM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwuX4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlGPfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6KOqkqm57TH2H3eDJAkSnh6/DNFu1Qg== +-----END CERTIFICATE----- diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_aes.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_aes.c new file mode 100644 index 000000000..5ac71e82e --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_aes.c @@ -0,0 +1,1588 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* mbedTLS AES test +*/ +#include +#include +#include +#include +#include "mbedtls/aes.h" +#include "mbedtls/gcm.h" +#include "unity.h" +#include "sdkconfig.h" +#include "esp_log.h" +#include "esp_timer.h" +#include "esp_heap_caps.h" +#include "test_utils.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_memory_utils.h" +#include "soc/lldesc.h" + + +static const uint8_t key_256[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, +}; + +static const uint8_t iv[] = { + 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, + 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, +}; + +/* Cipher produced via this Python: + from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + from cryptography.hazmat.backends import default_backend + + def as_c_array(byte_arr): + + hex_str = '' + for idx, byte in enumerate(byte_arr): + hex_str += "0x{:02x}, ".format(byte) + bytes_per_line = 8 + if idx % bytes_per_line == bytes_per_line - 1: + hex_str += '\n' + + return hex_str + + key = bytearray(range(32)) + iv = bytearray(range(16, 0, -1)) + + print("Key: \n{}".format(as_c_array(key))) + print("IV: \n{}".format(as_c_array(iv))) + + # Replace CTR with desired mode + cipher = Cipher(algorithms.AES(key), modes.CTR(iv), backend=default_backend()) + encryptor = cipher.encryptor() + + input_len = 1000 + + plain = b'\x3A'*input_len + print(as_c_array(plain)) + ct = encryptor.update(plain) + encryptor.finalize() + + print("Chipertext: {}".format(as_c_array(ct))) +*/ +TEST_CASE("mbedtls CBC AES-256 test", "[aes]") +{ + const unsigned SZ = 1600; + mbedtls_aes_context ctx; + uint8_t nonce[16]; + + const uint8_t expected_cipher_end[] = { + 0x3e, 0x68, 0x8a, 0x02, 0xe6, 0xf2, 0x6a, 0x9e, + 0x9b, 0xb2, 0xc0, 0xc4, 0x63, 0x63, 0xd9, 0x25, + 0x51, 0xdc, 0xc2, 0x71, 0x96, 0xb3, 0xe5, 0xcd, + 0xbd, 0x0e, 0xf2, 0xef, 0xa9, 0xab, 0xab, 0x2d, + }; + + memcpy(nonce, iv, 16); + + // allocate internal memory + uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(plaintext); + TEST_ASSERT_NOT_NULL(decryptedtext); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key_256, 256); + + memset(plaintext, 0x3A, SZ); + memset(decryptedtext, 0x0, SZ); + + // Encrypt + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, SZ, nonce, plaintext, chipertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32); + + // Decrypt + memcpy(nonce, iv, 16); + mbedtls_aes_setkey_dec(&ctx, key_256, 256); + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, SZ, nonce, chipertext, decryptedtext); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); + + mbedtls_aes_free(&ctx); + free(plaintext); + free(chipertext); + free(decryptedtext); +} + +TEST_CASE("mbedtls CBC AES-256 DMA buffer align test", "[aes]") +{ +#define ALIGN_DOWN(val, align) ((val) & ~((align) - 1)) + // Size is taken considering the maximum DMA buffer size + const unsigned SZ = ALIGN_DOWN((2*LLDESC_MAX_NUM_PER_DESC), 16); + mbedtls_aes_context ctx; + uint8_t nonce[16]; + + const uint8_t expected_cipher_end[] = { + 0x9e, 0xcb, 0x1d, 0x24, 0x01, 0xc8, 0x3f, 0xba, + 0xde, 0x76, 0xea, 0x9c, 0xf3, 0x64, 0x23, 0x19, + 0x8c, 0x67, 0xd4, 0x1a, 0xd1, 0xe0, 0xbf, 0xc3, + 0xd2, 0xb8, 0x40, 0x95, 0x89, 0x41, 0x09, 0xdb, + }; + + memcpy(nonce, iv, 16); + + // allocate internal memory + uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(plaintext); + TEST_ASSERT_NOT_NULL(decryptedtext); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key_256, 256); + + memset(plaintext, 0x3A, SZ); + memset(decryptedtext, 0x0, SZ); + + // Encrypt + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, SZ, nonce, plaintext, chipertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32); + + // Decrypt + memcpy(nonce, iv, 16); + mbedtls_aes_setkey_dec(&ctx, key_256, 256); + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, SZ, nonce, chipertext, decryptedtext); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); + + mbedtls_aes_free(&ctx); + free(plaintext); + free(chipertext); + free(decryptedtext); +} + +TEST_CASE("mbedtls CTR AES-256 test", "[aes]") +{ + const unsigned SZ = 1000; + mbedtls_aes_context ctx; + uint8_t nonce[16]; + uint8_t stream_block[16]; + size_t nc_off = 0; + + const uint8_t expected_cipher_end[] = { + 0xd4, 0xdc, 0x4f, 0x8f, 0xfe, 0x86, 0xee, 0xb5, + 0x14, 0x7f, 0xba, 0x30, 0x25, 0xa6, 0x7f, 0x6c, + 0xb5, 0x73, 0xaf, 0x90, 0xd7, 0xff, 0x36, 0xba, + 0x2b, 0x1d, 0xec, 0xb9, 0x38, 0xfa, 0x0d, 0xeb, + }; + + memcpy(nonce, iv, 16); + + // allocate internal memory + uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(plaintext); + TEST_ASSERT_NOT_NULL(decryptedtext); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key_256, 256); + + memset(plaintext, 0x3A, SZ); + memset(decryptedtext, 0x0, SZ); + + // Encrypt + mbedtls_aes_crypt_ctr(&ctx, SZ, &nc_off, nonce, stream_block, plaintext, chipertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32); + + // Decrypt + nc_off = 0; + memcpy(nonce, iv, 16); + mbedtls_aes_crypt_ctr(&ctx, SZ, &nc_off, nonce, stream_block, chipertext, decryptedtext); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); + + mbedtls_aes_free(&ctx); + free(plaintext); + free(chipertext); + free(decryptedtext); +} + +TEST_CASE("mbedtls OFB AES-256 test", "[aes]") +{ + const unsigned SZ = 1000; + mbedtls_aes_context ctx; + uint8_t nonce[16]; + size_t nc_off = 0; + + const uint8_t expected_cipher_end[] = { + 0xca, 0xc3, 0x05, 0x77, 0xae, 0xb9, 0x38, 0xd6, + 0x03, 0x0a, 0xad, 0x90, 0x6e, 0xdd, 0xf3, 0x9a, + 0x41, 0x4d, 0x71, 0x30, 0x04, 0x9f, 0xd3, 0x53, + 0xb7, 0x5e, 0xb4, 0xfd, 0x93, 0xf8, 0x31, 0x6a, + }; + + memcpy(nonce, iv, 16); + + // allocate internal memory + uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(plaintext); + TEST_ASSERT_NOT_NULL(decryptedtext); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key_256, 256); + + memset(plaintext, 0x3A, SZ); + memset(decryptedtext, 0x0, SZ); + + // Encrypt + mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, plaintext, chipertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32); + + // Decrypt + nc_off = 0; + memcpy(nonce, iv, 16); + mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, chipertext, decryptedtext); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); + + mbedtls_aes_free(&ctx); + free(plaintext); + free(chipertext); + free(decryptedtext); +} + +TEST_CASE("mbedtls CFB-8 AES-256 test", "[aes]") +{ + const unsigned SZ = 1000; + mbedtls_aes_context ctx; + uint8_t nonce[16]; + + const uint8_t expected_cipher_end[] = { + 0x69, 0xdc, 0x1d, 0x8a, 0x0b, 0x9e, 0xbc, 0x84, + 0x29, 0xa2, 0x04, 0xb6, 0x91, 0x6b, 0xb2, 0x83, + 0x13, 0x23, 0x54, 0xcb, 0xf9, 0x6d, 0xcc, 0x53, + 0x04, 0x59, 0xd1, 0xc9, 0xff, 0xab, 0xe2, 0x37, + }; + + memcpy(nonce, iv, 16); + + // allocate internal memory + uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(plaintext); + TEST_ASSERT_NOT_NULL(decryptedtext); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key_256, 256); + + memset(plaintext, 0x3A, SZ); + memset(decryptedtext, 0x0, SZ); + + // Encrypt + mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_ENCRYPT, SZ, nonce, plaintext, chipertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32); + + // Decrypt + memcpy(nonce, iv, 16); + mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_DECRYPT, SZ, nonce, chipertext, decryptedtext); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); + + mbedtls_aes_free(&ctx); + free(plaintext); + free(chipertext); + free(decryptedtext); +} + +TEST_CASE("mbedtls CFB-128 AES-256 test", "[aes]") +{ + const unsigned SZ = 1000; + mbedtls_aes_context ctx; + uint8_t nonce[16]; + size_t nc_off = 0; + + const uint8_t expected_cipher_end[] = { + 0xf3, 0x64, 0x20, 0xa1, 0x70, 0x2a, 0xd9, 0x3f, + 0xb7, 0x48, 0x8c, 0x2c, 0x1f, 0x65, 0x53, 0xc2, + 0xac, 0xfd, 0x82, 0xe5, 0x31, 0x24, 0x1f, 0x30, + 0xaf, 0xcc, 0x8d, 0xb3, 0xf3, 0x63, 0xe1, 0xa0, + }; + + memcpy(nonce, iv, 16); + + // allocate internal memory + uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(plaintext); + TEST_ASSERT_NOT_NULL(decryptedtext); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key_256, 256); + + memset(plaintext, 0x3A, SZ); + memset(decryptedtext, 0x0, SZ); + + // Encrypt + mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_ENCRYPT, SZ, &nc_off, nonce, plaintext, chipertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32); + + // Decrypt + nc_off = 0; + memcpy(nonce, iv, 16); + mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_DECRYPT, SZ, &nc_off, nonce, chipertext, decryptedtext); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); + + mbedtls_aes_free(&ctx); + free(plaintext); + free(chipertext); + free(decryptedtext); +} + +static void aes_ctr_stream_test(void) +{ + const unsigned SZ = 100; + mbedtls_aes_context ctx; + uint8_t nonce[16]; + uint8_t key[16]; + uint8_t stream_block[16]; + + /* Cipher produced via this Python: + import os, binascii + from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + from cryptography.hazmat.backends import default_backend + key = b'\x44' * 16 + nonce = b'\xee' * 16 + cipher = Cipher(algorithms.AES(key), modes.CTR(nonce), backend=default_backend()) + encryptor = cipher.encryptor() + ct = encryptor.update(b'\xaa' * 100) + encryptor.finalize() + ct_arr = "" + for idx, b in enumerate(ct): + if idx % 8 == 0: + ct_arr += '\n' + ct_arr += "0x{}, ".format(binascii.hexlify(b)) + print(ct_arr) + */ + const uint8_t expected_cipher[] = { + 0xc5, 0x78, 0xa7, 0xb4, 0xf3, 0xb9, 0xcb, 0x8b, + 0x09, 0xe0, 0xd6, 0x89, 0x14, 0x6a, 0x19, 0x09, + 0xde, 0xaf, 0x37, 0x19, 0x32, 0x4d, 0xca, 0xf6, + 0xff, 0x6e, 0xd2, 0x5d, 0x87, 0x51, 0xaa, 0x8c, + 0x1c, 0xe3, 0x3b, 0xbb, 0x18, 0xf5, 0xa0, 0x1b, + 0xdc, 0x29, 0x52, 0x63, 0xf6, 0x5d, 0x49, 0x85, + 0x29, 0xf1, 0xf0, 0x69, 0x8f, 0xa6, 0x9f, 0x38, + 0x5c, 0xdd, 0x26, 0xf8, 0x9d, 0x40, 0xa1, 0xff, + 0x52, 0x46, 0xe1, 0x72, 0x70, 0x39, 0x73, 0xff, + 0xd0, 0x5e, 0xe5, 0x3f, 0xc5, 0xed, 0x5c, 0x18, + 0xa7, 0x84, 0xd8, 0xdf, 0x9d, 0xb5, 0x06, 0xb1, + 0xa7, 0xcf, 0x2e, 0x7a, 0x51, 0xfc, 0x44, 0xc5, + 0xb9, 0x5f, 0x22, 0x47, + }; + + + memset(nonce, 0xEE, 16); + memset(key, 0x44, 16); + + // allocate internal memory + uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(plaintext); + TEST_ASSERT_NOT_NULL(decryptedtext); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key, 128); + memset(plaintext, 0xAA, SZ); + + /* Test that all the end results are the same + no matter how many bytes we encrypt each call + */ + for (int bytes_to_process = 1; bytes_to_process < SZ; bytes_to_process++) { + ESP_LOGD("test", "bytes_to_process %d", bytes_to_process); + memset(nonce, 0xEE, 16); + memset(chipertext, 0x0, SZ); + memset(decryptedtext, 0x0, SZ); + + size_t offset = 0; + // Encrypt + for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { + // Limit length of last call to avoid exceeding buffer size + size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process; + + mbedtls_aes_crypt_ctr(&ctx, length, &offset, nonce, + stream_block, plaintext + idx, chipertext + idx ); + } + ESP_LOG_BUFFER_HEXDUMP("expected", expected_cipher, SZ, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEXDUMP("actual ", chipertext, SZ, ESP_LOG_DEBUG); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ); + + // Decrypt + memset(nonce, 0xEE, 16); + memset(decryptedtext, 0x22, SZ); + offset = 0; + for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { + // Limit length of last call to avoid exceeding buffer size + size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process; + mbedtls_aes_crypt_ctr(&ctx, length, &offset, nonce, + stream_block, chipertext + idx, decryptedtext + idx ); + } + ESP_LOG_BUFFER_HEXDUMP("decrypted", decryptedtext, SZ, ESP_LOG_DEBUG); + TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); + } + + mbedtls_aes_free(&ctx); + free(plaintext); + free(chipertext); + free(decryptedtext); +} + +TEST_CASE("mbedtls CTR stream test", "[aes]") +{ + aes_ctr_stream_test(); +} + + +TEST_CASE("mbedtls OFB stream test", "[aes]") +{ + const unsigned SZ = 100; + mbedtls_aes_context ctx; + uint8_t iv[16]; + uint8_t key[16]; + + /* Cipher produced via this Python: + import os, binascii + from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + from cryptography.hazmat.backends import default_backend + key = b'\x44' * 16 + iv = b'\xee' * 16 + cipher = Cipher(algorithms.AES(key), modes.OFB(iv), backend=default_backend()) + encryptor = cipher.encryptor() + ct = encryptor.update(b'\xaa' * 100) + encryptor.finalize() + ct_arr = "" + for idx, b in enumerate(ct): + if idx % 8 == 0: + ct_arr += '\n' + ct_arr += "0x{}, ".format(binascii.hexlify(b)) + print(ct_arr) + */ + const uint8_t expected_cipher[] = { + 0xc5, 0x78, 0xa7, 0xb4, 0xf3, 0xb9, 0xcb, 0x8b, + 0x09, 0xe0, 0xd6, 0x89, 0x14, 0x6a, 0x19, 0x09, + 0x0a, 0x33, 0x8b, 0xab, 0x82, 0xcb, 0x20, 0x8f, + 0x74, 0x2a, 0x6c, 0xb3, 0xc6, 0xe8, 0x18, 0x89, + 0x09, 0xb6, 0xaf, 0x20, 0xcd, 0xea, 0x74, 0x14, + 0x48, 0x61, 0xe8, 0x4d, 0x50, 0x12, 0x9f, 0x5e, + 0xb8, 0x10, 0x53, 0x3b, 0x74, 0xd9, 0xd0, 0x95, + 0x13, 0xdc, 0x14, 0xcf, 0x0c, 0xa1, 0x90, 0xfd, + 0xa2, 0x58, 0x12, 0xb2, 0x00, 0x2c, 0x5b, 0x7a, + 0x2a, 0x76, 0x80, 0x20, 0x82, 0x39, 0xa2, 0x21, + 0xf8, 0x7a, 0xec, 0xae, 0x82, 0x6a, 0x5c, 0xd3, + 0x04, 0xd9, 0xbd, 0xe4, 0x53, 0xc9, 0xdf, 0x67, + 0xaa, 0x5c, 0xaf, 0xa6, + }; + + + memset(key, 0x44, 16); + + // allocate internal memory + uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(plaintext); + TEST_ASSERT_NOT_NULL(decryptedtext); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key, 128); + memset(plaintext, 0xAA, SZ); + + /* Test that all the end results are the same + no matter how many bytes we encrypt each call + */ + + for (int bytes_to_process = 1; bytes_to_process < SZ; bytes_to_process++) { + ESP_LOGD("test", "bytes_to_process %d", bytes_to_process); + // Encrypt + memset(iv, 0xEE, 16); + size_t offset = 0; + for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { + // Limit length of last call to avoid exceeding buffer size + size_t length = ( (idx + bytes_to_process) > SZ) ? (SZ - idx) : bytes_to_process; + mbedtls_aes_crypt_ofb(&ctx, length, &offset, iv, plaintext + idx, chipertext + idx); + + } + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ); + + // Decrypt + memset(iv, 0xEE, 16); + memset(decryptedtext, 0x22, SZ); + offset = 0; + for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { + // Limit length of last call to avoid exceeding buffer size + size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process; + mbedtls_aes_crypt_ofb(&ctx, length, &offset, iv, chipertext + idx, decryptedtext + idx); + } + TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); + } + + mbedtls_aes_free(&ctx); + free(plaintext); + free(chipertext); + free(decryptedtext); +} + +TEST_CASE("mbedtls CFB8 stream test", "[aes]") +{ + const unsigned SZ = 32; + mbedtls_aes_context ctx; + uint8_t iv[16]; + uint8_t key[16]; + + /* Cipher produced via this Python: + import os, binascii + from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + from cryptography.hazmat.backends import default_backend + key = b'\x44' * 16 + iv = b'\xee' * 16 + cipher = Cipher(algorithms.AES(key), modes.CFB8(iv), backend=default_backend()) + encryptor = cipher.encryptor() + ct = encryptor.update(b'\xaa' * 100) + encryptor.finalize() + ct_arr = "" + for idx, b in enumerate(ct): + if idx % 8 == 0: + ct_arr += '\n' + ct_arr += "0x{}, ".format(binascii.hexlify(b)) + print(ct_arr) + */ + const uint8_t expected_cipher[] = { + 0xc5, 0x2f, 0xb0, 0x9b, 0x94, 0x9c, 0xa4, 0x5c, + 0x0f, 0x4d, 0xa1, 0x9d, 0xd1, 0x19, 0xfc, 0x04, + 0xe2, 0x7f, 0x04, 0x82, 0x6a, 0xa3, 0x61, 0xbb, + 0x07, 0x6f, 0xac, 0xb9, 0xdf, 0x00, 0xf9, 0xa8, + 0xc4, 0xbe, 0x9d, 0x4d, 0xd9, 0x42, 0x8a, 0x83, + 0x12, 0x8b, 0xeb, 0xd7, 0x88, 0x70, 0x8a, 0xed, + 0x46, 0x81, 0x5b, 0x4c, 0x14, 0x67, 0xe0, 0xfb, + 0xab, 0x34, 0x90, 0x85, 0x24, 0xd2, 0x6b, 0x64, + 0xdf, 0x1d, 0x04, 0xfd, 0x69, 0xf6, 0x30, 0xbe, + 0xa6, 0xac, 0x0b, 0x54, 0x25, 0x24, 0x67, 0xd6, + 0x09, 0xb1, 0x8f, 0x91, 0x63, 0xbd, 0xdf, 0xa1, + 0x8a, 0xa3, 0x2e, 0xeb, 0x15, 0x7d, 0xe5, 0x37, + 0xe5, 0x5a, 0x9f, 0xa5, + }; + + + memset(key, 0x44, 16); + + // allocate internal memory + uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(plaintext); + TEST_ASSERT_NOT_NULL(decryptedtext); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key, 128); + memset(plaintext, 0xAA, SZ); + + /* Test that all the end results are the same + no matter how many bytes we encrypt each call + */ + + for (int bytes_to_process = 1; bytes_to_process < SZ; bytes_to_process++) { + memset(iv, 0xEE, 16); + for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { + // Limit length of last call to avoid exceeding buffer size + size_t length = ( (idx + bytes_to_process) > SZ) ? (SZ - idx) : bytes_to_process; + mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_ENCRYPT, length, iv, plaintext + idx, chipertext + idx); + + } + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ); + + memset(iv, 0xEE, 16); + for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { + // Limit length of last call to avoid exceeding buffer size + size_t length = ( (idx + bytes_to_process) > SZ) ? (SZ - idx) : bytes_to_process; + mbedtls_aes_crypt_cfb8(&ctx, MBEDTLS_AES_DECRYPT, length, iv, chipertext + idx, decryptedtext + idx); + + } + TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); + } + + mbedtls_aes_free(&ctx); + free(plaintext); + free(chipertext); + free(decryptedtext); +} + +TEST_CASE("mbedtls CFB128 stream test", "[aes]") +{ + const unsigned SZ = 32; + mbedtls_aes_context ctx; + uint8_t iv[16]; + uint8_t key[16]; + + /* Cipher produced via this Python: + import os, binascii + from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + from cryptography.hazmat.backends import default_backend + key = b'\x44' * 16 + iv = b'\xee' * 16 + cipher = Cipher(algorithms.AES(key), modes.CFB(iv), backend=default_backend()) + encryptor = cipher.encryptor() + ct = encryptor.update(b'\xaa' * 100) + encryptor.finalize() + ct_arr = "" + for idx, b in enumerate(ct): + if idx % 8 == 0: + ct_arr += '\n' + ct_arr += "0x{}, ".format(binascii.hexlify(b)) + print(ct_arr) + */ + const uint8_t expected_cipher[] = { + 0xc5, 0x78, 0xa7, 0xb4, 0xf3, 0xb9, 0xcb, 0x8b, + 0x09, 0xe0, 0xd6, 0x89, 0x14, 0x6a, 0x19, 0x09, + 0xf9, 0x08, 0x7e, 0xe1, 0x92, 0x8a, 0x7c, 0xa4, + 0x25, 0xa5, 0xa7, 0x43, 0x24, 0x8d, 0x85, 0x3e, + 0x99, 0x28, 0xeb, 0x36, 0x59, 0x74, 0x69, 0x0e, + 0x09, 0x9f, 0x4e, 0xc0, 0x6d, 0xc3, 0x2b, 0x80, + 0x01, 0xad, 0xa1, 0x0c, 0x99, 0x90, 0x8b, 0x07, + 0xd6, 0x00, 0xf0, 0x32, 0xd7, 0x6b, 0xa1, 0xf1, + 0x4d, 0x14, 0xd0, 0x28, 0xde, 0x64, 0x23, 0x71, + 0xf4, 0x23, 0x61, 0x12, 0x71, 0xbe, 0x03, 0x74, + 0x99, 0x81, 0x9d, 0x65, 0x48, 0xd9, 0xd4, 0x67, + 0xd1, 0x31, 0xe8, 0x44, 0x27, 0x17, 0xd4, 0x2d, + 0x3d, 0x59, 0xf7, 0xd3, + }; + + + memset(key, 0x44, 16); + + // allocate internal memory + uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(plaintext); + TEST_ASSERT_NOT_NULL(decryptedtext); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key, 128); + memset(plaintext, 0xAA, SZ); + + /* Test that all the end results are the same + no matter how many bytes we encrypt each call + */ + + //for (int bytes_to_process = 1; bytes_to_process < SZ; bytes_to_process++) { + int bytes_to_process = 17; + size_t offset = 0; + memset(iv, 0xEE, 16); + for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { + // Limit length of last call to avoid exceeding buffer size + size_t length = ( (idx + bytes_to_process) > SZ) ? (SZ - idx) : bytes_to_process; + mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_ENCRYPT, length, &offset, iv, plaintext + idx, chipertext + idx); + + } + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ); + + offset = 0; + memset(iv, 0xEE, 16); + for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { + // Limit length of last call to avoid exceeding buffer size + size_t length = ( (idx + bytes_to_process) > SZ) ? (SZ - idx) : bytes_to_process; + mbedtls_aes_crypt_cfb128(&ctx, MBEDTLS_AES_DECRYPT, length, &offset, iv, chipertext + idx, decryptedtext + idx); + + } + TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); + + mbedtls_aes_free(&ctx); + free(plaintext); + free(chipertext); + free(decryptedtext); +} + +/* Cipher produced via this Python: + import os, binascii + from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + from cryptography.hazmat.backends import default_backend + key = b'\x44' * 16 + nonce = b'\xee' * 16 + cipher = Cipher(algorithms.AES(key), modes.CTR(nonce), backend=default_backend()) + encryptor = cipher.encryptor() + ct = encryptor.update(b'\xaa' * 100) + encryptor.finalize() + ct_arr = "" + for idx, b in enumerate(ct): + if idx % 8 == 0: + ct_arr += '\n' + ct_arr += "0x{}, ".format(binascii.hexlify(b)) + print(ct_arr) +*/ + +/* Test the case where the input and output buffers point to the same location */ +TEST_CASE("mbedtls CTR, input buf = output buf", "[aes]") +{ + const unsigned SZ = 1000; + mbedtls_aes_context ctx; + uint8_t nonce[16]; + uint8_t stream_block[16]; + size_t nc_off = 0; + + const uint8_t expected_cipher_end[] = { + 0xd4, 0xdc, 0x4f, 0x8f, 0xfe, 0x86, 0xee, 0xb5, + 0x14, 0x7f, 0xba, 0x30, 0x25, 0xa6, 0x7f, 0x6c, + 0xb5, 0x73, 0xaf, 0x90, 0xd7, 0xff, 0x36, 0xba, + 0x2b, 0x1d, 0xec, 0xb9, 0x38, 0xfa, 0x0d, 0xeb, + }; + + memcpy(nonce, iv, 16); + + // allocate internal memory + uint8_t *buf = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(buf); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key_256, 256); + + memset(buf, 0x3A, SZ); + + // Encrypt + mbedtls_aes_crypt_ctr(&ctx, SZ, &nc_off, nonce, stream_block, buf, buf); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, buf + SZ - 32, 32); + + // Decrypt + nc_off = 0; + memcpy(nonce, iv, 16); + mbedtls_aes_crypt_ctr(&ctx, SZ, &nc_off, nonce, stream_block, buf, buf); + + for (int i = 0; i < SZ; i++) { + TEST_ASSERT_EQUAL_HEX8(0x3A, buf[i]); + } + + mbedtls_aes_free(&ctx); + free(buf); +} + +TEST_CASE("mbedtls OFB, chained DMA descriptors", "[aes]") +{ + // Max bytes in a single DMA descriptor is 4095 + const unsigned SZ = 6000; + mbedtls_aes_context ctx; + uint8_t nonce[16]; + size_t nc_off = 0; + + const uint8_t expected_cipher_end[] = { + 0xfe, 0xfa, 0xc9, 0x26, 0xb5, 0xc9, 0xea, 0xb0, + 0xdd, 0x1e, 0xe7, 0x0e, 0xfa, 0x5b, 0x4b, 0x94, + 0xaa, 0x5f, 0x60, 0x1e, 0xb2, 0x19, 0x3c, 0x2e, + 0xf6, 0x73, 0x56, 0x9f, 0xa7, 0xd5, 0xb7, 0x21, + }; + + memcpy(nonce, iv, 16); + + // allocate internal memory + uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(plaintext); + TEST_ASSERT_NOT_NULL(decryptedtext); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key_256, 256); + + memset(plaintext, 0x3A, SZ); + memset(decryptedtext, 0x0, SZ); + + // Encrypt + mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, plaintext, chipertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32); + + + // Decrypt + nc_off = 0; + memcpy(nonce, iv, 16); + mbedtls_aes_crypt_ofb(&ctx, SZ, &nc_off, nonce, chipertext, decryptedtext); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); + + mbedtls_aes_free(&ctx); + free(plaintext); + free(chipertext); + free(decryptedtext); +} + + + +const uint8_t expected_cipher_ctr_end[] = { + 0x93, 0xca, 0xe0, 0x44, 0x96, 0x6d, 0xcb, 0xb2, + 0xcf, 0x8a, 0x8d, 0x73, 0x8c, 0x6b, 0xfa, 0x4d, + 0xd6, 0xc4, 0x18, 0x49, 0xdd, 0xc6, 0xbf, 0xc2, + 0xb9, 0xf0, 0x09, 0x69, 0x45, 0x42, 0xc6, 0x05, +}; + + +void aes_ctr_alignment_test(uint32_t input_buf_caps, uint32_t output_buf_caps) +{ + mbedtls_aes_context ctx; + uint8_t nonce[16]; + uint8_t key[16]; + uint8_t stream_block[16]; + size_t SZ = 32*200; + size_t ALIGNMENT_SIZE_BYTES = 64; + memset(nonce, 0x2F, 16); + memset(key, 0x1E, 16); + + // allocate memory according the requested caps + uint8_t *chipertext = heap_caps_malloc(SZ + ALIGNMENT_SIZE_BYTES, output_buf_caps); + uint8_t *plaintext = heap_caps_malloc(SZ + ALIGNMENT_SIZE_BYTES, input_buf_caps); + uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(plaintext); + TEST_ASSERT_NOT_NULL(decryptedtext); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key, 128); + memset(plaintext, 0x26, SZ + ALIGNMENT_SIZE_BYTES); + + size_t offset; + + /* Shift buffers and test for all different misalignments */ + for (int i = 0; i < ALIGNMENT_SIZE_BYTES; i++ ) { + // Encrypt with input buffer in external ram + offset = 0; + memset(nonce, 0x2F, 16); + mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, plaintext + i, chipertext + i); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_ctr_end, chipertext + i + SZ - 32, 32); + + // Decrypt + offset = 0; + memset(nonce, 0x2F, 16); + // Decrypt with input buffer in instruction memory, the crypto DMA can't access this + mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, chipertext + i, decryptedtext); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); + + } + + mbedtls_aes_free(&ctx); + free(plaintext); + free(chipertext); + free(decryptedtext); +} + +TEST_CASE("mbedtls AES internal mem alignment tests", "[aes]") +{ + uint32_t internal_dma_caps = MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL; + aes_ctr_alignment_test(internal_dma_caps, internal_dma_caps); +} + + +#ifdef CONFIG_SPIRAM_USE_MALLOC + +void aes_psram_one_buf_ctr_test(void) +{ + mbedtls_aes_context ctx; + uint8_t nonce[16]; + uint8_t key[16]; + uint8_t stream_block[16]; + size_t SZ = 32*200; + size_t ALIGNMENT_SIZE_BYTES = 32; + memset(nonce, 0x2F, 16); + memset(key, 0x1E, 16); + + // allocate external memory + uint8_t *buf = heap_caps_malloc(SZ + ALIGNMENT_SIZE_BYTES, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + + TEST_ASSERT_NOT_NULL(buf); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key, 128); + memset(buf, 0x26, SZ + ALIGNMENT_SIZE_BYTES); + + size_t offset; + + /* Shift buffers and test for all different misalignments */ + for (int i = 0; i < ALIGNMENT_SIZE_BYTES; i++ ) { + // Encrypt with input buffer in external ram + offset = 0; + memset(buf, 0x26, SZ + ALIGNMENT_SIZE_BYTES); + memset(nonce, 0x2F, 16); + mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, buf + i, buf + i); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_ctr_end, buf + i + SZ - 32, 32); + + // Decrypt + offset = 0; + memset(nonce, 0x2F, 16); + // Decrypt with input buffer in instruction memory, the crypto DMA can't access this + mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, buf + i, buf); + + TEST_ASSERT_EACH_EQUAL_HEX8(0x26, buf + i, SZ - i); + + } + mbedtls_aes_free(&ctx); + free(buf); +} + + +const uint8_t long_input[] = { + 0xf7, 0xe6, 0x6b, 0x8d, 0x2e, 0xbf, 0x88, 0xd6, + 0xb0, 0x77, 0xdf, 0x72, 0xbf, 0xa8, 0x0, 0x55, + 0xd5, 0xd1, 0x49, 0xa3, 0x2c, 0xc, 0xfe, 0xdb, + 0x17, 0x37, 0xa4, 0x1d, 0x70, 0x6b, 0x99, 0xf5, + 0x9e, 0x6, 0xad, 0x6c, 0xe0, 0x3b, 0xfa, 0x50, + 0x28, 0xb2, 0x62, 0xf2, 0x99, 0x3a, 0xcc, 0xe4, + 0x86, 0x5f, 0x1, 0xf8, 0x69, 0xd7, 0xf5, 0xb2, + 0x8a, 0x5f, 0x5c, 0x38, 0x9f, 0x8a, 0xb8, 0x8c, + 0xea, 0x6, 0xe1, 0x68, 0xff, 0xaf, 0x5d, 0xd9, + 0x1f, 0xa5, 0x5c, 0x8c, 0x52, 0xa1, 0x5f, 0x45, + 0x55, 0xcb, 0x76, 0x59, 0x8f, 0xfe, 0x36, 0xd0, + 0x85, 0x1f, 0x8, 0x90, 0x6f, 0x62, 0xb1, 0x1a, + 0xde, 0x75, 0xab, 0x90, 0xb7, 0x75, 0xe9, 0xa0, + 0xa9, 0xb0, 0xac, 0x61, 0x5, 0x6d, 0x9a, 0xe3, + 0x3b, 0x43, 0x61, 0x13, 0x8c, 0x3a, 0xa0, 0xaa, + 0x91, 0xea, 0x3e, 0xe1, 0x87, 0x35, 0xff, 0x90, + 0xe2, 0x43, 0xa3, 0x70, 0x57, 0x65, 0x2d, 0xa2, + 0x65, 0xe6, 0xde, 0xb0, 0x52, 0x85, 0x5b, 0xb8, + 0x3, 0x8, 0x63, 0x8b, 0xa1, 0xc2, 0xe1, 0x35, + 0x2e, 0xba, 0xe0, 0x84, 0x56, 0x52, 0x5f, 0x12, + 0xd3, 0x22, 0x8d, 0xa5, 0xbb, 0xe1, 0xd3, 0xfc, + 0x18, 0x1c, 0x90, 0x3b, 0x79, 0xe, 0xab, 0x2d, + 0x5e, 0xb0, 0x7, 0xbb, 0x46, 0x73, 0x1d, 0x35, + 0xd9, 0xc5, 0xa7, 0x87, 0x80, 0xf7, 0xee, 0x29, + 0xb5, 0x17, 0xf3, 0xaf, 0x30, 0xe5, 0x19, 0x50, + 0xf9, 0x5d, 0x2b, 0xc3, 0xc0, 0xda, 0x8f, 0xca, + 0x3c, 0x4d, 0xd5, 0xd7, 0x6c, 0xd2, 0x36, 0xa4, + 0x22, 0x8, 0x66, 0x48, 0x31, 0xb4, 0x3d, 0xc2, + 0xf6, 0x6b, 0xce, 0xf0, 0x12, 0xe4, 0x38, 0x5c, + 0xd8, 0x71, 0xea, 0x30, 0x52, 0xdf, 0x34, 0x62, + 0xdc, 0xb4, 0x30, 0xe, 0x74, 0xc, 0x5, 0x14, + 0xf, 0x47, 0x25, 0x5, 0x72, 0xc9, 0x14, 0x7c, + 0x1f, 0x6e, 0xdb, 0x6f, 0x83, 0x6, 0xa0, 0xb2, + 0x7f, 0x29, 0xe6, 0xb6, 0xe3, 0x11, 0x23, 0x4b, + 0x68, 0x92, 0xa, 0x49, 0xb5, 0x9d, 0x5d, 0x39, + 0x90, 0xff, 0x9, 0xa0, 0xa, 0x69, 0x6b, 0x2, + 0x18, 0xfb, 0xca, 0x5a, 0x91, 0x1a, 0xd9, 0x19, + 0x6b, 0xd4, 0x92, 0xd3, 0xd9, 0x7, 0xce, 0xcb, + 0xc7, 0xf3, 0xa1, 0x33, 0xcd, 0xa9, 0xb1, 0x44, + 0x8c, 0x93, 0xcd, 0xac, 0xc1, 0x44, 0x12, 0x48, + 0x95, 0x3, 0xdf, 0xc, 0x2f, 0xfc, 0x34, 0x8d, + 0x3, 0xde, 0xc1, 0xed, 0xdc, 0xf0, 0xfa, 0xa5, + 0xb2, 0x62, 0xcd, 0xa2, 0xbf, 0xf7, 0x7e, 0x47, + 0xb6, 0xcc, 0xe4, 0xa6, 0x4e, 0x51, 0xc6, 0x34, + 0xee, 0x83, 0x21, 0xb7, 0xc2, 0xe3, 0x13, 0x92, + 0xfc, 0xc9, 0x6, 0x6b, 0x91, 0x76, 0x7b, 0x2e, + 0x1e, 0xa2, 0xe0, 0x17, 0xab, 0x10, 0xfa, 0xac, + 0xd1, 0x2, 0x33, 0xb0, 0xd3, 0x3d, 0xb9, 0xce, + 0xea, 0xe9, 0x93, 0x5c, 0x98, 0x14, 0x0, 0xc6, + 0x2c, 0xa6, 0xdb, 0x1f, 0xdc, 0x76, 0xfb, 0xeb, + 0x9d, 0x55, 0xa6, 0x5f, 0xd5, 0x8e, 0x13, 0x39, + 0x88, 0x58, 0xff, 0xe8, 0xb4, 0x98, 0x9e, 0x4b, + 0xe7, 0x46, 0xdc, 0x7a, 0x68, 0x5b, 0xa8, 0xc2, + 0xe5, 0xa9, 0x50, 0xe2, 0x8, 0x31, 0x6, 0x3e, + 0x8e, 0xaf, 0x80, 0x24, 0x4e, 0xbd, 0x73, 0x6d, + 0xd9, 0x4b, 0xb4, 0x3e, 0x84, 0x5e, 0x31, 0x8e, + 0xf7, 0xa8, 0x9b, 0x5e, 0x2c, 0xd5, 0xe9, 0x7c, + 0xca, 0xca, 0xfa, 0x8e, 0x87, 0xbf, 0xf5, 0xa3, + 0x2f, 0x73, 0x2f, 0xc0, 0x5f, 0x46, 0xf4, 0x2, + 0xfd, 0xd1, 0x23, 0x6f, 0xc2, 0xc1, 0xc0, 0x86, + 0x62, 0x43, 0xc3, 0x44, 0x3b, 0x2c, 0x3d, 0xc2, + 0xd5, 0xe0, 0x2, 0xae, 0x1, 0x5a, 0x9, 0x89, + 0x52, 0x34, 0xdf, 0xb1, 0x6c, 0x2b, 0x85, 0x77, + 0xa5, 0x83, 0xe3, 0xa5, 0x50, 0x13, 0x2f, 0xf3, + 0xa6, 0x83, 0x60, 0x33, 0xba, 0xd5, 0xd2, 0x96, + 0x8a, 0xcd, 0xee, 0xfa, 0x76, 0x2a, 0x63, 0xec, + 0x41, 0x3a, 0xf3, 0xe5, 0x9e, 0x1d, 0x5e, 0x46, + 0x8, 0xd7, 0xe2, 0x3a, 0x25, 0x6f, 0x37, 0x7e, + 0x0, 0x2d, 0x3d, 0x1b, 0x86, 0xf4, 0xbe, 0x0, + 0x3c, 0xda, 0x82, 0x4a, 0xa3, 0x8, 0x2a, 0x38, + 0x95, 0xe, 0x38, 0xf8, 0x18, 0x6c, 0x42, 0x6f, + 0x30, 0x19, 0x8e, 0x22, 0xf6, 0xb7, 0x18, 0xb7, + 0x93, 0xd, 0x54, 0x72, 0x4, 0x64, 0xc1, 0x19, + 0x76, 0x6e, 0xfc, 0x9e, 0xb0, 0x7c, 0x20, 0x37, + 0xb0, 0xcb, 0x82, 0x3a, 0x20, 0x1d, 0x12, 0x44, + 0xbf, 0x44, 0xc4, 0x4d, 0x33, 0x7e, 0x7b, 0xeb, + 0xd8, 0xb8, 0xa1, 0x75, 0x9e, 0x47, 0x99, 0x64, + 0x92, 0xd3, 0x21, 0x1d, 0x72, 0x63, 0xc7, 0xb3, + 0x3d, 0xfc, 0xb9, 0x4, 0x65, 0x18, 0x94, 0xcc, + 0x20, 0xfe, 0x6f, 0x66, 0x36, 0xba, 0x36, 0x2a, + 0x7, 0xf0, 0x5e, 0x8a, 0xf2, 0x7, 0x1e, 0x9e, + 0x47, 0x2a, 0xc3, 0x7d, 0x7a, 0x20, 0x3c, 0x30, + 0x6f, 0xbe, 0x43, 0x5e, 0x71, 0x6f, 0xd, 0xb8, + 0x3d, 0x1d, 0x3e, 0x18, 0x65, 0x62, 0x75, 0xe8, + 0x34, 0xfd, 0x72, 0xbb, 0xd9, 0x3f, 0xf0, 0xa2, + 0x55, 0xee, 0x91, 0x12, 0x88, 0xda, 0x7, 0x3d, + 0x44, 0x88, 0x70, 0x1f, 0xe0, 0xbe, 0x4b, 0x88, + 0xa8, 0x8e, 0x28, 0x7, 0x73, 0xfd, 0x3f, 0xff, + 0x3e, 0xb2, 0xb5, 0xdb, 0x18, 0x48, 0x9e, 0x73, + 0x6e, 0xd7, 0x24, 0xa9, 0x25, 0xdb, 0x4, 0xe0, + 0xe0, 0xf4, 0x45, 0xc0, 0x1b, 0x82, 0xdf, 0x4e, + 0x48, 0x60, 0x85, 0x9c, 0xd8, 0x90, 0x32, 0xca, + 0x4b, 0xf9, 0xb4, 0xb8, 0xe1, 0xfe, 0xd2, 0xe0, + 0xb2, 0xd6, 0xb8, 0x19, 0x38, 0x34, 0x17, 0x8d, + 0x5e, 0xdf, 0xf4, 0xf1, 0xac, 0x2c, 0x88, 0x7f, + 0x54, 0xbc, 0xf1, 0x39, 0xf2, 0xaf, 0x5a, 0xff, + 0xa7, 0x96, 0x0, 0xf0, 0x27, 0x79, 0x27, 0x2e, + 0x9c, 0xf1, 0x4b, 0xa3, 0xad, 0xdc, 0x8a, 0x2c, + 0x9, 0x4c, 0xd3, 0xcd, 0xd0, 0x2d, 0xb1, 0xec, + 0x4d, 0x68, 0x40, 0xb8, 0xc5, 0x5, 0xfa, 0xb2, + 0x61, 0xb8, 0x31, 0x5, 0xea, 0xb8, 0xa3, 0x34, + 0xa8, 0x8b, 0x3, 0x5b, 0x22, 0x93, 0xba, 0x91, + 0x33, 0x3f, 0x8b, 0x5e, 0xed, 0x86, 0x23, 0x95, + 0xbc, 0x9e, 0xdf, 0xa9, 0x8c, 0xca, 0xb9, 0x97, + 0x9b, 0xc5, 0xca, 0xf4, 0xff, 0x4d, 0x62, 0x52, + 0x1c, 0xd3, 0x4c, 0x42, 0xbf, 0x8a, 0x25, 0x47, + 0xc7, 0x9, 0x4e, 0xe0, 0xb1, 0x72, 0x7d, 0x2, + 0x8f, 0xca, 0x4f, 0x4, 0xc8, 0x74, 0x82, 0x8e, + 0x53, 0xfd, 0xa1, 0x37, 0xda, 0x29, 0x5c, 0xa3, + 0x83, 0xe9, 0xa8, 0xd8, 0x25, 0x27, 0xfe, 0xf7, + 0x41, 0xc4, 0xb0, 0xee, 0x1d, 0x89, 0x1c, 0xe7, + 0xef, 0x86, 0x68, 0xd8, 0x87, 0x4c, 0x4f, 0x49, + 0xeb, 0xbc, 0xb3, 0x81, 0xa7, 0xf4, 0xb4, 0x9b, + 0xc1, 0x52, 0x93, 0x7e, 0xdf, 0x75, 0x75, 0xfc, + 0x45, 0xb2, 0x86, 0xa9, 0x50, 0xb5, 0xa3, 0xf7, + 0x61, 0x60, 0xe4, 0x13, 0x99, 0xc0, 0xf8, 0x49, + 0x7b, 0x61, 0x8b, 0xa8, 0xfa, 0x77, 0x0, 0xe4, + 0x6, 0x9a, 0xc5, 0x51, 0xe4, 0xeb, 0xaf, 0x5f, + 0xb9, 0x5c, 0x74, 0xc8, 0xf8, 0x3e, 0x62, 0x26, + 0xe, 0xe5, 0x85, 0xca, 0x49, 0xa0, 0x2f, 0xf7, + 0x7, 0x99, 0x3e, 0x5c, 0xe0, 0x72, 0xfa, 0xd4, + 0x80, 0x2e, 0xd6, 0x40, 0x6, 0xde, 0x5f, 0xc5, + 0xc5, 0x1, 0xd, 0xbf, 0xdb, 0xb6, 0xb3, 0x92, + 0x76, 0xb3, 0x3f, 0x3d, 0x5d, 0x1, 0x23, 0xb8, + 0xa, 0xcb, 0x80, 0x17, 0x31, 0x19, 0xc7, 0x64, + 0x69, 0xf1, 0x99, 0x53, 0xe5, 0xf2, 0x9f, 0x9d, + 0x3c, 0xda, 0xcb, 0xa6, 0x94, 0x94, 0x44, 0xd3, + 0xc6, 0x8b, 0xb5, 0xae, 0x45, 0x25, 0xef, 0x2a, + 0x24, 0x1, 0x3a, 0xf6, 0xf, 0xe, 0xcb, 0x10, + 0xc4, 0xe0, 0xf4, 0x3d, 0xf4, 0xf5, 0xea, 0x9b, + 0xd1, 0x16, 0x1b, 0x62, 0x11, 0x3e, 0x20, 0x3a, + 0x68, 0xc8, 0xf0, 0xe, 0x55, 0xbe, 0x51, 0x4d, + 0xbe, 0x1f, 0x4f, 0xda, 0x84, 0xda, 0xc4, 0x9e, + 0x24, 0xd7, 0x46, 0x82, 0x56, 0x4e, 0x61, 0x63, + 0xda, 0x18, 0xea, 0xc6, 0xc3, 0x21, 0x89, 0x18, + 0xe, 0x87, 0xb7, 0x91, 0xfe, 0x8d, 0xe, 0xac, + 0x75, 0x58, 0xe5, 0x9f, 0x1f, 0x93, 0xa6, 0x49, + 0x24, 0xa2, 0xc6, 0xe8, 0x9d, 0x9c, 0x6d, 0xc1, + 0xf, 0xfc, 0xe3, 0x57, 0xd3, 0xc2, 0x10, 0x91, + 0x9a, 0xa8, 0xaa, 0xd7, 0xf, 0xaa, 0x75, 0x90, + 0x4a, 0x10, 0xef, 0xb6, 0xdd, 0x6c, 0xd5, 0x1a, + 0xe3, 0xbb, 0xe0, 0x64, 0x44, 0xc, 0x59, 0xa1, + 0xef, 0x3, 0x52, 0xac, 0xa4, 0x85, 0x3e, 0x40, + 0xee, 0x5c, 0xef, 0xcf, 0xb1, 0xaa, 0x88, 0xe5, + 0x56, 0xb8, 0xcd, 0x87, 0xc7, 0xc6, 0xd3, 0xb4, + 0x85, 0x8f, 0x2a, 0xc9, 0xcd, 0x8a, 0x8b, 0x25, + 0x12, 0x71, 0x76, 0xc9, 0xaa, 0x62, 0x75, 0x80, + 0x6e, 0xa3, 0xf9, 0xa5, 0xfc, 0x90, 0xac, 0x28, + 0x13, 0x82, 0xbb, 0x5d, 0xa6, 0x93, 0x47, 0xd4, + 0xf, 0x3b, 0x19, 0xf6, 0x81, 0xdb, 0x55, 0xb0, + 0x47, 0x75, 0x63, 0x93, 0xb4, 0xdd, 0xf0, 0xaf, + 0xb7, 0x44, 0xcb, 0x7, 0x7b, 0x35, 0xc5, 0xe4, + 0x45, 0xfe, 0xbb, 0x11, 0x1a, 0x90, 0x96, 0x3a, + 0x7, 0x2a, 0xef, 0x9c, 0xc, 0xae, 0x38, 0x26, + 0xef, 0xc2, 0xc3, 0x53, 0xfa, 0x54, 0xcf, 0x6f, + 0xf7, 0xa, 0xea, 0x19, 0xa8, 0xf, 0xbd, 0xa7, + 0x3f, 0xcd, 0x38, 0x2c, 0xf3, 0x97, 0xfb, 0xdb, + 0xcb, 0xc5, 0x83, 0x80, 0x91, 0x3d, 0xc7, 0x29, + 0x67, 0x16, 0xa5, 0xd1, 0x41, 0xd0, 0xa1, 0x9b, + 0xde, 0x13, 0x83, 0x12, 0x36, 0x75, 0x81, 0x71, + 0x6b, 0xbc, 0x72, 0xcb, 0x37, 0x4, 0x6, 0x7c, + 0x3a, 0x22, 0x2b, 0xa, 0x11, 0xd3, 0x33, 0x8f, + 0x3, 0x54, 0x8e, 0x79, 0xb6, 0x36, 0x93, 0x92, + 0xb8, 0xf, 0x24, 0x4a, 0xd3, 0xd5, 0x27, 0x66, + 0xd1, 0xde, 0xe3, 0xaa, 0x4b, 0x2a, 0xe9, 0x22, + 0x9b, 0xbf, 0x6e, 0x9a, 0xf7, 0xa, 0x2f, 0x24, + 0x13, 0xd5, 0xd5, 0xbb, 0xa3, 0xba, 0x8f, 0xfc, + 0x28, 0xa8, 0xbe, 0xe6, 0x9f, 0xea, 0xed, 0xb1, + 0xba, 0xaf, 0xf, 0x1c, 0x1e, 0x51, 0xf8, 0xd7, + 0x1b, 0xa5, 0xa6, 0x63, 0x40, 0x6e, 0x3f, 0xa2, + 0x57, 0x6f, 0x57, 0xe4, 0x27, 0xc2, 0x3c, 0x33, + 0xc6, 0x9c, 0x24, 0xd0, 0x53, 0xc4, 0xfc, 0xed, + 0x8e, 0x1d, 0xf, 0xc3, 0x86, 0x9, 0x3d, 0x1d, + 0xc2, 0xdb, 0x24, 0x1a, 0x65, 0xf4, 0x30, 0xa5, + 0xc, 0x48, 0x37, 0xc5, 0x53, 0x35, 0x3b, 0xab, + 0xd, 0x96, 0x30, 0xd7, 0x1d, 0x66, 0x18, 0xc2, + 0x47, 0x3a, 0xef, 0xbe, 0x2e, 0xe4, 0x54, 0x9d, + 0xc4, 0xa5, 0xb9, 0xb3, 0x4c, 0x12, 0x73, 0x35, + 0xf0, 0x7, 0xe, 0x36, 0x88, 0xb2, 0x4b, 0x29, + 0xb, 0x4e, 0x84, 0x11, 0xaa, 0x9a, 0x3e, 0xb1, + 0xd7, 0xec, 0xfb, 0x7f, 0x10, 0x70, 0x1f, 0x26, + 0xf0, 0x27, 0x46, 0x5d, 0x4, 0x51, 0x97, 0x29, + 0xb4, 0x66, 0x39, 0x1, 0x82, 0x47, 0xd8, 0x5f, + 0xa9, 0xb3, 0xa1, 0xb8, 0xde, 0x1, 0xe1, 0xc4, + 0x47, 0xc5, 0xe8, 0xe6, 0xbb, 0xc0, 0xb6, 0x41, + 0x55, 0x10, 0x79, 0xa8, 0xd0, 0xd, 0x1, 0x56, + 0x29, 0x6c, 0xa5, 0x96, 0x87, 0x59, 0x4b, 0xd, + 0xc8, 0x3, 0x5, 0xaa, 0xa9, 0x6a, 0xb1, 0x10, + 0xbc, 0x1, 0x68, 0xd3, 0xa5, 0x52, 0x41, 0xe1, + 0x1f, 0x53, 0x7, 0xc6, 0xad, 0xb8, 0xc4, 0xf0, + 0x28, 0xe9, 0x3, 0x3a, 0xee, 0xce, 0x2c, 0xe2, + 0xb0, 0xda, 0x78, 0x3d, 0x37, 0x7, 0x2d, 0x1f, + 0xf1, 0x47, 0x81, 0x4, 0x67, 0x6e, 0xd, 0xa1, + 0x2b, 0x4, 0xe8, 0xd9, 0xf4, 0xaf, 0x35, 0xca, + 0xa5, 0xd1, 0xe3, 0xec, 0xc5, 0x82, 0x50, 0x99, + 0x9a, 0xee, 0xea, 0x53, 0x41, 0x86, 0x97, 0x44, + 0xeb, 0x58, 0x43, 0x47, 0xe7, 0xa0, 0xd3, 0x28, + 0xfc, 0xe7, 0x13, 0x8b, 0x56, 0xe3, 0xdb, 0xa9, + 0xcd, 0x9, 0xc8, 0x7, 0x11, 0xeb, 0xbf, 0xac, + 0x76, 0x72, 0x60, 0xaf, 0x9c, 0xba, 0x8a, 0x64, + 0xfb, 0xf4, 0xab, 0x27, 0x29, 0xe7, 0xec, 0x69, + 0x21, 0xcb, 0x5b, 0x79, 0x56, 0x10, 0xc1, 0x8, + 0xd5, 0x5d, 0x93, 0xb1, 0x70, 0x88, 0xf2, 0x19, + 0x41, 0xc6, 0xc2, 0x84, 0xdd, 0xf0, 0xb3, 0x40, + 0x12, 0x71, 0x24, 0x54, 0xc4, 0x5e, 0xfb, 0x5f, + 0x47, 0x8c, 0xa9, 0x4, 0x5a, 0xd5, 0x61, 0x19, + 0xb5, 0x7f, 0xc9, 0xbd, 0x87, 0xb2, 0xcd, 0x57, + 0x99, 0x50, 0x67, 0x1d, 0xb0, 0x1d, 0x82, 0xdd, + 0xef, 0x32, 0x38, 0xb9, 0xc7, 0x86, 0xb4, 0xd2, + 0xd6, 0xe1, 0x33, 0xb2, 0xdb, 0x5e, 0xc2, 0xa3, + 0x49, 0xa6, 0x5f, 0x79, 0x32, 0x50, 0x41, 0x5b, + 0xd7, 0x87, 0x74, 0xf5, 0xc9, 0x9c, 0x78, 0xb7, + 0xb, 0x1f, 0x72, 0xba, 0xd9, 0x3a, 0x4d, 0x18, + 0x45, 0x1d, 0xad, 0xef, 0xc4, 0xdc, 0x30, 0xe8, + 0x2, 0xb1, 0x7f, 0x6c, 0x8f, 0xaa, 0xd0, 0x40, + 0x17, 0xe, 0x58, 0x93, 0x42, 0x49, 0x63, 0x77, + 0x48, 0x55, 0x90, 0x2f, 0x7c, 0x3b, 0xee, 0x3c, + 0xac, 0xd, 0xd8, 0x72, 0x23, 0xd7, 0xa5, 0x6e, + 0xb0, 0xd2, 0x91, 0x25, 0x60, 0x9a, 0x52, 0xab, + 0xbd, 0x63, 0xce, 0xba, 0xda, 0xb1, 0xd7, 0xc7, + 0x3d, 0x21, 0x4e, 0x9c, 0x5a, 0x1e, 0x8d, 0xf4, + 0xa, 0xdb, 0xd9, 0xf, 0x20, 0x7e, 0xfb, 0xbf, + 0x36, 0x9c, 0x4f, 0xbd, 0xf7, 0xdb, 0x5b, 0xa2, + 0x6, 0xb2, 0x0, 0xe2, 0xa2, 0x9e, 0x4e, 0x19, + 0xd4, 0x69, 0xa9, 0x51, 0x69, 0x8b, 0xf5, 0xe1, + 0xad, 0x89, 0x8, 0xc5, 0x4f, 0xac, 0x1b, 0x7d, + 0xe7, 0xa, 0x9, 0x7d, 0x34, 0xf5, 0x3f, 0x46, + 0x80, 0xb9, 0xb9, 0x45, 0x58, 0xcd, 0x6c, 0xb5, + 0x5f, 0x60, 0xeb, 0x5a, 0xe3, 0xa3, 0x8, 0x5e, + 0xb1, 0xc4, 0x73, 0xc5, 0xa5, 0x67, 0x56, 0xd3, + 0xc6, 0x8a, 0x55, 0x6b, 0xd7, 0xd7, 0xc, 0x20, + 0xe6, 0xc, 0x73, 0x8, 0x2, 0x4b, 0xfb, 0xdd, + 0x4d, 0x4e, 0xa8, 0xb8, 0xd8, 0x4b, 0x53, 0x2f, + 0xc2, 0xfb, 0x5d, 0xa1, 0x6a, 0x16, 0x6b, 0xe, + 0xf1, 0xa1, 0xa5, 0x5b, 0xdf, 0x9c, 0x23, 0xb5, + 0x94, 0x9c, 0xae, 0x7b, 0xbe, 0x42, 0xb5, 0x79, + 0x80, 0xc3, 0x43, 0x41, 0xa4, 0x1b, 0x18, 0xfc, + 0x52, 0xcf, 0x43, 0xc5, 0x80, 0x7b, 0xbd, 0xc1, + 0x20, 0x5e, 0x65, 0xec, 0xc5, 0xfc, 0x3, 0xec, + 0x8f, 0x61, 0x66, 0xf5, 0x15, 0x67, 0xc8, 0xb6, + 0xef, 0x9a, 0xba, 0xb7, 0xcb, 0x2c, 0xac, 0x1b, + 0x50, 0xda, 0xb6, 0x29, 0xa4, 0x37, 0xe9, 0x96, + 0xa0, 0x7, 0x7d, 0x49, 0xa6, 0xce, 0xf3, 0xf0, + 0x19, 0xdf, 0x61, 0xc7, 0xa4, 0x7b, 0x5a, 0xd4, + 0x99, 0xb2, 0x64, 0xe7, 0xd1, 0x6b, 0x7f, 0xe8, + 0xb8, 0xd3, 0x89, 0xee, 0x96, 0xc0, 0xed, 0x5d, + 0x7e, 0x48, 0x2, 0xd2, 0x25, 0xd0, 0x5, 0xef, + 0x93, 0x72, 0x7c, 0x8c, 0xbd, 0x6e, 0x49, 0xd3, + 0x38, 0x46, 0x1c, 0xff, 0x28, 0x4e, 0x1b, 0xad, + 0x39, 0x2f, 0x65, 0x26, 0xe2, 0x70, 0x3d, 0xb8, + 0x7a, 0xd3, 0x38, 0x38, 0xfc, 0x3a, 0x67, 0x78, + 0xdb, 0x9, 0xcb, 0xbf, 0xc9, 0xe1, 0xee, 0x69, + 0x2b, 0xd, 0xb1, 0x79, 0x13, 0xd0, 0xa5, 0x75, + 0x6, 0x8, 0x79, 0xa7, 0x7c, 0xc, 0xe7, 0x1b, + 0x9c, 0x36, 0x64, 0xbe, 0x20, 0x65, 0xa2, 0xd4, + 0xd9, 0xc, 0x68, 0xe, 0x88, 0x2b, 0x93, 0x60, + 0xf1, 0xa5, 0x82, 0xc5, 0x4d, 0x2b, 0x7d, 0x73, + 0xe9, 0x13, 0x8c, 0xc1, 0x8, 0xbd, 0x21, 0x65, + 0x77, 0x2f, 0x34, 0xb1, 0x97, 0x9f, 0xd8, 0x55, + 0xcf, 0x75, 0xc2, 0xf2, 0x41, 0x68, 0xc1, 0x9c, + 0x1c, 0xd7, 0x23, 0xbf, 0x83, 0x2a, 0x9, 0x66, + 0xce, 0x8f, 0xd2, 0x12, 0x79, 0x93, 0xef, 0x8, + 0x9b, 0xeb, 0x2f, 0xc, 0xe4, 0x5b, 0x71, 0x1a, + 0xef, 0x11, 0x65, 0xd8, 0x6d, 0x8c, 0x59, 0x53, + 0x70, 0x1d, 0xb5, 0x81, 0xff, 0xc0, 0x7d, 0x87, + 0xa5, 0x21, 0x5d, 0x9f, 0x63, 0xb2, 0xe7, 0xe9, + 0xd0, 0x49, 0x41, 0xc7, 0x3c, 0xe1, 0x2b, 0xb1, + 0xac, 0x15, 0xcd, 0xb0, 0xa8, 0xdc, 0xae, 0x3b, + 0xef, 0x32, 0x98, 0x8c, 0xc7, 0x40, 0xa6, 0x81, + 0x1, 0xa1, 0x7d, 0x89, 0x46, 0x99, 0x91, 0x24, + 0xce, 0xb2, 0x70, 0x82, 0x92, 0xf3, 0x60, 0x66, + 0x34, 0x6, 0x37, 0xad, 0x5c, 0xed, 0xc3, 0x27, + 0x68, 0x8c, 0x56, 0xe7, 0xf, 0x73, 0x5c, 0x7e, + 0x9e, 0xd0, 0x8c, 0x99, 0x5a, 0xb1, 0x15, 0x98, + 0xbb, 0x79, 0x9f, 0xd1, 0x69, 0xce, 0x76, 0x5, + 0xcb, 0x8e, 0x18, 0xb3, 0x84, 0x65, 0xa9, 0x2, + 0xbc, 0x43, 0x8b, 0x7e, 0xe9, 0xe2, 0xe6, 0x74, + 0x31, 0x8d, 0xe7, 0xa2, 0x42, 0x8f, 0xca, 0x38, + 0x59, 0x85, 0x25, 0x47, 0xd2, 0x86, 0x47, 0x9, + 0xc2, 0x11, 0x2, 0x91, 0xe6, 0xf3, 0x47, 0xc2, + 0x9c, 0x28, 0x2f, 0xbb, 0xac, 0xde, 0x9f, 0xd, + 0xc2, 0x96, 0x4f, 0x43, 0xca, 0x32, 0xed, 0x34, + 0xba, 0xad, 0xef, 0xbe, 0x68, 0xc7, 0xa2, 0x83, + 0xaf, 0xe, 0xd3, 0x72, 0x52, 0xd1, 0x76, 0x3d, + 0x9a, 0x98, 0x39, 0xf4, 0x3e, 0x14, 0x27, 0xff, + 0xb2, 0x37, 0x23, 0xc5, 0x6d, 0x66, 0xef, 0xaa, + 0xfe, 0xe7, 0xe4, 0x86, 0xa1, 0xe, 0x4e, 0x36, + 0x64, 0xb1, 0x67, 0xf, 0x94, 0x6f, 0x77, 0xd5, + 0xec, 0xe2, 0x5e, 0xc8, 0xe3, 0x64, 0x29, 0x92, + 0xd, 0x20, 0x34, 0x9f, 0x19, 0x6e, 0x85, 0xf8, + 0x48, 0x78, 0xb0, 0xf, 0x42, 0xb2, 0x8c, 0xea, + 0xc2, 0x4d, 0xd3, 0x23, 0xb, 0x4d, 0x20, 0x33, + 0xc7, 0x46, 0x0, 0x45, 0x37, 0xc6, 0xcb, 0xd0, + 0xec, 0x11, 0xc6, 0x74, 0x91, 0x7d, 0x6b, 0x54, + 0x56, 0x10, 0x8d, 0xd0, 0xce, 0xe8, 0x57, 0x3b, + 0x83, 0xd8, 0x25, 0x51, 0x79, 0x48, 0xa, 0xa5, + 0xc3, 0xe4, 0x65, 0x33, 0xb2, 0x89, 0xa6, 0x4c, + 0xe8, 0xc8, 0x9e, 0xce, 0xea, 0x2a, 0x55, 0x40, + 0xfc, 0x26, 0x29, 0xd4, 0x2d, 0x7e, 0xe1, 0xb1, + 0x4d, 0x65, 0x1, 0xe9, 0x98, 0xc9, 0xf4, 0x69, + 0x10, 0xd9, 0xa3, 0xf9, 0x34, 0xaf, 0x3c, 0x34, + 0x64, 0x23, 0xde, 0xb8, 0x1c, 0x33, 0x18, 0x74, + 0x67, 0xb4, 0x4a, 0x71, 0xa6, 0x89, 0x2, 0xfe, + 0xf7, 0xf1, 0x32, 0xc7, 0x98, 0xad, 0xe5, 0x10, + 0x98, 0x3c, 0x6c, 0xaf, 0x1f, 0x13, 0x3d, 0xcc, + 0xfc, 0x3b, 0x67, 0x33, 0x34, 0xc9, 0x31, 0xcd, + 0x3f, 0xd, 0x3c, 0x5a, 0xb6, 0xc2, 0x8, 0xea, + 0xe2, 0xae, 0xdd, 0xfc, 0x6f, 0xca, 0xb5, 0x67, + 0x11, 0xce, 0xd5, 0xda, 0x3a, 0x8b, 0x7, 0xf2, + 0xc0, 0x9e, 0x78, 0x18, 0x92, 0x9f, 0x64, 0x26, + 0x9f, 0x66, 0x62, 0x66, 0xa1, 0x7e, 0x3, 0xf5, + 0xb9, 0xe6, 0x74, 0x20, 0x88, 0xb7, 0x7e, 0x62, + 0x7a, 0x33, 0x21, 0x9, 0x9c, 0x91, 0x3b, 0x62, + 0x9, 0x46, 0xd3, 0xd1, 0x1f, 0xc5, 0x3a, 0x8f, + 0x69, 0x27, 0x2c, 0x7b, 0xec, 0xda, 0x79, 0xf1, + 0xc9, 0xe9, 0x98, 0xd0, 0xa, 0xc9, 0xf6, 0x37, + 0x28, 0xf8, 0xfc, 0xe, 0xdc, 0xf, 0xe9, 0x23, + 0xf6, 0x84, 0x25, 0x96, 0x2c, 0x24, 0x14, 0xd7, + 0xe2, 0x5e, 0x1c, 0x56, 0x7f, 0x99, 0x98, 0x62, + 0x76, 0xcc, 0x84, 0x44, 0xd6, 0xb9, 0x47, 0x2b, + 0x52, 0xfb, 0x42, 0x40, 0xf3, 0x63, 0xaf, 0xd4, + 0x10, 0x5, 0xf9, 0x3b, 0xc8, 0x53, 0xa9, 0x45, + 0xa4, 0x50, 0x41, 0x83, 0xe8, 0x4a, 0x9, 0xb6, + 0xf1, 0x77, 0x70, 0xe3, 0x61, 0x30, 0xd8, 0x90, + 0x49, 0x52, 0x4b, 0x4a, 0xf2, 0x66, 0x84, 0xaf, + 0x71, 0x1, 0x40, 0x66, 0xf6, 0x3, 0xc9, 0x23, + 0xb1, 0x1a, 0xc1, 0xb2, 0xf7, 0x35, 0x1a, 0xc9, + 0x3a, 0x75, 0xb1, 0xa7, 0x4, 0xff, 0x69, 0xa, + 0x90, 0x58, 0xd4, 0xf4, 0x16, 0x79, 0xe1, 0xae, + 0x39, 0x9d, 0xbb, 0x32, 0x6b, 0x3, 0xe2, 0xf5, + 0x73, 0x83, 0x7e, 0x3c, 0xf8, 0x29, 0xab, 0xcc, + 0xdc, 0xf0, 0x13, 0xdb, 0x86, 0x28, 0x88, 0x8e, + 0xde, 0x6a, 0x29, 0xf1, 0xea, 0x0, 0x83, 0x97, + 0x1, 0x32, 0x5f, 0xaa, 0x5b, 0x1b, 0xe4, 0x87, + 0xec, 0x90, 0x45, 0xc7, 0xc5, 0x6c, 0x11, 0x83, + 0x95, 0xab, 0xdd, 0x71, 0x69, 0x24, 0xc, 0x5c, + 0xc0, 0xf3, 0xc1, 0xb0, 0x5e, 0x1, 0x5e, 0x4, + 0xa1, 0x6e, 0x6e, 0x7d, 0x3f, 0x6f, 0xbd, 0x5d, + 0x9, 0x8f, 0x23, 0x53, 0x74, 0x4b, 0xa9, 0x53, + 0xd2, 0x10, 0xa1, 0xc0, 0x8e, 0x18, 0xa, 0x2f, + 0x88, 0x8d, 0x4b, 0xf8, 0xc2, 0x3d, 0xeb, 0x34, + 0x23, 0xa, 0x80, 0xc, 0x69, 0x21, 0x3, 0xc1, + 0x6f, 0xbe, 0xdf, 0xf6, 0x2c, 0x27, 0x77, 0xa2, + 0xc5, 0x5c, 0x9, 0x54, 0x5d, 0x4a, 0x4c, 0xb, + 0x6b, 0xb5, 0x88, 0x11, 0x42, 0x62, 0x39, 0x89, + 0x9e, 0x36, 0xd3, 0x91, 0xf6, 0x70, 0x18, 0x35, + 0x79, 0xaf, 0x73, 0xf3, 0x0, 0x75, 0x5a, 0xa3, + 0xce, 0xf1, 0x42, 0x80, 0x19, 0x5e, 0x42, 0x56, + 0x53, 0x85, 0xbb, 0xf4, 0x29, 0xac, 0x84, 0x1d, + 0x97, 0x1, 0x1c, 0xc4, 0x58, 0xcb, 0x33, 0xc4, + 0xdc, 0x1e, 0x59, 0x8f, 0x48, 0xa9, 0x59, 0xfd, + 0xaf, 0xa3, 0x5c, 0x19, 0x17, 0x6b, 0x46, 0x2d, + 0xab, 0x44, 0xa3, 0xcc, 0x1a, 0xaa, 0x23, 0x4e, + 0x58, 0x37, 0x7b, 0x11, 0x14, 0xc2, 0xf1, 0xc9, + 0x58, 0x99, 0xd3, 0x3c, 0xec, 0xb9, 0xbe, 0x17, + 0x3c, 0x8d, 0x1c, 0x87, 0x9d, 0xe1, 0xb9, 0xad, + 0x68, 0x36, 0xd5, 0xfc, 0x24, 0x9b, 0x34, 0x5, + 0x26, 0xac, 0x15, 0x9f, 0xd6, 0x70, 0x74, 0x6c, + 0x72, 0xf, 0x6, 0x6, 0x5a, 0xc, 0xc0, 0x78, + 0x47, 0x8e, 0xcf, 0xf2, 0xce, 0x8, 0xe2, 0xa4, + 0xc6, 0x7d, 0x2d, 0x70, 0x14, 0xe2, 0xc6, 0xfc, + 0x63, 0x7a, 0x42, 0x8c, 0x45, 0xae, 0xe8, 0x3b, + 0x30, 0x48, 0xda, 0x3e, 0x14, 0xb5, 0x8b, 0x10, + 0xae, 0x56, 0xbd, 0x17, 0xdf, 0xcb, 0x63, 0xf5, + 0xb, 0x2b, 0xd7, 0x34, 0x7c, 0x96, 0x43, 0xe9, + 0x17, 0xd4, 0x53, 0x2b, 0x4e, 0xba, 0x61, 0x57, + 0x92, 0xdb, 0xe8, 0x37, 0xf4, 0xa3, 0x59, 0x88, + 0x74, 0xc2, 0x3c, 0x5d, 0x54, 0x30, 0xb9, 0x6, + 0xbe, 0x75, 0x13, 0xe8, 0xf2, 0xe8, 0xcb, 0x45, + 0x73, 0x70, 0xaf, 0x94, 0xe6, 0xc5, 0xb0, 0xdf, + 0xd2, 0xd5, 0x57, 0x97, 0x7c, 0x97, 0xde, 0x55, + 0xaf, 0xbb, 0xed, 0x19, 0x35, 0x17, 0xf4, 0x23, + 0x38, 0x9c, 0xce, 0x37, 0xfe, 0xd8, 0x4e, 0xd8, + 0x99, 0xba, 0x33, 0x22, 0xf2, 0xeb, 0xab, 0x97, + 0xee, 0x9d, 0xab, 0x67, 0x95, 0x35, 0xdf, 0xc8, + 0xb6, 0xa0, 0xf, 0x15, 0x51, 0xa9, 0x76, 0x15, + 0xdd, 0xbd, 0xac, 0x12, 0xce, 0x51, 0xde, 0x68, + 0x15, 0xaf, 0x27, 0xcf, 0xd1, 0xba, 0x7c, 0x17, + 0xef, 0xbf, 0xbb, 0xc0, 0x6e, 0x58, 0x73, 0xf6, + 0x57, 0xe1, 0x8d, 0xb0, 0x9a, 0x5a, 0x9, 0x19, + 0xef, 0xdd, 0x4, 0xe1, 0x76, 0x94, 0x31, 0xd7, + 0x26, 0x9f, 0x9c, 0x27, 0xc4, 0x2b, 0x4b, 0xf6, + 0x3b, 0xa1, 0x8c, 0xf4, 0x21, 0xde, 0x39, 0x14, + 0x5a, 0x54, 0xac, 0x95, 0x2f, 0xa0, 0x60, 0x53, + 0x87, 0x5b, 0x71, 0x92, 0xae, 0xf9, 0x6c, 0x62, + 0x76, 0x7e, 0x91, 0x11, 0xa6, 0xf4, 0xf2, 0xa8, + 0xdf, 0xc1, 0xf6, 0x3a, 0xdb, 0x34, 0x96, 0x9, + 0x71, 0xb4, 0x4, 0xfa, 0xd4, 0x3, 0x46, 0x16, + 0x78, 0x41, 0x42, 0x7d, 0x15, 0x68, 0x63, 0x55, + 0x23, 0x4, 0x46, 0x5d, 0xe1, 0xd8, 0xe7, 0x5f, + 0x55, 0x39, 0xd2, 0x45, 0xb2, 0x0, 0x35, 0xde, + 0xd8, 0x9d, 0xc7, 0x3a, 0x8f, 0x37, 0x7e, 0xe5, + 0x9e, 0xcf, 0xd1, 0x6a, 0x22, 0xe1, 0x51, 0xb2, + 0xe6, 0x99, 0x3e, 0x83, 0xeb, 0x34, 0x9d, 0x34, + 0x7, 0x1c, 0xbe, 0x91, 0x69, 0x9e, 0xaa, 0xcb, + 0x86, 0xd2, 0xb6, 0xed, 0xa5, 0x4, 0xf9, 0x7d, + 0xf8, 0xba, 0x2a, 0x27, 0x38, 0xe1, 0xaa, 0x22, + 0x94, 0x46, 0x1f, 0x1b, 0xcf, 0xc4, 0x78, 0x88, + 0x3d, 0x50, 0x83, 0x30, 0x61, 0x87, 0xb6, 0x38, + 0x5b, 0x4f, 0x5a, 0x3, 0x2d, 0x5d, 0xa6, 0x33, + 0x38, 0xe7, 0x8b, 0x60, 0x1, 0x8e, 0xde, 0x69, + 0x8e, 0x4d, 0x60, 0x24, 0x3b, 0x47, 0x4b, 0x56, + 0xea, 0xf9, 0xc8, 0xfa, 0x2d, 0x65, 0x7b, 0xad, + 0xee, 0xe4, 0x91, 0x20, 0x6f, 0x64, 0x6e, 0x81, + 0x69, 0xda, 0xf5, 0x3c, 0x3d, 0xff, 0x4c, 0xe9, + 0x9b, 0x4d, 0xa8, 0x67, 0x9e, 0x67, 0x7f, 0x84, + 0xdb, 0x7a, 0xb7, 0x24, 0x32, 0xa0, 0x80, 0x16, + 0x55, 0x2d, 0x1d, 0xc1, 0x3a, 0x19, 0xd3, 0x17, + 0x74, 0x8e, 0x2a, 0x5c, 0xf6, 0x71, 0xf7, 0x25, + 0x3a, 0x54, 0x28, 0xef, 0x50, 0x78, 0x14, 0x5, + 0x49, 0x8a, 0xbb, 0x71, 0xb2, 0xed, 0xa2, 0x5b, + 0xff, 0x2, 0xe, 0xd8, 0x1a, 0x8b, 0x3c, 0xcc, + 0x58, 0x27, 0x71, 0x2d, 0xb, 0x11, 0x9f, 0x6, + 0xc3, 0xfd, 0x37, 0x19, 0xdb, 0xec, 0xa5, 0x4b, + 0x93, 0x81, 0xb6, 0xff, 0xd4, 0xf5, 0x7b, 0xf5, + 0x49, 0x5b, 0x95, 0x9, 0xa4, 0xca, 0xa5, 0x33, + 0x9a, 0xfc, 0x97, 0xec, 0x7b, 0xb, 0xb9, 0x2e, + 0x3b, 0x9d, 0x52, 0xc2, 0xa2, 0x9, 0xc8, 0xbf, + 0x39, 0x16, 0xce, 0x42, 0x3, 0x4b, 0xe3, 0xfc, + 0xfd, 0xc, 0x37, 0x96, 0x10, 0x36, 0xad, 0x44, + 0xda, 0xc5, 0x58, 0x3e, 0x78, 0x52, 0xa1, 0x65, + 0xed, 0x89, 0xe7, 0xea, 0xbf, 0xa8, 0x6a, 0xf2, + 0xa7, 0x8e, 0x9d, 0x1, 0x25, 0x83, 0x57, 0x5f, + 0x51, 0xe6, 0xe1, 0xa4, 0x4f, 0xf6, 0x81, 0xd7, + 0xe6, 0x98, 0x29, 0x98, 0x58, 0xfe, 0xda, 0x45, + 0xab, 0x38, 0x6, 0x91, 0x97, 0xb7, 0xa3, 0x4f, + 0x93, 0x8d, 0x8a, 0x8b, 0x5, 0xe9, 0x5, 0x98, + 0x3b, 0xc4, 0xb7, 0xe1, 0x68, 0x58, 0xa0, 0x3b, + 0x99, 0xea, 0x8a, 0xa9, 0xfb, 0x55, 0xe2, 0xc7, + 0x1d, 0x87, 0x3, 0x40, 0x24, 0x13, 0x28, 0x6a, + 0x34, 0x8a, 0xff, 0x62, 0x91, 0xb8, 0x7d, 0x28, + 0x1a, 0xd2, 0xfc, 0x4e, 0xa3, 0xda, 0x66, 0x69, + 0x15, 0xc0, 0xda, 0x15, 0x3e, 0x67, 0x12, 0x95, + 0x6, 0x1b, 0xf4, 0x60, 0xe4, 0x39, 0x82, 0xe9, + 0x2e, 0xbe, 0xab, 0x8c, 0x2c, 0x6e, 0xd6, 0x40, + 0x91, 0xc0, 0x68, 0xf7, 0xa2, 0x41, 0xd0, 0xa8, + 0x7, 0xab, 0x13, 0x34, 0x16, 0xf4, 0x73, 0x4f, + 0x1d, 0x21, 0x1a, 0x7d, 0xad, 0x43, 0x12, 0xf, + 0xb7, 0xfe, 0xa3, 0x81, 0xe9, 0xb5, 0x2d, 0xd3, + 0xa, 0x29, 0xb5, 0x32, 0xcb, 0x49, 0x6f, 0x1, + 0x90, 0x45, 0x62, 0xca, 0x1b, 0x66, 0x39, 0x88, + 0x1c, 0xee, 0x30, 0xa8, 0xb5, 0x37, 0xd0, 0xfa, + 0x46, 0x52, 0x16, 0x30, 0x17, 0xcf, 0x88, 0xd0, + 0x4, 0x5d, 0xde, 0x5e, 0x4f, 0xe7, 0xa9, 0xbf, + 0x3c, 0x29, 0x3a, 0x63, 0x67, 0x23, 0xb3, 0x7c, + 0x51, 0x17, 0xfe, 0x8d, 0xdb, 0xc8, 0x8d, 0x70, + 0xe9, 0x6f, 0x56, 0xe5, 0x44, 0xb2, 0x94, 0xeb, + 0x47, 0xca, 0x3a, 0xdc, 0xe3, 0x33, 0x87, 0x9c, + 0xe8, 0x89, 0x4b, 0x41, 0xb8, 0xb3, 0x69, 0xb0, + 0x7f, 0xc8, 0xc7, 0x74, 0xf5, 0xcb, 0x20, 0xad, + 0xea, 0xbb, 0x3d, 0x11, 0xc6, 0xc0, 0xd2, 0x88, + 0x8b, 0x16, 0xee, 0x62, 0x5a, 0x4d, 0x32, 0xe7, + 0x48, 0xae, 0xab, 0x5e, 0xc2, 0x83, 0xc4, 0xfc, + 0xd1, 0xb9, 0x71, 0xf2, 0x9, 0x7f, 0xdc, 0xbc, + 0x28, 0x74, 0xa0, 0x37, 0xa9, 0x5b, 0x6c, 0x7c, + 0x9b, 0x61, 0x94, 0x88, 0xf7, 0x40, 0x84, 0x75, + 0xa5, 0x50, 0xab, 0xb0, 0x92, 0x66, 0x10, 0x66, + 0xf6, 0xec, 0x6b, 0x5e, 0x31, 0x9b, 0xc4, 0xfa, + 0x95, 0x8b, 0xe7, 0xd4, 0xba, 0x81, 0xd2, 0x85, + 0x30, 0x4, 0x8b, 0x3d, 0xfa, 0x8a, 0x8f, 0x9b, + 0x54, 0x6a, 0x4d, 0x35, 0xa2, 0xe9, 0x58, 0x95, + 0xe3, 0xd1, 0x71, 0xcd, 0x3a, 0x54, 0xae, 0xd9, + 0x5c, 0x83, 0xd, 0x15, 0x64, 0x66, 0xee, 0x39, + 0xa1, 0x85, 0xe2, 0x28, 0xf5, 0x66, 0x5f, 0xec, + 0x39, 0x70, 0x96, 0x2c, 0x72, 0x9e, 0x57, 0xfd, + 0x57, 0x27, 0xb7, 0xda, 0x79, 0x39, 0xd8, 0x3b, + 0x2e, 0xa3, 0xb0, 0xde, 0xbf, 0x60, 0xb6, 0x42, + 0x78, 0x9d, 0x8f, 0xe8, 0x1c, 0x7c, 0x45, 0x72, + 0x3, 0xc4, 0xd5, 0x81, 0xf6, 0xe6, 0x9, 0x29, + 0x1e, 0xcd, 0xf3, 0xe, 0xd6, 0x65, 0xee, 0x6d, + 0x90, 0x17, 0x95, 0x20, 0x54, 0xf1, 0xd, 0x2f, + 0xa0, 0xac, 0xe3, 0x4b, 0xfc, 0xa4, 0xdc, 0xab, + 0x9d, 0x9e, 0x32, 0x63, 0x72, 0xd1, 0xb4, 0xef, + 0xf1, 0x83, 0xa7, 0xd7, 0x2b, 0x1a, 0x9a, 0x9e, + 0xfa, 0x1e, 0xb, 0x2b, 0xdc, 0x7b, 0x87, 0x96, + 0xf, 0xdb, 0x75, 0xb9, 0x6, 0x2b, 0xd3, 0x95, + 0xc5, 0xb3, 0x9, 0x53, 0x94, 0x54, 0x1f, 0xd0, + 0x75, 0x5a, 0x36, 0x6a, 0x7c, 0x82, 0xdb, 0xb1, + 0xa2, 0x17, 0xbc, 0xeb, 0x1f, 0xfa, 0x34, 0x3d, + 0xee, 0x68, 0xee, 0x93, 0x33, 0xfb, 0xcb, 0xd2, + 0xa3, 0xd1, 0x24, 0x5e, 0xf4, 0x9, 0xbe, 0x5a, + 0x68, 0x9e, 0x3e, 0xd4, 0x81, 0xcd, 0xa3, 0x1e, + 0x2, 0x13, 0xb4, 0x79, 0x94, 0xc9, 0xb2, 0xde, + 0x56, 0xf1, 0x7b, 0x2f, 0xe2, 0x56, 0xe1, 0x10, + 0xf4, 0x73, 0x2d, 0xc9, 0xca, 0x4d, 0x5f, 0x11, + 0x9e, 0xd6, 0x3c, 0x73, 0x12, 0x57, 0xe9, 0x14, + 0xe0, 0x8d, 0xdd, 0x4b, 0x8a, 0xbb, 0xb3, 0x78, + 0xbe, 0x16, 0x94, 0x93, 0x51, 0x33, 0x7a, 0xa5, + 0x41, 0x14, 0x60, 0x82, 0x94, 0x67, 0x70, 0xea, + 0xe6, 0x3, 0x7f, 0xc5, 0xa0, 0x20, 0x15, 0x88, + 0x53, 0xe3, 0x7e, 0x16, 0x52, 0xe4, 0xca, 0xa0, + 0x6f, 0xb9, 0x68, 0x4e, 0x30, 0xb9, 0x8c, 0xe6, + 0x9c, 0x5e, 0xc2, 0x93, 0xf9, 0xe1, 0x41, 0x4b, + 0x18, 0x42, 0x6f, 0x8f, 0x96, 0x3d, 0x2b, 0x28, + 0xd5, 0x53, 0x62, 0xdd, 0x6b, 0xd0, 0xf8, 0x2e, + 0xa6, 0x97, 0xe5, 0x87, 0xc5, 0xf6, 0x96, 0x7b, + 0xc4, 0x3e, 0x84, 0xc9, 0xf6, 0x34, 0x63, 0x46, + 0xe1, 0x10, 0xa5, 0x91, 0x6b, 0xff, 0x10, 0x3f, + 0x50, 0x2e, 0xd7, 0x39, 0x12, 0x7a, 0x15, 0x85, + 0xed, 0x99, 0xdb, 0x9b, 0x99, 0x6b, 0xfa, 0xfa, + 0x93, 0x7, 0x44, 0xbe, 0xbe, 0x60, 0x23, 0xc1, + 0xec, 0x5c, 0xf6, 0x93, 0x38, 0xf9, 0x89, 0x0, + 0xc5, 0x5f, 0x5b, 0xe2, 0x9d, 0x2b, 0xea, 0x6b, + 0x2e, 0xee, 0xb7, 0x4a, 0x4e, 0x8d, 0xd0, 0x35, + 0xe9, 0xc1, 0x5, 0x2b, 0x83, 0xb7, 0x72, 0x25, + 0xbb, 0xbe, 0xe8, 0x15, 0xf4, 0x74, 0x69, 0x69, + 0x67, 0x8c, 0x5c, 0x31, 0x79, 0x78, 0x2e, 0x43, + 0x83, 0xd1, 0xdd, 0x9, 0xc3, 0xa1, 0x0, 0x13, + 0x31, 0x4b, 0x86, 0xce, 0xee, 0xd7, 0xec, 0xb1, + 0x2c, 0x38, 0x46, 0x68, 0x62, 0xd9, 0x84, 0xdb, + 0x24, 0x62, 0x82, 0xc, 0x12, 0xb7, 0x4f, 0x86, + 0x54, 0x18, 0xc6, 0xd7, 0x94, 0x8b, 0xf2, 0x4c, + 0x17, 0x98, 0xaa, 0xe0, +}; + +const uint8_t expected_cipher_long_input_end[] = { + 0x05, 0x95, 0x58, 0x7b, 0xb4, 0x60, 0x15, + 0x32, 0x9f, 0x38, 0xcc, 0x98, 0x1b, 0xbe, 0x10, 0xa5, 0x06, 0x67, 0xae, 0x38, + 0xbd, 0x7d, 0xb5, 0xcd, 0x58, 0x32, 0xdd, 0x9e, + 0x6a, 0xde, 0xe3, 0x53, +}; + +void aes_ext_flash_ctr_test(uint32_t output_buf_caps) +{ + mbedtls_aes_context ctx; + uint8_t nonce[16]; + uint8_t key[16]; + uint8_t stream_block[16]; + size_t SZ = sizeof(long_input); + memset(nonce, 0x2F, 16); + memset(key, 0x1E, 16); + + uint8_t *chipertext = heap_caps_malloc(SZ, output_buf_caps); + uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(decryptedtext); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key, 128); + + size_t offset; + + // Encrypt with input buffer in external flash + offset = 0; + memset(nonce, 0x2F, 16); + mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, long_input, chipertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_long_input_end, chipertext + SZ - 32, 32); + + // Decrypt + offset = 0; + memset(nonce, 0x2F, 16); + // Decrypt with input buffer in external flash, the crypto DMA can't access this + mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, chipertext, decryptedtext); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(long_input, decryptedtext, SZ); + + mbedtls_aes_free(&ctx); + free(chipertext); + free(decryptedtext); +} + +/* Tests how crypto DMA handles data in external memory */ +TEST_CASE("mbedtls AES PSRAM tests", "[aes]") +{ + aes_ctr_alignment_test(MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + aes_ctr_alignment_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + aes_ctr_alignment_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + aes_psram_one_buf_ctr_test(); +} + +/* Tests how crypto DMA handles data from external flash */ +TEST_CASE("mbedtls AES external flash tests", "[aes]") +{ + aes_ext_flash_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + aes_ext_flash_ctr_test(MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); +} +#endif // CONFIG_SPIRAM_USE_MALLOC + + +static SemaphoreHandle_t done_sem; + +static void __attribute__((unused)) aes_ctr_stream_test_task(void *pv) +{ + aes_ctr_stream_test(); + xSemaphoreGive(done_sem); + vTaskDelete(NULL); +} + +#if CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK + +TEST_CASE("mbedtls AES stack in RTC RAM", "[mbedtls]") +{ + done_sem = xSemaphoreCreateBinary(); + static StaticTask_t rtc_task; + size_t STACK_SIZE = 3072; + uint8_t *rtc_stack = heap_caps_calloc(STACK_SIZE, 1, MALLOC_CAP_RTCRAM); + TEST_ASSERT(esp_ptr_in_rtc_dram_fast(rtc_stack)); + + TEST_ASSERT_NOT_NULL(xTaskCreateStatic(aes_ctr_stream_test_task, "aes_ctr_task", STACK_SIZE, NULL, + 3, rtc_stack, &rtc_task)); + TEST_ASSERT_TRUE(xSemaphoreTake(done_sem, 10000 / portTICK_PERIOD_MS)); + + /* Give task time to cleanup before freeing stack */ + vTaskDelay(1000 / portTICK_PERIOD_MS); + free(rtc_stack); + + vSemaphoreDelete(done_sem); +} + +#endif //CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK + +#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY && CONFIG_SPIRAM_USE_MALLOC + +TEST_CASE("mbedtls AES stack in PSRAM", "[mbedtls]") +{ + done_sem = xSemaphoreCreateBinary(); + static StaticTask_t psram_task; + size_t STACK_SIZE = 3072; + uint8_t *psram_stack = heap_caps_calloc(STACK_SIZE, 1, MALLOC_CAP_SPIRAM); + + TEST_ASSERT(esp_ptr_external_ram(psram_stack)); + + TEST_ASSERT_NOT_NULL(xTaskCreateStatic(aes_ctr_stream_test_task, "aes_ctr_task", STACK_SIZE, NULL, + 3, psram_stack, &psram_task)); + TEST_ASSERT_TRUE(xSemaphoreTake(done_sem, 10000 / portTICK_PERIOD_MS)); + + /* Give task time to cleanup before freeing stack */ + vTaskDelay(1000 / portTICK_PERIOD_MS); + free(psram_stack); + + vSemaphoreDelete(done_sem); +} + +#endif //CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY && CONFIG_SPIRAM_USE_MALLOC diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_aes_gcm.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_aes_gcm.c new file mode 100644 index 000000000..1946d275e --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_aes_gcm.c @@ -0,0 +1,885 @@ +/* mbedTLS GCM test + * + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include "mbedtls/aes.h" +#include "mbedtls/gcm.h" +#include "unity.h" +#include "sdkconfig.h" +#include "esp_heap_caps.h" +#include "test_utils.h" +#include "ccomp_timer.h" +#include "sys/param.h" + +#if CONFIG_MBEDTLS_HARDWARE_AES + +/* + Python example code for generating test vectors + + import os, binascii + from cryptography.hazmat.primitives.ciphers.aead import AESGCM + + def as_c_array(byte_arr): + hex_str = '' + for idx, byte in enumerate(byte_arr): + hex_str += "0x{:02x}, ".format(byte) + bytes_per_line = 8 + if idx % bytes_per_line == bytes_per_line - 1: + hex_str += '\n' + + return hex_str + + key = b'\x44' * 16 + iv = b'\xEE' * 16 + data = b'\xAA' * 3200 + aad = b'\x76' * 16 + + aesgcm = AESGCM(key) + + ct = aesgcm.encrypt(iv, data, aad) + + print(as_c_array(ct)) +*/ + +TEST_CASE("mbedtls GCM stream test", "[aes-gcm]") +{ + + const unsigned SZ = 100; + mbedtls_gcm_context ctx; + uint8_t nonce[16]; + uint8_t key[16]; + uint8_t tag[16]; + mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; + + const uint8_t expected_cipher[] = { + 0x03, 0x92, 0x13, 0x49, 0x1f, 0x1f, 0x24, 0x41, + 0xe8, 0xeb, 0x89, 0x47, 0x50, 0x0a, 0xce, 0xa3, + 0xc7, 0x1c, 0x10, 0x70, 0xb0, 0x89, 0x82, 0x5e, + 0x0f, 0x4a, 0x23, 0xee, 0xd2, 0xfc, 0xff, 0x45, + 0x61, 0x4c, 0xd1, 0xfb, 0x6d, 0xe2, 0xbe, 0x67, + 0x6f, 0x94, 0x72, 0xa3, 0xe7, 0x04, 0x99, 0xb3, + 0x4a, 0x46, 0xf9, 0x2b, 0xaf, 0xac, 0xa9, 0x0e, + 0x43, 0x7e, 0x8b, 0xc4, 0xbf, 0x49, 0xa4, 0x83, + 0x9c, 0x31, 0x11, 0x1c, 0x09, 0xac, 0x90, 0xdf, + 0x00, 0x34, 0x08, 0xe5, 0x70, 0xa3, 0x7e, 0x4b, + 0x36, 0x48, 0x5a, 0x3f, 0x28, 0xc7, 0x1c, 0xd9, + 0x1b, 0x1b, 0x49, 0x96, 0xe9, 0x7c, 0xea, 0x54, + 0x7c, 0x71, 0x29, 0x0d + }; + const uint8_t expected_tag[] = { + 0x35, 0x1c, 0x21, 0xc6, 0xbc, 0x6b, 0x18, 0x52, + 0x90, 0xe1, 0xf2, 0x5b, 0xe1, 0xf6, 0x15, 0xee, + }; + + + memset(nonce, 0x89, 16); + memset(key, 0x56, 16); + + // allocate internal memory + uint8_t *ciphertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(ciphertext); + TEST_ASSERT_NOT_NULL(plaintext); + TEST_ASSERT_NOT_NULL(decryptedtext); + + memset(plaintext, 0xAB, SZ); + /* Test that all the end results are the same + no matter how many bytes we encrypt each call + */ + for (int bytes_to_process = 16; bytes_to_process < SZ; bytes_to_process = bytes_to_process + 16) { + memset(nonce, 0x89, 16); + memset(ciphertext, 0x0, SZ); + memset(decryptedtext, 0x0, SZ); + memset(tag, 0x0, 16); + + mbedtls_gcm_init(&ctx); + mbedtls_gcm_setkey(&ctx, cipher, key, 128); + mbedtls_gcm_starts( &ctx, MBEDTLS_AES_ENCRYPT, nonce, sizeof(nonce) ); + mbedtls_gcm_update_ad( &ctx, NULL, 0 ); + + size_t olen; + // Encrypt + for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { + // Limit length of last call to avoid exceeding buffer size + size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process; + mbedtls_gcm_update(&ctx, plaintext + idx, length, ciphertext + idx, length, &olen); + } + mbedtls_gcm_finish( &ctx, NULL, 0, &olen, tag, sizeof(tag) ); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, ciphertext, SZ); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag, sizeof(tag)); + + // Decrypt + memset(nonce, 0x89, 16); + mbedtls_gcm_free( &ctx ); + + mbedtls_gcm_init(&ctx); + mbedtls_gcm_setkey(&ctx, cipher, key, 128); + mbedtls_gcm_starts( &ctx, MBEDTLS_AES_DECRYPT, nonce, sizeof(nonce)); + mbedtls_gcm_update_ad( &ctx, NULL, 0 ); + + for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) { + // Limit length of last call to avoid exceeding buffer size + + size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process; + mbedtls_gcm_update(&ctx, ciphertext + idx, length, decryptedtext + idx, length, &olen); + } + mbedtls_gcm_finish( &ctx, NULL, 0, &olen, tag, sizeof(tag) ); + TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); + mbedtls_gcm_free( &ctx ); + } + free(plaintext); + free(ciphertext); + free(decryptedtext); +} + +TEST_CASE("mbedtls AES GCM self-tests", "[aes-gcm]") +{ + TEST_ASSERT_FALSE_MESSAGE(mbedtls_gcm_self_test(1), "AES GCM self-test should pass."); +} + +typedef struct { + uint8_t *plaintext; + size_t plaintext_length; + uint32_t output_caps; + uint8_t *add_buf; + size_t add_length; + uint8_t *iv; + size_t iv_length; + uint8_t *key; + size_t key_bits; + size_t tag_len; +} aes_gcm_test_cfg_t; + +typedef struct { + const uint8_t *expected_tag; + const uint8_t *ciphertext_last_block; // Last block of the ciphertext +} aes_gcm_test_expected_res_t; + + +typedef enum { + AES_GCM_TEST_CRYPT_N_TAG, + AES_GCM_TEST_START_UPDATE_FINISH, +} aes_gcm_test_type_t; + +static void aes_gcm_test(aes_gcm_test_cfg_t *cfg, aes_gcm_test_expected_res_t *res, aes_gcm_test_type_t aes_gcm_type) +{ + mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; + mbedtls_gcm_context ctx; + + uint8_t tag_buf_encrypt[16] = {}; + uint8_t tag_buf_decrypt[16] = {}; + uint8_t iv_buf[16] = {}; + + uint8_t *ciphertext = heap_caps_malloc(cfg->plaintext_length, cfg->output_caps); + uint8_t *output = heap_caps_malloc(cfg->plaintext_length, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + + if (cfg->plaintext_length != 0) { + TEST_ASSERT_NOT_NULL(ciphertext); + TEST_ASSERT_NOT_NULL(output); + } + + memset(ciphertext, 0, cfg->plaintext_length); + memset(output, 0, cfg->plaintext_length); + memcpy(iv_buf, cfg->iv, cfg->iv_length); + + mbedtls_gcm_init(&ctx); + mbedtls_gcm_setkey(&ctx, cipher, cfg->key, cfg->key_bits); + size_t olen; + /* Encrypt and tag */ + if (aes_gcm_type == AES_GCM_TEST_CRYPT_N_TAG) { + mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_AES_ENCRYPT, cfg->plaintext_length, iv_buf, cfg->iv_length, cfg->add_buf, cfg->add_length, cfg->plaintext, ciphertext, cfg->tag_len, tag_buf_encrypt); + } else if (aes_gcm_type == AES_GCM_TEST_START_UPDATE_FINISH) { + TEST_ASSERT(mbedtls_gcm_starts( &ctx, MBEDTLS_AES_ENCRYPT, iv_buf, cfg->iv_length) == 0 ); + TEST_ASSERT(mbedtls_gcm_update_ad( &ctx, cfg->add_buf, cfg->add_length) == 0 ); + TEST_ASSERT(mbedtls_gcm_update( &ctx, cfg->plaintext, cfg->plaintext_length, ciphertext, cfg->plaintext_length, &olen) == 0 ); + TEST_ASSERT(mbedtls_gcm_finish( &ctx, NULL, 0, &olen, tag_buf_encrypt, cfg->tag_len) == 0 ); + } + size_t offset = cfg->plaintext_length > 16 ? cfg->plaintext_length - 16 : 0; + /* Sanity check: make sure the last ciphertext block matches what we expect to see. */ + TEST_ASSERT_EQUAL_HEX8_ARRAY(res->ciphertext_last_block, ciphertext + offset, MIN(16, cfg->plaintext_length)); + TEST_ASSERT_EQUAL_HEX8_ARRAY(res->expected_tag, tag_buf_encrypt, cfg->tag_len); + + + /* Decrypt and authenticate */ + if (aes_gcm_type == AES_GCM_TEST_CRYPT_N_TAG) { + TEST_ASSERT(mbedtls_gcm_auth_decrypt(&ctx, cfg->plaintext_length, iv_buf, cfg->iv_length, cfg->add_buf, cfg->add_length, res->expected_tag, cfg->tag_len, ciphertext, output) == 0); + } else if (aes_gcm_type == AES_GCM_TEST_START_UPDATE_FINISH) { + TEST_ASSERT(mbedtls_gcm_starts( &ctx, MBEDTLS_AES_DECRYPT, iv_buf, cfg->iv_length) == 0 ); + TEST_ASSERT(mbedtls_gcm_update_ad( &ctx, cfg->add_buf, cfg->add_length) == 0 ); + TEST_ASSERT(mbedtls_gcm_update( &ctx, ciphertext, cfg->plaintext_length, output, cfg->plaintext_length, &olen) == 0 ); + TEST_ASSERT(mbedtls_gcm_finish( &ctx, NULL, 0, &olen, tag_buf_decrypt, cfg->tag_len) == 0 ); + + /* mbedtls_gcm_auth_decrypt already checks tag so only needed for AES_GCM_TEST_START_UPDATE_FINISH */ + TEST_ASSERT_EQUAL_HEX8_ARRAY(res->expected_tag, tag_buf_decrypt, cfg->tag_len); + } + + TEST_ASSERT_EQUAL_HEX8_ARRAY(cfg->plaintext, output, cfg->plaintext_length); + mbedtls_gcm_free( &ctx ); + free(ciphertext); + free(output); +} + + + +TEST_CASE("mbedtls AES GCM", "[aes-gcm]") +{ + uint8_t iv[16]; + uint8_t key[16]; + uint8_t add[30]; + + memset(iv, 0xB1, sizeof(iv)); + memset(key, 0x27, sizeof(key)); + memset(add, 0x90, sizeof(add)); + + size_t length[] = {10, 16, 500, 5000, 12345}; + + const uint8_t expected_last_block[][16] = { + + { + 0x37, 0x99, 0x4b, 0x16, 0x5f, 0x8d, 0x27, 0xb1, + 0x60, 0x72 + }, + + { + 0x37, 0x99, 0x4b, 0x16, 0x5f, 0x8d, 0x27, 0xb1, + 0x60, 0x72, 0x9a, 0x81, 0x8d, 0x3c, 0x69, 0x66 + }, + + { + 0x9d, 0x7a, 0xac, 0x84, 0xe3, 0x70, 0x43, 0x0f, + 0xa7, 0x83, 0x43, 0xc9, 0x04, 0xf8, 0x7d, 0x48 + }, + + { + 0xee, 0xfd, 0xab, 0x2a, 0x09, 0x44, 0x41, 0x6a, + 0x91, 0xb0, 0x74, 0x24, 0xee, 0x35, 0xb1, 0x39 + }, + + { + 0x51, 0xf7, 0x1f, 0x67, 0x1a, 0x4a, 0x12, 0x37, + 0x60, 0x3b, 0x68, 0x01, 0x20, 0x4f, 0xf3, 0xd9 + }, + }; + + const uint8_t expected_tag[][16] = { + + { + 0x06, 0x4f, 0xb5, 0x91, 0x12, 0x24, 0xb4, 0x24, + 0x0b, 0xc2, 0x85, 0x59, 0x6a, 0x7c, 0x1f, 0xc9 + }, + + { + 0x45, 0xc2, 0xa8, 0xfe, 0xff, 0x49, 0x1f, 0x45, + 0x8e, 0x29, 0x74, 0x41, 0xed, 0x9b, 0x54, 0x28 + }, + + { + 0xe1, 0xf9, 0x40, 0xfa, 0x29, 0x6f, 0x30, 0xae, + 0xb6, 0x9b, 0x33, 0xdb, 0x8a, 0xf9, 0x70, 0xc4 + }, + + { + 0x22, 0xe1, 0x22, 0x34, 0x0c, 0x91, 0x0b, 0xcf, + 0xa3, 0x42, 0xe0, 0x48, 0xe6, 0xfe, 0x2e, 0x28 + }, + + { + 0xfb, 0xfe, 0x5a, 0xed, 0x26, 0x5c, 0x5e, 0x66, + 0x4e, 0xb2, 0x48, 0xce, 0xe9, 0x88, 0x1c, 0xe0 + }, + }; + + aes_gcm_test_cfg_t cfg = { + .output_caps = MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, + .iv = iv, + .iv_length = sizeof(iv), + .key = key, + .key_bits = 8 * sizeof(key), + .add_buf = add, + .add_length = sizeof(add), + .tag_len = 16 + }; + + aes_gcm_test_expected_res_t res = { + }; + + for (int i = 0; i < sizeof(length) / sizeof(length[0]); i++) { + printf("Test AES-GCM with plaintext length = %d\n", length[i]); + uint8_t *input = heap_caps_malloc(length[i], MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT(input != NULL || length[i] == 0); + memset(input, 0x36, length[i]); + + cfg.plaintext = input; + cfg.plaintext_length = length[i]; + res.expected_tag = expected_tag[i]; + res.ciphertext_last_block = expected_last_block[i], + + aes_gcm_test(&cfg, &res, AES_GCM_TEST_CRYPT_N_TAG); + aes_gcm_test(&cfg, &res, AES_GCM_TEST_START_UPDATE_FINISH); + + free(input); + } +} + + +TEST_CASE("mbedtls AES GCM - Different add messages", "[aes-gcm]") +{ + const unsigned CALL_SZ = 160; + uint8_t iv[16]; + uint8_t key[16]; + uint8_t *input = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(input); + + memset(input, 0x67, CALL_SZ); + memset(iv, 0xA2, sizeof(iv)); + memset(key, 0x48, sizeof(key)); + + const uint8_t expected_last_block[] = { + 0xcd, 0xb9, 0xad, 0x6f, 0xc9, 0x35, 0x21, 0x0d, + 0xc9, 0x5d, 0xea, 0xd9, 0xf7, 0x1d, 0x43, 0xed + }; + + size_t add_len[] = {0, 10, 16, 500, 5000}; + + const uint8_t expected_tag[][16] = { + { + 0xe3, 0x91, 0xad, 0x40, 0x96, 0xb7, 0x8c, 0x53, + 0x4d, 0x15, 0x7d, 0x55, 0x15, 0xdf, 0x10, 0x69 + }, + + { + 0xc2, 0x38, 0x36, 0xe9, 0x12, 0x72, 0x5b, 0x31, + 0x0c, 0xde, 0xb5, 0xc9, 0x8c, 0xa3, 0xcb, 0xe7 + }, + + { + 0x57, 0x10, 0x22, 0x91, 0x65, 0xfa, 0x89, 0xba, + 0x0a, 0x3e, 0xc1, 0x7c, 0x93, 0x6e, 0x35, 0xac + }, + + { + 0x3c, 0x28, 0x03, 0xc2, 0x14, 0x40, 0xec, 0xb6, + 0x25, 0xfb, 0xdd, 0x55, 0xa0, 0xb2, 0x47, 0x7b + }, + + { + 0xfa, 0x66, 0x4a, 0x97, 0x2d, 0x02, 0x32, 0x5b, + 0x92, 0x94, 0xf1, 0x00, 0x1c, 0xfa, 0xe3, 0x07 + } + }; + + aes_gcm_test_cfg_t cfg = { + .plaintext = input, + .plaintext_length = CALL_SZ, + .output_caps = MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, + .iv = iv, + .iv_length = sizeof(iv), + .key = key, + .key_bits = 8 * sizeof(key), + .tag_len = 16 + }; + + aes_gcm_test_expected_res_t res = { + .ciphertext_last_block = expected_last_block, + }; + + for (int i = 0; i < sizeof(add_len) / sizeof(add_len[0]); i++) { + printf("Test AES-GCM with add length = %d\n", add_len[i]); + uint8_t *add = heap_caps_malloc(add_len[i], MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT(add != NULL || add_len[i] == 0); + memset(add, 0x12, add_len[i]); + + cfg.add_buf = add; + cfg.add_length = add_len[i]; + res.expected_tag = expected_tag[i]; + + aes_gcm_test(&cfg, &res, AES_GCM_TEST_CRYPT_N_TAG); + aes_gcm_test(&cfg, &res, AES_GCM_TEST_START_UPDATE_FINISH); + + free(add); + } + free(input); +} + + + +TEST_CASE("mbedtls AES GCM performance, start, update, ret", "[aes-gcm]") +{ + const unsigned CALL_SZ = 16 * 3200; + mbedtls_gcm_context ctx; + float elapsed_usec; + unsigned char tag_buf[16]; + mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; + uint8_t iv[16]; + uint8_t key[16]; + uint8_t aad[16]; + size_t olen; + memset(iv, 0xEE, 16); + memset(key, 0x44, 16); + memset(aad, 0x76, 16); + + // allocate internal memory + uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(buf); + + mbedtls_gcm_init(&ctx); + mbedtls_gcm_setkey( &ctx, cipher, key, 128); + + ccomp_timer_start(); + + memset(buf, 0xAA, CALL_SZ); + + TEST_ASSERT(mbedtls_gcm_starts( &ctx, MBEDTLS_AES_ENCRYPT, iv, sizeof(iv) ) == 0 ); + TEST_ASSERT(mbedtls_gcm_update_ad( &ctx, aad, sizeof(aad)) == 0 ); + TEST_ASSERT(mbedtls_gcm_update( &ctx, buf, CALL_SZ, buf, CALL_SZ, &olen) == 0 ); + TEST_ASSERT(mbedtls_gcm_finish( &ctx, NULL, 0, &olen, tag_buf, 16 ) == 0 ); + + elapsed_usec = ccomp_timer_stop(); + + /* Sanity check: make sure the last ciphertext block matches + what we expect to see. + */ + const uint8_t expected_last_block[] = { + 0xd4, 0x25, 0x88, 0xd4, 0x32, 0x52, 0x3d, 0x6f, + 0xae, 0x49, 0x19, 0xb5, 0x95, 0x01, 0xde, 0x7d, + }; + + const uint8_t expected_tag[] = { + 0xf5, 0x10, 0x1f, 0x21, 0x5b, 0x07, 0x0d, 0x3f, + 0xac, 0xc9, 0xd0, 0x42, 0x45, 0xef, 0xc7, 0xfa, + }; + + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16, 16); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag_buf, 16); + + free(buf); + + // bytes/usec = MB/sec + float mb_sec = CALL_SZ / elapsed_usec; + printf("GCM encryption rate %.3fMB/sec\n", mb_sec); + +#ifdef CONFIG_MBEDTLS_HARDWARE_GCM + // Don't put a hard limit on software AES performance + TEST_PERFORMANCE_GREATER_THAN(AES_GCM_UPDATE_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec); +#endif +} + + +TEST_CASE("mbedtls AES GCM performance, crypt-and-tag", "[aes-gcm]") +{ + const unsigned CALL_SZ = 16 * 3200; + mbedtls_gcm_context ctx; + float elapsed_usec; + unsigned char tag_buf[16] = {}; + mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; + uint8_t iv[16]; + uint8_t key[16]; + uint8_t aad[16]; + + memset(iv, 0xEE, 16); + memset(key, 0x44, 16); + memset(aad, 0x76, 16); + + // allocate internal memory + uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(buf); + + mbedtls_gcm_init(&ctx); + mbedtls_gcm_setkey( &ctx, cipher, key, 128); + + memset(buf, 0xAA, CALL_SZ); + + ccomp_timer_start(); + mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_AES_ENCRYPT, CALL_SZ, iv, sizeof(iv), aad, sizeof(aad), buf, buf, 16, tag_buf); + + elapsed_usec = ccomp_timer_stop(); + + /* Sanity check: make sure the last ciphertext block matches + what we expect to see. + */ + + const uint8_t expected_last_block[] = { + 0xd4, 0x25, 0x88, 0xd4, 0x32, 0x52, 0x3d, 0x6f, + 0xae, 0x49, 0x19, 0xb5, 0x95, 0x01, 0xde, 0x7d, + }; + + const uint8_t expected_tag[] = { + 0xf5, 0x10, 0x1f, 0x21, 0x5b, 0x07, 0x0d, 0x3f, + 0xac, 0xc9, 0xd0, 0x42, 0x45, 0xef, 0xc7, 0xfa, + }; + + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16, 16); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag_buf, 16); + + free(buf); + + // bytes/usec = MB/sec + float mb_sec = CALL_SZ / elapsed_usec; + printf("GCM encryption rate %.3fMB/sec\n", mb_sec); + +#ifdef CONFIG_MBEDTLS_HARDWARE_GCM + // Don't put a hard limit on software AES performance + TEST_PERFORMANCE_GREATER_THAN(AES_GCM_CRYPT_TAG_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec); +#endif +} + +TEST_CASE("mbedtls AES GCM - Combine different IV/Key/Plaintext/AAD lengths", "[aes-gcm]") +{ + #define IV_BYTES_VALUE 0xA2 + #define KEY_BYTES_VALUE 0x48 + #define INPUT_BYTES_VALUE 0x36 + #define ADD_BYTES_VALUE 0x12 + + uint8_t iv[16]; + uint8_t key[32]; + + memset(iv, IV_BYTES_VALUE, sizeof(iv)); + memset(key, KEY_BYTES_VALUE, sizeof(key)); + + /* Key length is: 16 bytes, 32 bytes */ + size_t key_length[] = {16, 32}; + + /* IV length is: 12 bytes (standard), 16 bytes */ + size_t iv_length[] = {12, 16}; + + /* Plaintext length is: a multiple of 16 bytes, a non-multiple of 16 bytes */ + size_t length[] = {160, 321}; + + /* Add len is: 0, a multiple of 16 bytes, a non-multiple of 16 bytes */ + size_t add_len[] = {0, 160, 321}; + + /*indexes: Key - IV - Plaintext */ + const uint8_t expected_last_block[2][2][2][16] = { + { + /* 16 byte key */ + + { + { + 0xa2, 0x1e, 0x23, 0x3c, 0xfc, 0x7c, 0xec, 0x9a, + 0x91, 0xe5, 0xdb, 0x3a, 0xe5, 0x0c, 0x3f, 0xc2, + }, + + { + 0xa8, 0xeb, 0x40, 0x9b, 0x7b, 0x87, 0x07, + 0x68, 0x17, 0x5c, 0xc0, 0xb7, 0xb4, 0xb3, 0x81, + 0xbe, + } + }, + { + { + 0x9c, 0xe8, 0xfc, 0x3e, 0x98, 0x64, 0x70, 0x5c, + 0x98, 0x0c, 0xbb, 0x88, 0xa6, 0x4c, 0x12, 0xbc + }, + + { + 0x8b, 0x66, 0xf5, 0xbc, 0x56, 0x59, 0xae, + 0xf0, 0x9e, 0x5c, 0xdb, 0x6d, 0xfc, 0x1f, 0x2e, + 0x00 + } + }, + }, + { + /* 32 byte key */ + { + { + 0xde, 0xc2, 0xd3, 0xeb, 0x5e, 0x03, 0x53, 0x4b, + 0x04, 0x0d, 0x63, 0xf1, 0xd8, 0x5b, 0x1f, 0x85, + }, + + { + 0xb5, 0x53, 0x8e, 0xd3, 0xab, 0x10, 0xf1, + 0x77, 0x41, 0x92, 0xea, 0xdd, 0xdd, 0x9e, 0x5d, + 0x40, + } + }, + { + { + 0x3b, 0xc7, 0xf0, 0x3f, 0xba, 0x97, 0xbd, 0xa0, + 0xa5, 0x48, 0xf3, 0x7a, 0xde, 0x23, 0x19, 0x7a, + }, + + { + 0x57, 0xc7, 0x4d, 0xe3, 0x79, 0x5e, 0xbd, + 0x0d, 0xd7, 0x6a, 0xef, 0x1f, 0x54, 0x29, 0xa6, + 0xd7, + } + }, + }, + }; + + /*indexes: Key - IV - Plaintext - Add len*/ + const uint8_t expected_tag[2][2][2][3][16] = { + { + { + { + // Plaintext 160 bytes + { + 0x67, 0x92, 0xb1, 0x7f, 0x44, 0x1f, 0x95, 0xfb, + 0x33, 0x76, 0x66, 0xb7, 0x4f, 0x3e, 0xec, 0x4d, + }, + + { + 0xb1, 0x99, 0xed, 0x1b, 0x4e, 0x12, 0x87, 0x5e, + 0xf4, 0xe3, 0x81, 0xd8, 0x96, 0x07, 0xda, 0xff, + }, + + { + 0x73, 0x35, 0x0c, 0xf5, 0x70, 0x1e, 0xc0, 0x99, + 0x34, 0xba, 0x1a, 0x50, 0x23, 0xac, 0x21, 0x33, + }, + }, + { + // Plaintext 321 bytes + { + 0x2d, 0xf6, 0xd0, 0x7a, 0x75, 0x4d, 0x9d, + 0xb5, 0x9d, 0x43, 0xbf, 0x57, 0x10, 0xa3, 0xff, + 0x3d + }, + + { + 0x06, 0x91, 0xe4, 0x38, 0x3a, 0xe1, 0x6e, + 0x2d, 0x83, 0x68, 0x2e, 0xb0, 0x26, 0x2f, 0xe4, + 0x78 + }, + + { + 0x1b, 0x58, 0x2f, 0x9b, 0xe9, 0xe0, 0xe0, + 0x43, 0x83, 0x08, 0xec, 0x58, 0x3a, 0x78, 0xe9, + 0x69, + } + } + }, + { + { + // Plaintext 160 bytes + { + 0x77, 0xe5, 0x2e, 0x2d, 0x94, 0xb8, 0x03, 0x61, + 0x7a, 0xd5, 0x0c, 0x3c, 0x9c, 0x40, 0x92, 0x9b + }, + + { + 0xa1, 0xee, 0x72, 0x49, 0x9e, 0xb5, 0x11, 0xc4, + 0xbd, 0x40, 0xeb, 0x53, 0x45, 0x79, 0xa4, 0x29 + }, + + { + 0x63, 0x42, 0x93, 0xa7, 0xa0, 0xb9, 0x56, 0x03, + 0x7d, 0x19, 0x70, 0xdb, 0xf0, 0xd2, 0x5f, 0xe5 + }, + }, + { + // Plaintext 321 bytes + { + 0x50, 0xa3, 0x79, 0xfc, 0x17, 0xb8, 0xf4, + 0xf6, 0x14, 0xaa, 0x4a, 0xe7, 0xd4, 0xa0, 0xea, + 0xee + }, + + { + 0x7b, 0xc4, 0x4d, 0xbe, 0x58, 0x14, 0x07, + 0x6e, 0x0a, 0x81, 0xdb, 0x00, 0xe2, 0x2c, 0xf1, + 0xab + }, + + { + 0x66, 0x0d, 0x86, 0x1d, 0x8b, 0x15, 0x89, + 0x00, 0x0a, 0xe1, 0x19, 0xe8, 0xfe, 0x7b, 0xfc, + 0xba + } + } + }, + }, + { + { + { + // Plaintext 160 bytes + { + 0x04, 0x04, 0x15, 0xb1, 0xd3, 0x98, 0x15, 0x45, + 0xa2, 0x44, 0xba, 0x4a, 0xde, 0xc2, 0x8d, 0xd6, + }, + + { + 0x94, 0x3e, 0xc3, 0x5d, 0xdc, 0x42, 0xf6, 0x4c, + 0x80, 0x15, 0xe4, 0xb9, 0x0b, 0xc9, 0x87, 0x01, + }, + + { + 0x93, 0x6e, 0x26, 0x5b, 0x7e, 0x17, 0xc8, 0x73, + 0x9b, 0x71, 0x31, 0x7a, 0x8b, 0x0e, 0x19, 0x89, + } + }, + { + // Plaintext 321 bytes + { + 0x99, 0x5e, 0x77, 0x28, 0x8b, 0xa8, 0x9b, + 0xb3, 0x35, 0xc3, 0x99, 0x90, 0xd4, 0x5d, 0x63, + 0xa7, + }, + + { + 0xbc, 0xc2, 0x9f, 0xe6, 0x38, 0xef, 0xf5, + 0x11, 0x76, 0x09, 0x17, 0x3a, 0xd4, 0x91, 0xee, + 0xfe, + }, + + { + 0x9f, 0xa6, 0x23, 0x5a, 0x4d, 0x78, 0xae, + 0xce, 0x10, 0x35, 0xc1, 0x0c, 0x6e, 0xc2, 0x4e, + 0xe8, + } + } + }, + { + { + // Plaintext 160 bytes + { + 0xfb, 0x74, 0x7e, 0x21, 0xf2, 0xe7, 0xe3, 0xf5, + 0xfa, 0xc8, 0x23, 0xab, 0x54, 0x9a, 0xb9, 0xcf, + }, + + { + 0x6b, 0x4e, 0xa8, 0xcd, 0xfd, 0x3d, 0x00, 0xfc, + 0xd8, 0x99, 0x7d, 0x58, 0x81, 0x91, 0xb3, 0x18, + }, + + { + 0x6c, 0x1e, 0x4d, 0xcb, 0x5f, 0x68, 0x3e, 0xc3, + 0xc3, 0xfd, 0xa8, 0x9b, 0x01, 0x56, 0x2d, 0x90, + }, + }, + { + // Plaintext 321 bytes + { + 0xcd, 0x49, 0x75, 0x4c, 0x2a, 0x62, 0x65, + 0x6f, 0xfe, 0x14, 0xc2, 0x5d, 0x41, 0x07, 0x24, + 0x55 + }, + + { + 0xe8, 0xd5, 0x9d, 0x82, 0x99, 0x25, 0x0b, + 0xcd, 0xbd, 0xde, 0x4c, 0xf7, 0x41, 0xcb, 0xa9, + 0x0c, + }, + + { + 0xcb, 0xb1, 0x21, 0x3e, 0xec, 0xb2, 0x50, + 0x12, 0xdb, 0xe2, 0x9a, 0xc1, 0xfb, 0x98, 0x09, + 0x1a, + } + } + }, + }, + }; + + aes_gcm_test_cfg_t cfg = { + .output_caps = MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, + .tag_len = 16 + }; + + + for (int i_key = 0; i_key < sizeof(key_length) / sizeof(key_length[0]); i_key++) { + printf("Test AES-GCM with key length = %d\n", key_length[i_key]); + + cfg.key = key; + cfg.key_bits = 8 * key_length[i_key]; + + for (int i_iv = 0; i_iv < sizeof(iv_length) / sizeof(iv_length[0]); i_iv++) { + printf("Test AES-GCM with IV length = %d\n", iv_length[i_iv]); + + cfg.iv = iv; + cfg.iv_length = iv_length[i_iv]; + + for (int i_len = 0; i_len < sizeof(length) / sizeof(length[0]); i_len++) { + printf("Test AES-GCM with plaintext length = %d\n", length[i_len]); + uint8_t *input = heap_caps_malloc(length[i_len], MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT(input != NULL || length[i_len] == 0); + memset(input, INPUT_BYTES_VALUE, length[i_len]); + cfg.plaintext = input; + cfg.plaintext_length = length[i_len]; + + aes_gcm_test_expected_res_t res = {0}; + + for (int i_add = 0; i_add < sizeof(add_len) / sizeof(add_len[0]); i_add++) { + + printf("Test AES-GCM with add length = %d\n", add_len[i_add]); + uint8_t *add = heap_caps_malloc(add_len[i_add], MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT(add != NULL || add_len[i_add] == 0); + memset(add, ADD_BYTES_VALUE, add_len[i_add]); + + cfg.add_buf = add; + cfg.add_length = add_len[i_add]; + + res.expected_tag = expected_tag[i_key][i_iv][i_len][i_add]; + res.ciphertext_last_block = expected_last_block[i_key][i_iv][i_len], + + aes_gcm_test(&cfg, &res, AES_GCM_TEST_CRYPT_N_TAG); + + free(add); + } + free(input); + } + } + } +} + +TEST_CASE("mbedtls AES GCM - Different Authentication Tag lengths", "[aes-gcm]") +{ + const unsigned CALL_SZ = 160; + uint8_t iv[16]; + uint8_t key[16]; + uint8_t aad[16]; + uint8_t *input = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(input); + + memset(input, 0x67, CALL_SZ); + memset(iv, 0xA2, sizeof(iv)); + memset(key, 0x48, sizeof(key)); + memset(aad, 0x12, sizeof(aad)); + + size_t tag_len[] = {4, 8, 11, 16}; + + const uint8_t expected_last_block[] = { + 0xcd, 0xb9, 0xad, 0x6f, 0xc9, 0x35, 0x21, 0x0d, + 0xc9, 0x5d, 0xea, 0xd9, 0xf7, 0x1d, 0x43, 0xed + }; + + const uint8_t expected_tag[16] = { + 0x57, 0x10, 0x22, 0x91, 0x65, 0xfa, 0x89, 0xba, + 0x0a, 0x3e, 0xc1, 0x7c, 0x93, 0x6e, 0x35, 0xac + }; + + aes_gcm_test_cfg_t cfg = { + .plaintext = input, + .plaintext_length = CALL_SZ, + .output_caps = MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, + .add_buf = aad, + .add_length = sizeof(aad), + .iv = iv, + .iv_length = sizeof(iv), + .key = key, + .key_bits = 8 * sizeof(key), + }; + + aes_gcm_test_expected_res_t res = { + .expected_tag = expected_tag, + .ciphertext_last_block = expected_last_block, + }; + + for (int i = 0; i < sizeof(tag_len) / sizeof(tag_len[0]); i++) { + printf("Test AES-GCM with tag length = %d\n", tag_len[i]); + cfg.tag_len = tag_len[i]; + aes_gcm_test(&cfg, &res, AES_GCM_TEST_CRYPT_N_TAG); + aes_gcm_test(&cfg, &res, AES_GCM_TEST_START_UPDATE_FINISH); + } + free(input); +} + +#endif //CONFIG_MBEDTLS_HARDWARE_AES diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_aes_perf.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_aes_perf.c new file mode 100644 index 000000000..6ba8f15c1 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_aes_perf.c @@ -0,0 +1,75 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* mbedTLS AES performance test +*/ +#include +#include +#include +#include +#include "mbedtls/aes.h" +#include "mbedtls/gcm.h" +#include "unity.h" +#include "sdkconfig.h" +#include "esp_heap_caps.h" +#include "test_utils.h" +#include "ccomp_timer.h" + +TEST_CASE("mbedtls AES performance", "[aes][timeout=60]") +{ + const unsigned CALLS = 256; + const unsigned CALL_SZ = 32 * 1024; + mbedtls_aes_context ctx; + float elapsed_usec; + uint8_t iv[16]; + uint8_t key[16]; + + memset(iv, 0xEE, 16); + memset(key, 0x44, 16); + + // allocate internal memory + uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(buf); + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key, 128); + + ccomp_timer_start(); + for (int c = 0; c < CALLS; c++) { + memset(buf, 0xAA, CALL_SZ); + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, CALL_SZ, iv, buf, buf); + } + elapsed_usec = ccomp_timer_stop(); + + /* Sanity check: make sure the last ciphertext block matches + what we expect to see. + + Last block produced via this Python: + import os, binascii + from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + from cryptography.hazmat.backends import default_backend + key = b'\x44' * 16 + iv = b'\xee' * 16 + cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()) + encryptor = cipher.encryptor() + ct = encryptor.update(b'\xaa' * 256 * 32 * 1024) + encryptor.finalize() + print(binascii.hexlify(ct[-16:])) + */ + const uint8_t expected_last_block[] = { + 0x50, 0x81, 0xe0, 0xe1, 0x15, 0x2f, 0x14, 0xe9, + 0x97, 0xa0, 0xc6, 0xe6, 0x36, 0xf3, 0x5c, 0x25, + }; + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16, 16); + + mbedtls_aes_free(&ctx); + free(buf); + + // bytes/usec = MB/sec + float mb_sec = (CALL_SZ * CALLS) / elapsed_usec; + printf("Encryption rate %.3fMB/sec\n", mb_sec); +#ifdef CONFIG_MBEDTLS_HARDWARE_AES + // Don't put a hard limit on software AES performance + TEST_PERFORMANCE_CCOMP_GREATER_THAN(AES_CBC_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec); +#endif +} diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_aes_sha_parallel.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_aes_sha_parallel.c new file mode 100644 index 000000000..ddbb5baff --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_aes_sha_parallel.c @@ -0,0 +1,133 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include "mbedtls/aes.h" +#include "mbedtls/sha256.h" +#include "unity.h" +#include "sdkconfig.h" +#include "esp_heap_caps.h" +#include "test_utils.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" + + +static SemaphoreHandle_t done_sem; + +static const unsigned char *one_hundred_bs = (unsigned char *) + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; + +static const uint8_t sha256_thousand_bs[32] = { + 0xf6, 0xf1, 0x18, 0xe1, 0x20, 0xe5, 0x2b, 0xe0, 0xbd, 0x0c, 0xfd, 0xf2, 0x79, 0x4c, 0xd1, 0x2c, 0x07, 0x68, 0x6c, 0xc8, 0x71, 0x23, 0x5a, 0xc2, 0xf1, 0x14, 0x59, 0x37, 0x8e, 0x6d, 0x23, 0x5b +}; + +static void tskRunSHA256Test(void *pvParameters) +{ + mbedtls_sha256_context sha256_ctx; + unsigned char sha256[32]; + + for (int i = 0; i < 1000; i++) { + + mbedtls_sha256_init(&sha256_ctx); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(&sha256_ctx, false)); + for (int j = 0; j < 10; j++) { + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&sha256_ctx, (unsigned char *)one_hundred_bs, 100)); + } + TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&sha256_ctx, sha256)); + mbedtls_sha256_free(&sha256_ctx); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_bs, sha256, 32, "SHA256 calculation"); + } + xSemaphoreGive(done_sem); + vTaskDelete(NULL); +} + + +static void tskRunAES256Test(void *pvParameters) +{ + static const uint8_t iv[] = { + 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, + 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, + }; + + static const uint8_t key_256[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + }; + + for (int i = 0; i <1000; i++) + { + const unsigned SZ = 1600; + mbedtls_aes_context ctx; + uint8_t nonce[16]; + + const uint8_t expected_cipher_end[] = { + 0x3e, 0x68, 0x8a, 0x02, 0xe6, 0xf2, 0x6a, 0x9e, + 0x9b, 0xb2, 0xc0, 0xc4, 0x63, 0x63, 0xd9, 0x25, + 0x51, 0xdc, 0xc2, 0x71, 0x96, 0xb3, 0xe5, 0xcd, + 0xbd, 0x0e, 0xf2, 0xef, 0xa9, 0xab, 0xab, 0x2d, + }; + + memcpy(nonce, iv, 16); + + // allocate internal memory + uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + + TEST_ASSERT_NOT_NULL(chipertext); + TEST_ASSERT_NOT_NULL(plaintext); + TEST_ASSERT_NOT_NULL(decryptedtext); + + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key_256, 256); + + memset(plaintext, 0x3A, SZ); + memset(decryptedtext, 0x0, SZ); + + // Encrypt + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, SZ, nonce, plaintext, chipertext); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + SZ - 32, 32); + + // Decrypt + memcpy(nonce, iv, 16); + mbedtls_aes_setkey_dec(&ctx, key_256, 256); + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, SZ, nonce, chipertext, decryptedtext); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); + + mbedtls_aes_free(&ctx); + free(plaintext); + free(chipertext); + free(decryptedtext); + } + xSemaphoreGive(done_sem); + vTaskDelete(NULL); + +} + +#include "esp_crypto_shared_gdma.h" + +#define TASK_STACK_SIZE (20*1024) + +TEST_CASE("mbedtls AES/SHA multithreading", "[mbedtls]") +{ + done_sem = xSemaphoreCreateCounting(2, 0); + + xTaskCreate(tskRunSHA256Test, "SHA256Task", TASK_STACK_SIZE, NULL, 3, NULL); + xTaskCreate(tskRunAES256Test, "AES256Task", TASK_STACK_SIZE, NULL, 3, NULL); + + for (int i = 0; i < 2; i++) { + if (!xSemaphoreTake(done_sem, 10000 / portTICK_PERIOD_MS)) { + TEST_FAIL_MESSAGE("done_sem not released by test task"); + } + } + + vSemaphoreDelete(done_sem); +} diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_aes_sha_rsa.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_aes_sha_rsa.c new file mode 100644 index 000000000..497180fba --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_aes_sha_rsa.c @@ -0,0 +1,295 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include + +#if CONFIG_IDF_TARGET_ESP32 + +#include "esp_types.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/xtensa_timer.h" +#include "unity.h" +#include "test_utils.h" +#include "esp32/rom/sha.h" +#include "soc/uart_periph.h" +#include "soc/dport_reg.h" +#include "soc/rtc.h" +#include "esp_log.h" +#include "sha/sha_parallel_engine.h" +#include "aes/esp_aes.h" +#include "mbedtls/rsa.h" +#include "mbedtls/sha256.h" + +static const char *TAG = "test"; +static volatile bool exit_flag = false; +#define TASK_STACK_SIZE (8*1024) + +static void aes_task(void *pvParameters) +{ + SemaphoreHandle_t *sema = (SemaphoreHandle_t *) pvParameters; + ESP_LOGI(TAG, "aes_task is started"); + esp_aes_context ctx = { + .key_bytes = 16, + .key = {101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116} + }; + const unsigned char input[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + unsigned char output[16]; + unsigned char output2[16]; + while (exit_flag == false) { + memset(output, 0, sizeof(output)); + memset(output, 0, sizeof(output2)); + esp_internal_aes_encrypt(&ctx, input, output); + esp_internal_aes_decrypt(&ctx, output, output2); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(input, output2, sizeof(input), "AES must match"); + } + xSemaphoreGive(*sema); + vTaskDelete(NULL); +} + +static void sha_task(void *pvParameters) +{ + SemaphoreHandle_t *sema = (SemaphoreHandle_t *) pvParameters; + ESP_LOGI(TAG, "sha_task is started"); + const char *input = "Space!#$%&()*+,-.0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz~DEL0123456789"; + unsigned char output[64]; + unsigned char output_origin[64]; + esp_sha(SHA2_512, (const unsigned char *)input, sizeof(input), output); + memcpy(output_origin, output, sizeof(output)); + while (exit_flag == false) { + memset(output, 0, sizeof(output)); + esp_sha(SHA2_512, (const unsigned char *)input, sizeof(input), output); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(output, output_origin, sizeof(output), "SHA256 must match"); + } + xSemaphoreGive(*sema); + vTaskDelete(NULL); +} + +static void mbedtls_sha256_task(void *pvParameters) +{ + SemaphoreHandle_t *sema = (SemaphoreHandle_t *) pvParameters; + ESP_LOGI(TAG, "mbedtls_sha256_task is started"); + const char *input = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz~DEL0123456789Space!#$%&()*+,-.0123456789:;<=>?"; + mbedtls_sha256_context sha256_ctx; + unsigned char output[32]; + unsigned char output_origin[32]; + + mbedtls_sha256_init(&sha256_ctx); + memset(output, 0, sizeof(output)); + mbedtls_sha256_starts(&sha256_ctx, false); + for (int i = 0; i < 3; ++i) { + mbedtls_sha256_update(&sha256_ctx, (unsigned char *)input, 100); + } + mbedtls_sha256_finish(&sha256_ctx, output); + memcpy(output_origin, output, sizeof(output)); + + while (exit_flag == false) { + mbedtls_sha256_init(&sha256_ctx); + memset(output, 0, sizeof(output)); + mbedtls_sha256_starts(&sha256_ctx, false); + for (int i = 0; i < 3; ++i) { + mbedtls_sha256_update(&sha256_ctx, (unsigned char *)input, 100); + } + mbedtls_sha256_finish(&sha256_ctx, output); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(output, output_origin, sizeof(output), "MBEDTLS SHA256 must match"); + } + xSemaphoreGive(*sema); + vTaskDelete(NULL); +} + +TEST_CASE("Test shared using AES SHA512 SHA256", "[hw_crypto]") +{ +#ifndef CONFIG_FREERTOS_UNICORE + const int max_tasks = 6; +#else + const int max_tasks = 3; +#endif + SemaphoreHandle_t exit_sema[max_tasks]; + + for (int i = 0; i < max_tasks; ++i) { + exit_sema[i] = xSemaphoreCreateBinary(); + } + exit_flag = false; +#ifndef CONFIG_FREERTOS_UNICORE + xTaskCreatePinnedToCore(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL, 1); + xTaskCreatePinnedToCore(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 0); + xTaskCreatePinnedToCore(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[2], UNITY_FREERTOS_PRIORITY - 1, NULL, 1); + xTaskCreatePinnedToCore(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[3], UNITY_FREERTOS_PRIORITY - 1, NULL, 0); + xTaskCreatePinnedToCore(&mbedtls_sha256_task, "mbedtls_sha256_task", TASK_STACK_SIZE, &exit_sema[4], UNITY_FREERTOS_PRIORITY - 1, NULL, 1); + xTaskCreatePinnedToCore(&mbedtls_sha256_task, "mbedtls_sha256_task", TASK_STACK_SIZE, &exit_sema[5], UNITY_FREERTOS_PRIORITY - 1, NULL, 0); +#else + xTaskCreate(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL); + xTaskCreate(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL); + xTaskCreate(&mbedtls_sha256_task, "mbedtls_sha256_task", TASK_STACK_SIZE, &exit_sema[2], UNITY_FREERTOS_PRIORITY - 1, NULL); +#endif + + ESP_LOGI(TAG, "Waiting for 10s ..."); + vTaskDelay(10000 / portTICK_PERIOD_MS); + + // set exit flag to let thread exit + exit_flag = true; + for (int i = 0; i < max_tasks; ++i) { + if (!xSemaphoreTake(exit_sema[i], 2000/portTICK_PERIOD_MS)) { + TEST_FAIL_MESSAGE("exit_sema not released by test task"); + } + vSemaphoreDelete(exit_sema[i]); + } +} + +static void rsa_task(void *pvParameters) +{ + SemaphoreHandle_t *sema = (SemaphoreHandle_t *) pvParameters; + ESP_LOGI(TAG, "rsa_task is started"); + while (exit_flag == false) { + mbedtls_rsa_self_test(0); + } + xSemaphoreGive(*sema); + vTaskDelete(NULL); +} + +TEST_CASE("Test shared using AES RSA", "[hw_crypto]") +{ +#ifndef CONFIG_FREERTOS_UNICORE + const int max_tasks = 2; +#else + const int max_tasks = 2; +#endif + SemaphoreHandle_t exit_sema[max_tasks]; + + for (int i = 0; i < max_tasks; ++i) { + exit_sema[i] = xSemaphoreCreateBinary(); + } + exit_flag = false; +#ifndef CONFIG_FREERTOS_UNICORE + xTaskCreatePinnedToCore(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL, 1); + xTaskCreatePinnedToCore(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 0); +#else + xTaskCreate(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL); + xTaskCreate(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL); +#endif + + ESP_LOGI(TAG, "Waiting for 10s ..."); + vTaskDelay(10000 / portTICK_PERIOD_MS); + + // set exit flag to let thread exit + exit_flag = true; + for (int i = 0; i < max_tasks; ++i) { + if (!xSemaphoreTake(exit_sema[i], 2000/portTICK_PERIOD_MS)) { + TEST_FAIL_MESSAGE("exit_sema not released by test task"); + } + vSemaphoreDelete(exit_sema[i]); + } +} + +TEST_CASE("Test shared using SHA512 RSA", "[hw_crypto]") +{ +#ifndef CONFIG_FREERTOS_UNICORE + const int max_tasks = 2; +#else + const int max_tasks = 2; +#endif + SemaphoreHandle_t exit_sema[max_tasks]; + + for (int i = 0; i < max_tasks; ++i) { + exit_sema[i] = xSemaphoreCreateBinary(); + } + exit_flag = false; +#ifndef CONFIG_FREERTOS_UNICORE + xTaskCreatePinnedToCore(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 2, NULL, 1); + xTaskCreatePinnedToCore(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 0); +#else + xTaskCreate(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL); + xTaskCreate(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL); +#endif + + ESP_LOGI(TAG, "Waiting for 10s ..."); + vTaskDelay(10000 / portTICK_PERIOD_MS); + + // set exit flag to let thread exit + exit_flag = true; + for (int i = 0; i < max_tasks; ++i) { + if (!xSemaphoreTake(exit_sema[i], 2000/portTICK_PERIOD_MS)) { + TEST_FAIL_MESSAGE("exit_sema not released by test task"); + } + vSemaphoreDelete(exit_sema[i]); + } +} + +TEST_CASE("Test shared using SHA256 RSA", "[hw_crypto]") +{ +#ifndef CONFIG_FREERTOS_UNICORE + const int max_tasks = 2; +#else + const int max_tasks = 2; +#endif + SemaphoreHandle_t exit_sema[max_tasks]; + + for (int i = 0; i < max_tasks; ++i) { + exit_sema[i] = xSemaphoreCreateBinary(); + } + exit_flag = false; +#ifndef CONFIG_FREERTOS_UNICORE + xTaskCreatePinnedToCore(&mbedtls_sha256_task, "mbedtls_sha256_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL, 1); + xTaskCreatePinnedToCore(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 0); +#else + xTaskCreate(&mbedtls_sha256_task, "mbedtls_sha256_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL); + xTaskCreate(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL); +#endif + + ESP_LOGI(TAG, "Waiting for 10s ..."); + vTaskDelay(10000 / portTICK_PERIOD_MS); + + // set exit flag to let thread exit + exit_flag = true; + for (int i = 0; i < max_tasks; ++i) { + if (!xSemaphoreTake(exit_sema[i], 2000/portTICK_PERIOD_MS)) { + TEST_FAIL_MESSAGE("exit_sema not released by test task"); + } + vSemaphoreDelete(exit_sema[i]); + } +} + +TEST_CASE("Test shared using AES SHA RSA", "[hw_crypto]") +{ +#ifndef CONFIG_FREERTOS_UNICORE + const int max_tasks = 3; +#else + const int max_tasks = 3; +#endif + SemaphoreHandle_t exit_sema[max_tasks]; + + for (int i = 0; i < max_tasks; ++i) { + exit_sema[i] = xSemaphoreCreateBinary(); + } + exit_flag = false; +#ifndef CONFIG_FREERTOS_UNICORE + xTaskCreatePinnedToCore(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL, 0); + xTaskCreatePinnedToCore(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 0); + xTaskCreatePinnedToCore(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[2], UNITY_FREERTOS_PRIORITY - 1, NULL, 1); +#else + xTaskCreate(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL); + xTaskCreate(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL); + xTaskCreate(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[2], UNITY_FREERTOS_PRIORITY - 1, NULL); +#endif + + ESP_LOGI(TAG, "Waiting for 10s ..."); + vTaskDelay(10000 / portTICK_PERIOD_MS); + + // set exit flag to let thread exit + exit_flag = true; + for (int i = 0; i < max_tasks; ++i) { + if (!xSemaphoreTake(exit_sema[i], 2000/portTICK_PERIOD_MS)) { + TEST_FAIL_MESSAGE("exit_sema not released by test task"); + } + vSemaphoreDelete(exit_sema[i]); + } +} + +#endif // CONFIG_IDF_TARGET_ESP32 diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_apb_dport_access.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_apb_dport_access.c new file mode 100644 index 000000000..34cb95687 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_apb_dport_access.c @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* Implementation of utility functions to verify + unit tests aren't performing SMP-unsafe DPORT reads. +*/ + +#include "unity.h" +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "soc/uart_periph.h" +#include "test_apb_dport_access.h" +#include "test_utils.h" + +#ifndef CONFIG_FREERTOS_UNICORE + +static void apb_access_loop_task(void *ignore); + +static volatile bool apb_access_corrupt; +static TaskHandle_t apb_task_handle; + +void start_apb_access_loop(void) +{ + apb_access_corrupt = false; + xTaskCreatePinnedToCore(apb_access_loop_task, "accessAPB", 2048, NULL, + UNITY_FREERTOS_PRIORITY - 1, + &apb_task_handle, !UNITY_FREERTOS_CPU); +} + +void verify_apb_access_loop(void) +{ + vTaskDelete(apb_task_handle); + apb_task_handle = NULL; + TEST_ASSERT_FALSE(apb_access_corrupt); + printf("Verified no APB corruption from operations\n"); +} + +static void apb_access_loop_task(void *ignore) +{ + uint32_t initial = REG_READ(UART_DATE_REG(0)); + while(1) { + if (REG_READ(UART_DATE_REG(0)) != initial) { + apb_access_corrupt = true; + } + } +} + +#else /*CONFIG_FREERTOS_UNICORE */ + +void start_apb_access_loop(void) +{ +} + +void verify_apb_access_loop(void) +{ +} + +#endif diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_apb_dport_access.h b/components/mbedtls/mbedtls_v3/test_apps/main/test_apb_dport_access.h new file mode 100644 index 000000000..3231d745e --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_apb_dport_access.h @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* Utility functions to test that APB access is still safe + while the other CPU performs some set of DPORT accesses + + (see ECO 3.10 and the standalone esp32 test_dport.c for more). +*/ + +/* start_apb_access_loop() starts a task reading from APB in a loop on the non-Unity-test CPU. + + Call this before doing something which involes DPORT reads. + + Does nothing in unicore mode. +*/ +void start_apb_access_loop(void); + +/* verify_apb_access_loop() kills the task started by start_apb_access_loop() + and verifies that none of the APB reads were corrupted by unsafe DPORT reads. +*/ +void verify_apb_access_loop(void); diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_ecp.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_ecp.c new file mode 100644 index 000000000..db4258703 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_ecp.c @@ -0,0 +1,333 @@ +/* mbedTLS Elliptic Curve functionality tests + * + * Focus on testing functionality where we use ESP32 hardware + * accelerated crypto features. + * + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "test_utils.h" +#include "ccomp_timer.h" +#include "unity.h" + +/* Note: negative value here so that assert message prints a grep-able + error hex value (mbedTLS uses -N for error codes) */ +#define TEST_ASSERT_MBEDTLS_OK(X) TEST_ASSERT_EQUAL_HEX32(0, -(X)) + +/* TODO: Currently MBEDTLS_ECDH_LEGACY_CONTEXT is enabled by default + * when MBEDTLS_ECP_RESTARTABLE is enabled. + * This is a temporary workaround to allow that. + * + * The legacy option is soon going to be removed in future mbedtls + * versions and this workaround will be removed once the appropriate + * solution is available. + */ +#ifdef CONFIG_MBEDTLS_ECDH_LEGACY_CONTEXT +#define ACCESS_ECDH(S, var) S.MBEDTLS_PRIVATE(var) +#else +#define ACCESS_ECDH(S, var) S.MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(var) +#endif + +#if CONFIG_NEWLIB_NANO_FORMAT +#define NEWLIB_NANO_COMPAT_FORMAT PRIu32 +#define NEWLIB_NANO_COMPAT_CAST(int64_t_var) (uint32_t)int64_t_var +#else +#define NEWLIB_NANO_COMPAT_FORMAT PRId64 +#define NEWLIB_NANO_COMPAT_CAST(int64_t_var) int64_t_var +#endif + +TEST_CASE("mbedtls ECDH Generate Key", "[mbedtls]") +{ + mbedtls_ecdh_context ctx; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + + mbedtls_ecdh_init(&ctx); + mbedtls_ctr_drbg_init(&ctr_drbg); + + mbedtls_entropy_init(&entropy); + TEST_ASSERT_MBEDTLS_OK( mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0) ); + + TEST_ASSERT_MBEDTLS_OK( mbedtls_ecp_group_load(ACCESS_ECDH(&ctx, grp), MBEDTLS_ECP_DP_CURVE25519) ); + + TEST_ASSERT_MBEDTLS_OK( mbedtls_ecdh_gen_public(ACCESS_ECDH(&ctx, grp), ACCESS_ECDH(&ctx, d), ACCESS_ECDH(&ctx, Q), + mbedtls_ctr_drbg_random, &ctr_drbg ) ); + + mbedtls_ecdh_free(&ctx); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); +} + +TEST_CASE("mbedtls ECP self-tests", "[mbedtls]") +{ + TEST_ASSERT_EQUAL(0, mbedtls_ecp_self_test(1)); +} + +TEST_CASE("mbedtls ECP mul w/ koblitz", "[mbedtls]") +{ + /* Test case code via https://github.com/espressif/esp-idf/issues/1556 */ + mbedtls_entropy_context ctxEntropy; + mbedtls_ctr_drbg_context ctxRandom; + mbedtls_ecdsa_context ctxECDSA; + const char* pers = "myecdsa"; + + mbedtls_entropy_init(&ctxEntropy); + mbedtls_ctr_drbg_init(&ctxRandom); + TEST_ASSERT_MBEDTLS_OK( mbedtls_ctr_drbg_seed(&ctxRandom, mbedtls_entropy_func, &ctxEntropy, + (const unsigned char*) pers, strlen(pers)) ); + + mbedtls_ecdsa_init(&ctxECDSA); + + TEST_ASSERT_MBEDTLS_OK( mbedtls_ecdsa_genkey(&ctxECDSA, MBEDTLS_ECP_DP_SECP256K1, + mbedtls_ctr_drbg_random, &ctxRandom) ); + + + TEST_ASSERT_MBEDTLS_OK(mbedtls_ecp_mul(&ctxECDSA.MBEDTLS_PRIVATE(grp), &ctxECDSA.MBEDTLS_PRIVATE(Q), + &ctxECDSA.MBEDTLS_PRIVATE(d), &ctxECDSA.MBEDTLS_PRIVATE(grp).G, + mbedtls_ctr_drbg_random, &ctxRandom) ); + + mbedtls_ecdsa_free(&ctxECDSA); + mbedtls_ctr_drbg_free(&ctxRandom); + mbedtls_entropy_free(&ctxEntropy); +} + +#if CONFIG_MBEDTLS_HARDWARE_ECC + +#define SMALL_SCALAR 127 + +/* + * Coordinates and integers stored in big endian format + */ +const uint8_t ecc_p192_point_x[] = { + 0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6, + 0x7C, 0xBF, 0x20, 0xEB, 0x43, 0xA1, 0x88, 0x00, + 0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12 +}; + +const uint8_t ecc_p192_point_y[] = { + 0x07, 0x19, 0x2B, 0x95, 0xFF, 0xC8, 0xDA, 0x78, + 0x63, 0x10, 0x11, 0xED, 0x6B, 0x24, 0xCD, 0xD5, + 0x73, 0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11 +}; + +const uint8_t ecc_p192_scalar[] = { + 0x6f, 0x18, 0x34, 0xeb, 0x16, 0xb7, 0xac, 0x9f, + 0x3c, 0x77, 0x71, 0xb3, 0x02, 0x30, 0x70, 0x48, + 0x75, 0x87, 0xbb, 0x6f, 0x80, 0x34, 0x8d, 0x5e +}; + +const uint8_t ecc_p192_mul_res_x[] = { + 0x3F, 0xEE, 0x6F, 0x1F, 0x99, 0xDC, 0xCB, 0x78, + 0xB7, 0x47, 0x1C, 0x2A, 0xF5, 0xA0, 0xAC, 0xE6, + 0xEC, 0x24, 0x82, 0x37, 0x6C, 0xC0, 0x27, 0xC5, +}; + +const uint8_t ecc_p192_mul_res_y[] = { + 0xDF, 0xF3, 0x9E, 0x76, 0x24, 0xF4, 0xF6, 0xB4, + 0xF0, 0x0A, 0x18, 0xE1, 0x0B, 0xD2, 0xD9, 0x83, + 0xE8, 0x29, 0x5E, 0xD9, 0x46, 0x54, 0xC3, 0xE1 +}; + +const uint8_t ecc_p192_small_mul_res_x[] = { + 0x62, 0xBF, 0x33, 0xC1, 0x75, 0xB5, 0xEB, 0x1D, + 0xBE, 0xC7, 0x15, 0x04, 0x03, 0xA7, 0xDD, 0x9D, + 0x0B, 0x17, 0x9D, 0x3B, 0x06, 0x63, 0xFE, 0xD3 +}; + +const uint8_t ecc_p192_small_mul_res_y[] = { + 0xD4, 0xE9, 0x4E, 0x4D, 0x89, 0x4D, 0xB5, 0x99, + 0x8A, 0xE1, 0x85, 0x81, 0x27, 0x38, 0x23, 0x32, + 0x92, 0xCF, 0xE8, 0x38, 0xCA, 0x39, 0xF2, 0xE1 +}; + +const uint8_t ecc_p256_point_x[] = { + 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, + 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, + 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, + 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96 +}; + +const uint8_t ecc_p256_point_y[] = { + 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, + 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, + 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, + 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 +}; + +const uint8_t ecc_p256_scalar[] = { + 0xB2, 0xC5, 0x9E, 0x92, 0x64, 0xCD, 0x5F, 0x66, + 0x9E, 0xC8, 0x83, 0x6D, 0x99, 0x61, 0x18, 0x72, + 0xC8, 0x60, 0x83, 0x1E, 0xE5, 0x79, 0xCC, 0x73, + 0xA9, 0xB4, 0x74, 0x85, 0x70, 0x11, 0x2D, 0xA2, +}; + +const uint8_t ecc_p256_mul_res_x[] = { + 0x26, 0x1A, 0x0F, 0xBD, 0xA5, 0xE5, 0x1E, 0xE7, + 0xB3, 0xC3, 0xB7, 0x09, 0xD1, 0x4A, 0x7A, 0x2A, + 0x16, 0x69, 0x4B, 0xAF, 0x76, 0x5C, 0xD4, 0x0E, + 0x93, 0x57, 0xB8, 0x67, 0xF9, 0xA1, 0xE5, 0xE8 +}; + +const uint8_t ecc_p256_mul_res_y[] = { + 0xA0, 0xF4, 0x2E, 0x62, 0x36, 0x25, 0x9F, 0xE0, + 0xF2, 0xA0, 0x41, 0x42, 0xD2, 0x95, 0x89, 0x41, + 0x38, 0xF0, 0xEB, 0x6E, 0xA7, 0x96, 0x29, 0x24, + 0xC7, 0xD4, 0x0C, 0x90, 0xA1, 0xC9, 0xD3, 0x3A +}; + +const uint8_t ecc_p256_small_mul_res_x[] = { + 0x53, 0x4D, 0x45, 0xDB, 0x6B, 0xAC, 0xA8, 0xE2, + 0xD2, 0xA5, 0xD0, 0xA7, 0x65, 0xF1, 0x60, 0x13, + 0xA8, 0xD4, 0xEB, 0x58, 0xC6, 0xAA, 0xAD, 0x35, + 0x67, 0xCE, 0xBD, 0xFA, 0xC4, 0x2D, 0x62, 0x3C +}; + +const uint8_t ecc_p256_small_mul_res_y[] = { + 0xFA, 0xD6, 0x69, 0xC8, 0x9A, 0x2A, 0x54, 0xE4, + 0x41, 0x54, 0x35, 0x7F, 0x99, 0x2C, 0xCE, 0xC8, + 0xEE, 0xF0, 0x93, 0xE0, 0xF2, 0x3A, 0x63, 0x1D, + 0x17, 0xFD, 0xF6, 0x64, 0x41, 0x9E, 0x50, 0x0C +}; + + +static int rng_wrapper(void *ctx, unsigned char *buf, size_t len) +{ + esp_fill_random(buf, len); + return 0; +} + +static void test_ecp_mul(mbedtls_ecp_group_id id, const uint8_t *x_coord, const uint8_t *y_coord, const uint8_t *scalar, + const uint8_t *result_x_coord, const uint8_t *result_y_coord) +{ + int64_t elapsed_time; + uint8_t x[32]; + uint8_t y[32]; + int size; + int ret; + + mbedtls_ecp_group grp; + mbedtls_ecp_point R; + mbedtls_ecp_point P; + mbedtls_mpi m; + + mbedtls_ecp_group_init(&grp); + mbedtls_ecp_point_init(&R); + mbedtls_ecp_point_init(&P); + mbedtls_mpi_init(&m); + + mbedtls_ecp_group_load(&grp, id); + + size = grp.pbits / 8; + + if (!scalar) { + mbedtls_mpi_lset(&m, SMALL_SCALAR); + } else { + mbedtls_mpi_read_binary(&m, scalar, size); + } + + mbedtls_mpi_read_binary(&P.MBEDTLS_PRIVATE(X), x_coord, size); + mbedtls_mpi_read_binary(&P.MBEDTLS_PRIVATE(Y), y_coord, size); + + mbedtls_mpi_lset(&P.MBEDTLS_PRIVATE(Z), 1); + + ccomp_timer_start(); + ret = mbedtls_ecp_mul(&grp, &R, &m, &P, rng_wrapper, NULL); + elapsed_time = ccomp_timer_stop(); + + TEST_ASSERT_EQUAL(0, ret); + + mbedtls_mpi_write_binary(&R.MBEDTLS_PRIVATE(X), x, mbedtls_mpi_size(&R.MBEDTLS_PRIVATE(X))); + mbedtls_mpi_write_binary(&R.MBEDTLS_PRIVATE(Y), y, mbedtls_mpi_size(&R.MBEDTLS_PRIVATE(Y))); + + TEST_ASSERT_EQUAL(0, memcmp(x, result_x_coord, mbedtls_mpi_size(&R.MBEDTLS_PRIVATE(X)))); + TEST_ASSERT_EQUAL(0, memcmp(y, result_y_coord, mbedtls_mpi_size(&R.MBEDTLS_PRIVATE(Y)))); + + if (id == MBEDTLS_ECP_DP_SECP192R1) { + TEST_PERFORMANCE_CCOMP_LESS_THAN(ECP_P192_POINT_MULTIPLY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time)); + } else if (id == MBEDTLS_ECP_DP_SECP256R1) { + TEST_PERFORMANCE_CCOMP_LESS_THAN(ECP_P256_POINT_MULTIPLY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time)); + } + + mbedtls_ecp_point_free(&R); + mbedtls_ecp_point_free(&P); + mbedtls_mpi_free(&m); + mbedtls_ecp_group_free(&grp); +} + +TEST_CASE("mbedtls ECP point multiply with SECP192R1", "[mbedtls]") +{ + test_ecp_mul(MBEDTLS_ECP_DP_SECP192R1, ecc_p192_point_x, ecc_p192_point_y, ecc_p192_scalar, + ecc_p192_mul_res_x, ecc_p192_mul_res_y); + + test_ecp_mul(MBEDTLS_ECP_DP_SECP192R1, ecc_p192_point_x, ecc_p192_point_y, NULL, + ecc_p192_small_mul_res_x, ecc_p192_small_mul_res_y); +} + +TEST_CASE("mbedtls ECP point multiply with SECP256R1", "[mbedtls]") +{ + test_ecp_mul(MBEDTLS_ECP_DP_SECP256R1, ecc_p256_point_x, ecc_p256_point_y, ecc_p256_scalar, + ecc_p256_mul_res_x, ecc_p256_mul_res_y); + + test_ecp_mul(MBEDTLS_ECP_DP_SECP256R1, ecc_p256_point_x, ecc_p256_point_y, NULL, + ecc_p256_small_mul_res_x, ecc_p256_small_mul_res_y); +} + +static void test_ecp_verify(mbedtls_ecp_group_id id, const uint8_t *x_coord, const uint8_t *y_coord) +{ + int64_t elapsed_time; + int size; + int ret; + + mbedtls_ecp_group grp; + mbedtls_ecp_point P; + + mbedtls_ecp_group_init(&grp); + mbedtls_ecp_point_init(&P); + + mbedtls_ecp_group_load(&grp, id); + + size = grp.pbits / 8; + + mbedtls_mpi_read_binary(&P.MBEDTLS_PRIVATE(X), x_coord, size); + mbedtls_mpi_read_binary(&P.MBEDTLS_PRIVATE(Y), y_coord, size); + mbedtls_mpi_lset(&P.MBEDTLS_PRIVATE(Z), 1); + + ccomp_timer_start(); + ret = mbedtls_ecp_check_pubkey(&grp, &P); + elapsed_time = ccomp_timer_stop(); + + TEST_ASSERT_EQUAL(0, ret); + + if (id == MBEDTLS_ECP_DP_SECP192R1) { + TEST_PERFORMANCE_CCOMP_LESS_THAN(ECP_P192_POINT_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time)); + } else if (id == MBEDTLS_ECP_DP_SECP256R1) { + TEST_PERFORMANCE_CCOMP_LESS_THAN(ECP_P256_POINT_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time)); + } + + mbedtls_ecp_point_free(&P); + mbedtls_ecp_group_free(&grp); +} + +TEST_CASE("mbedtls ECP point verify with SECP192R1", "[mbedtls]") +{ + test_ecp_verify(MBEDTLS_ECP_DP_SECP192R1, ecc_p192_mul_res_x, ecc_p192_mul_res_y); +} + +TEST_CASE("mbedtls ECP point verify with SECP256R1", "[mbedtls]") +{ + test_ecp_verify(MBEDTLS_ECP_DP_SECP256R1, ecc_p256_mul_res_x, ecc_p256_mul_res_y); +} +#endif /* CONFIG_MBEDTLS_HARDWARE_ECC */ diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_esp_crt_bundle.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_esp_crt_bundle.c new file mode 100644 index 000000000..a4b0af46a --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_esp_crt_bundle.c @@ -0,0 +1,487 @@ +/* SSL server using plain mbedTLS sockets + * + * Adapted from the ssl_server example in mbedtls. + * + * SPDX-FileCopyrightText: The Mbed TLS Contributors + * + * SPDX-License-Identifier: Apache-2.0 + * + * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD + */ +#include "esp_err.h" +#include "esp_log.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" + +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/x509.h" +#include "mbedtls/ssl.h" +#include "entropy_poll.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/error.h" +#include "mbedtls/debug.h" +#include "mbedtls/esp_debug.h" + +#include "esp_crt_bundle.h" +#include "esp_random.h" + +#include "unity.h" +#include "test_utils.h" +#include "unity_test_utils.h" + +#define SERVER_ADDRESS "localhost" +#define SERVER_PORT "4433" + +extern const uint8_t server_cert_chain_pem_start[] asm("_binary_server_cert_chain_pem_start"); +extern const uint8_t server_cert_chain_pem_end[] asm("_binary_server_cert_chain_pem_end"); + +extern const uint8_t server_pk_start[] asm("_binary_prvtkey_pem_start"); +extern const uint8_t server_pk_end[] asm("_binary_prvtkey_pem_end"); + +extern const uint8_t server_cert_bundle_start[] asm("_binary_server_cert_bundle_start"); +extern const uint8_t server_cert_bundle_end[] asm("_binary_server_cert_bundle_end"); + +extern const uint8_t bad_md_crt_pem_start[] asm("_binary_bad_md_crt_pem_start"); +extern const uint8_t bad_md_crt_pem_end[] asm("_binary_bad_md_crt_pem_end"); + +extern const uint8_t wrong_sig_crt_pem_start[] asm("_binary_wrong_sig_crt_esp32_com_pem_start"); +extern const uint8_t wrong_sig_crt_pem_end[] asm("_binary_wrong_sig_crt_esp32_com_pem_end"); + +extern const uint8_t correct_sig_crt_pem_start[] asm("_binary_correct_sig_crt_esp32_com_pem_start"); +extern const uint8_t correct_sig_crt_pem_end[] asm("_binary_correct_sig_crt_esp32_com_pem_end"); + +#define SEM_TIMEOUT 10000 +typedef struct { + mbedtls_ssl_context ssl; + mbedtls_net_context listen_fd; + mbedtls_net_context client_fd; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + + mbedtls_ssl_config conf; + mbedtls_x509_crt cert; + mbedtls_pk_context pkey; + +} mbedtls_endpoint_t; + +typedef enum { + ESP_CRT_VALIDATE_UNKNOWN, + ESP_CRT_VALIDATE_OK, + ESP_CRT_VALIDATE_FAIL, +}esp_crt_validate_res_t; + +int esp_crt_verify_callback(void *buf, mbedtls_x509_crt *crt, int data, uint32_t *flags); + +static const char *TAG = "cert_bundle_test"; + +static volatile bool exit_flag; + +esp_err_t endpoint_teardown(mbedtls_endpoint_t *endpoint); + +static int myrand(void *rng_state, unsigned char *output, size_t len) +{ + size_t olen; + return mbedtls_hardware_poll(rng_state, output, len, &olen); +} + +esp_err_t server_setup(mbedtls_endpoint_t *server) +{ + int ret; + mbedtls_ssl_config_init( &server->conf ); +#if CONFIG_MBEDTLS_DEBUG + mbedtls_esp_enable_debug_log( &server->conf, CONFIG_MBEDTLS_DEBUG_LEVEL ); +#endif + mbedtls_net_init( &server->listen_fd ); + mbedtls_net_init( &server->client_fd ); + mbedtls_ssl_init( &server->ssl ); + mbedtls_x509_crt_init( &server->cert ); + mbedtls_pk_init( &server->pkey ); + mbedtls_entropy_init( &server->entropy ); + mbedtls_ctr_drbg_init( &server->ctr_drbg ); + + ESP_LOGI(TAG, "Loading the server cert and key"); + ret = mbedtls_x509_crt_parse( &server->cert, server_cert_chain_pem_start, + server_cert_chain_pem_end - server_cert_chain_pem_start); + + if ( ret != 0 ) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned %d", ret ); + return ESP_FAIL; + } + + ret = mbedtls_pk_parse_key( &server->pkey, (const unsigned char *)server_pk_start, + server_pk_end - server_pk_start, NULL, 0, myrand, NULL ); + if ( ret != 0 ) { + ESP_LOGE(TAG, "mbedtls_pk_parse_key returned %d", ret ); + return ESP_FAIL; + } + + ESP_LOGI(TAG, "Bind on https://%s:%s/", SERVER_ADDRESS, SERVER_PORT ); + if ( ( ret = mbedtls_net_bind( &server->listen_fd, NULL, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { + ESP_LOGE(TAG, "mbedtls_net_bind returned %d", ret ); + return ESP_FAIL; + } + mbedtls_net_set_nonblock(&server->listen_fd); + + ESP_LOGI(TAG, "Seeding the random number generator"); + if ( ( ret = mbedtls_ctr_drbg_seed( &server->ctr_drbg, mbedtls_entropy_func, &server->entropy, + NULL, 0) ) != 0 ) { + ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned %d", ret ); + return ESP_FAIL; + } + + ESP_LOGI(TAG, "Setting up the SSL data"); + if ( ( ret = mbedtls_ssl_config_defaults( &server->conf, + MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { + ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret ); + return ESP_FAIL; + } + + mbedtls_ssl_conf_rng( &server->conf, mbedtls_ctr_drbg_random, &server->ctr_drbg ); + + if (( ret = mbedtls_ssl_conf_own_cert( &server->conf, &server->cert, &server->pkey ) ) != 0 ) { + ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned %d", ret ); + return ESP_FAIL; + } + + if (( ret = mbedtls_ssl_setup( &server->ssl, &server->conf ) ) != 0 ) { + ESP_LOGE(TAG, "mbedtls_ssl_setup returned %d", ret ); + return ESP_FAIL; + } + return ESP_OK; +} + +void server_task(void *pvParameters) +{ + int ret; + mbedtls_endpoint_t server; + SemaphoreHandle_t *sema = (SemaphoreHandle_t *) pvParameters; + + + if (server_setup(&server) != ESP_OK) { + ESP_LOGE(TAG, "SSL server setup failed"); + goto exit; + } + + /* Signal that server is up and hence client task can start now */ + xSemaphoreGive(*sema); + + bool connected = false; + while (!exit_flag) { + + ret = mbedtls_net_accept( &server.listen_fd, &server.client_fd, NULL, 0, NULL ); + + if (ret == 0) { + connected = true; + } + + if (connected) { + mbedtls_ssl_set_bio( &server.ssl, &server.client_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); + ret = mbedtls_ssl_handshake( &server.ssl ); + mbedtls_ssl_session_reset(&server.ssl); + connected = false; + } + + vTaskDelay(20 / portTICK_PERIOD_MS); + } + ESP_LOGE(TAG, "Server shutdown"); +exit: + endpoint_teardown(&server); + xSemaphoreGive(*sema); + vTaskSuspend(NULL); +} + + +esp_err_t endpoint_teardown(mbedtls_endpoint_t *endpoint) +{ + mbedtls_net_free( &endpoint->client_fd ); + mbedtls_net_free( &endpoint->listen_fd ); + + mbedtls_x509_crt_free( &endpoint->cert ); + mbedtls_pk_free( &endpoint->pkey ); + mbedtls_ssl_free( &endpoint->ssl ); + mbedtls_ssl_config_free( &endpoint->conf ); + + mbedtls_ctr_drbg_free( &endpoint->ctr_drbg ); + mbedtls_entropy_free( &endpoint->entropy ); + + return ESP_OK; +} + +esp_err_t client_setup(mbedtls_endpoint_t *client) +{ + int ret; + mbedtls_ssl_config_init( &client->conf ); +#if CONFIG_MBEDTLS_DEBUG + mbedtls_esp_enable_debug_log( &client->conf, CONFIG_MBEDTLS_DEBUG_LEVEL ); +#endif + mbedtls_net_init( &client->client_fd ); + mbedtls_ssl_init( &client->ssl ); + mbedtls_x509_crt_init( &client->cert ); + mbedtls_pk_init( &client->pkey ); + mbedtls_entropy_init( &client->entropy ); + mbedtls_ctr_drbg_init( &client->ctr_drbg ); + + ESP_LOGI(TAG, "Seeding the random number generator"); + if ((ret = mbedtls_ctr_drbg_seed(&client->ctr_drbg, mbedtls_entropy_func, &client->entropy, + NULL, 0)) != 0) { + ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned %d", ret); + return ESP_FAIL; + } + + ESP_LOGI(TAG, "Setting hostname for TLS session..."); + /* Hostname set here should match CN in server certificate */ + if ((ret = mbedtls_ssl_set_hostname(&client->ssl, SERVER_ADDRESS)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret); + return ESP_FAIL; + } + + ESP_LOGI(TAG, "Setting up the SSL/TLS structure..."); + if ((ret = mbedtls_ssl_config_defaults(&client->conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret); + return ESP_FAIL; + } + mbedtls_ssl_conf_rng(&client->conf, mbedtls_ctr_drbg_random, &client->ctr_drbg); + + if ((ret = mbedtls_ssl_setup(&client->ssl, &client->conf)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x\n\n", -ret); + return ESP_FAIL; + } + + return ESP_OK; +} + +void client_task(void *pvParameters) +{ + SemaphoreHandle_t *client_signal_sem = (SemaphoreHandle_t *) pvParameters; + int ret = ESP_FAIL; + + mbedtls_endpoint_t client; + esp_crt_validate_res_t res = ESP_CRT_VALIDATE_UNKNOWN; + + if (client_setup(&client) != ESP_OK) { + ESP_LOGE(TAG, "SSL client setup failed"); + goto exit; + } + + /* Test with default crt bundle that doesnt contain the ca crt */ + ESP_LOGI(TAG, "Connecting to %s:%s...", SERVER_ADDRESS, SERVER_PORT); + if ((ret = mbedtls_net_connect(&client.client_fd, SERVER_ADDRESS, SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) { + ESP_LOGE(TAG, "mbedtls_net_connect returned -%x", -ret); + goto exit; + } + + ESP_LOGI(TAG, "Connected."); + mbedtls_ssl_set_bio(&client.ssl, &client.client_fd, mbedtls_net_send, mbedtls_net_recv, NULL); + + ESP_LOGI(TAG, "Performing the SSL/TLS handshake with bundle that is missing the server root certificate"); + while ( ( ret = mbedtls_ssl_handshake( &client.ssl ) ) != 0 ) { + if ( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { + printf( "mbedtls_ssl_handshake failed with -0x%x\n", -ret ); + break; + } + } + + ESP_LOGI(TAG, "Verifying peer X.509 certificate for bundle ..."); + ret = mbedtls_ssl_get_verify_result(&client.ssl); + + res = (ret == 0) ? ESP_CRT_VALIDATE_OK : ESP_CRT_VALIDATE_FAIL; + + if (res == ESP_CRT_VALIDATE_OK) { + ESP_LOGI(TAG, "Certificate verification passed!"); + } else { + ESP_LOGE(TAG, "Certificate verification failed!"); + } + TEST_ASSERT(res == ESP_CRT_VALIDATE_FAIL); + + // Reset session before new connection + mbedtls_ssl_close_notify(&client.ssl); + mbedtls_ssl_session_reset(&client.ssl); + mbedtls_net_free( &client.client_fd); + + /* Test with bundle that does contain the CA crt */ + esp_crt_bundle_attach(&client.conf); + esp_crt_bundle_set(server_cert_bundle_start, server_cert_bundle_end - server_cert_bundle_start); + + ESP_LOGI(TAG, "Connecting to %s:%s...", SERVER_ADDRESS, SERVER_PORT); + if ((ret = mbedtls_net_connect(&client.client_fd, SERVER_ADDRESS, SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) { + ESP_LOGE(TAG, "mbedtls_net_connect returned -%x", -ret); + goto exit; + } + + ESP_LOGI(TAG, "Connected."); + mbedtls_ssl_set_bio(&client.ssl, &client.client_fd, mbedtls_net_send, mbedtls_net_recv, NULL); + + ESP_LOGI(TAG, "Performing the SSL/TLS handshake with bundle that is missing the server root certificate"); + while ( ( ret = mbedtls_ssl_handshake( &client.ssl ) ) != 0 ) { + if ( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { + printf( "mbedtls_ssl_handshake failed with -0x%x\n", -ret ); + break; + } + } + + ESP_LOGI(TAG, "Verifying peer X.509 certificate for bundle ..."); + ret = mbedtls_ssl_get_verify_result(&client.ssl); + + res = (ret == 0) ? ESP_CRT_VALIDATE_OK : ESP_CRT_VALIDATE_FAIL; + + if (res == ESP_CRT_VALIDATE_OK) { + ESP_LOGI(TAG, "Certificate verification passed!"); + } else { + ESP_LOGE(TAG, "Certificate verification failed!"); + } + TEST_ASSERT(res == ESP_CRT_VALIDATE_OK); + + // Reset session before new connection + mbedtls_ssl_close_notify(&client.ssl); + mbedtls_ssl_session_reset(&client.ssl); + mbedtls_net_free( &client.client_fd); + + +exit: + mbedtls_ssl_close_notify(&client.ssl); + mbedtls_ssl_session_reset(&client.ssl); + esp_crt_bundle_detach(&client.conf); + endpoint_teardown(&client); + xSemaphoreGive(*client_signal_sem); + vTaskSuspend(NULL); +} + + +TEST_CASE("custom certificate bundle", "[mbedtls]") +{ + test_case_uses_tcpip(); + + SemaphoreHandle_t signal_sem = xSemaphoreCreateBinary(); + TEST_ASSERT_NOT_NULL(signal_sem); + + exit_flag = false; + TaskHandle_t server_task_handle; + xTaskCreate(server_task, "server task", 8192, &signal_sem, 10, &server_task_handle); + + // Wait for the server to start up + if (!xSemaphoreTake(signal_sem, SEM_TIMEOUT / portTICK_PERIOD_MS)) { + TEST_FAIL_MESSAGE("signal_sem not released, server start failed"); + } + + SemaphoreHandle_t client_signal_sem = xSemaphoreCreateBinary(); + TEST_ASSERT_NOT_NULL(client_signal_sem); + + TaskHandle_t client_task_handle; + xTaskCreate(client_task, "client task", 8192, &client_signal_sem, 10, &client_task_handle); + + if (!xSemaphoreTake(client_signal_sem, SEM_TIMEOUT / portTICK_PERIOD_MS)) { + TEST_FAIL_MESSAGE("client_signal_sem not released, client exit failed"); + } + unity_utils_task_delete(client_task_handle); + + exit_flag = true; + + if (!xSemaphoreTake(signal_sem, SEM_TIMEOUT / portTICK_PERIOD_MS)) { + TEST_FAIL_MESSAGE("signal_sem not released, server exit failed"); + } + unity_utils_task_delete(server_task_handle); + vSemaphoreDelete(client_signal_sem); + vSemaphoreDelete(signal_sem); +} + +TEST_CASE("custom certificate bundle - weak hash", "[mbedtls]") +{ + /* A weak signature hash on the trusted certificate should not stop + us from verifying the chain, since we already trust it a weak signature hash is + not a security issue */ + + mbedtls_x509_crt crt; + uint32_t flags = 0; + + esp_crt_bundle_attach(NULL); + + mbedtls_x509_crt_init( &crt ); + mbedtls_x509_crt_parse(&crt, bad_md_crt_pem_start, bad_md_crt_pem_end - bad_md_crt_pem_start); + TEST_ASSERT(mbedtls_x509_crt_verify(&crt, NULL, NULL, NULL, &flags, esp_crt_verify_callback, NULL) == 0); + + mbedtls_x509_crt_free(&crt); + + esp_crt_bundle_detach(NULL); +} + +TEST_CASE("custom certificate bundle - wrong signature", "[mbedtls]") +{ + /* Check that the bundle will not verify a valid certificate from trusted root where the signature is wrong */ + + mbedtls_x509_crt crt; + uint32_t flags = 0; + + esp_crt_bundle_attach(NULL); + + mbedtls_x509_crt_init( &crt ); + /* esp32.com cert chain where 1 byte in the signature is changed */ + printf("Testing certificate with wrong signature\n"); + mbedtls_x509_crt_parse(&crt, wrong_sig_crt_pem_start, wrong_sig_crt_pem_end - wrong_sig_crt_pem_start); + TEST_ASSERT(mbedtls_x509_crt_verify(&crt, NULL, NULL, NULL, &flags, esp_crt_verify_callback, NULL) != 0); + mbedtls_x509_crt_free(&crt); + + mbedtls_x509_crt_init( &crt ); + /* the correct esp32.com cert chain*/ + printf("Testing certificate with correct signature\n"); + mbedtls_x509_crt_parse(&crt, correct_sig_crt_pem_start, correct_sig_crt_pem_end - correct_sig_crt_pem_start); + TEST_ASSERT(mbedtls_x509_crt_verify(&crt, NULL, NULL, NULL, &flags, esp_crt_verify_callback, NULL) == 0); + mbedtls_x509_crt_free(&crt); + + esp_crt_bundle_detach(NULL); +} + +TEST_CASE("custom certificate bundle init API - bound checking", "[mbedtls]") +{ + + uint8_t test_bundle[256] = {0}; + esp_err_t esp_ret; + /* The API should fail with bundle size given as 1 */ + esp_ret = esp_crt_bundle_set(test_bundle, 1); + TEST_ASSERT( esp_ret == ESP_ERR_INVALID_ARG); + + /* Check that the esp_crt_bundle_set API will not accept a bundle + * which has more no. of certs than configured in + * CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS */ + + uint8_t rand; + esp_fill_random(&rand, 1); + test_bundle[0] = rand; + + /* Make sure that the number of certs will always be greater than + * CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS */ + test_bundle[1] = rand + CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS; + + esp_ret = esp_crt_bundle_set(test_bundle, sizeof(test_bundle)); + TEST_ASSERT( esp_ret == ESP_ERR_INVALID_ARG); + + /* The API should fail with bundle_size < BUNDLE_HEADER_OFFSET (2) + CRT_HEADER_OFFSET (4) */ + test_bundle[0] = 0; + test_bundle[1] = 1; /* set num_certs = 1 */ + esp_ret = esp_crt_bundle_set(test_bundle, 5); + TEST_ASSERT(esp_ret == ESP_ERR_INVALID_ARG); + + /* Cert number is greater than actual certs present, The API should fail */ + /* Actual No. of certs present in bundle = 1, setting num_certs to 5 */ + test_bundle[1] = 5; /* num_certs */ + test_bundle[3] = 5; /* cert_1_name_len */ + test_bundle[5] = 10; /* cert_1_pub_key_len */ + /* Actual bundle size becomes BUNDLE_HEADER_OFFSET (2) + CRT_HEADER_OFFSET (4) + cert_1_name_len(5) + cert_1_pub_key_len(10) + * i.e. 21 bytes */ + esp_ret = esp_crt_bundle_set(test_bundle, 21); + TEST_ASSERT(esp_ret == ESP_ERR_INVALID_ARG); + + /* The API should fail if bundle_size < BUNDLE_HEADER_OFFSET (2) + CRT_HEADER_OFFSET (4) + cert_1_name_len(5) + cert_1_pub_key_len(10) */ + esp_ret = esp_crt_bundle_set(test_bundle, 20); + TEST_ASSERT(esp_ret == ESP_ERR_INVALID_ARG); + + esp_crt_bundle_detach(NULL); +} diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_gcm.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_gcm.c new file mode 100644 index 000000000..07af880d9 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_gcm.c @@ -0,0 +1,144 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include "sys/param.h" +#include "esp_heap_caps.h" +#include "mbedtls/gcm.h" +#include "sdkconfig.h" +#include "unity.h" + + +#if CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER + +typedef struct { + uint8_t *plaintext; + size_t plaintext_length; + uint8_t *aad_buf; + size_t aad_length; + uint8_t *iv; + size_t iv_length; + uint8_t *key; + size_t key_bits; + size_t tag_len; +} gcm_test_cfg_t; + +typedef struct { + const uint8_t *expected_tag; + const uint8_t *ciphertext_last_block; // Last block of the ciphertext +} gcm_test_expected_res_t; + +typedef enum { + GCM_TEST_CRYPT_N_TAG, + GCM_TEST_START_UPDATE_FINISH, +} gcm_test_type_t; + +static void gcm_test(gcm_test_cfg_t *cfg, gcm_test_expected_res_t *res, gcm_test_type_t gcm_type) +{ + mbedtls_gcm_context ctx; + mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_ARIA; + + uint8_t tag_buf_encrypt[16] = {}; + uint8_t tag_buf_decrypt[16] = {}; + uint8_t iv_buf[16] = {}; + uint8_t *ciphertext = malloc(cfg->plaintext_length); + uint8_t *output = malloc(cfg->plaintext_length); + size_t olen; + + if (cfg->plaintext_length != 0) { + TEST_ASSERT_NOT_NULL(ciphertext); + TEST_ASSERT_NOT_NULL(output); + } + + memset(ciphertext, 0, cfg->plaintext_length); + memset(output, 0, cfg->plaintext_length); + memcpy(iv_buf, cfg->iv, cfg->iv_length); + + mbedtls_gcm_init(&ctx); + TEST_ASSERT(mbedtls_gcm_setkey(&ctx, cipher, cfg->key, cfg->key_bits) == 0); + + if (gcm_type == GCM_TEST_CRYPT_N_TAG) { + mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT, cfg->plaintext_length, iv_buf, cfg->iv_length, cfg->aad_buf, cfg->aad_length, cfg->plaintext, ciphertext, cfg->tag_len, tag_buf_encrypt); + } else if (gcm_type == GCM_TEST_START_UPDATE_FINISH) { + TEST_ASSERT(mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT, iv_buf, cfg->iv_length) == 0); + TEST_ASSERT(mbedtls_gcm_update_ad(&ctx, cfg->aad_buf, cfg->aad_length) == 0); + TEST_ASSERT(mbedtls_gcm_update(&ctx, cfg->plaintext, cfg->plaintext_length, ciphertext, cfg->plaintext_length, &olen) == 0); + TEST_ASSERT(mbedtls_gcm_finish(&ctx, ciphertext, cfg->plaintext_length, &olen, tag_buf_encrypt, cfg->tag_len) == 0); + } + + size_t offset = cfg->plaintext_length > 16 ? cfg->plaintext_length - 16 : 0; + /* Sanity check: make sure the last ciphertext block matches what we expect to see. */ + TEST_ASSERT_EQUAL_HEX8_ARRAY(res->ciphertext_last_block, ciphertext + offset, MIN(16, cfg->plaintext_length)); + TEST_ASSERT_EQUAL_HEX8_ARRAY(res->expected_tag, tag_buf_encrypt, cfg->tag_len); + + + if (gcm_type == GCM_TEST_CRYPT_N_TAG) { + TEST_ASSERT(mbedtls_gcm_auth_decrypt(&ctx, cfg->plaintext_length, iv_buf, cfg->iv_length, cfg->aad_buf, cfg->aad_length, res->expected_tag, cfg->tag_len, ciphertext, output) == 0); + } else if (gcm_type == GCM_TEST_START_UPDATE_FINISH) { + TEST_ASSERT(mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv_buf, cfg->iv_length) == 0); + TEST_ASSERT(mbedtls_gcm_update_ad(&ctx, cfg->aad_buf, cfg->aad_length) == 0); + TEST_ASSERT(mbedtls_gcm_update(&ctx, ciphertext, cfg->plaintext_length, output, cfg->plaintext_length, &olen) == 0); + TEST_ASSERT(mbedtls_gcm_finish(&ctx, output, cfg->plaintext_length, &olen, tag_buf_decrypt, cfg->tag_len) == 0); + + /* mbedtls_gcm_auth_decrypt already checks tag so only needed for GCM_TEST_START_UPDATE_FINISH */ + TEST_ASSERT_EQUAL_HEX8_ARRAY(res->expected_tag, tag_buf_decrypt, cfg->tag_len); + } + + TEST_ASSERT_EQUAL_HEX8_ARRAY(cfg->plaintext, output, cfg->plaintext_length); + + mbedtls_gcm_free(&ctx); + free(ciphertext); + free(output); +} + + +TEST_CASE("mbedtls ARIA GCM test", "[gcm]") +{ + const unsigned SZ = 1600; + uint8_t aad[16]; + uint8_t iv[16]; + uint8_t key[16]; + + const uint8_t expected_last_block[] = { + 0xbe, 0x96, 0xf1, 0x57, 0x34, 0x07, 0x3f, 0x9d, + 0x87, 0x6b, 0x39, 0x22, 0xe4, 0xef, 0xff, 0xf0, + }; + const uint8_t expected_tag[] = { + 0xef, 0x4e, 0xa8, 0x24, 0x07, 0x65, 0x36, 0x12, + 0xb1, 0xde, 0x7e, 0x23, 0xda, 0xea, 0x7c, 0x6b, + }; + + uint8_t *plaintext = malloc(SZ); + TEST_ASSERT_NOT_NULL(plaintext); + + memset(plaintext, 0xAA, SZ); + memset(iv, 0xEE, 16); + memset(key, 0x44, 16); + memset(aad, 0x76, 16); + + gcm_test_cfg_t cfg = { + .plaintext = plaintext, + .plaintext_length = SZ, + .iv = iv, + .iv_length = sizeof(iv), + .key = key, + .key_bits = 8 * sizeof(key), + .aad_buf = aad, + .aad_length = sizeof(aad), + .tag_len = 16 + }; + + gcm_test_expected_res_t res = { + .expected_tag = expected_tag, + .ciphertext_last_block = expected_last_block, + }; + + gcm_test(&cfg, &res, GCM_TEST_CRYPT_N_TAG); + gcm_test(&cfg, &res, GCM_TEST_START_UPDATE_FINISH); + free(plaintext); +} + +#endif /* CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER */ diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls.c new file mode 100644 index 000000000..a35ba2140 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls.c @@ -0,0 +1,50 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* mbedTLS self-tests as unit tests + + Focus on testing functionality where we use ESP32 hardware + accelerated crypto features. + + See also test_hwcrypto.c in esp32 component, which tests hardware crypto without mbedTLS. +*/ +#include +#include +#include +#include +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +#include "mbedtls/aes.h" +#include "mbedtls/bignum.h" +#include "mbedtls/rsa.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "unity.h" +#include "sdkconfig.h" +#include "test_apb_dport_access.h" +#include "test_utils.h" + +TEST_CASE("mbedtls AES self-tests", "[aes]") +{ + start_apb_access_loop(); + TEST_ASSERT_FALSE_MESSAGE(mbedtls_aes_self_test(1), "AES self-tests should pass."); + verify_apb_access_loop(); +} + +TEST_CASE("mbedtls MPI self-tests", "[bignum]") +{ + start_apb_access_loop(); + TEST_ASSERT_FALSE_MESSAGE(mbedtls_mpi_self_test(1), "MPI self-tests should pass."); + verify_apb_access_loop(); +} + +TEST_CASE("mbedtls RSA self-tests", "[bignum]") +{ + start_apb_access_loop(); + TEST_ASSERT_FALSE_MESSAGE(mbedtls_rsa_self_test(1), "RSA self-tests should pass."); + verify_apb_access_loop(); +} diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls_ecdsa.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls_ecdsa.c new file mode 100644 index 000000000..aeb830f0b --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls_ecdsa.c @@ -0,0 +1,237 @@ +/* mbedTLS Elliptic Curve Digital Signature performance tests + * + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "test_utils.h" +#include "ccomp_timer.h" +#include "unity.h" + +#include "ecdsa/ecdsa_alt.h" + +#define TEST_ASSERT_MBEDTLS_OK(X) TEST_ASSERT_EQUAL_HEX32(0, -(X)) + +#if CONFIG_NEWLIB_NANO_FORMAT +#define NEWLIB_NANO_COMPAT_FORMAT PRIu32 +#define NEWLIB_NANO_COMPAT_CAST(int64_t_var) (uint32_t)int64_t_var +#else +#define NEWLIB_NANO_COMPAT_FORMAT PRId64 +#define NEWLIB_NANO_COMPAT_CAST(int64_t_var) int64_t_var +#endif + +/* + * All the following values are in big endian format, as required by the mbedTLS APIs + */ + +const uint8_t sha[] = { + 0x0c, 0xaa, 0x08, 0xb4, 0xf0, 0x89, 0xd3, 0x45, + 0xbb, 0x55, 0x98, 0xd9, 0xc2, 0xe9, 0x65, 0x5d, + 0x7e, 0xa3, 0xa9, 0xc3, 0xcd, 0x69, 0xb1, 0xcf, + 0x91, 0xbe, 0x58, 0x10, 0xfe, 0x80, 0x65, 0x6e +}; + +#if CONFIG_MBEDTLS_HARDWARE_ECC || CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY + +const uint8_t ecdsa256_r[] = { + 0x26, 0x1a, 0x0f, 0xbd, 0xa5, 0xe5, 0x1e, 0xe7, + 0xb3, 0xc3, 0xb7, 0x09, 0xd1, 0x4a, 0x7a, 0x2a, + 0x16, 0x69, 0x4b, 0xaf, 0x76, 0x5c, 0xd4, 0x0e, + 0x93, 0x57, 0xb8, 0x67, 0xf9, 0xa1, 0xe5, 0xe8 +}; + +const uint8_t ecdsa256_s[] = { + 0x63, 0x59, 0xc0, 0x3b, 0x6a, 0xc2, 0xc4, 0xc4, + 0xaf, 0x47, 0x5c, 0xe6, 0x6d, 0x43, 0x3b, 0xa7, + 0x91, 0x51, 0x15, 0x62, 0x7e, 0x46, 0x0e, 0x68, + 0x84, 0xce, 0x72, 0xa0, 0xd8, 0x8b, 0x69, 0xd5 +}; + +const uint8_t ecdsa256_pub_x[] = { + 0xcb, 0x59, 0xde, 0x9c, 0xbb, 0x28, 0xaa, 0xac, + 0x72, 0x06, 0xc3, 0x43, 0x2a, 0x65, 0x82, 0xcc, + 0x68, 0x01, 0x76, 0x68, 0xfc, 0xec, 0xf5, 0x91, + 0xd1, 0x9e, 0xbf, 0xcf, 0x67, 0x7d, 0x7d, 0xbe +}; + +const uint8_t ecdsa256_pub_y[] = { + 0x00, 0x66, 0x14, 0x74, 0xe0, 0x06, 0x44, 0x66, + 0x6f, 0x3b, 0x8c, 0x3b, 0x2d, 0x05, 0xf6, 0xd5, + 0xb2, 0x5d, 0xe4, 0x85, 0x6c, 0x61, 0x38, 0xc5, + 0xb1, 0x21, 0xde, 0x2b, 0x44, 0xf5, 0x13, 0x62 +}; + +const uint8_t ecdsa192_r[] = { + 0x2b, 0x8a, 0x18, 0x2f, 0xb2, 0x75, 0x26, 0xb7, + 0x1c, 0xe1, 0xe2, 0x6d, 0xaa, 0xe7, 0x74, 0x2c, + 0x42, 0xc8, 0xd5, 0x09, 0x4f, 0xb7, 0xee, 0x9f +}; + +const uint8_t ecdsa192_s[] = { + 0x1a, 0x74, 0xb4, 0x5, 0xf4, 0x28, 0xa5, 0xb6, + 0xce, 0xed, 0xa5, 0xff, 0xa8, 0x60, 0x06, 0x2f, + 0xf6, 0xeb, 0x24, 0x59, 0x24, 0x30, 0x5b, 0x12 +}; + +const uint8_t ecdsa192_pub_x[] = { + 0xd0, 0x3f, 0x6f, 0xe7, 0x5d, 0xaa, 0xf4, 0xc0, + 0x1e, 0x63, 0x7b, 0x82, 0xab, 0x23, 0x33, 0x34, + 0x74, 0x59, 0x56, 0x5d, 0x21, 0x10, 0x9c, 0xb1 +}; + +const uint8_t ecdsa192_pub_y[] = { + 0x85, 0xfc, 0x76, 0xcb, 0x65, 0xbc, 0xc4, 0xbe, + 0x74, 0x09, 0xfd, 0xf3, 0x74, 0xdc, 0xc2, 0xde, + 0x7e, 0x4b, 0x23, 0xad, 0x46, 0x5c, 0x87, 0xc2 +}; + +void test_ecdsa_verify(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8_t *r_comp, const uint8_t *s_comp, + const uint8_t *pub_x, const uint8_t *pub_y) +{ + int64_t elapsed_time; + mbedtls_mpi r, s; + + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + mbedtls_ecdsa_context ecdsa_context; + mbedtls_ecdsa_init(&ecdsa_context); + + mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), id); + size_t plen = mbedtls_mpi_size(&ecdsa_context.MBEDTLS_PRIVATE(grp).P); + + TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&r, r_comp, plen)); + + TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&s, s_comp, plen)); + + TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), pub_x, plen)); + TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), pub_y, plen)); + TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_lset(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1)); + + ccomp_timer_start(); + TEST_ASSERT_MBEDTLS_OK(mbedtls_ecdsa_verify(&ecdsa_context.MBEDTLS_PRIVATE(grp), hash, 32, &ecdsa_context.MBEDTLS_PRIVATE(Q), &r, &s)); + elapsed_time = ccomp_timer_stop(); + + if (id == MBEDTLS_ECP_DP_SECP192R1) { + TEST_PERFORMANCE_CCOMP_LESS_THAN(ECDSA_P192_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time)); + } else if (id == MBEDTLS_ECP_DP_SECP256R1) { + TEST_PERFORMANCE_CCOMP_LESS_THAN(ECDSA_P256_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time)); + } + + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); + mbedtls_ecdsa_free(&ecdsa_context); +} + +TEST_CASE("mbedtls ECDSA signature verification performance on SECP192R1", "[mbedtls]") +{ + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP192R1, sha, ecdsa192_r, ecdsa192_s, + ecdsa192_pub_x, ecdsa192_pub_y); +} + +TEST_CASE("mbedtls ECDSA signature verification performance on SECP256R1", "[mbedtls]") +{ + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_r, ecdsa256_s, + ecdsa256_pub_x, ecdsa256_pub_y); +} + +#endif /* CONFIG_MBEDTLS_HARDWARE_ECC */ + +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN + +/* + * This test assumes that ECDSA private key has been burnt in efuse. + * + * ecdsa_key_p192.pem must be burnt in efuse block 4 + * ecdsa_key_p256.pem must be burnt in efuse block 5 + */ +#define SECP192R1_EFUSE_BLOCK 4 // EFUSE_BLK_KEY0 +#define SECP256R1_EFUSE_BLOCK 5 // EFUSE_BLK_KEY1 + +#define MAX_ECDSA_COMPONENT_LEN 32 +#define HASH_LEN 32 + +const uint8_t ecdsa256_sign_pub_x[] = { + 0xa2, 0x8f, 0x52, 0x60, 0x20, 0x9b, 0x54, 0x3c, + 0x13, 0x2f, 0x51, 0xb1, 0x89, 0xbf, 0xc7, 0xfa, + 0x84, 0x5c, 0x56, 0x96, 0x2a, 0x00, 0x67, 0xdd, + 0x7c, 0x8c, 0x0f, 0x63, 0x8b, 0x76, 0x7f, 0xb9, +}; + +const uint8_t ecdsa256_sign_pub_y[] = { + 0xf6, 0x4c, 0x87, 0x5b, 0x5a, 0x9b, 0x59, 0x0a, + 0xc4, 0x53, 0x04, 0x72, 0x0d, 0x7c, 0xde, 0xac, + 0x7e, 0xad, 0x49, 0x8c, 0xf7, 0x5c, 0xc3, 0x1c, + 0x1e, 0x81, 0xf2, 0x47, 0x01, 0x74, 0x05, 0xd5 +}; + +const uint8_t ecdsa192_sign_pub_x[] = { + 0x88, 0x47, 0x25, 0x3c, 0xb4, 0xb7, 0x87, 0x24, + 0x5e, 0x07, 0xe1, 0xc7, 0xfc, 0x76, 0x0f, 0x6b, + 0x83, 0xf6, 0x81, 0x7d, 0x9b, 0x5f, 0xc4, 0xb9, +}; + +const uint8_t ecdsa192_sign_pub_y[] = { + 0x9c, 0xfc, 0xaa, 0xed, 0xef, 0xba, 0x02, 0xc3, + 0x1c, 0x0a, 0x55, 0x17, 0xe0, 0x9d, 0x10, 0xcb, + 0x23, 0xae, 0x7e, 0x0f, 0x1f, 0x4d, 0x69, 0xd5 +}; + +void test_ecdsa_sign(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8_t *pub_x, const uint8_t *pub_y) +{ + uint8_t r_be[MAX_ECDSA_COMPONENT_LEN] = {0}; + uint8_t s_be[MAX_ECDSA_COMPONENT_LEN] = {0}; + + mbedtls_mpi r, s; + mbedtls_mpi key_mpi; + + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + mbedtls_ecdsa_context ecdsa_context; + mbedtls_ecdsa_init(&ecdsa_context); + + if (id == MBEDTLS_ECP_DP_SECP192R1) { + mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP192R1); + esp_ecdsa_privkey_load_mpi(&key_mpi, SECP192R1_EFUSE_BLOCK); + } else if (id == MBEDTLS_ECP_DP_SECP256R1) { + mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1); + esp_ecdsa_privkey_load_mpi(&key_mpi, SECP256R1_EFUSE_BLOCK); + } + + mbedtls_ecdsa_sign(&ecdsa_context.MBEDTLS_PRIVATE(grp), &r, &s, &key_mpi, sha, HASH_LEN, NULL, NULL); + + mbedtls_mpi_write_binary(&r, r_be, MAX_ECDSA_COMPONENT_LEN); + mbedtls_mpi_write_binary(&s, s_be, MAX_ECDSA_COMPONENT_LEN); + + if (id == MBEDTLS_ECP_DP_SECP192R1) { + // Skip the initial zeroes + test_ecdsa_verify(id, sha, &r_be[8], &s_be[8], pub_x, pub_y); + } else if (id == MBEDTLS_ECP_DP_SECP256R1) { + test_ecdsa_verify(id, sha, r_be, s_be, pub_x, pub_y); + } +} + +TEST_CASE("mbedtls ECDSA signature generation on SECP192R1", "[mbedtls][efuse_key]") +{ + test_ecdsa_sign(MBEDTLS_ECP_DP_SECP192R1, sha, ecdsa192_sign_pub_x, ecdsa192_sign_pub_y); +} + +TEST_CASE("mbedtls ECDSA signature generation on SECP256R1", "[mbedtls][efuse_key]") +{ + test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_sign_pub_x, ecdsa256_sign_pub_y); +} + +#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */ diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls_mpi.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls_mpi.c new file mode 100644 index 000000000..14bdc8497 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls_mpi.c @@ -0,0 +1,282 @@ +/* mbedTLS bignum (MPI) self-tests as unit tests + * + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include +#include "mbedtls/bignum.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "unity.h" +#include "sdkconfig.h" +#include "test_utils.h" + +#define MBEDTLS_OK 0 + +/* Debugging function to print an MPI number to stdout. Happens to + print output that can be copy-pasted directly into a Python shell. +*/ +void mbedtls_mpi_printf(const char *name, const mbedtls_mpi *X) +{ + static char buf[2048]; + size_t n; + memset(buf, 0, sizeof(buf)); + mbedtls_mpi_write_string(X, 16, buf, sizeof(buf)-1, &n); + if(n) { + printf("%s = (s=%d) 0x%s\n", name, X->MBEDTLS_PRIVATE(s), buf); + } else { + printf("%s = TOOLONG\n", name); + } +} + +/* + Assert E == X, X=A*B if res_operands_overlap==0 + Assert E == A, A=A*B if res_operands_overlap==1 + Assert E == B, B=A*B if res_operands_overlap==2 +*/ +static void test_bignum_mult_variant(const char *a_str, const char *b_str, const char *e_str, size_t mod_bits, int res_operands_overlap) +{ + mbedtls_mpi A, B, X, E; + char x_buf[2048] = {0}; + size_t x_buf_len = 0; + + mbedtls_mpi_init(&A); + mbedtls_mpi_init(&B); + mbedtls_mpi_init(&X); + mbedtls_mpi_init(&E); + + TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&A, 16, a_str)); + TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&B, 16, b_str)); + + /* calulate X = A * B variant */ + TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&E, 16, e_str)); + if (res_operands_overlap == 0) { + TEST_ASSERT_FALSE(mbedtls_mpi_mul_mpi(&X, &A, &B)); + } else if (res_operands_overlap == 1) { + mbedtls_mpi_copy( &X, &A ); + TEST_ASSERT_FALSE(mbedtls_mpi_mul_mpi(&X, &X, &B)); + } else if (res_operands_overlap == 2) { + mbedtls_mpi_copy( &X, &B ); + TEST_ASSERT_FALSE(mbedtls_mpi_mul_mpi(&X, &A, &X)); + } + + mbedtls_mpi_write_string(&X, 16, x_buf, sizeof(x_buf)-1, &x_buf_len); + TEST_ASSERT_EQUAL_STRING_MESSAGE(e_str, x_buf, "mbedtls_mpi_mul_mpi result wrong"); + +#ifdef CONFIG_MBEDTLS_HARDWARE_MPI + mbedtls_mpi M; + /* if mod_bits arg is set, also do a esp_mpi_mul_mod() call */ + if (mod_bits > 0 && mod_bits <= SOC_RSA_MAX_BIT_LEN) { + mbedtls_mpi_init(&M); + for(int i = 0; i < mod_bits; i++) { + mbedtls_mpi_set_bit(&M, i, 1); + } + TEST_ASSERT_FALSE(esp_mpi_mul_mpi_mod(&X, &A, &B, &M)); + + mbedtls_mpi_write_string(&X, 16, x_buf, sizeof(x_buf)-1, &x_buf_len); + TEST_ASSERT_EQUAL_STRING_MESSAGE(e_str, x_buf, "esp_mpi_mul_mpi_mod result wrong"); + + mbedtls_mpi_free(&M); + } +#endif + + mbedtls_mpi_free(&A); + mbedtls_mpi_free(&B); + mbedtls_mpi_free(&X); + mbedtls_mpi_free(&E); +} + +/* Assert E = A * B, including 3 variants: X=A*B A*=B, B*=A */ +static void test_bignum_mult(const char *a_str, const char *b_str, const char *e_str, size_t mod_bits) +{ + for (int overlap_operands=0; overlap_operands < 3; ++overlap_operands) { + test_bignum_mult_variant(a_str, b_str, e_str, mod_bits, overlap_operands); + } +} + + +TEST_CASE("test MPI multiplication", "[bignum]") +{ + /* Run some trivial numbers tests w/ various high modulo bit counts, + should make no difference to the result + */ + for(int i = 512; i <= SOC_RSA_MAX_BIT_LEN; i+= 512) { + test_bignum_mult("10", "100", "1000", + i); + } + + test_bignum_mult("60006FA8D3E3BD746BE39B860FFAADB4F108E15CF2ED8F685FB0E86CC4CB107A488720B41C3F1E18550F00619CD3CA8442296ECB54D2F52ECEE5346D310195700000000", + "BF474CA7", + "047BB102CAF58A48D3D97E4231BC0B753051D8232B9B939A2A4E310F88E65FEFD7762FC2DE0E2BAD6AA51A391DFFABD120653A312E4998F42E2C03AA404EE63B67275BC100000000", + 1024); + + test_bignum_mult("49493AC229831EC01EEB01EAF3BBEBC44768EADF9ABC30C87D1791F5E04245756ED4965361EC0599626884DF079B6B5738985CE76BD66FAA67E3AAAD60775D5C9D44C09FDF9E27C033696C007BE1C540D718CA148BA01FFA4A358541E9E9F02F72BE37AFAB037DAEA5E3669A770400D2F4A5DBBD83A83919D05E3DD64787BC80000000", + "B878CC29", + "34CF37013066D5BDA2C86CF1FE7BDA66604E0D55DAFF9864B6E727BFF5871012B0AB73D28D4E100BA1E4607AA2A247C912FDBC435C6BF7C5F8E00278AE1381B1E5F6E3D52D2CBE819F0D65CB37370666D156E7A7B1FD4698D8C9D3165FC8A83F9293C839521993619CCF8180E521300C4306206C9121D629754F1FCC7839BF6DFAF33080000000", + 3072); + + test_bignum_mult("24BF6185468786FDD303083D25E64EFC66CA472BC44D253102F8B4A9D3BFA75091386C0077937FE33FA3252D28855837AE1B484A8A9A45F7EE8C0C634F9E8CDDF79C5CE07EE72C7F123142198164234CABB724CF78B8173B9F880FC86322407AF1FEDFDDE2BEB674CA15F3E81A1521E071513A1E85B5DFA031F21ECAE9A34D", + "010001", + "24BF8644A80CCD855A00DB402E2374E2B5C6ADF60B78E97E2829B7A288697B103888FD38E393F776BF8664D04DB280BD0652F665D2E4D0923483FAEF5C01DC7C847A547CDBC7AB663EB0544AC37DA4B0CF03D0869D878FF3B6C3AF5072EAA39D3279D1DCC29C9933808ABDFE0DFD3BF59331AB6FBFD46556119250BD086E36A34D", + 1536); + + test_bignum_mult("-5D88B669C417EDD02213723546A906B7E9DA7683780E9B54856A2147467ADA316F8819D69486FC8056FE1E8EA7DEC5D5EF12340B95C4FC966F4B348D35893620", + "9AE7FBC99546432DF71896FC239EADAEF38D18D2B2F0E2DD275AA977E2BF4411F5A3B2A5D33605AEBBCCBA7FEB9F2D2FA74206CEC169D74BF5A8C50D6F48EA08", + "-38990016EB21810E3B5E6AEE339AEE72BB7CD629C4C9270A3D832701A2949BC82B2BE5A7F900C0C9937464699862821976095187D646884E8FBF01DE8C3442F3BC97B670AF573EFB74A9BBEBE4432EE74B0A83BBCDF59485D332B1FF49EB461A3A8B12C38FD72C7772D75EC6EBA5633199540C47678BD2F4ADEEA40830C2F100", + 2048); + + + /* 1 << 2050 * 0X1234 */ + test_bignum_mult("400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "1234", + "48D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 3072); + + /* multiply a 1178 bit number by a 2050 bit number */ + test_bignum_mult("AAAAAAAAAA75124938ABBECD0EEEEE333333333333333333333FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAAAAAAABBBBBBBBBBBBBBBBBBBB000000000000000000000000000000000004988A5293848932948872398400000000000FFFFFFFFFFF0000000000000EDFABC0204048975876873487387478327482374871327482347328742837483247283748234723874238", + "390587293875124938ABBECD0EEEEE3333333333333333333333333333333399999888000AAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBB00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000EDFABC0204048975876873487387478327482374871327482347328742837483247283748234723874238478327400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003012111111111111111100000000000000000000000111111111111111111111111", + "02603AF70D0421C1AD82CE623F28F70B128118D06D00C27D433EC25BA86E6105C3890A0B1973B8BE068CA68E159A21078785DDB37F94216FBF4AEC939958AF4B8CEA2A48895CECA87562FC846EAAE0C866AF9D41EEABFB1D579F5828E9666A15E2AF946F16A189B5C645872FDCA247D309AB0BCAFB0D112881186FCFFEDC87061B4AE4A375E9BBCF579A7BC87A8EAC8C6F66E107986FC603F920F5E1A0FD8C619D88D90066FFFC8F4DB77437EBD7E3BD7E398C4C01F93426E347E039DCA7B0A73C0C90A9C4271BB761ADFF88971D190CE5DA98EFC5D7390D33BC034908AF81D784A4D7F32D0902E0C5DABC706635D5A28FC0E3A364EDEB21E8E117041D0E4B51CA6F9684F434057E7FCF2AF6BD050334B1D11E043B0967154E57354B681161D3C618974D5A7E0385755B80B931AE9B59DD4402BAEC206F04B8440741B3C4CA6D9F7DAF0AE6B3BF1B24B76C2F12B9E9A7C50D32E2093608FC9A30CBD852329E64A9AE0BC3F513899EBFA28629C1DF38081FB8C6630408F70D7B9A37701ABA4176C8B7DCB8CC78BD7783B861A7FC50862E75191DB8", + 4096); + + + /* multiply two very large numbers (4080 bits x 4088 bits) with and without overlapping multipliers/multiplicant */ + test_bignum_mult("B96BF707C8CD3CA5AE8247C5CA2AF98140EFAE60179BE3F5BEAD7DA3C6D17404C529239DD1EFE6CADAE1AAFB4FE936B0107839C28A7861E4364EB093CB4698E4BBF6BD8BEF85D9B35781D14AEE1BE86E57B49DF98896CF037CCBD8C622603D84891FD6AC48BE4728E564E64FB715C149C243BAA289569D0FF2E0C9E183D38C8A669CEFF542737E35F3E484D39FF7A3727EF8DB733DAB3E359E1456C0AE33C358EFEC8079EDDD5D58E09B37744EE1DBDF567742CFC0CE98BCC9AD90242ECCF7F6FA696C8C1B32A4D7285C56AB3658DB1AD89A7331F69DEFE212DE8EEEE5B377EC7A4112A27A0FD02EFABB9D3025F6563B65DC214A38A6E7BF8C78B6A3D2A8BA12D75BFBF26ACA655EF13A145AC18D2A6C9B535AAF8290314A2512451B3BD6DA19C42F1FD1B958E1F49303EDEC0392A8CD8450FBC177B26FD2D6CC23F051655565B42FEDE9685A9E708CFC8EA766B94D7B9B627BFA98945BB8EF88E9E7FB696BC4729240F1C25F7085E8C8A9DE2241BBC388FFC65E0058B4327D554FD2D8AA872614052C38BE177F9EC0E705DFDD5F82DD5ED49DAF3582CA64E7F14CE97FD6F25B53FD888D1593450EDC5E79A947F18D0917E01F66ACE99FF4A249C14957A9860B839CEE5096F78FE02C7610E558FC0FCA803A6EF0FBA64AB94893E61080BC5D2AC5DA548E9E0D8E2B63BAB6B82247DF22007D925711E0FE45EB14B92665B6", + "C15B96BF707C8CD3CA5AE8247C5CA2AF98140EFAE60179BE3F5BEAD7DA3C6D17404C529239DD1EFE6CADAE1AAFB4FE936B0107839C28A7861E4364EB093CB4698E4BBF6BD8BEF85D9B35781D14AEE1BE86E57B49DF98896CF037CCBD8C622603D84891FD6AC48BE4728E564E64FB715C149C243BAA289569D0FF2E0C9E183D38C8A669CEFF542737E35F3E484D39FF7A3727EF8DB733DAB3E359E1456C0AE33C358EFEC8079EDDD5D58E09B37744EE1DBDF567742CFC0CE98BCC9AD90242ECCF7F6FA696C8C1B32A4D7285C56AB3658DB1AD89A7331F69DEFE212DE8EEEE5B377EC7A4112A27A0FD02EFABB9D3025F6563B65DC214A38A6E7BF8C78B6A3D2A8BA12D75BFBF26ACA655EF13A145AC18D2A6C9B535AAF8290314A2512451B3BD6DA19C42F1FD1B958E1F49303EDEC0392A8CD8450FBC177B26FD2D6CC23F051655565B42FEDE9685A9E708CFC8EA766B94D7B9B627BFA98945BB8EF88E9E7FB696BC4729240F1C25F7085E8C8A9DE2241BBC388FFC65E0058B4327D554FD2D8AA872614052C38BE177F9EC0E705DFDD5F82DD5ED49DAF3582CA64E7F14CE97FD6F25B53FD888D1593450EDC5E79A947F18D0917E01F66ACE99FF4A249C14957A9860B839CEE5096F78FE02C7610E558FC0FCA803A6EF0FBA64AB94893E61080BC5D2AC5DA548E9E0D8E2B63BAB6B82247DF22007D925711E0FE45EB14B92665B6", + "08C0CBBCD99EC6C840B63887B07378C45DF268C118061B2AFFD9D0C854EE0F7DE5F548FF5BA7F155CCA81EF086F9760FCD86722167AC88E504723CB19A772D9EFF4EC75DD29F6187D34535B2A801C82DF9B1D0F08B64373A5AE5BD31346EE06EDB032B0A306A871E4FDB576F3E8D8F32ED4E054D9292719E77A1C5500FBEC23C59F5CC49A4E0B49D15F92D426FEF36376CB674AACDABF68A731746CA74440C71534D30CBF0252DE4EC38EA53E5821C9868F636239923C460CB813C4F05DD5EC36987A390FDBB7EE345F9D2687D1EF9A26A1FF84BF38049E995E1A5F2D5318A7BEFC9AA15528F7A2253299D30718459CF7958694AA58D91CA28F22718D07105C3FBFA4FEA970A810DD52BFC6AB4D44E3253347A3C5F42C1E723588343B210581F3B8A97C616A26C9C99C1376E169B8C8ED5DE6FA2272D24FB05BA6351B687A27C5CA1CF3FC1BA2BF06DD7598DED3F89080A2AB6DD694000698A7488274396E55EA78104584A5A0523C4744D018DCBFD3E411DA8CA679199FE818C59E08B126356028E3B6AAEA61ACE679D6EF2587CCAE513AB99EB161A405A8AA6FB36BB308BB7CBC21E2117B7CE4B4D1A1FE7EE0386DD229220BFD892A293FD7B8F6617743612736CC2F6200C736FD49C6A4AC9565E4B4EFD841C5FC3F6883621FD4319A11319EF462B549A12DA699612F2E8CE08525559C3487AAD57DFDBF1CAB847174C2FF8BA8D5232E33E5D8F60E5BE4CD8BE5857A860B615EFCFFF38DC0EE6A40F725D5275892419D3915EDB534166AC402B5849EB16AF1E8ADA68EF8C2E6AC8BE254DAEDAC135DA0ECA0E5A3CCF5332CFAB4C2249A92EF96A7DD6F69B4B0F9379CDA164FB1CB1934F27F42C0CEF9AFBA6A0B1716A4A1092E6CC7081AC74503A22F3C2071BB4D3A6842772C02CE78BD1FB4E0D39EB19E2425D3DC77777A8E8254F86A69950C75C1D8CF98C512ECEAF2FF15DC8A6D373A20045F63166BFDB8899C6095D91FC282D49DB9154E74DC64C41A98EFABDB207FF31A88718FF5410EA5A15E76F9591E5BE3B26035FD8567117588D9B94708B98FD764529B43B09EC6A2CDF79E2C05D3A799484516369795E103C7FCB78F1B1CADA47C3092695220FF2DB05136A9401897DE182EDB89022E4E7419B43172808C0A9F3ED80A8DF0A9E5F8E59E57994053050E709E63A4809AAECC3DEABDF5E2B9ED3F8FDA6297811A666E81BB0914B1F9D5D558EE40DBD89BE8B9D7F58575CE66C5A5EC2939463D1CECDD760B2C0584535FEEB2125CB675A1AB09CEDC81F27FA6830423B1F8D426E361EB1B9AD203C33176ACAB28C618714E068DA294C9338EF92FF4ED9F67F438E33E53797C1C31F8FF8D5466887E5610EA41C0CABC07ED90894BA73ECF84F5F3C5443EFAC61F9826C54D176D482CB5174D08A7EA3C3933FEE4986DB38A1EEC08D3366711D64", + 0); + + /* Multiply two specific MPI values to reproduce issue mentioned in https://github.com/espressif/esp-idf/issues/11850 */ + test_bignum_mult("454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545", + "03", + "CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF", + 0); +} + +static bool test_bignum_modexp(const char *z_str, const char *x_str, const char *y_str, const char *m_str, int ret_error) +{ + mbedtls_mpi Z = {0}; // Z is non-initialized (the sign Z.s=0) + mbedtls_mpi X, Y, M; + char z_buf[400] = { 0 }; + size_t z_buf_len = 0; + bool fail = false; + + printf("%s = (%s ^ %s) mod %s ret=%d ... ", z_str, x_str, y_str, m_str, ret_error); + + mbedtls_mpi_init(&X); + mbedtls_mpi_init(&Y); + mbedtls_mpi_init(&M); + + TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&X, 16, x_str)); + TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&Y, 16, y_str)); + TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&M, 16, m_str)); + + /* Z = (X ^ Y) mod M */ + // (Z is passed to mbedtls_mpi_exp_mod() as a non-initialized with the sign s=0) + int err = mbedtls_mpi_exp_mod(&Z, &X, &Y, &M, NULL); + if (ret_error != err) { + printf("\nExpected ret_error %d, Was %d \n", ret_error, err); + fail = true; + } + + if (ret_error == MBEDTLS_OK) { + mbedtls_mpi_write_string(&Z, 16, z_buf, sizeof(z_buf)-1, &z_buf_len); + if (strlen(z_str) != z_buf_len - 1 || memcmp(z_str, z_buf, strlen(z_str)) != 0) { + printf("\n"); + mbedtls_mpi_printf("Z", &Z); + mbedtls_mpi_printf("X", &X); + mbedtls_mpi_printf("Y", &Y); + mbedtls_mpi_printf("M", &M); + printf("\nsize: Expected %d, Was %d \n", strlen(z_str), z_buf_len - 1); + printf("Expected '%s' Was '%s' \n", z_str, z_buf); + fail = true; + } + } + + mbedtls_mpi_free(&Z); + mbedtls_mpi_free(&X); + mbedtls_mpi_free(&Y); + mbedtls_mpi_free(&M); + + if (fail == true) { + printf(" FAIL\n\n"); + } else { + printf(" PASS\n"); + } + return fail; +} + +TEST_CASE("test MPI modexp", "[bignum]") +{ + bool test_error = false; + printf("Z = (X ^ Y) mod M \n"); + // test_bignum_modexp(Z, X, Y, M, ret_error); + test_error |= test_bignum_modexp("01000000", "1000", "2", "FFFFFFFF", MBEDTLS_OK); + test_error |= test_bignum_modexp("014B5A90", "1234", "2", "FFFFFFF", MBEDTLS_OK); + test_error |= test_bignum_modexp("01234321", "1111", "2", "FFFFFFFF", MBEDTLS_OK); + test_error |= test_bignum_modexp("02", "5", "1", "3", MBEDTLS_OK); + test_error |= test_bignum_modexp("22", "55", "1", "33", MBEDTLS_OK); + test_error |= test_bignum_modexp("0222", "555", "1", "333", MBEDTLS_OK); + test_error |= test_bignum_modexp("2222", "5555", "1", "3333", MBEDTLS_OK); + test_error |= test_bignum_modexp("11", "5555", "1", "33", MBEDTLS_OK); + test_error |= test_bignum_modexp("55", "1111", "1", "77", MBEDTLS_OK); + test_error |= test_bignum_modexp("88", "1111", "2", "BB", MBEDTLS_OK); + test_error |= test_bignum_modexp("01000000", "2", "128", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", MBEDTLS_OK); + test_error |= test_bignum_modexp("0ABCDEF12345", "ABCDEF12345", "1", "FFFFFFFFFFFF", MBEDTLS_OK); + test_error |= test_bignum_modexp("0ABCDE", "ABCDE", "1", "FFFFF", MBEDTLS_OK); + + test_error |= test_bignum_modexp("04", "2", "2", "9", MBEDTLS_OK); + test_error |= test_bignum_modexp("04", "2", "-2", "9", MBEDTLS_ERR_MPI_BAD_INPUT_DATA); + test_error |= test_bignum_modexp("04", "2", "2", "-9", MBEDTLS_ERR_MPI_BAD_INPUT_DATA); + test_error |= test_bignum_modexp("04", "2", "-2", "-9", MBEDTLS_ERR_MPI_BAD_INPUT_DATA); + + test_error |= test_bignum_modexp("01", "2", "0", "9", MBEDTLS_OK); + test_error |= test_bignum_modexp("04", "2", "0", "0", MBEDTLS_ERR_MPI_BAD_INPUT_DATA); + test_error |= test_bignum_modexp("04", "2", "2", "0", MBEDTLS_ERR_MPI_BAD_INPUT_DATA); + test_error |= test_bignum_modexp("00", "0", "2", "9", MBEDTLS_OK); + test_error |= test_bignum_modexp("01", "0", "0", "9", MBEDTLS_OK); + + test_error |= test_bignum_modexp("04", "-2", "2", "9", MBEDTLS_OK); + test_error |= test_bignum_modexp("01", "-2", "0", "9", MBEDTLS_OK); + test_error |= test_bignum_modexp("07", "-2", "7", "9", MBEDTLS_OK); + test_error |= test_bignum_modexp("07", "-2", "1", "9", MBEDTLS_OK); + test_error |= test_bignum_modexp("02", "2", "1", "9", MBEDTLS_OK); + test_error |= test_bignum_modexp("01", "2", "0", "9", MBEDTLS_OK); + + test_error |= test_bignum_modexp("05", "5", "7", "7", MBEDTLS_OK); + test_error |= test_bignum_modexp("02", "-5", "7", "7", MBEDTLS_OK); + test_error |= test_bignum_modexp("01", "-5", "7", "3", MBEDTLS_OK); + + test_error |= test_bignum_modexp("00", "123456789", "123456789", "123456789", MBEDTLS_OK); + test_error |= test_bignum_modexp("01", "123456788", "123456788", "123456789", MBEDTLS_OK); + test_error |= test_bignum_modexp("01", "12345678A", "12345678A", "123456789", MBEDTLS_OK); + test_error |= test_bignum_modexp("06", "-32", "03E9", "07", MBEDTLS_OK); + + test_error |= test_bignum_modexp( + "5FA6CB1F76A157EC6CB02835DAD05B207DF883AB90CE4180277AB525801C9B5AF0C89B5C5E9DB2BB20CD0B86A308F006D19D4B1FBF355F2A8024B012A49ED483F5DF3FD77EFB40C221B6D67F28B5313F18728EFDF204C903A247A4A2CEE9542A15AD27F9EFB6AC0940D71BBCC4CB31B4D0372FAC26937A8CBA541503E0B8C80B", + "02", + "471CC5F6A82CCAB3B4FED79ADA3DEAF532166B1F0A5F2DA4CF364770CB883A85884C0E32029A256A3617251A1ACF4CB1E9FFD47A62699C3454444D193E2B0C1D3E6071E0D15C29A736E4EE76F6C63D3D157F8BE2CDFF05BD11C88A9691537869BF8DE4ED103E8EB9DB42B4E733F2D8FB1684435DC529B67305AB4A0FA9E42102", + "CF5CF5C38419A724957FF5DD323B9C45C3CDD261EB740F69AA94B8BB1A5C96409153BD76B24222D03274E4725A5406092E9E82E9135C643CAE98132B0D95F7D65347C68AFC1E677DA90E51BBAB5F5CF429C291B4BA39C6B2DC5E8C7231E46AA7728E87664532CDF547BE20C9A3FA8342BE6E34371A27C06F7DC0EDDDD2F86373", + MBEDTLS_OK); + + test_error |= test_bignum_modexp( + "368A32291EA9B22B11BE9D23636C4AB69C1936527AE70A33B8240556F886BD3E242A381FB752845287ED74EF2AE01E9736C374897A6DD910FC607769A66745368E683E34222DA242DD4C5B68A5B817C10F3BC207F9354188E70A90F64DF3A6156B7569069D459304EB85C9FEFA1D0AEDB1279B89633131980A05C37472837FBB", + "02", + "31FBCFDDC81A8696DA8A33798AF97F041D4C659AC82C0D5C608386013E84EBC3229E03B509F7FC81B2A2DE08659AC8699D109034B22D47A0C5D34DC6B90D3299AEE0F18E321E02FE53793857F73A0E3DC1D9A7CE3E0FC930185D67C02C08454EA5CB53285EB67C32C94C1E56DC34FBA796BC54898B4CDBF76A920E46C0AC270D", + "CF5CF5C38419A724957FF5DD323B9C45C3CDD261EB740F69AA94B8BB1A5C96409153BD76B24222D03274E4725A5406092E9E82E9135C643CAE98132B0D95F7D65347C68AFC1E677DA90E51BBAB5F5CF429C291B4BA39C6B2DC5E8C7231E46AA7728E87664532CDF547BE20C9A3FA8342BE6E34371A27C06F7DC0EDDDD2F86373", + MBEDTLS_OK); + + test_error |= test_bignum_modexp( + "631B2A9124600E91C030E6650284AE120CBAEFCB24083905F17B5B758A32CA071CA4BB109CDBA411F3136A009186E5E4F59A8DD481EDFD23FC95437749E971EB4C28E076FA3EC8E3E81A5A33E2B04598B987D7B11D74077E7B6F5C965A52558F5495D3FC518193132844E745D6C67C287C3239083A34DCB9F77F5348E0FC973D", + "BDAD66C8632D9E50A7EFDF9EC1465FFF445D45F1F2B57C8A18084E6743658BC45DCFD1F9F10ED6C2DDC0B14F1546D7DDE6624AE89722DB6B7BBE3AFBB26C5B2406E583834034C1F2162DD5BA5165B72C876EB7EE834268F1400F8FD8E88187B5264A452A5D795C6090CA02284E2E5CA136BED5AA05DAF5689136FA85F17D532D", + "471CC5F6A82CCAB3B4FED79ADA3DEAF532166B1F0A5F2DA4CF364770CB883A85884C0E32029A256A3617251A1ACF4CB1E9FFD47A62699C3454444D193E2B0C1D3E6071E0D15C29A736E4EE76F6C63D3D157F8BE2CDFF05BD11C88A9691537869BF8DE4ED103E8EB9DB42B4E733F2D8FB1684435DC529B67305AB4A0FA9E42102", + "CF5CF5C38419A724957FF5DD323B9C45C3CDD261EB740F69AA94B8BB1A5C96409153BD76B24222D03274E4725A5406092E9E82E9135C643CAE98132B0D95F7D65347C68AFC1E677DA90E51BBAB5F5CF429C291B4BA39C6B2DC5E8C7231E46AA7728E87664532CDF547BE20C9A3FA8342BE6E34371A27C06F7DC0EDDDD2F86373", + MBEDTLS_OK); + + TEST_ASSERT_FALSE_MESSAGE(test_error, "mbedtls_mpi_exp_mod incorrect for some tests\n"); +} diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls_sha.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls_sha.c new file mode 100644 index 000000000..68bc6a367 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls_sha.c @@ -0,0 +1,612 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * mbedTLS SHA unit tests + */ +#include +#include +#include +#include +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "unity.h" +#include "sdkconfig.h" +#include "test_apb_dport_access.h" +#include "soc/soc_caps.h" +#include "test_utils.h" +#include "esp_memory_utils.h" + +TEST_CASE("mbedtls SHA self-tests", "[mbedtls]") +{ + start_apb_access_loop(); + TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha1_self_test(1), "SHA1 self-tests should pass."); + TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha256_self_test(1), "SHA256 self-tests should pass."); + TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha512_self_test(1), "SHA512 self-tests should pass."); + verify_apb_access_loop(); +} + +static const unsigned char *one_hundred_as = (unsigned char *) + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + +static const unsigned char *one_hundred_bs = (unsigned char *) + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; + +static const uint8_t sha256_thousand_as[32] = { + 0x41, 0xed, 0xec, 0xe4, 0x2d, 0x63, 0xe8, 0xd9, 0xbf, 0x51, 0x5a, 0x9b, 0xa6, 0x93, 0x2e, 0x1c, + 0x20, 0xcb, 0xc9, 0xf5, 0xa5, 0xd1, 0x34, 0x64, 0x5a, 0xdb, 0x5d, 0xb1, 0xb9, 0x73, 0x7e, 0xa3 +}; + + +static const uint8_t sha256_thousand_bs[32] = { + 0xf6, 0xf1, 0x18, 0xe1, 0x20, 0xe5, 0x2b, 0xe0, 0xbd, 0x0c, 0xfd, 0xf2, 0x79, 0x4c, 0xd1, 0x2c, 0x07, 0x68, 0x6c, 0xc8, 0x71, 0x23, 0x5a, 0xc2, 0xf1, 0x14, 0x59, 0x37, 0x8e, 0x6d, 0x23, 0x5b +}; + +static const uint8_t sha512_thousand_bs[64] = { + 0xa6, 0x68, 0x68, 0xa3, 0x73, 0x53, 0x2a, 0x5c, 0xc3, 0x3f, 0xbf, 0x43, 0x4e, 0xba, 0x10, 0x86, 0xb3, 0x87, 0x09, 0xe9, 0x14, 0x3f, 0xbf, 0x37, 0x67, 0x8d, 0x43, 0xd9, 0x9b, 0x95, 0x08, 0xd5, 0x80, 0x2d, 0xbe, 0x9d, 0xe9, 0x1a, 0x54, 0xab, 0x9e, 0xbc, 0x8a, 0x08, 0xa0, 0x1a, 0x89, 0xd8, 0x72, 0x68, 0xdf, 0x52, 0x69, 0x7f, 0x1c, 0x70, 0xda, 0xe8, 0x3f, 0xe5, 0xae, 0x5a, 0xfc, 0x9d +}; + +static const uint8_t sha384_thousand_bs[48] = { + 0x6d, 0xe5, 0xf5, 0x88, 0x57, 0x60, 0x83, 0xff, 0x7c, 0x94, 0x61, 0x5f, 0x8d, 0x96, 0xf2, 0x76, 0xd5, 0x3f, 0x77, 0x0c, 0x8e, 0xc1, 0xbf, 0xb6, 0x04, 0x27, 0xa4, 0xba, 0xea, 0x6c, 0x68, 0x44, 0xbd, 0xb0, 0x9c, 0xef, 0x6a, 0x09, 0x28, 0xe8, 0x1f, 0xfc, 0x95, 0x03, 0x69, 0x99, 0xab, 0x1a +}; + +static const uint8_t sha1_thousand_as[20] = { + 0x29, 0x1e, 0x9a, 0x6c, 0x66, 0x99, 0x49, 0x49, 0xb5, 0x7b, 0xa5, + 0xe6, 0x50, 0x36, 0x1e, 0x98, 0xfc, 0x36, 0xb1, 0xba +}; + + +TEST_CASE("mbedtls SHA interleaving", "[mbedtls]") +{ + mbedtls_sha1_context sha1_ctx; + mbedtls_sha256_context sha256_ctx; + mbedtls_sha512_context sha512_ctx; + unsigned char sha1[20], sha256[32], sha512[64]; + + mbedtls_sha1_init(&sha1_ctx); + mbedtls_sha256_init(&sha256_ctx); + mbedtls_sha512_init(&sha512_ctx); + + TEST_ASSERT_EQUAL(0, mbedtls_sha1_starts(&sha1_ctx)); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(&sha256_ctx, false)); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_starts(&sha512_ctx, false)); + + for (int i = 0; i < 10; i++) { + TEST_ASSERT_EQUAL(0, mbedtls_sha1_update(&sha1_ctx, one_hundred_as, 100)); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&sha256_ctx, one_hundred_as, 100)); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&sha512_ctx, one_hundred_bs, 100)); + } + + TEST_ASSERT_EQUAL(0, mbedtls_sha1_finish(&sha1_ctx, sha1)); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&sha256_ctx, sha256)); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish(&sha512_ctx, sha512)); + + mbedtls_sha1_free(&sha1_ctx); + mbedtls_sha256_free(&sha256_ctx); + mbedtls_sha512_free(&sha512_ctx); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 calculation"); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 calculation"); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha1_thousand_as, sha1, 20, "SHA1 calculation"); +} + +#define SHA_TASK_STACK_SIZE (10*1024) +static SemaphoreHandle_t done_sem; + +static void tskRunSHA1Test(void *pvParameters) +{ + mbedtls_sha1_context sha1_ctx; + unsigned char sha1[20]; + + for (int i = 0; i < 1000; i++) { + mbedtls_sha1_init(&sha1_ctx); + TEST_ASSERT_EQUAL(0, mbedtls_sha1_starts(&sha1_ctx)); + for (int j = 0; j < 10; j++) { + TEST_ASSERT_EQUAL(0, mbedtls_sha1_update(&sha1_ctx, (unsigned char *)one_hundred_as, 100)); + } + TEST_ASSERT_EQUAL(0, mbedtls_sha1_finish(&sha1_ctx, sha1)); + mbedtls_sha1_free(&sha1_ctx); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha1_thousand_as, sha1, 20, "SHA1 calculation"); + } + xSemaphoreGive(done_sem); + vTaskDelete(NULL); +} + +static void tskRunSHA256Test(void *pvParameters) +{ + mbedtls_sha256_context sha256_ctx; + unsigned char sha256[32]; + + for (int i = 0; i < 1000; i++) { + mbedtls_sha256_init(&sha256_ctx); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(&sha256_ctx, false)); + for (int j = 0; j < 10; j++) { + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&sha256_ctx, (unsigned char *)one_hundred_bs, 100)); + } + TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&sha256_ctx, sha256)); + mbedtls_sha256_free(&sha256_ctx); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_bs, sha256, 32, "SHA256 calculation"); + } + xSemaphoreGive(done_sem); + vTaskDelete(NULL); +} + + +TEST_CASE("mbedtls SHA multithreading", "[mbedtls]") +{ + done_sem = xSemaphoreCreateCounting(4, 0); + xTaskCreate(tskRunSHA1Test, "SHA1Task1", SHA_TASK_STACK_SIZE, NULL, 3, NULL); + xTaskCreate(tskRunSHA1Test, "SHA1Task2", SHA_TASK_STACK_SIZE, NULL, 3, NULL); + xTaskCreate(tskRunSHA256Test, "SHA256Task1", SHA_TASK_STACK_SIZE, NULL, 3, NULL); + xTaskCreate(tskRunSHA256Test, "SHA256Task2", SHA_TASK_STACK_SIZE, NULL, 3, NULL); + + for (int i = 0; i < 4; i++) { + if (!xSemaphoreTake(done_sem, 10000 / portTICK_PERIOD_MS)) { + TEST_FAIL_MESSAGE("done_sem not released by test task"); + } + } + vSemaphoreDelete(done_sem); +} + +void tskRunSHASelftests(void *param) +{ + for (int i = 0; i < 5; i++) { + if (mbedtls_sha1_self_test(1)) { + printf("SHA1 self-tests failed.\n"); + while (1) {} + } + + if (mbedtls_sha256_self_test(1)) { + printf("SHA256 self-tests failed.\n"); + while (1) {} + } + +#if SOC_SHA_SUPPORT_SHA512 + if (mbedtls_sha512_self_test(1)) { + printf("SHA512 self-tests failed.\n"); + while (1) {} + } + + if (mbedtls_sha512_self_test(1)) { + printf("SHA512 self-tests failed.\n"); + while (1) {} + } +#endif //SOC_SHA_SUPPORT_SHA512 + } + xSemaphoreGive(done_sem); + vTaskDelete(NULL); +} + +TEST_CASE("mbedtls SHA self-tests multithreaded", "[mbedtls]") +{ + done_sem = xSemaphoreCreateCounting(2, 0); + xTaskCreate(tskRunSHASelftests, "SHASelftests1", SHA_TASK_STACK_SIZE, NULL, 3, NULL); + xTaskCreate(tskRunSHASelftests, "SHASelftests2", SHA_TASK_STACK_SIZE, NULL, 3, NULL); + + const int TIMEOUT_MS = 40000; + + for (int i = 0; i < 2; i++) { + if (!xSemaphoreTake(done_sem, TIMEOUT_MS / portTICK_PERIOD_MS)) { + TEST_FAIL_MESSAGE("done_sem not released by test task"); + } + } + vSemaphoreDelete(done_sem); +} + +TEST_CASE("mbedtls SHA512 clone", "[mbedtls]") +{ + mbedtls_sha512_context ctx; + mbedtls_sha512_context clone; + unsigned char sha512[64]; + + mbedtls_sha512_init(&ctx); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_starts(&ctx, false)); + for (int i = 0; i < 5; i++) { + TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&ctx, one_hundred_bs, 100)); + } + + mbedtls_sha512_init(&clone); + mbedtls_sha512_clone(&clone, &ctx); + for (int i = 0; i < 5; i++) { + TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&ctx, one_hundred_bs, 100)); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&clone, one_hundred_bs, 100)); + } + TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish(&ctx, sha512)); + mbedtls_sha512_free(&ctx); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 original calculation"); + + TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish(&clone, sha512)); + mbedtls_sha512_free(&clone); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 cloned calculation"); +} + +TEST_CASE("mbedtls SHA384 clone", "[mbedtls][") +{ + mbedtls_sha512_context ctx; + mbedtls_sha512_context clone; + + unsigned char sha384[48]; + + mbedtls_sha512_init(&ctx); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_starts(&ctx, true)); + for (int i = 0; i < 5; i++) { + TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&ctx, one_hundred_bs, 100)); + } + + mbedtls_sha512_init(&clone); + mbedtls_sha512_clone(&clone, &ctx); + + for (int i = 0; i < 5; i++) { + TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&ctx, one_hundred_bs, 100)); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&clone, one_hundred_bs, 100)); + } +/* intended warning supression: is384 == true */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" + TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish(&ctx, sha384)); +#pragma GCC diagnostic pop + mbedtls_sha512_free(&ctx); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha384_thousand_bs, sha384, 48, "SHA512 original calculation"); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" + TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish(&clone, sha384)); +#pragma GCC diagnostic pop + mbedtls_sha512_free(&clone); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha384_thousand_bs, sha384, 48, "SHA512 cloned calculation"); +} + + +TEST_CASE("mbedtls SHA256 clone", "[mbedtls]") +{ + mbedtls_sha256_context ctx; + mbedtls_sha256_context clone; + unsigned char sha256[64]; + + mbedtls_sha256_init(&ctx); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(&ctx, false)); + for (int i = 0; i < 5; i++) { + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&ctx, one_hundred_as, 100)); + } + + mbedtls_sha256_init(&clone); + mbedtls_sha256_clone(&clone, &ctx); + for (int i = 0; i < 5; i++) { + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&ctx, one_hundred_as, 100)); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&clone, one_hundred_as, 100)); + } + TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&ctx, sha256)); + mbedtls_sha256_free(&ctx); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 original calculation"); + + TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&clone, sha256)); + mbedtls_sha256_free(&clone); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 cloned calculation"); +} + +typedef struct { + mbedtls_sha256_context ctx; + uint8_t result[32]; + int ret; + bool done; +} finalise_sha_param_t; + +static void tskFinaliseSha(void *v_param) +{ + finalise_sha_param_t *param = (finalise_sha_param_t *)v_param; + + for (int i = 0; i < 5; i++) { + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(¶m->ctx, one_hundred_as, 100)); + } + + param->ret = mbedtls_sha256_finish(¶m->ctx, param->result); + mbedtls_sha256_free(¶m->ctx); + + param->done = true; + vTaskDelete(NULL); +} + + +TEST_CASE("mbedtls SHA session passed between tasks", "[mbedtls]") +{ + finalise_sha_param_t param = { 0 }; + + mbedtls_sha256_init(¶m.ctx); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(¶m.ctx, false)); + for (int i = 0; i < 5; i++) { + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(¶m.ctx, one_hundred_as, 100)); + } + + // pass the SHA context off to a different task + // + // note: at the moment this doesn't crash even if a mutex semaphore is used as the + // engine lock, but it can crash... + xTaskCreate(tskFinaliseSha, "SHAFinalise", SHA_TASK_STACK_SIZE, ¶m, 3, NULL); + + while (!param.done) { + vTaskDelay(1); + } + + TEST_ASSERT_EQUAL(0, param.ret); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, param.result, 32, "SHA256 result from other task"); +} + + + +/* Random input generated and hashed using python: + + import hashlib + import os, binascii + + input = bytearray(os.urandom(150)) + arr = '' + for idx, b in enumerate(input): + if idx % 8 == 0: + arr += '\n' + arr += "{}, ".format(hex(b)) + digest = hashlib.sha256(input).hexdigest() + +*/ +const uint8_t test_vector[] = { + 0xe4, 0x1a, 0x1a, 0x30, 0x71, 0xd3, 0x94, 0xb0, + 0xc3, 0x7e, 0x99, 0x9f, 0x1a, 0xde, 0x4a, 0x36, + 0xb1, 0x1, 0x81, 0x2b, 0x41, 0x91, 0x11, 0x7f, + 0xd8, 0xe1, 0xd5, 0xe5, 0x52, 0x6d, 0x92, 0xee, + 0x6c, 0xf7, 0x70, 0xea, 0x3a, 0xb, 0xc9, 0x97, + 0xc0, 0x12, 0x6f, 0x10, 0x5b, 0x90, 0xd8, 0x52, + 0x91, 0x69, 0xea, 0xc4, 0x1f, 0xc, 0xcf, 0xc6, + 0xf0, 0x43, 0xc6, 0xa3, 0x1f, 0x46, 0x3c, 0x3d, + 0x25, 0xe5, 0xa8, 0x27, 0x86, 0x85, 0x32, 0x3f, + 0x33, 0xd8, 0x40, 0xc4, 0x41, 0xf6, 0x4b, 0x12, + 0xd8, 0x5e, 0x4, 0x27, 0x42, 0x90, 0x73, 0x4, + 0x8, 0x42, 0xd1, 0x64, 0xd, 0x84, 0x3, 0x1, + 0x76, 0x88, 0xe4, 0x95, 0xdf, 0xe7, 0x62, 0xb4, + 0xb3, 0xb2, 0x7e, 0x6d, 0x78, 0xca, 0x79, 0x82, + 0xcc, 0xba, 0x22, 0xd2, 0x90, 0x2e, 0xe3, 0xa8, + 0x2a, 0x53, 0x3a, 0xb1, 0x9a, 0x7f, 0xb7, 0x8b, + 0xfa, 0x32, 0x47, 0xc1, 0x5c, 0x6, 0x4f, 0x7b, + 0xcd, 0xb3, 0xf4, 0xf1, 0xd0, 0xb5, 0xbf, 0xfb, + 0x7c, 0xc3, 0xa5, 0xb2, 0xc4, 0xd4, +}; + +const uint8_t test_vector_digest[] = { + 0xff, 0x1c, 0x60, 0xcb, 0x21, 0xf0, 0x63, 0x68, + 0xb9, 0xfc, 0xfe, 0xad, 0x3e, 0xb0, 0x2e, 0xd1, + 0xf9, 0x08, 0x82, 0x82, 0x83, 0x06, 0xc1, 0x8a, + 0x98, 0x5d, 0x36, 0xc0, 0xb7, 0xeb, 0x35, 0xe0, +}; + + +TEST_CASE("mbedtls SHA, input in flash", "[mbedtls]") +{ + mbedtls_sha256_context sha256_ctx; + unsigned char sha256[32]; + + mbedtls_sha256_init(&sha256_ctx); + + TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(&sha256_ctx, false)); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&sha256_ctx, test_vector, sizeof(test_vector))); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&sha256_ctx, sha256)); + mbedtls_sha256_free(&sha256_ctx); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(test_vector_digest, sha256, 32, "SHA256 calculation"); +} + +/* Function are not implemented in SW */ +#if CONFIG_MBEDTLS_HARDWARE_SHA && SOC_SHA_SUPPORT_SHA512_T + +/* + * FIPS-180-2 test vectors + */ +static unsigned char sha512T_test_buf[2][113] = { + { "abc" }, + { + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" + } +}; + +static const size_t sha512T_test_buflen[2] = { + 3, 112 +}; + +static const esp_sha_type sha512T_algo[4] = { + SHA2_512224, SHA2_512256, SHA2_512T, SHA2_512T +}; + +static const size_t sha512T_t_len[4] = { 224, 256, 224, 256 }; + +static const unsigned char sha512_test_sum[4][32] = { + /* SHA512-224 */ + { + 0x46, 0x34, 0x27, 0x0f, 0x70, 0x7b, 0x6a, 0x54, + 0xda, 0xae, 0x75, 0x30, 0x46, 0x08, 0x42, 0xe2, + 0x0e, 0x37, 0xed, 0x26, 0x5c, 0xee, 0xe9, 0xa4, + 0x3e, 0x89, 0x24, 0xaa + }, + { + 0x23, 0xfe, 0xc5, 0xbb, 0x94, 0xd6, 0x0b, 0x23, + 0x30, 0x81, 0x92, 0x64, 0x0b, 0x0c, 0x45, 0x33, + 0x35, 0xd6, 0x64, 0x73, 0x4f, 0xe4, 0x0e, 0x72, + 0x68, 0x67, 0x4a, 0xf9 + }, + + /* SHA512-256 */ + { + 0x53, 0x04, 0x8e, 0x26, 0x81, 0x94, 0x1e, 0xf9, + 0x9b, 0x2e, 0x29, 0xb7, 0x6b, 0x4c, 0x7d, 0xab, + 0xe4, 0xc2, 0xd0, 0xc6, 0x34, 0xfc, 0x6d, 0x46, + 0xe0, 0xe2, 0xf1, 0x31, 0x07, 0xe7, 0xaf, 0x23 + }, + { + 0x39, 0x28, 0xe1, 0x84, 0xfb, 0x86, 0x90, 0xf8, + 0x40, 0xda, 0x39, 0x88, 0x12, 0x1d, 0x31, 0xbe, + 0x65, 0xcb, 0x9d, 0x3e, 0xf8, 0x3e, 0xe6, 0x14, + 0x6f, 0xea, 0xc8, 0x61, 0xe1, 0x9b, 0x56, 0x3a + } + + /* For SHA512_T testing we use t=224 & t=256 + * so the hash digest should be same as above + */ +}; + +/* This will run total of 8 test cases, 2 for each of the below MODE + * SHA512/224, SHA512/256, SHA512/t with t=224 & SHA512/t with t=256 + * + * Test is disabled for ESP32 as there is no hardware for SHA512/t + */ +TEST_CASE("mbedtls SHA512/t", "[mbedtls]") +{ + mbedtls_sha512_context sha512_ctx; + unsigned char sha512[64], k; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 2; j++) { + k = i * 2 + j; + mbedtls_sha512_init(&sha512_ctx); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_starts(&sha512_ctx, false)); + esp_sha512_set_mode(&sha512_ctx, sha512T_algo[i]); + if (i > 1) { + k = (i - 2) * 2 + j; + esp_sha512_set_t(&sha512_ctx, sha512T_t_len[i]); + } + TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&sha512_ctx, sha512T_test_buf[j], sha512T_test_buflen[j])); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish(&sha512_ctx, sha512)); + mbedtls_sha512_free(&sha512_ctx); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_test_sum[k], sha512, sha512T_t_len[i] / 8, "SHA512t calculation"); + } + } +} +#endif //CONFIG_MBEDTLS_HARDWARE_SHA + +#ifdef CONFIG_SPIRAM_USE_MALLOC +#include "test_mbedtls_utils.h" +TEST_CASE("mbedtls SHA256 PSRAM DMA", "[mbedtls]") +{ + const unsigned CALLS = 256; + const unsigned CALL_SZ = 16 * 1024; + mbedtls_sha256_context sha256_ctx; + unsigned char sha256[32]; + + // allocate external memory + uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + TEST_ASSERT(esp_ptr_external_ram(buf)); + memset(buf, 0x54, CALL_SZ); + + mbedtls_sha256_init(&sha256_ctx); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(&sha256_ctx, false)); + for (int c = 0; c < CALLS; c++) { + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&sha256_ctx, buf, CALL_SZ)); + } + TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&sha256_ctx, sha256)); + + free(buf); + mbedtls_sha256_free(&sha256_ctx); + + /* Check the result. Reference value can be calculated using: + * dd if=/dev/zero bs=$((16*1024)) count=256 | tr '\000' '\124' | sha256sum + */ + const char *expected_hash = "8d031167bd706ac337e07aa9129c34ae4ae792d0a79a2c70e7f012102e8adc3d"; + char hash_str[sizeof(sha256) * 2 + 1]; + utils_bin2hex(hash_str, sizeof(hash_str), sha256, sizeof(sha256)); + + TEST_ASSERT_EQUAL_STRING(expected_hash, hash_str); + +} + +#if SOC_SHA_SUPPORT_DMA +TEST_CASE("mbedtls SHA256 PSRAM DMA large buffer", "[hw_crypto]") +{ + mbedtls_sha256_context sha256_ctx; + unsigned char sha256[32]; + + const size_t SZ = 257984; // specific size to cover issue in https://github.com/espressif/esp-idf/issues/11915 + void *buffer = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + TEST_ASSERT_NOT_NULL(buffer); + memset(buffer, 0x55, SZ); + + mbedtls_sha256_init(&sha256_ctx); + int r = mbedtls_sha256_starts(&sha256_ctx, false); + TEST_ASSERT_EQUAL(0, r); + r = mbedtls_sha256_update(&sha256_ctx, buffer, SZ); + TEST_ASSERT_EQUAL(0, r); + r = mbedtls_sha256_finish(&sha256_ctx, sha256); + TEST_ASSERT_EQUAL(0, r); + mbedtls_sha256_free(&sha256_ctx); + free(buffer); + + /* Check the result. Reference value can be calculated using: + * dd if=/dev/zero bs=257984 count=1 | tr '\000' '\125' | sha256sum + */ + const char *expected_hash = "f2330c9f81ff1c8f0515247faa82be8b6f9685601de6f5dae79172766f136c33"; + + char hash_str[sizeof(sha256) * 2 + 1]; + utils_bin2hex(hash_str, sizeof(hash_str), sha256, sizeof(sha256)); + + TEST_ASSERT_EQUAL_STRING(expected_hash, hash_str); +} +#endif // SOC_SHA_SUPPORT_DMA + +#endif //CONFIG_SPIRAM_USE_MALLOC + +#if CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK + +TEST_CASE("mbedtls SHA stack in RTC RAM", "[mbedtls]") +{ + done_sem = xSemaphoreCreateBinary(); + static StaticTask_t rtc_task; + size_t STACK_SIZE = 3072; + uint8_t *rtc_stack = heap_caps_calloc(STACK_SIZE, 1, MALLOC_CAP_RTCRAM); + + TEST_ASSERT(esp_ptr_in_rtc_dram_fast(rtc_stack)); + + TEST_ASSERT_NOT_NULL(xTaskCreateStatic(tskRunSHA256Test, "tskRunSHA256Test_task", STACK_SIZE, NULL, + 3, rtc_stack, &rtc_task)); + TEST_ASSERT_TRUE(xSemaphoreTake(done_sem, 10000 / portTICK_PERIOD_MS)); + + /* Give task time to cleanup before freeing stack */ + vTaskDelay(1000 / portTICK_PERIOD_MS); + free(rtc_stack); + + vSemaphoreDelete(done_sem); +} + +#endif //CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK + +#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY && CONFIG_SPIRAM_USE_MALLOC + +TEST_CASE("mbedtls SHA stack in PSRAM", "[mbedtls]") +{ + done_sem = xSemaphoreCreateBinary(); + static StaticTask_t psram_task; + size_t STACK_SIZE = 3072; + uint8_t *psram_stack = heap_caps_calloc(STACK_SIZE, 1, MALLOC_CAP_SPIRAM); + + TEST_ASSERT(esp_ptr_external_ram(psram_stack)); + + TEST_ASSERT_NOT_NULL(xTaskCreateStatic(tskRunSHA256Test, "tskRunSHA256Test_task", STACK_SIZE, NULL, + 3, psram_stack, &psram_task)); + TEST_ASSERT_TRUE(xSemaphoreTake(done_sem, 10000 / portTICK_PERIOD_MS)); + + /* Give task time to cleanup before freeing stack */ + vTaskDelay(1000 / portTICK_PERIOD_MS); + free(psram_stack); + + vSemaphoreDelete(done_sem); +} + +#endif //CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY && CONFIG_SPIRAM_USE_MALLOC diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls_utils.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls_utils.c new file mode 100644 index 000000000..a2db38918 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls_utils.c @@ -0,0 +1,30 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "test_mbedtls_utils.h" + +static inline char to_hex_digit(unsigned val) +{ + return (val < 10) ? ('0' + val) : ('a' + val - 10); +} + + +void utils_bin2hex(char *const hex, const size_t hex_maxlen, const unsigned char *const bin, const size_t bin_len) +{ + assert(bin_len < SIZE_MAX / 2); + assert(hex_maxlen > bin_len * 2U); + assert(hex); + assert(bin); + + int i; + for (i = 0; i < bin_len; i++) { + hex[2*i] = to_hex_digit(bin[i] >> 4); + hex[2*i + 1] = to_hex_digit(bin[i] & 0xf); + } + hex[i * 2U] = 0U; +} diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls_utils.h b/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls_utils.h new file mode 100644 index 000000000..8d2b73c08 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_mbedtls_utils.h @@ -0,0 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +void utils_bin2hex(char *const hex, const size_t hex_maxlen, const unsigned char *const bin, const size_t bin_len); diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_rsa.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_rsa.c new file mode 100644 index 000000000..f69a0238f --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_rsa.c @@ -0,0 +1,603 @@ +/* mbedTLS RSA functionality tests + * + * Focus on testing functionality where we use ESP32 hardware + * accelerated crypto features + * + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "esp_system.h" +#include "esp_task_wdt.h" +#include "mbedtls/rsa.h" +#include "mbedtls/pk.h" +#include "mbedtls/x509_crt.h" +#include +#include +#include "entropy_poll.h" +#include "freertos/FreeRTOS.h" +#include "unity.h" +#include "test_utils.h" +#include "memory_checks.h" +#include "ccomp_timer.h" + +#define PRINT_DEBUG_INFO + +/* Taken from openssl s_client -connect api.gigafive.com:443 -showcerts + */ +static const char *rsa4096_cert = "-----BEGIN CERTIFICATE-----\n"\ + "MIIExzCCA6+gAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBkjELMAkGA1UEBhMCVVMx\n"\ + "CzAJBgNVBAgMAkNBMRQwEgYDVQQHDAtTYW50YSBDbGFyYTElMCMGA1UECgwcR2ln\n"\ + "YWZpdmUgVGVjaG5vbG9neSBQYXJ0bmVyczEZMBcGA1UEAwwQR2lnYWZpdmUgUm9v\n"\ + "dCBDQTEeMBwGCSqGSIb3DQEJARYPY2FAZ2lnYWZpdmUuY29tMB4XDTE2MDgyNzE2\n"\ + "NDYyM1oXDTI2MDgyNTE2NDYyM1owgZcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJD\n"\ + "QTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExKTAnBgNVBAoMIEdpZ2FmaXZlIFRlY2hu\n"\ + "b2xvZ3kgUGFydG5lcnMgTExDMRkwFwYDVQQDDBBhcGkuZ2lnYWZpdmUuY29tMR8w\n"\ + "HQYJKoZIhvcNAQkBFhBjcmxAZ2lnYWZpdmUuY29tMIICIjANBgkqhkiG9w0BAQEF\n"\ + "AAOCAg8AMIICCgKCAgEAof82VrEpXMpsI/ddW6RLeTeSYtxiXZZkRbDKN6otYgEk\n"\ + "vA8yRbzei2cO2A/8+Erhe9beYLAMXWF+bjoUAFwnuIcbmufgHprOYzX/7CYXCsrH\n"\ + "LrJfVF6kvjCXy2W3xSvgh8ZgHNWnBGzl13tq19Fz8x0AhK5GQ9608oJCbnQjpVSI\n"\ + "lZDl3JVOifCeXf2c7nMhVOC/reTeto0Gbchs8Ox50WyojmfYbVjOQcA7f8p1eI+D\n"\ + "XUJK01cUGVu6/KarVArGHh5LsiyXOadbyeyOXPmjyrgarG3IIBeQSNECfJZPc/OW\n"\ + "lFszjU4YLDckI4x+tReiuFQbQPN5sDplcEldmZZm/8XD36ddvAaDds+SYlPXxDK7\n"\ + "7L8RBVUG2Ylc9YZf7RE6IMDmdQmsCZDX0VxySYEmzv5lnAx4mzzaXcgS+kHMOLyK\n"\ + "n9UxmpzwQoqqC9tMZqwRaeKW1njR1dSwQLqirBPfGCWKkpkpm7C3HEfeeLrasral\n"\ + "aPf6LAwN3A4ZKHa5Jmne7W+1eYS1aTXOAOLIPcXRAh1B80H+SusIdM9d6vk2YTIg\n"\ + "khwGQV3sgM6nIO5+T/8z141UEjWbtP7pb/u0+G9Cg7TwvRoO2UukxdvOwNto1G2e\n"\ + "J3rKB/JSYsYWnPHvvh9XR+55PZ4iCf9Rqw/IP82uyGipR9gxlHqN8WhMTj9tNEkC\n"\ + "AwEAAaMhMB8wHQYDVR0OBBYEFISCemcSriz1HFhRXluw9H+Bv9lEMA0GCSqGSIb3\n"\ + "DQEBCwUAA4IBAQCMetK0xe6Y/uZpb1ARh+hHYcHI3xI+IG4opWJeoB1gDh/xpNAW\n"\ + "j6t5MGbLoqNMBXbqL26hnKVspyvCxw7ebI5ZJgjtbrD1t+0D8yrgIZzr7AWGA9Hj\n"\ + "WIHqDHGDxwkmfjVVPmuO3l5RtJmL6KV6kVL2bOvVI6gECpFLddmOTtg+iXDfSw3x\n"\ + "0+ueMYKr8QLF+TCxfzQTHvTHvOJtcZHecc1n7PYbRmI2p7tV6RoBpV69oM6NAVUV\n"\ + "i2QoSxm0pYzDzavOaxwhEPHT34Tpg6fwXy1QokFD9OtxRFtdpTjL3bMWpatZE+ba\n"\ + "cjvvf0utMW5fNjTTxu1nnpuxZM3ifTCqZJ+9\n"\ + "-----END CERTIFICATE-----\n"; + +static const char *rsa3072_cert = "-----BEGIN CERTIFICATE-----\n"\ + "MIIEszCCAxugAwIBAgIUNTBsyv59/rRarOVm3KBA29zqEtUwDQYJKoZIhvcNAQEL\n"\ + "BQAwaTELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFNoYW5naGFpMREwDwYDVQQHDAhT\n"\ + "aGFuZ2hhaTESMBAGA1UECgwJRXNwcmVzc2lmMQwwCgYDVQQLDANJREYxEjAQBgNV\n"\ + "BAMMCWVzcHJlc3NpZjAeFw0yMDA3MTQwODQ5NDdaFw0yMTA3MTQwODQ5NDdaMGkx\n"\ + "CzAJBgNVBAYTAkNOMREwDwYDVQQIDAhTaGFuZ2hhaTERMA8GA1UEBwwIU2hhbmdo\n"\ + "YWkxEjAQBgNVBAoMCUVzcHJlc3NpZjEMMAoGA1UECwwDSURGMRIwEAYDVQQDDAll\n"\ + "c3ByZXNzaWYwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDMj3ZwPd2y\n"\ + "+UxzmMUdZC5I5JQIzvUmHRNJWUe99Vht/rIEQuNSGg7xjyvuZoyeFo+Yg+QYUICa\n"\ + "Ipe4y2bZS12QsTxUmeoEhYORDSeQXFEo4aUmWuKIs6Y41dBOL7eDYDL3FRmIgmcn\n"\ + "qMonyCrSzXlcgHOVtMd8U8ifkX5u+nTigQLSIHVeAFz8CvC0tIiPm9YFurtMN15p\n"\ + "P1K/AH17ljtwVqacrI/asZgX+ECY5rauNJLigEYgfr7+xV6GofaXp6rUpGgWbVxM\n"\ + "hqKe/dbDuIzte3VK+zRDNDCeE5gPQjgoSDblOVmPemrq7KKjZ/PKmP47ct5a/0Ov\n"\ + "zWcdCgaXDRoPiwbpmz3Z6uh3JdvsDf214svLK+z4EDIRzpvggM0pfDvOADatiPkr\n"\ + "KmnFD1ZZx3R29/7IZ5OVvQL1hgWbm3cL4JADOc8PQKcqCzBE9JDdAVoa228ESaJ/\n"\ + "n4b63qaqfgBnoaFzCEruEcXj5nuXBxlk19WWtgY1tZtAgoA8hTWxxH0CAwEAAaNT\n"\ + "MFEwHQYDVR0OBBYEFPlwrvgkde/r+F8VRMMtpDUIxAtgMB8GA1UdIwQYMBaAFPlw\n"\ + "rvgkde/r+F8VRMMtpDUIxAtgMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL\n"\ + "BQADggGBAH9nBaEP+FWyaZnmxCblKhs8eIEYXzjxbnRUPo5b3uL/PAv1XD1kEUwY\n"\ + "GWnJ7Z5HOSCdVMgo1opmKGLWuiVP6Vlt9QuA/tWh0bGScL4QfriPXuA7aXAcLbW/\n"\ + "BqHNJ9Z+H2Fq09XktkZE4Nfnv3iTMMqfNCchM3t3iWZRf2sRVYIdd5OjhM+CLLUK\n"\ + "kYNiseAgbcBX0/kqTdHlC6OS8Mcu9btJ/663DZy8tndf+PH+EB6fexQd9T31jWoj\n"\ + "OkEkJ4vDRZP+0LceK7kNcMOcLx8DnF9LwUyHQitW7NMFServoTfxy8A0yep7nIOH\n"\ + "M/ndECzirQ6WkR9jMG3cw0Jm5mZvA9IAvnLhUO45AyZGC8mShJ0AaXtqejqPg9ng\n"\ + "//5VIpzoqwVkrMYlMA7ZrccQiRsd2nlBHr+64PRwRCp7y5FOxIzhGzsJibXUpO/V\n"\ + "FNwuPz+VcnPvJE7r4gB1oRViiGYojMDQV3G+jbgvpTHKUKP6zzavSAKs+FlfEAmh\n"\ + "EtmuT/beDA==\n"\ + "-----END CERTIFICATE-----\n"; + +/* Root cert from openssl s_client -connect google.com:443 -showcerts + */ +static const char *rsa2048_cert = "-----BEGIN CERTIFICATE-----\n"\ + "MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT\n"\ + "MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0\n"\ + "aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDIwNTIxMDQwMDAwWhcNMTgwODIxMDQwMDAw\n"\ + "WjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE\n"\ + "AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n"\ + "CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9m\n"\ + "OSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu\n"\ + "T8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6c\n"\ + "JmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmR\n"\ + "Cw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5asz\n"\ + "PeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo4HwMIHtMB8GA1UdIwQYMBaAFEjm\n"\ + "aPkr0rKV10fYIyAQTzOYkJ/UMB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrM\n"\ + "TjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA6BgNVHR8EMzAxMC+g\n"\ + "LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDBO\n"\ + "BgNVHSAERzBFMEMGBFUdIAAwOzA5BggrBgEFBQcCARYtaHR0cHM6Ly93d3cuZ2Vv\n"\ + "dHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5MA0GCSqGSIb3DQEBBQUAA4GB\n"\ + "AHbhEm5OSxYShjAGsoEIz/AIx8dxfmbuwu3UOx//8PDITtZDOLC5MH0Y0FWDomrL\n"\ + "NhGc6Ehmo21/uBPUR/6LWlxz/K7ZGzIZOKuXNBSqltLroxwUCEm2u+WR74M26x1W\n"\ + "b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S\n"\ + "-----END CERTIFICATE-----\n"; + + +/* Some random input bytes to public key encrypt */ +static const uint8_t pki_input[4096/8] = { + 0, 1, 4, 6, 7, 9, 33, 103, 49, 11, 56, 211, 67, 92 }; + +/* Result of an RSA4096 operation using cert's public key + (raw PKI, no padding/etc) */ +static const uint8_t pki_rsa4096_output[] = { + 0x91, 0x87, 0xcd, 0x04, 0x80, 0x7c, 0x8b, 0x0b, + 0x0c, 0xc0, 0x38, 0x37, 0x7a, 0xe3, 0x2c, 0x94, + 0xea, 0xc4, 0xcb, 0x83, 0x2c, 0x77, 0x71, 0x14, + 0x11, 0x85, 0x16, 0x61, 0xd3, 0x64, 0x2a, 0x0f, + 0xf9, 0x6b, 0x45, 0x04, 0x66, 0x5d, 0x15, 0xf1, + 0xcf, 0x69, 0x77, 0x90, 0xb9, 0x41, 0x68, 0xa9, + 0xa6, 0xfd, 0x94, 0xdc, 0x6a, 0xce, 0xc7, 0xb6, + 0x41, 0xd9, 0x44, 0x3c, 0x02, 0xb6, 0xc7, 0x26, + 0xce, 0xec, 0x66, 0x21, 0xa8, 0xe8, 0xf4, 0xa9, + 0x33, 0x4a, 0x6c, 0x28, 0x0f, 0x50, 0x30, 0x32, + 0x28, 0x00, 0xbb, 0x2c, 0xc3, 0x44, 0x72, 0x31, + 0x93, 0xd4, 0xde, 0x29, 0x6b, 0xfa, 0x31, 0xfd, + 0x3a, 0x05, 0xc6, 0xb1, 0x28, 0x43, 0x57, 0x20, + 0xf7, 0xf8, 0x13, 0x0c, 0x4a, 0x80, 0x00, 0xab, + 0x1f, 0xe8, 0x88, 0xad, 0x56, 0xf2, 0xda, 0x5a, + 0x50, 0xe9, 0x02, 0x09, 0x21, 0x2a, 0xfc, 0x82, + 0x68, 0x34, 0xf9, 0x04, 0xa3, 0x25, 0xe1, 0x0f, + 0xa8, 0x77, 0x29, 0x94, 0xb6, 0x9d, 0x5a, 0x08, + 0x33, 0x8d, 0x27, 0x6a, 0xc0, 0x3b, 0xad, 0x91, + 0x8a, 0x83, 0xa9, 0x2e, 0x48, 0xcd, 0x67, 0xa3, + 0x3a, 0x35, 0x41, 0x85, 0xfa, 0x3f, 0x61, 0x1f, + 0x80, 0xeb, 0xcd, 0x5a, 0xc5, 0x14, 0x7b, 0xab, + 0x9c, 0x45, 0x11, 0xd2, 0x25, 0x9a, 0x16, 0xeb, + 0x9c, 0xfa, 0xbe, 0x73, 0x18, 0xbd, 0x25, 0x8e, + 0x99, 0x6d, 0xb3, 0xbc, 0xac, 0x2d, 0xa2, 0x53, + 0xe8, 0x7c, 0x38, 0x1b, 0x7a, 0x75, 0xff, 0x76, + 0x4f, 0x48, 0x5b, 0x39, 0x20, 0x5a, 0x7b, 0x82, + 0xd3, 0x33, 0x33, 0x2a, 0xab, 0x6a, 0x7a, 0x42, + 0x1d, 0x1f, 0xd1, 0x61, 0x58, 0xd7, 0x38, 0x52, + 0xdf, 0xb0, 0x61, 0x98, 0x63, 0xb7, 0xa1, 0x4e, + 0xdb, 0x9b, 0xcb, 0xb7, 0x85, 0xc4, 0x3e, 0x03, + 0xe5, 0x59, 0x50, 0x28, 0x5a, 0x4d, 0x7f, 0x53, + 0x2e, 0x99, 0x1d, 0x6d, 0x85, 0x27, 0x78, 0x34, + 0x5e, 0xae, 0xc9, 0x1b, 0x37, 0x96, 0xde, 0x40, + 0x87, 0x35, 0x3c, 0x1f, 0xe0, 0x8f, 0xfb, 0x3a, + 0x58, 0x0e, 0x60, 0xe9, 0x06, 0xbd, 0x83, 0x03, + 0x92, 0xde, 0x5e, 0x69, 0x28, 0xb1, 0x00, 0xeb, + 0x44, 0xca, 0x3c, 0x49, 0x03, 0x10, 0xa8, 0x84, + 0xa6, 0xbb, 0xd5, 0xda, 0x98, 0x8c, 0x6f, 0xa3, + 0x0f, 0x39, 0xf3, 0xa7, 0x7d, 0xd5, 0x3b, 0xe2, + 0x85, 0x12, 0xda, 0xa4, 0x4d, 0x80, 0x97, 0xcb, + 0x11, 0xe0, 0x89, 0x90, 0xff, 0x5b, 0x72, 0x19, + 0x59, 0xd1, 0x39, 0x23, 0x9f, 0xb0, 0x00, 0xe2, + 0x45, 0x72, 0xc6, 0x9a, 0xbc, 0xe1, 0xd1, 0x51, + 0x6b, 0x35, 0xd2, 0x49, 0xbf, 0xb6, 0xfe, 0xab, + 0x09, 0xf7, 0x9d, 0xa4, 0x6e, 0x69, 0xb6, 0xf9, + 0xde, 0xe3, 0x57, 0x0c, 0x1a, 0x96, 0xf1, 0xcc, + 0x1c, 0x92, 0xdb, 0x44, 0xf4, 0x45, 0xfa, 0x8f, + 0x87, 0xcf, 0xf4, 0xd2, 0xa1, 0xf8, 0x69, 0x18, + 0xcf, 0xdc, 0xa0, 0x1f, 0xb0, 0x26, 0xad, 0x81, + 0xab, 0xdf, 0x78, 0x18, 0xa2, 0x74, 0xba, 0x2f, + 0xec, 0x70, 0xa2, 0x1f, 0x56, 0xee, 0xff, 0xc9, + 0xfe, 0xb1, 0xe1, 0x9b, 0xea, 0x0e, 0x33, 0x14, + 0x5f, 0x6e, 0xca, 0xee, 0x02, 0x56, 0x5a, 0x67, + 0x42, 0x9a, 0xbf, 0x55, 0xc0, 0x0f, 0x8e, 0x01, + 0x67, 0x63, 0x6e, 0xd1, 0x57, 0xf7, 0xf1, 0xc6, + 0x92, 0x9e, 0xb5, 0x45, 0xe1, 0x50, 0x58, 0x94, + 0x20, 0x90, 0x6a, 0x29, 0x2d, 0x4b, 0xd1, 0xb5, + 0x68, 0x63, 0xb5, 0xe6, 0xd8, 0x6e, 0x84, 0x80, + 0xad, 0xe6, 0x03, 0x1e, 0x51, 0xc2, 0xa8, 0x6d, + 0x84, 0xec, 0x2d, 0x7c, 0x61, 0x02, 0xd1, 0xda, + 0xf5, 0x94, 0xfa, 0x2d, 0xa6, 0xed, 0x89, 0x6a, + 0x6a, 0xda, 0x07, 0x5d, 0x83, 0xfc, 0x43, 0x76, + 0x7c, 0xca, 0x8c, 0x00, 0xfc, 0xb9, 0x2c, 0x23, +}; + +static const uint8_t pki_rsa3072_output[] = { + 0x86, 0xc0, 0xe4, 0xa5, 0x4b, 0x45, 0xe4, 0xd4, 0x0f, 0xb7, 0xe3, 0x10, 0x4f, 0xea, 0x88, 0x91, + 0x3d, 0xad, 0x43, 0x86, 0x90, 0xf0, 0xd8, 0xf0, 0x29, 0x21, 0xc7, 0x5c, 0x75, 0x49, 0x91, 0xce, + 0xf8, 0x34, 0x91, 0xbd, 0x89, 0x61, 0xcf, 0x47, 0x0e, 0x4d, 0x3f, 0x29, 0xd1, 0x02, 0xa7, 0xa8, + 0x8f, 0x6a, 0xda, 0x1a, 0xf2, 0xf1, 0x18, 0x92, 0x35, 0xf6, 0x0c, 0x07, 0x5a, 0x84, 0xfa, 0x65, + 0xd3, 0x02, 0xe0, 0x53, 0x17, 0x5d, 0xf7, 0x45, 0x26, 0xcc, 0xf9, 0x26, 0xf5, 0x6a, 0x66, 0xbb, + 0xef, 0x33, 0xcb, 0x03, 0x6e, 0x6a, 0x93, 0x6c, 0x2a, 0x27, 0xa7, 0xf7, 0x2c, 0xdc, 0x00, 0xdd, + 0x98, 0x52, 0xfb, 0xce, 0x31, 0xe2, 0x96, 0x20, 0x98, 0x0a, 0xf4, 0x19, 0x0f, 0xbf, 0x22, 0xed, + 0x37, 0xb2, 0x14, 0x10, 0x88, 0xa3, 0x6a, 0x43, 0x26, 0xb8, 0x54, 0xf1, 0xb8, 0xc6, 0x56, 0xb7, + 0x89, 0x34, 0xc0, 0xba, 0xae, 0x38, 0x35, 0x2c, 0x13, 0x57, 0x7a, 0xa4, 0x4b, 0xf2, 0x21, 0x82, + 0xf4, 0xea, 0x1a, 0x2c, 0xd8, 0x32, 0xe8, 0x5f, 0x37, 0x04, 0x52, 0x3d, 0xff, 0xc2, 0x85, 0x00, + 0xd2, 0x8d, 0x84, 0x36, 0x61, 0x61, 0x7b, 0xea, 0x7c, 0x3d, 0xeb, 0x51, 0xea, 0xf2, 0x67, 0xc9, + 0xb8, 0xa6, 0x98, 0x54, 0x3f, 0x5b, 0x8f, 0x1a, 0x8a, 0x93, 0x81, 0x05, 0xa3, 0x15, 0xf8, 0x54, + 0x8f, 0x75, 0xe2, 0x01, 0xc3, 0x47, 0xc3, 0x8f, 0xc7, 0x6d, 0x04, 0xbc, 0x05, 0x88, 0xd9, 0x62, + 0xcc, 0x14, 0xea, 0x30, 0x68, 0x73, 0xd5, 0xe5, 0x53, 0x7c, 0xb1, 0xa0, 0xe5, 0x6c, 0xd0, 0xa3, + 0x07, 0x2a, 0x5e, 0x2a, 0x0f, 0x89, 0x39, 0xea, 0xf9, 0xf5, 0xfb, 0x3b, 0xee, 0x66, 0xd9, 0xd4, + 0x04, 0x2d, 0x1b, 0xc9, 0xc2, 0x37, 0xc8, 0xa8, 0x71, 0xea, 0xa8, 0xf6, 0xe6, 0xc1, 0xdc, 0x5b, + 0x70, 0x68, 0x89, 0xa5, 0x69, 0xc0, 0x7f, 0x15, 0x8b, 0x6d, 0xc6, 0x88, 0x41, 0x8b, 0x25, 0x8f, + 0x2f, 0x5c, 0x81, 0x94, 0x1b, 0x8c, 0x52, 0x3f, 0xe5, 0x97, 0x6d, 0x4a, 0xc6, 0x42, 0x35, 0x0e, + 0x59, 0xce, 0x00, 0x3c, 0x2b, 0x0f, 0x5a, 0xc5, 0x1b, 0x01, 0xf3, 0x02, 0x70, 0xb1, 0x88, 0xda, + 0x7b, 0x5b, 0x4d, 0x3e, 0xd1, 0x15, 0x57, 0xc8, 0x39, 0x14, 0xff, 0x8d, 0x2b, 0x12, 0xf5, 0x5b, + 0xaf, 0x78, 0x2e, 0x0b, 0xcd, 0x27, 0x83, 0xdb, 0x4e, 0xe1, 0x5d, 0xa5, 0xbd, 0xfe, 0x2b, 0x6e, + 0x8b, 0x54, 0x7d, 0x14, 0x6f, 0x4d, 0xe1, 0x14, 0xc8, 0x30, 0x0e, 0x10, 0x23, 0x2a, 0xe1, 0xe5, + 0xee, 0xa3, 0x69, 0x8d, 0xe2, 0x9a, 0xed, 0x0c, 0x23, 0x16, 0x8e, 0x95, 0xae, 0x1a, 0xa2, 0x28, + 0x61, 0x25, 0xa2, 0x15, 0x74, 0xc4, 0xec, 0x6b, 0x73, 0xb2, 0x8c, 0xd2, 0x64, 0xfd, 0x2b, 0x92, +}; + +static const uint8_t pki_rsa2048_output[] = { + 0x47, 0x0b, 0xe5, 0x8a, 0xcd, 0x2f, 0x78, 0x07, + 0x69, 0x69, 0x70, 0xff, 0x81, 0xdf, 0x96, 0xf0, + 0xed, 0x82, 0x3a, 0x3d, 0x46, 0xab, 0xe9, 0xc3, + 0xb5, 0xd9, 0xca, 0xa2, 0x05, 0xa9, 0xf6, 0x6e, + 0xad, 0x6c, 0xe0, 0xd1, 0xa2, 0xb4, 0xf2, 0x78, + 0x4a, 0x93, 0xfc, 0x45, 0xe1, 0x9b, 0xdd, 0x62, + 0xf9, 0x66, 0x2a, 0x14, 0x38, 0x12, 0xb6, 0x50, + 0x0b, 0xe3, 0x53, 0x9c, 0x12, 0x56, 0xf1, 0xb7, + 0x83, 0xd5, 0xf3, 0x24, 0x81, 0xcc, 0x5a, 0xeb, + 0xec, 0xac, 0x68, 0xa8, 0x0c, 0xd7, 0x84, 0x7a, + 0xbb, 0x77, 0x7b, 0xd5, 0x5b, 0xcf, 0x7b, 0x25, + 0xd0, 0x75, 0x80, 0x21, 0x12, 0x97, 0x6b, 0xe1, + 0xb6, 0x51, 0x12, 0x52, 0x6e, 0x01, 0x92, 0xb7, + 0xcc, 0x70, 0x4b, 0x46, 0x11, 0x98, 0x5a, 0x84, + 0x1c, 0x90, 0x45, 0x0f, 0x15, 0x77, 0xdb, 0x79, + 0xe8, 0xff, 0x1f, 0xaa, 0x58, 0x95, 0xce, 0x3c, + 0x65, 0x0c, 0x66, 0x29, 0xe1, 0x9c, 0x41, 0xbb, + 0xde, 0x65, 0xb8, 0x29, 0x36, 0x94, 0xbd, 0x87, + 0x93, 0x39, 0xc5, 0xeb, 0x49, 0x21, 0xc1, 0xeb, + 0x48, 0xbd, 0x19, 0x13, 0x4d, 0x40, 0x90, 0x88, + 0xc6, 0x12, 0xd9, 0xf7, 0xdd, 0xc8, 0x4f, 0x89, + 0xc0, 0x91, 0xf8, 0xeb, 0xcf, 0xe3, 0x12, 0x17, + 0x88, 0x9c, 0x88, 0xf4, 0xf5, 0xae, 0xf4, 0x15, + 0xfe, 0x17, 0xf6, 0xa4, 0x74, 0x49, 0x02, 0x05, + 0x11, 0x3b, 0x92, 0x25, 0x39, 0x2c, 0x4b, 0x08, + 0x19, 0x76, 0x13, 0x8d, 0xf9, 0xda, 0xae, 0xdf, + 0x30, 0xda, 0xcc, 0xbb, 0x3f, 0xb9, 0xb0, 0xd6, + 0x5c, 0x78, 0x4b, 0x2b, 0x35, 0x51, 0x17, 0x48, + 0xf5, 0xd4, 0x39, 0x7e, 0x05, 0x83, 0x68, 0x86, + 0x44, 0x5f, 0x56, 0x1d, 0x2c, 0x53, 0xd3, 0x64, + 0x3a, 0xb2, 0x0c, 0x4a, 0x85, 0xd6, 0x5b, 0x7e, + 0xf9, 0xe9, 0x50, 0x29, 0x5d, 0x4f, 0xcc, 0xc9, +}; + +#ifdef CONFIG_MBEDTLS_HARDWARE_MPI +/* Pregenerated RSA 4096 size keys using openssl */ +static const char privkey_4096_buf[] = "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIJKAIBAAKCAgEA1blr9wfIzTylroJHxcoq+YFA765gF5vj9b6tfaPG0XQExSkjndHv5sra4ar7T+k2sBB4OcKKeGHkNk6wk8tGmOS79r2L74XZs1eB0UruG+huV7Sd+YiWzwN8y9jGImA9hIkf1qxIvkco5WTmT7cVwUnCQ7qiiVadD/LgyeGD04yKZpzv9UJzfjXz5ITTn/ejcn7423M9qz41nhRWwK4zw1jv7IB57d1dWOCbN3RO4dvfVndCz8DOmLzJrZAkLsz39vppbIwbMqTXKFxWqzZY2xrYmnMx9p3v4hLeju7ls3fsekESonoP0C76u50wJfZWO2XcIUo4pue/jHi2o9KouhLXW/vyasplXvE6FFrBjSpsm1Nar4KQMUolEkUbO9baGcQvH9G5WOH0kwPt7AOSqM2EUPvBd7Jv0tbMI/BRZVVltC/t6WhannCM/I6nZrlNe5tie/qYlFu474jp5/tpa8RykkDxwl9whejIqd4iQbvDiP/GXgBYtDJ9VU/S2KqHJhQFLDi+F3+ewOcF391fgt1e1J2vNYLKZOfxTOl/1vJbU/2IjRWTRQ7cXnmpR/GNCRfgH2as6Z/0oknBSVephguDnO5QlveP4Cx2EOVY/A/KgDpu8PumSrlIk+YQgLxdKsXaVI6eDY4rY7q2uCJH3yIAfZJXEeD+ResUuSZltvECAwEAAQKCAgBwR89+oipOGHR6b5tBP+q/1bXFtXhqLs3eBuSiQu5qj2cKJYi+mtJMD3paYDdTThQa/ywKPDf+8n6wQTrnCj32iQRupjnkBg/O9kQPLixVoRCHJy5vL+D6tLxVY3cEDEeFX3zIjQ5SWJQVn6KXcnoNZ7CVYHGPcV9mR5TsuntFImp7aituUBDY14NgJKABRFosBqS6tZpKYo5MlCbXZy1ujUTOnNhxrIAj9yvUQFhIs/hrNpB1ELf46gWSF03LAIesyvWjvx9yxcL7QzeNDyozQbFVwvsWsvaZcIxXzw4B8RjdSV5+2V2BY4z6D6SB7R50ahjxrEqC9PFe3PQmsL9OvFjV9idYwFOhxiWXGjIm3wwFFLOj3e0TShscj2Iw+Ghd3wApvSdBZxzdjap1NHC+Q6yYU+BnivxUHcopVPPM3rsLndyRC6zfrQw/OkOlAP3bNL1hRedPRmRDOz0V1ihEpgC1VfXx6XOu4eg8xWiJgWX+BGvT5GWjfQg2hB1Jm344r3l0eLhr25dO80GIac2QGT2+WmYkXcsQ3AiqAn2VF8UB5mU+Iyh96jmSFVVltGZgfp98yFYN63/7wB++lhVQmJZwbglutng1qjQBFslIULddIHiYvF+AVvkrO3Hc2zg8rT91tbE13k06A1zlNGcQuQKLax8e+2/BNjsZU2E4uQKCAQEA7L4obKWYRHgG6j1VEDRrQU8Vkm4L11B+ZD/rsEh3q7LbzViOPv+1dZ40jX2qYScWyaefI46bukJlk/mlNv4Dh3EnSFvHPCInDM3oImCYImwUx0hkbSRyRNwlwRwx81LJzIR84cCqpNWrXXcplomUSM62ea1E1vtNSZs9Bg2OLoWvFOTPgk/xDi6ezdb6JFiId6cARup/bmZ363mg8jCq0wpTLVdUGrezfMj4GpB1uQET5xqXleumQu/04cHPOfXwpV0ikIOId/ldY/PetiRd86B32aB2Xd4fHUpxHMY+63MFmL6SsqMQJMPubv+eIrOId4HhT+nXNFBZXolT5XG5NwKCAQEA5xvvccHNyCTL0AebxD6EihWnp0/Dd0DwXWxZw0Yhhc9xa/W/QtygB6kPb35oKGvCKdm4dWCIGln03dU5D6CMNkJlbkxpo8gybz34SJ/6OvU836rBLHZXE3Xiqbe5XkdMdarA7kTEhEUqekDXPxhws9dWh0YjtAnBPpm1GQppiykI2edkiIhRgju5ghe+/UjAjxrEgCKZeAODh46hwZHERRKQN2MFUOFcOVDq+2wTJem9r3h1uBQAiZn8PDyx0rlRkwH2dZSSauVW+I713N0JGucOV7FeMO0ebioqqckh0i91ZJNH//Io8Sp8WuBsU/vcP9jT+5BDkCbc71BRO/AFFwKCAQBj4a6oeA0QBhvUw9+ZoKQHv9f4GZnBU+KfZSCJFWn39NQrhMsu5S+n2gGOGJDDwHwqxB+uHsKxCMZWciM0WmMex6ytKJucUURscIsZxespyrPRiEdmjNPxHXiISt8AK9OcB+GwVVsphERygI35Rz5aoWv3VhUPJqNrBKXwYdO06Q3/ILIz5oprU1wIuER9BSU+ZiUFxnXRHEZIAN7Yj5Piyh5hqNCBHTQK17dlbcFdNokxHdUKmYth/l8wyFYnvA21lt+4XOY8x+aQ/xjde+ZvnSozlTGbVNWHxBqI61MsfzDDStQVrhpniIqWJh6PwXM4CIII9z2mgqfR7NqKmTptAoIBAQDTYQOigmZbFvyrayoXVi8XtTLAnv3jByxR5pY7OtvSbagJ3J1w5CYim4iYq39M6TKP4KkMApy5rWl/tFQabPeRcS0gsxc0TBmFEaMTme7fGgrxcFZ6+koubHZCUN5k0sWmIeWQiKlNaY2uf7vf49TBSMXFuGtTclCjlybCnnlmZMPJuhCDqFsUyNelm15+f5pPyWXM5NiFooEc7WIZj996Zb4uSo1EKruVWONzzqe814s9AOp60SCkuoiv97uVRxbLZNItPRSmXNktQmSx/CEl0AuYPYwvJ9HbZQncfTBH9ExlDyidernjyr4uyHGMZyJN614ICy0gncsZv9ZtAd1FAoIBAA4toGPU/VcKFmK92zgO05jsg5vJzw5xeoxRWKrLg7iby6Su6BuNgaVwfYWeZuOhnXakid7FvFXKH6x44o9gyFm5bKqFhaXDzAnxzqcLeM5V+gititOsstpZCbVOoKQOhgTHyxpFNVX3E/nB8EunydWyhQMxKme//NsRroFm1vWljQKyL3zER82AzyseEpEYZoB/6g0n5uF2lR7KllxeBlINsceQ8g3JkmJTdS1hoXcyUSsZ+EgrRbCykNB5aVC5G3/W1OSZsFHbbMrYHCMnaYKwMqLmOkb11o6nOrJJ4pgHj8CVcp2TNjfy3y0Ru6RZ42b0Q+3LktJBGu9r5d04FgI=\n" + "-----END RSA PRIVATE KEY-----"; + +static const char privkey_2048_buf[] = "-----BEGIN RSA PRIVATE KEY-----\r\n" + "MIIEowIBAAKCAQEA8N8hdkemvj6Tpk975/OWhv9BrTsCBCu+ZYfDb5VI7U2meKBg\r\n" + "3dAkyyhRlY3fNwSRzBUMCzsHjpgnsB40wxOgiwlB9n6PMhq0qUVKAdCpKwFztsKd\r\n" + "JJAsCUC+Zlwxn4RpH6ZnMl3a/njRYjuDyI32kucMP/lBRo7ks1798Gy/j+x1h5xA\r\n" + "vZSlFoEXKjCC6S1DWhALePuZnk4m/jGP6g+YfyJXSTqsenKa/DcWndfn/JoElZ0J\r\n" + "nhud8lBXwVe6mMheE1yqfL+VTU1nwg/TPNZrZsFz2sXig/RQCKt6LuSuzhRpsLp+\r\n" + "BdwqEs9xrwlhZnp7j4kQBomISd6kAxQfYVROHQIDAQABAoIBAHgtO4rB8QWWPyCJ\r\n" + "I670r7OnA2OkvzrJgHMzq2SuvPX4+gfRLMM+qDzcXugZIrdWhk+maJ3p07lnXNXY\r\n" + "HEcAMedstQaA2n0LKfwSX/xL2TtlvBABRVoKvI3ZSaXUdcW60KBD69ULUsoICZ/T\r\n" + "Rcr4WX+t20TH3bOQc7ayvEwKVgE95xIUpTH9asw8uOPvKxW2j5OLQgZuWrWyUDg0\r\n" + "MFh92PhWtw3i5zq6OpTTsFJeceKYV/VstIYjZ+FslmhjQxJbr+2DJRbpHXKceqy6\r\n" + "9yWlSV0EM7neFCHlDa2WPhK8we+6IvMiNVQKj46fHGYNBaW/ZSX7TiG5J0Uqj2e9\r\n" + "0MUGJ8ECgYEA+frJabhfzW5+JfGjTObeznJZE6fAOjFzaBIwFu8Kz2mIjYpQlwVK\r\n" + "EepMkv2KkrJuqS4GnI+Nkq7G0BAUyUj9tTJ3HQzvtJrxsnxVi99Yofx1s1P4YAnu\r\n" + "c8t3ElJoQ4BRoQIs/hIvyYn22IxllBHiGESrnPQ38D82xyXQgd6S8JkCgYEA9qww\r\n" + "j7jx6Xpy/D1Dq8Dvalm7pz3J+yHnti4w2cqZ67grUoyGnNPtciNDdfi4JzLiKkUu\r\n" + "SDS3DacvFpFyND0m8sbpMjnR8Rvhj+bfH8KcOAowD+YR/+6vSb/P/aBt6gYXcaBn\r\n" + "cjepx+sE81mnC7UrHb4TjG4hO5t3ZTc6X28gyCUCgYAMZn9lSisecrO5SCJUp0M4\r\n" + "NH3stq6XdGqIKBbQnG0J2u9WLh1PUIjbGKdRx1f/bPCGXe0gCRL5yse7/IA7d+51\r\n" + "9ZnpDAI8EE+bDgXkWWD5MB/alHjGstdsURSICSR47L2f4g6/T8GlGr3vAg/r53My\r\n" + "xv1IXOkFdu1NtbeBKbxaSQKBgENDmw5mAVmIcXiFAEICn4ahp4EoYT6g9T2BhQKu\r\n" + "s6BKnU2qUj7Lr5ETOp8dzqGpx3B9Yux/q3cGotmFmd3S2x8SzJ5MlAoqbyy9aRSR\r\n" + "DeZeKNL9CuV+YcA7lOz1ZWOOe7AZbHwB38NLPBNb3CheI769iTkfAuLtNvabw8go\r\n" + "VokdAoGBALyvBhW+Squ5tx8NOEgAisakhAVOnT6jcoeKy6FyjcvKaWagmCOCC7Gz\r\n" + "QB9Yf1tJ+3di+aLtWWdmU494iKJHBtPMhfrYltCpxHHQGlUc/GLPY3Z5bBYYYWpb\r\n" + "Wzw4ZvDraKlAs7a9CRwS5cpktk5ptK4rc5noSXkvV+yOT75zXat2\r\n" + "-----END RSA PRIVATE KEY-----\r\n"; + +static const char privkey_3072_buf[] = "-----BEGIN RSA PRIVATE KEY-----\r\n" + "MIIG4wIBAAKCAYEAoMPuYRnHVPP49qiPACIsYBLVuj8xH4XqAuXmurOyPPFfKSch\r\n" + "52dn97sXvfXQw6hj+iPBeMSzbSAompjx4mUHtwn2+EvyXjqUe8qtI0y12uzXgOr8\r\n" + "vdwNLJO1kTmUWxQIa/e6dZpiKcEYYZ6qWNUGVH9IiMB9HdIFLNIdCAAC+gsK+Q0w\r\n" + "OT2CwnGOoZ/PzOXHyfte9pJTDk6nQJDKVTBoOLgVcJoCLwctGf7VJ9YI9+YXJKvW\r\n" + "1ZYq8PXM8KAVE7KHN7KiskJxDLSR4xuplxdT//LIBJMRvxAEPYohe7QvejFjtQc6\r\n" + "WbEJxV/Y4vWHOb2PVGUHATNK2kQ7/N5HgEdxABgLrXQSkGfKKmWwoy/W5TVDS+qX\r\n" + "fR/7WeJa/2e2+ZZVSQtiXdrWSKdgEmVdmM43Aso5ppC2C5QBajHAw2MKMZwxLHbI\r\n" + "nhQJQMJdmRvXI8Kg/+WEgknxQLFWrRW4ss3wR+2KvZ0eynEuzHkQxtUAWB8xgNAH\r\n" + "Bch/tr+xq1g3DFNXAgMBAAECggGAFvaFiScWesLyb8D51AoNjpeCIb0+9gK5vzo5\r\n" + "b7eVIPFVJ1qolBYIGrGFnaOL8zaNOUB8NRTbkB3EzvhDrJPDu1hYB3VJpD330YrM\r\n" + "mjstypyD16049qGE3DYo/BpeX3gID+vtnTi1BsPHCMKSEGg1JEKeCLJ97JGAHbvR\r\n" + "W8AsrKyBH7vLhJGNqNpxhhJ+qwSzOd2G3e9en6+KYkWMMQjeCiP5JAFLiI4c2ha1\r\n" + "OaBv3YDnE1zcLdvqPErPwBsNh6e7QLYbEvQj5mZ84/kCbrwFy//+Bf7to0u6weOy\r\n" + "8E1HU8UKdJfWsKwh+5BGDnKs8qgVQWJdPJWy25PVgkzp0ZnSKzp2AddMCrI2YHRM\r\n" + "Q+G+9bET/D96y7/08EAobDdXCplcPeOVb8ETbQTNTrHJibUCB4fqkN8tR2ZZTQ1F\r\n" + "axhmHDThsVFqWk+629j8c6XOQbx2dvzb7YfLK06ShiBcD0V6E7VFXHzR+x/xA9ir\r\n" + "zUcgLt9zvzj9puxlkhtzBZKcF3nBAoHBANCtY4NDnFoO+QUS59iz9hsoPAe8+S+U\r\n" + "PkvMSN7iziUkiXbXjQsr0v/PLHCuuXRyARBORaI4moLxzbTA1l1C+gBulI29j9zH\r\n" + "GwNnl587u5VCpbzuzr5YwHtp85Y1la2/ti+x0Qaw5uoa8G2TqoU4V6SG0qwinQl2\r\n" + "9mdNZzVmIBMbE0tTTTzc+CRIPBl9lRQR3Ff3o6eUs6uPE6g1lGZR1ydb2MLBM/wV\r\n" + "NgUUf7L5h/s8abrRjS+dnPmtxNgrRZQe9wKBwQDFOQyBzD3xkBgTSFQkU8OgNZyW\r\n" + "gNYglE1vLA+wv49NVAErHfKzYf/yw3fkYLDo9JfTJ3KckU6J815VnPXJFNMvjr2J\r\n" + "ExXG2JSbZHeUBRgExLU0iFlhQaxbAhuJ6PDrkGy+1ZtsJxYCPpifyNwjkZ0QKQlf\r\n" + "n3SwTMXIp0wd80FXVSwKPSuWUlrhByBcJDVwdCIeD8Oi9DrmVe0E9fXDboY2HARb\r\n" + "cgrN3n9jnEF/asIsfaHg8EI2z/EVC+C1mHuZdqECgcA5d4ZwH65vHrB1NT+j7etY\r\n" + "jzv45ZG6CJkfRqLKvqsGj4lLsRCmgusYh3U1kuh/qOWiF+wVQIFMjkqX/IMMK+Wt\r\n" + "OMawQgPcSPind1/J+ikucawy25ET2l0nn4X1V8xgjOsfN1jY/t6YmdKcWo4bIekA\r\n" + "5iAeR2n3sUsqJ6bEjdtHZ61okQg0OqYbV8k1O+BSJpkHoKrw+4J/PGetaxPzGZam\r\n" + "wCRxfcNTKIQ34e1I3G8WQQzc5dh7xGv2VmRfI4uFvwECgcEAuNGAVfZ3KfNVjGRg\r\n" + "bXaNwYncBvIPN5KiigbpYUHyYY3SVnyHHvE8cFwa80plHrlvubGi5vQIfKAzC9m+\r\n" + "PsSkL1H9bgITizcU9BYPNQgc/QL1qJgJ4mkvwk1UT0Wa17WNIrx8HLr4Ffxg/IO3\r\n" + "QCHJ5QX/wbtlF32qbyHP49U8q0GmtqWiPglJHs2V1qMb7Rj3i+JL/F4RAB8PsXFo\r\n" + "8M6XOQfCUYuqckgKaudYPbZm5liJJYkhE8qD6qwp1SNi2GphAoHABjUL8DTHgBWn\r\n" + "sr9/XQyornm0sruHcwr7SmGqIJ/hZUUYd4UfDW76e8SjvhRQ7nkpR3f4+LEBCqaJ\r\n" + "LDJDhg+6AColwKaWRWV9M1GXHhVD4vaTM46JAvH9wbhmJDUORHq8viyHlwO9QKpK\r\n" + "iHE/MtcYb5QBGP5md5wc8LY1lcQazDsJMLlcYNk6ZICNWWrcc2loG4VeOERpHU02\r\n" + "6AsKaaMGqBp/T9wYwFPUzk1i+jWCu66xfCYKvEubNdxT/R5juXrd\r\n" + "-----END RSA PRIVATE KEY-----\r\n"; + +#endif + +_Static_assert(sizeof(pki_rsa2048_output) == 2048/8, "rsa2048 output is wrong size"); +_Static_assert(sizeof(pki_rsa3072_output) == 3072/8, "rsa3072 output is wrong size"); +_Static_assert(sizeof(pki_rsa4096_output) == 4096/8, "rsa4096 output is wrong size"); + +void mbedtls_mpi_printf(const char *name, const mbedtls_mpi *X); + + +static void test_cert(const char *cert, const uint8_t *expected_output, size_t output_len); + +TEST_CASE("mbedtls RSA4096 cert", "[mbedtls]") +{ + + test_cert(rsa4096_cert, pki_rsa4096_output, 4096/8); +} + +TEST_CASE("mbedtls RSA3072 cert", "[mbedtls]") +{ + + test_cert(rsa3072_cert, pki_rsa3072_output, 3072/8); +} + +TEST_CASE("mbedtls RSA2048 cert", "[mbedtls]") +{ + test_cert(rsa2048_cert, pki_rsa2048_output, 2048/8); +} + +static void test_cert(const char *cert, const uint8_t *expected_output, size_t output_len) +{ + mbedtls_x509_crt crt; + mbedtls_rsa_context *rsa; + char buf[output_len]; + int res; + + bzero(buf, output_len); + + mbedtls_x509_crt_init(&crt); + + TEST_ASSERT_EQUAL_HEX16_MESSAGE(0, + -mbedtls_x509_crt_parse(&crt, + (const uint8_t *)cert, + strlen(cert)+1), + "parse cert"); + + rsa = mbedtls_pk_rsa(crt.pk); + TEST_ASSERT_NOT_NULL(rsa); + + res = mbedtls_rsa_check_pubkey(rsa); + TEST_ASSERT_EQUAL_HEX16_MESSAGE(0, + -res, + "check cert pubkey"); + + mbedtls_x509_crt_info(buf, sizeof(buf), "", &crt); + puts(buf); + + res = mbedtls_rsa_public(rsa, pki_input, (uint8_t *)buf); + if (res == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE + MBEDTLS_ERR_RSA_PUBLIC_FAILED) { + mbedtls_x509_crt_free(&crt); + TEST_IGNORE_MESSAGE("Hardware does not support this key length"); + } + + TEST_ASSERT_EQUAL_HEX16_MESSAGE(0, + -res, + "RSA PK operation"); + + /* + // Dump buffer for debugging + for(int i = 0; i < output_len; i++) { + printf("0x%02x, ", buf[i]); + } + printf("\n"); + */ + + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_output, buf, output_len); + + mbedtls_x509_crt_free(&crt); +} + +#ifdef CONFIG_MBEDTLS_HARDWARE_MPI +static void rsa_key_operations(int keysize, bool check_performance, bool generate_new_rsa); + +static int myrand(void *rng_state, unsigned char *output, size_t len) +{ + size_t olen; + return mbedtls_hardware_poll(rng_state, output, len, &olen); +} + +#ifdef PRINT_DEBUG_INFO +static void print_rsa_details(mbedtls_rsa_context *rsa) +{ + mbedtls_mpi X[5]; + for (int i=0; i<5; ++i) { + mbedtls_mpi_init( &X[i] ); + } + + if (0 == mbedtls_rsa_export(rsa, &X[0], &X[1], &X[2], &X[3], &X[4])) { + for (int i=0; i<5; ++i) { + mbedtls_mpi_printf((char*)"N\0P\0Q\0D\0E" + 2*i, &X[i]); + mbedtls_mpi_free( &X[i] ); + } + } +} +#endif + +#if CONFIG_FREERTOS_SMP // IDF-5260 +TEST_CASE("test performance RSA key operations", "[bignum][timeout=60]") +#else +TEST_CASE("test performance RSA key operations", "[bignum]") +#endif +{ + /** NOTE: + * For ESP32-S3, CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG is enabled + * by default; allocating a lock of 92 bytes, which is never freed. + * + * MR !18574 adds the MPI crypto lock for S3 increasing the leakage by + * 92 bytes. This caused the RSA UT to fail with a leakage more than + * 1024 bytes. + * + * The allocations made by ESP32-S2 (944 bytes) and ESP32-S3 are the same, + * except for the JTAG lock (92 + 944 > 1024). + */ + TEST_ESP_OK(test_utils_set_leak_level(1088, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL)); + for (int keysize = 2048; keysize <= SOC_RSA_MAX_BIT_LEN; keysize += 1024) { + rsa_key_operations(keysize, true, false); + } +} + +#if CONFIG_FREERTOS_SMP // IDF-5260 +TEST_CASE("test RSA-3072 calculations", "[bignum][timeout=60]") +#else +TEST_CASE("test RSA-3072 calculations", "[bignum]") +#endif +{ + // use pre-genrated keys to make the test run a bit faster + rsa_key_operations(3072, false, false); +} + +#if CONFIG_FREERTOS_SMP // IDF-5260 +TEST_CASE("test RSA-2048 calculations", "[bignum][timeout=60]") +#else +TEST_CASE("test RSA-2048 calculations", "[bignum]") +#endif +{ + // use pre-genrated keys to make the test run a bit faster + rsa_key_operations(2048, false, false); +} + +#if CONFIG_FREERTOS_SMP // IDF-5260 +TEST_CASE("test RSA-4096 calculations", "[bignum][timeout=60]") +#else +TEST_CASE("test RSA-4096 calculations", "[bignum]") +#endif +{ + // use pre-genrated keys to make the test run a bit faster + rsa_key_operations(4096, false, false); +} + + +static void rsa_key_operations(int keysize, bool check_performance, bool generate_new_rsa) +{ + mbedtls_pk_context clientkey; + mbedtls_rsa_context rsa; + unsigned char orig_buf[4096 / 8]; + unsigned char encrypted_buf[4096 / 8]; + unsigned char decrypted_buf[4096 / 8]; + int res = 0; + + printf("First, orig_buf is encrypted by the public key, and then decrypted by the private key\n"); + printf("keysize=%d check_performance=%d generate_new_rsa=%d\n", keysize, check_performance, generate_new_rsa); + + memset(orig_buf, 0xAA, sizeof(orig_buf)); + orig_buf[0] = 0; // Ensure that orig_buf is smaller than rsa.N + if (generate_new_rsa) { + mbedtls_rsa_init(&rsa); + TEST_ASSERT_EQUAL(0, mbedtls_rsa_gen_key(&rsa, myrand, NULL, keysize, 65537)); + } else { + mbedtls_pk_init(&clientkey); + + switch(keysize) { + case 4096: + res = mbedtls_pk_parse_key(&clientkey, (const uint8_t *)privkey_4096_buf, sizeof(privkey_4096_buf), NULL, 0, myrand, NULL); + break; + case 3072: + res = mbedtls_pk_parse_key(&clientkey, (const uint8_t *)privkey_3072_buf, sizeof(privkey_3072_buf), NULL, 0, myrand, NULL); + break; + case 2048: + res = mbedtls_pk_parse_key(&clientkey, (const uint8_t *)privkey_2048_buf, sizeof(privkey_2048_buf), NULL, 0, myrand, NULL); + break; + default: + TEST_FAIL_MESSAGE("unsupported keysize, pass generate_new_rsa=true or update test"); + } + + TEST_ASSERT_EQUAL_HEX16(0, -res); + + memcpy(&rsa, mbedtls_pk_rsa(clientkey), sizeof(mbedtls_rsa_context)); + } + +#ifdef PRINT_DEBUG_INFO + print_rsa_details(&rsa); +#endif + + TEST_ASSERT_EQUAL(keysize, (int)rsa.MBEDTLS_PRIVATE(len) * 8); + TEST_ASSERT_EQUAL(keysize, (int)rsa.MBEDTLS_PRIVATE(D).MBEDTLS_PRIVATE(n) * sizeof(mbedtls_mpi_uint) * 8); // The private exponent + +#ifdef SOC_CCOMP_TIMER_SUPPORTED + int public_perf, private_perf; + ccomp_timer_start(); + res = mbedtls_rsa_public(&rsa, orig_buf, encrypted_buf); + public_perf = ccomp_timer_stop(); + + if (res == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE + MBEDTLS_ERR_RSA_PUBLIC_FAILED) { + mbedtls_rsa_free(&rsa); + TEST_IGNORE_MESSAGE("Hardware does not support this key length"); + } + TEST_ASSERT_EQUAL_HEX16(0, -res); + + ccomp_timer_start(); + res = mbedtls_rsa_private(&rsa, myrand, NULL, encrypted_buf, decrypted_buf); + private_perf = ccomp_timer_stop(); + TEST_ASSERT_EQUAL_HEX16(0, -res); + + if (check_performance && keysize == 2048) { + TEST_PERFORMANCE_CCOMP_LESS_THAN(RSA_2048KEY_PUBLIC_OP, "%d us", public_perf); + TEST_PERFORMANCE_CCOMP_LESS_THAN(RSA_2048KEY_PRIVATE_OP, "%d us", private_perf); + } else if (check_performance && keysize == 4096) { + TEST_PERFORMANCE_CCOMP_LESS_THAN(RSA_4096KEY_PUBLIC_OP, "%d us", public_perf); + TEST_PERFORMANCE_CCOMP_LESS_THAN(RSA_4096KEY_PRIVATE_OP, "%d us", private_perf); + } +#else + res = mbedtls_rsa_public(&rsa, orig_buf, encrypted_buf); + TEST_ASSERT_EQUAL_HEX16(0, -res); + res = mbedtls_rsa_private(&rsa, myrand, NULL, encrypted_buf, decrypted_buf); + TEST_ASSERT_EQUAL_HEX16(0, -res); + TEST_IGNORE_MESSAGE("Performance check skipped! (soc doesn't support ccomp timer)"); +#endif + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(orig_buf, decrypted_buf, keysize / 8, "RSA operation"); + + mbedtls_rsa_free(&rsa); +} + + +TEST_CASE("mbedtls RSA Generate Key", "[mbedtls][timeout=60]") +{ + + mbedtls_rsa_context ctx; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + + const unsigned int key_size = 2048; + const int exponent = 65537; + +#if CONFIG_MBEDTLS_MPI_USE_INTERRUPT && CONFIG_ESP_TASK_WDT_EN && !CONFIG_ESP_TASK_WDT_INIT + /* Check that generating keys doesnt starve the watchdog if interrupt-based driver is used */ + esp_task_wdt_config_t twdt_config = { + .timeout_ms = 1000, + .idle_core_mask = (1 << 0), // Watch core 0 idle + .trigger_panic = true, + }; + TEST_ASSERT_EQUAL(ESP_OK, esp_task_wdt_init(&twdt_config)); +#endif // CONFIG_MBEDTLS_MPI_USE_INTERRUPT && CONFIG_ESP_TASK_WDT_EN && !CONFIG_ESP_TASK_WDT_INIT + + mbedtls_rsa_init(&ctx); + mbedtls_ctr_drbg_init(&ctr_drbg); + + mbedtls_entropy_init(&entropy); + TEST_ASSERT_FALSE( mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0) ); + + TEST_ASSERT_FALSE( mbedtls_rsa_gen_key(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg, key_size, exponent) ); + + mbedtls_rsa_free(&ctx); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + +#if CONFIG_MBEDTLS_MPI_USE_INTERRUPT && CONFIG_ESP_TASK_WDT_EN && !CONFIG_ESP_TASK_WDT_INIT + TEST_ASSERT_EQUAL(ESP_OK, esp_task_wdt_deinit()); +#endif // CONFIG_MBEDTLS_MPI_USE_INTERRUPT && CONFIG_ESP_TASK_WDT_EN && !CONFIG_ESP_TASK_WDT_INIT + +} + +#endif // CONFIG_MBEDTLS_HARDWARE_MPI diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_sha.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_sha.c new file mode 100644 index 000000000..5a314514b --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_sha.c @@ -0,0 +1,145 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include "esp_types.h" +#include "esp_log.h" +#include "ccomp_timer.h" +#include "esp_heap_caps.h" +#include "idf_performance.h" +#include "esp_private/esp_clk.h" +#include "spi_flash_mmap.h" + +#include "soc/soc_caps.h" + +#include "unity.h" +#include "test_utils.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" + +#if SOC_SHA_SUPPORT_SHA512 +#include "mbedtls/sha512.h" +#endif + +#include "sha/sha_parallel_engine.h" + +/* Note: Most of the SHA functions are called as part of mbedTLS, so +are tested as part of mbedTLS tests. Only esp_sha() is different. +*/ + +#define TAG "sha_test" + +#if SOC_SHA_SUPPORTED +TEST_CASE("Test esp_sha()", "[hw_crypto]") +{ + const size_t BUFFER_SZ = 32 * 1024 + 6; // NB: not an exact multiple of SHA block size + + int64_t elapsed; + uint32_t us_sha1; + uint8_t sha1_result[20] = { 0 }; + +#if SOC_SHA_SUPPORT_SHA512 + uint32_t us_sha512; + uint8_t sha512_result[64] = { 0 }; +#endif + + void *buffer = heap_caps_malloc(BUFFER_SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(buffer); + memset(buffer, 0xEE, BUFFER_SZ); + + const uint8_t sha1_expected[20] = { 0xc7, 0xbb, 0xd3, 0x74, 0xf2, 0xf6, 0x20, 0x86, + 0x61, 0xf4, 0x50, 0xd5, 0xf5, 0x18, 0x44, 0xcc, + 0x7a, 0xb7, 0xa5, 0x4a }; +#if SOC_SHA_SUPPORT_SHA512 + const uint8_t sha512_expected[64] = { 0xc7, 0x7f, 0xda, 0x8c, 0xb3, 0x58, 0x14, 0x8a, + 0x52, 0x3b, 0x46, 0x04, 0xc0, 0x85, 0xc5, 0xf0, + 0x46, 0x64, 0x14, 0xd5, 0x96, 0x7a, 0xa2, 0x80, + 0x20, 0x9c, 0x04, 0x27, 0x7d, 0x3b, 0xf9, 0x1f, + 0xb2, 0xa3, 0x45, 0x3c, 0xa1, 0x6a, 0x8d, 0xdd, + 0x35, 0x5e, 0x35, 0x57, 0x76, 0x22, 0x74, 0xd8, + 0x1e, 0x07, 0xc6, 0xa2, 0x9e, 0x3b, 0x65, 0x75, + 0x80, 0x7d, 0xe6, 0x6e, 0x47, 0x61, 0x2c, 0x94 }; +#endif + + ccomp_timer_start(); + esp_sha(SHA1, buffer, BUFFER_SZ, sha1_result); + elapsed = ccomp_timer_stop(); + TEST_ASSERT_EQUAL_HEX8_ARRAY(sha1_expected, sha1_result, sizeof(sha1_expected)); + us_sha1 = elapsed; + ESP_LOGI(TAG, "esp_sha() 32KB SHA1 in %" PRIu32 " us", us_sha1); + +#if SOC_SHA_SUPPORT_SHA512 + ccomp_timer_start(); + esp_sha(SHA2_512, buffer, BUFFER_SZ, sha512_result); + elapsed = ccomp_timer_stop(); + TEST_ASSERT_EQUAL_HEX8_ARRAY(sha512_expected, sha512_result, sizeof(sha512_expected)); + + us_sha512 = elapsed; + ESP_LOGI(TAG, "esp_sha() 32KB SHA512 in %" PRIu32 " us", us_sha512); +#endif + + free(buffer); + + TEST_PERFORMANCE_CCOMP_LESS_THAN(TIME_SHA1_32KB, "%" PRId32 " us", us_sha1); + +#if SOC_SHA_SUPPORT_SHA512 + TEST_PERFORMANCE_CCOMP_LESS_THAN(TIME_SHA512_32KB, "%" PRId32 " us", us_sha512); +#endif +} + +TEST_CASE("Test esp_sha() function with long input", "[hw_crypto]") +{ + const void* ptr; + spi_flash_mmap_handle_t handle; + uint8_t sha1_espsha[20] = { 0 }; + uint8_t sha1_mbedtls[20] = { 0 }; + uint8_t sha256_espsha[32] = { 0 }; + uint8_t sha256_mbedtls[32] = { 0 }; + +#if SOC_SHA_SUPPORT_SHA512 + uint8_t sha512_espsha[64] = { 0 }; + uint8_t sha512_mbedtls[64] = { 0 }; +#endif + + const size_t LEN = 1024 * 1024; + + /* mmap() 1MB of flash, we don't care what it is really */ + esp_err_t err = spi_flash_mmap(0x0, LEN, SPI_FLASH_MMAP_DATA, &ptr, &handle); + + TEST_ASSERT_EQUAL_HEX32(ESP_OK, err); + TEST_ASSERT_NOT_NULL(ptr); + + /* Compare esp_sha() result to the mbedTLS result, should always be the same */ + + esp_sha(SHA1, ptr, LEN, sha1_espsha); + int r = mbedtls_sha1(ptr, LEN, sha1_mbedtls); + TEST_ASSERT_EQUAL(0, r); + + esp_sha(SHA2_256, ptr, LEN, sha256_espsha); + r = mbedtls_sha256(ptr, LEN, sha256_mbedtls, 0); + TEST_ASSERT_EQUAL(0, r); + +#if SOC_SHA_SUPPORT_SHA512 + esp_sha(SHA2_512, ptr, LEN, sha512_espsha); + r = mbedtls_sha512(ptr, LEN, sha512_mbedtls, 0); + TEST_ASSERT_EQUAL(0, r); +#endif + + /* munmap() 1MB of flash when the usge of memory-mapped ptr is over */ + spi_flash_munmap(handle); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha1_espsha, sha1_mbedtls, sizeof(sha1_espsha), "SHA1 results should match"); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_espsha, sha256_mbedtls, sizeof(sha256_espsha), "SHA256 results should match"); + +#if SOC_SHA_SUPPORT_SHA512 + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_espsha, sha512_mbedtls, sizeof(sha512_espsha), "SHA512 results should match"); +#endif +} + +#endif // SOC_SHA_SUPPORTED diff --git a/components/mbedtls/mbedtls_v3/test_apps/main/test_sha_perf.c b/components/mbedtls/mbedtls_v3/test_apps/main/test_sha_perf.c new file mode 100644 index 000000000..41101e712 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/main/test_sha_perf.c @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * mbedTLS SHA performance test + */ +#include +#include +#include +#include "mbedtls/sha256.h" +#include "unity.h" +#include "sdkconfig.h" +#include "esp_heap_caps.h" +#include "test_utils.h" +#include "ccomp_timer.h" +#include "test_mbedtls_utils.h" + +TEST_CASE("mbedtls SHA performance", "[aes]") +{ + const unsigned CALLS = 256; + const unsigned CALL_SZ = 16 * 1024; + mbedtls_sha256_context sha256_ctx; + float elapsed_usec; + unsigned char sha256[32]; + + // allocate internal memory + uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(buf); + memset(buf, 0x55, CALL_SZ); + + mbedtls_sha256_init(&sha256_ctx); + ccomp_timer_start(); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(&sha256_ctx, false)); + for (int c = 0; c < CALLS; c++) { + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&sha256_ctx, buf, CALL_SZ)); + } + TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&sha256_ctx, sha256)); + elapsed_usec = ccomp_timer_stop(); + + free(buf); + mbedtls_sha256_free(&sha256_ctx); + + /* Check the result. Reference value can be calculated using: + * dd if=/dev/zero bs=$((16*1024)) count=256 | tr '\000' '\125' | sha256sum + */ + const char *expected_hash = "c88df2638fb9699abaad05780fa5e0fdb6058f477069040eac8bed3231286275"; + char hash_str[sizeof(sha256) * 2 + 1]; + utils_bin2hex(hash_str, sizeof(hash_str), sha256, sizeof(sha256)); + + TEST_ASSERT_EQUAL_STRING(expected_hash, hash_str); + + // bytes/usec = MB/sec + float mb_sec = (CALL_SZ * CALLS) / elapsed_usec; + printf("SHA256 rate %.3fMB/sec\n", mb_sec); +#ifdef CONFIG_MBEDTLS_HARDWARE_SHA + // Don't put a hard limit on software SHA performance + TEST_PERFORMANCE_CCOMP_GREATER_THAN(SHA256_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec); +#endif +} diff --git a/components/mbedtls/mbedtls_v3/test_apps/pytest_mbedtls_ut.py b/components/mbedtls/mbedtls_v3/test_apps/pytest_mbedtls_ut.py new file mode 100644 index 000000000..1445e9a5a --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/pytest_mbedtls_ut.py @@ -0,0 +1,89 @@ +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import pytest +from pytest_embedded import Dut + + +@pytest.mark.supported_targets +@pytest.mark.generic +def test_mbedtls(dut: Dut) -> None: + dut.run_all_single_board_cases() + + +@pytest.mark.esp32 +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'perf_esp32', + ], + indirect=True, +) +def test_mbedtls_esp32_compiler_perf_opt(dut: Dut) -> None: + dut.run_all_single_board_cases() + + +@pytest.mark.esp32 +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.esp32c3 +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'aes_no_hw', + ], + indirect=True, +) +def test_mbedtls_aes_no_hw(dut: Dut) -> None: + dut.run_all_single_board_cases() + + +@pytest.mark.esp32 +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'psram', + ], + indirect=True, +) +def test_mbedtls_psram(dut: Dut) -> None: + dut.run_all_single_board_cases() + + +@pytest.mark.esp32 +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'psram_esp32', + 'psram_all_ext', + ], + indirect=True, +) +def test_mbedtls_psram_esp32(dut: Dut) -> None: + dut.run_all_single_board_cases() + + +@pytest.mark.esp32h2 +@pytest.mark.ecdsa_efuse +@pytest.mark.parametrize('config', ['ecdsa_sign',], indirect=True) +def test_mbedtls_ecdsa_sign(dut: Dut) -> None: + dut.run_all_single_board_cases(group='efuse_key') + + +@pytest.mark.esp32c2 +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'rom_impl', + ], + indirect=True, +) +def test_mbedtls_rom_impl_esp32c2(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.aes_no_hw b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.aes_no_hw new file mode 100644 index 000000000..aadb89a89 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.aes_no_hw @@ -0,0 +1,2 @@ +CONFIG_MBEDTLS_HARDWARE_AES=n +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=n diff --git a/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.default b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.default new file mode 100644 index 000000000..e69de29bb diff --git a/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.ecdsa_sign b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.ecdsa_sign new file mode 100644 index 000000000..be59d96a4 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.ecdsa_sign @@ -0,0 +1,2 @@ +CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY=y +CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN=y diff --git a/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.perf_esp32 b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.perf_esp32 new file mode 100644 index 000000000..3c5a0fabe --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.perf_esp32 @@ -0,0 +1 @@ +CONFIG_COMPILER_OPTIMIZATION_PERF=y diff --git a/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.psram b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.psram new file mode 100644 index 000000000..e09896976 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.psram @@ -0,0 +1,2 @@ +CONFIG_SPIRAM=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=800 diff --git a/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.psram_all_ext b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.psram_all_ext new file mode 100644 index 000000000..ad3452cf7 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.psram_all_ext @@ -0,0 +1,4 @@ +CONFIG_SPIRAM=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=800 +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0 diff --git a/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.psram_esp32 b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.psram_esp32 new file mode 100644 index 000000000..5acbcfd7f --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.psram_esp32 @@ -0,0 +1,3 @@ +CONFIG_SPIRAM=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=800 +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y diff --git a/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.rom_impl b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.rom_impl new file mode 100644 index 000000000..4f79484e4 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.ci.rom_impl @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32c2" +CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL=y diff --git a/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults new file mode 100644 index 000000000..35ba075f2 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults @@ -0,0 +1,10 @@ +# General options for additional checks +CONFIG_HEAP_POISONING_COMPREHENSIVE=y +CONFIG_COMPILER_WARN_WRITE_STRINGS=y +CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y +CONFIG_COMPILER_STACK_CHECK_MODE_STRONG=y +CONFIG_COMPILER_STACK_CHECK=y + +CONFIG_ESP_TASK_WDT_EN=y +CONFIG_ESP_TASK_WDT_INIT=n diff --git a/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults.esp32 b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults.esp32 new file mode 100644 index 000000000..66cbe6577 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults.esp32 @@ -0,0 +1,4 @@ +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_XTAL_FREQ_AUTO=y +CONFIG_SPI_FLASH_SHARE_SPI1_BUS=y +CONFIG_COMPILER_OPTIMIZATION_SIZE=y diff --git a/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults.esp32c2 b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults.esp32c2 new file mode 100644 index 000000000..bb33cff20 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults.esp32c2 @@ -0,0 +1,2 @@ +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y diff --git a/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults.esp32c3 b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults.esp32c3 new file mode 100644 index 000000000..d0ea27a6c --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults.esp32c3 @@ -0,0 +1 @@ +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n diff --git a/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults.esp32s2 b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults.esp32s2 new file mode 100644 index 000000000..da22be442 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults.esp32s2 @@ -0,0 +1,2 @@ +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n diff --git a/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults.esp32s3 b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults.esp32s3 new file mode 100644 index 000000000..da22be442 --- /dev/null +++ b/components/mbedtls/mbedtls_v3/test_apps/sdkconfig.defaults.esp32s3 @@ -0,0 +1,2 @@ +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n diff --git a/components/nvs_flash/CMakeLists.txt b/components/nvs_flash/CMakeLists.txt index b36e6ba52..7ce2871c1 100644 --- a/components/nvs_flash/CMakeLists.txt +++ b/components/nvs_flash/CMakeLists.txt @@ -1,6 +1,51 @@ -set(COMPONENT_SRCDIRS "src") -set(COMPONENT_ADD_INCLUDEDIRS "include") +idf_build_get_property(target IDF_TARGET) -set(COMPONENT_PRIV_REQUIRES "spi_flash") +set(srcs "src/nvs_api.cpp" + "src/nvs_cxx_api.cpp" + "src/nvs_item_hash_list.cpp" + "src/nvs_page.cpp" + "src/nvs_pagemanager.cpp" + "src/nvs_storage.cpp" + "src/nvs_handle_simple.cpp" + "src/nvs_handle_locked.cpp" + "src/nvs_partition.cpp" + "src/nvs_partition_lookup.cpp" + "src/nvs_partition_manager.cpp" + "src/nvs_types.cpp") -register_component() +set(public_req spi_flash) + +set(include_dirs "include") + +idf_component_register(SRCS "${srcs}" + REQUIRES "${public_req}" + INCLUDE_DIRS "${include_dirs}") + +# If we use the linux target, we need to redirect the crc functions to the linux +if(${target} STREQUAL "linux") + if(CONFIG_NVS_ENCRYPTION) + # mbedtls isn't configured for building with linux or as mock target. It will draw in all kind of dependencies + message(FATAL_ERROR "NVS currently doesn't support encryption if built for Linux.") + endif() + idf_component_get_property(spi_flash_dir spi_flash COMPONENT_DIR) + target_include_directories(${COMPONENT_LIB} PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/mock/int" + "${spi_flash_dir}/sim/stubs/freertos/include") + target_sources(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/mock/int/crc.cpp") + target_compile_options(${COMPONENT_LIB} PUBLIC "-DLINUX_TARGET") +else() + # TODO: this is a workaround until IDF-2085 is fixed + idf_component_get_property(mbedtls_lib mbedtls COMPONENT_LIB) + target_link_libraries(${COMPONENT_LIB} PUBLIC ${mbedtls_lib}) +endif() + +if(CONFIG_NVS_ENCRYPTION) + target_sources(${COMPONENT_LIB} PRIVATE "src/nvs_encrypted_partition.cpp") + idf_component_get_property(mbedtls_lib mbedtls COMPONENT_LIB) + target_link_libraries(${COMPONENT_LIB} PUBLIC ${mbedtls_lib}) +endif() + +if(${target} STREQUAL "linux") + target_compile_options(${COMPONENT_LIB} PUBLIC --coverage) + target_link_libraries(${COMPONENT_LIB} PUBLIC --coverage) +endif() diff --git a/components/nvs_flash/README.rst b/components/nvs_flash/README.rst deleted file mode 100644 index f04ac592c..000000000 --- a/components/nvs_flash/README.rst +++ /dev/null @@ -1,234 +0,0 @@ -Non-volatile storage library -============================ - -Introduction ------------- - -Non-volatile storage (NVS) library is designed to store key-value pairs in flash. This sections introduces some concepts used by NVS. - -Underlying storage -^^^^^^^^^^^^^^^^^^ - -Currently NVS uses a portion of main flash memory through ``spi_flash_{read|write|erase}`` APIs. The library uses the all the partitions with ``data`` type and ``nvs`` subtype. The application can choose to use the partition with label ``nvs`` through ``nvs_open`` API or any of the other partition by specifying its name through ``nvs_open_from_part`` API. - -Future versions of this library may add other storage backends to keep data in another flash chip (SPI or I2C), RTC, FRAM, etc. - -.. note:: if an NVS partition is truncated (for example, when the partition table layout is changed), its contents should be erased. ESP-IDF build system provides a ``make erase_flash`` target to erase all contents of the flash chip. - -.. note:: NVS works best for storing many small values, rather than a few large values of type 'string' and 'blob'. If storing large blobs or strings is required, consider using the facilities provided by the FAT filesystem on top of the wear levelling library. - -Keys and values -^^^^^^^^^^^^^^^ - -NVS operates on key-value pairs. Keys are ASCII strings, maximum key length is currently 15 characters. Values can have one of the following types: - -- integer types: ``uint8_t``, ``int8_t``, ``uint16_t``, ``int16_t``, ``uint32_t``, ``int32_t``, ``uint64_t``, ``int64_t`` -- zero-terminated string -- variable length binary data (blob) - -.. note:: - String and blob values are currently limited to 1984 bytes. For strings, this includes the null terminator. - -Additional types, such as ``float`` and ``double`` may be added later. - -Keys are required to be unique. Writing a value for a key which already exists behaves as follows: - -- if the new value is of the same type as old one, value is updated -- if the new value has different data type, an error is returned - -Data type check is also performed when reading a value. An error is returned if data type of read operation doesn’t match the data type of the value. - -Namespaces -^^^^^^^^^^ - -To mitigate potential conflicts in key names between different components, NVS assigns each key-value pair to one of namespaces. Namespace names follow the same rules as key names, i.e. 15 character maximum length. Namespace name is specified in the ``nvs_open`` or ``nvs_open_from_part`` call. This call returns an opaque handle, which is used in subsequent calls to ``nvs_read_*``, ``nvs_write_*``, and ``nvs_commit`` functions. This way, handle is associated with a namespace, and key names will not collide with same names in other namespaces. -Please note that the namespaces with same name in different NVS partitions are considered as separate namespaces. - -Security, tampering, and robustness -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -NVS library doesn't implement tamper prevention measures. It is possible for anyone with physical access to the flash chip to alter, erase, or add key-value pairs. - -NVS is compatible with the ESP32 flash encryption system, and it can store key-value pairs in an encrypted form. Some metadata, like page state and write/erase flags of individual entries can not be encrypted as they are represented as bits of flash memory for efficient access and manipulation. Flash encryption can prevent some forms of modification: - -- replacing keys or values with arbitrary data -- changing data types of values - -The following forms of modification are still possible when flash encryption is used: - -- erasing a page completely, removing all key-value pairs which were stored in that page -- corrupting data in a page, which will cause the page to be erased automatically when such condition is detected -- rolling back the contents of flash memory to an earlier snapshot -- merging two snapshots of flash memory, rolling back some key-value pairs to an earlier state (although this is possible to mitigate with the current design — TODO) - -The library does try to recover from conditions when flash memory is in an inconsistent state. In particular, one should be able to power off the device at any point and time and then power it back on. This should not result in loss of data, expect for the new key-value pair if it was being written at the moment of power off. The library should also be able to initialize properly with any random data present in flash memory. - -Internals ---------- - -Log of key-value pairs -^^^^^^^^^^^^^^^^^^^^^^ - -NVS stores key-value pairs sequentially, with new key-value pairs being added at the end. When a value of any given key has to be updated, new key-value pair is added at the end of the log and old key-value pair is marked as erased. - -Pages and entries -^^^^^^^^^^^^^^^^^ - -NVS library uses two main entities in its operation: pages and entries. Page is a logical structure which stores a portion of the overall log. Logical page corresponds to one physical sector of flash memory. Pages which are in use have a *sequence number* associated with them. Sequence numbers impose an ordering on pages. Higher sequence numbers correspond to pages which were created later. Each page can be in one of the following states: - -Empty/uninitialized - Flash storage for the page is empty (all bytes are ``0xff``). Page isn't used to store any data at this point and doesn’t have a sequence number. - -Active - Flash storage is initialized, page header has been written to flash, page has a valid sequence number. Page has some empty entries and data can be written there. At most one page can be in this state at any given moment. - -Full - Flash storage is in a consistent state and is filled with key-value pairs. - Writing new key-value pairs into this page is not possible. It is still possible to mark some key-value pairs as erased. - -Erasing - Non-erased key-value pairs are being moved into another page so that the current page can be erased. This is a transient state, i.e. page should never stay in this state when any API call returns. In case of a sudden power off, move-and-erase process will be completed upon next power on. - -Corrupted - Page header contains invalid data, and further parsing of page data was canceled. Any items previously written into this page will not be accessible. Corresponding flash sector will not be erased immediately, and will be kept along with sectors in *uninitialized* state for later use. This may be useful for debugging. - -Mapping from flash sectors to logical pages doesn't have any particular order. Library will inspect sequence numbers of pages found in each flash sector and organize pages in a list based on these numbers. - -:: - - +--------+ +--------+ +--------+ +--------+ - | Page 1 | | Page 2 | | Page 3 | | Page 4 | - | Full +---> | Full +---> | Active | | Empty | <- states - | #11 | | #12 | | #14 | | | <- sequence numbers - +---+----+ +----+---+ +----+---+ +---+----+ - | | | | - | | | | - | | | | - +---v------+ +-----v----+ +------v---+ +------v---+ - | Sector 3 | | Sector 0 | | Sector 2 | | Sector 1 | <- physical sectors - +----------+ +----------+ +----------+ +----------+ - -Structure of a page -^^^^^^^^^^^^^^^^^^^ - -For now we assume that flash sector size is 4096 bytes and that ESP32 flash encryption hardware operates on 32-byte blocks. It is possible to introduce some settings configurable at compile-time (e.g. via menuconfig) to accommodate flash chips with different sector sizes (although it is not clear if other components in the system, e.g. SPI flash driver and SPI flash cache can support these other sizes). - -Page consists of three parts: header, entry state bitmap, and entries themselves. To be compatible with ESP32 flash encryption, entry size is 32 bytes. For integer types, entry holds one key-value pair. For strings and blobs, an entry holds part of key-value pair (more on that in the entry structure description). - -The following diagram illustrates page structure. Numbers in parentheses indicate size of each part in bytes. :: - - +-----------+--------------+-------------+-----------+ - | State (4) | Seq. no. (4) | Unused (20) | CRC32 (4) | Header (32) - +-----------+--------------+-------------+-----------+ - | Entry state bitmap (32) | - +----------------------------------------------------+ - | Entry 0 (32) | - +----------------------------------------------------+ - | Entry 1 (32) | - +----------------------------------------------------+ - / / - / / - +----------------------------------------------------+ - | Entry 125 (32) | - +----------------------------------------------------+ - -Page header and entry state bitmap are always written to flash unencrypted. Entries are encrypted if flash encryption feature of the ESP32 is used. - -Page state values are defined in such a way that changing state is possible by writing 0 into some of the bits. Therefore it not necessary to erase the page to change page state, unless that is a change to *erased* state. - -CRC32 value in header is calculated over the part which doesn't include state value (bytes 4 to 28). Unused part is currently filled with ``0xff`` bytes. Future versions of the library may store format version there. - -The following sections describe structure of entry state bitmap and entry itself. - -Entry and entry state bitmap -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Each entry can be in one of the following three states. Each state is represented with two bits in the entry state bitmap. Final four bits in the bitmap (256 - 2 * 126) are unused. - -Empty (2'b11) - Nothing is written into the specific entry yet. It is in an uninitialized state (all bytes ``0xff``). - -Written (2'b10) - A key-value pair (or part of key-value pair which spans multiple entries) has been written into the entry. - -Erased (2'b00) - A key-value pair in this entry has been discarded. Contents of this entry will not be parsed anymore. - - -Structure of entry -^^^^^^^^^^^^^^^^^^ - -For values of primitive types (currently integers from 1 to 8 bytes long), entry holds one key-value pair. For string and blob types, entry holds part of the whole key-value pair. In case when a key-value pair spans multiple entries, all entries are stored in the same page. - -:: - - +--------+----------+----------+---------+-----------+---------------+----------+ - | NS (1) | Type (1) | Span (1) | Rsv (1) | CRC32 (4) | Key (16) | Data (8) | - +--------+----------+----------+---------+-----------+---------------+----------+ - - +--------------------------------+ - +-> Fixed length: | Data (8) | - | +--------------------------------+ - Data format ---+ - | +----------+---------+-----------+ - +-> Variable length: | Size (2) | Rsv (2) | CRC32 (4) | - +----------+---------+-----------+ - - -Individual fields in entry structure have the following meanings: - -NS - Namespace index for this entry. See section on namespaces implementation for explanation of this value. - -Type - One byte indicating data type of value. See ``ItemType`` enumeration in ``nvs_types.h`` for possible values. - -Span - Number of entries used by this key-value pair. For integer types, this is equal to 1. For strings and blobs this depends on value length. - -Rsv - Unused field, should be ``0xff``. - -CRC32 - Checksum calculated over all the bytes in this entry, except for the CRC32 field itself. - -Key - Zero-terminated ASCII string containing key name. Maximum string length is 15 bytes, excluding zero terminator. - -Data - For integer types, this field contains the value itself. If the value itself is shorter than 8 bytes it is padded to the right, with unused bytes filled with ``0xff``. For string and blob values, these 8 bytes hold additional data about the value, described next: - -Size - (Only for strings and blobs.) Size, in bytes, of actual data. For strings, this includes zero terminator. - -CRC32 - (Only for strings and blobs.) Checksum calculated over all bytes of data. - -Variable length values (strings and blobs) are written into subsequent entries, 32 bytes per entry. `Span` field of the first entry indicates how many entries are used. - - -Namespaces -^^^^^^^^^^ - -As mentioned above, each key-value pair belongs to one of the namespaces. Namespaces identifiers (strings) are stored as keys of key-value pairs in namespace with index 0. Values corresponding to these keys are indexes of these namespaces. - -:: - - +-------------------------------------------+ - | NS=0 Type=uint8_t Key="wifi" Value=1 | Entry describing namespace "wifi" - +-------------------------------------------+ - | NS=1 Type=uint32_t Key="channel" Value=6 | Key "channel" in namespace "wifi" - +-------------------------------------------+ - | NS=0 Type=uint8_t Key="pwm" Value=2 | Entry describing namespace "pwm" - +-------------------------------------------+ - | NS=2 Type=uint16_t Key="channel" Value=20 | Key "channel" in namespace "pwm" - +-------------------------------------------+ - - -Item hash list -^^^^^^^^^^^^^^ - -To reduce the number of reads performed from flash memory, each member of Page class maintains a list of pairs: (item index; item hash). This list makes searches much quicker. Instead of iterating over all entries, reading them from flash one at a time, ``Page::findItem`` first performs search for item hash in the hash list. This gives the item index within the page, if such an item exists. Due to a hash collision it is possible that a different item will be found. This is handled by falling back to iteration over items in flash. - -Each node in hash list contains a 24-bit hash and 8-bit item index. Hash is calculated based on item namespace and key name. CRC32 is used for calculation, result is truncated to 24 bits. To reduce overhead of storing 32-bit entries in a linked list, list is implemented as a doubly-linked list of arrays. Each array holds 29 entries, for the total size of 128 bytes, together with linked list pointers and 32-bit count field. Minimal amount of extra RAM useage per page is therefore 128 bytes, maximum is 640 bytes. - diff --git a/components/nvs_flash/component.mk b/components/nvs_flash/component.mk index 20b0ec407..8b2fda4f5 100755 --- a/components/nvs_flash/component.mk +++ b/components/nvs_flash/component.mk @@ -6,4 +6,6 @@ COMPONENT_ADD_INCLUDEDIRS := include COMPONENT_SRCDIRS := src -CPPFLAGS += -DNVS_CRC_HEADER_FILE=\"rom/crc.h\" +ifndef CONFIG_NVS_ENCRYPTION +COMPONENT_OBJEXCLUDE := src/nvs_encr.o +endif diff --git a/components/nvs_flash/host_test/fixtures/test_fixtures.hpp b/components/nvs_flash/host_test/fixtures/test_fixtures.hpp new file mode 100644 index 000000000..b0915682f --- /dev/null +++ b/components/nvs_flash/host_test/fixtures/test_fixtures.hpp @@ -0,0 +1,436 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "nvs_partition.hpp" +#include "nvs.h" +#include "nvs_page.hpp" +#include "nvs_storage.hpp" +#include +#include + +#ifdef CONFIG_NVS_ENCRYPTION +#include "nvs_encrypted_partition.hpp" +#endif + +extern "C" { +#include "Mockesp_partition.h" +} + +struct FixtureException : std::exception { + FixtureException(const std::string& msg) : msg(msg) { } + + const char *what() { + return msg.c_str(); + } + + std::string msg; +}; + +class PartitionMock : public nvs::Partition { +public: + PartitionMock(uint32_t address, uint32_t size) + : partition(), address(address), size(size) + { + assert(size); + } + + const char *get_partition_name() override + { + return ""; + } + + esp_err_t read_raw(size_t src_offset, void* dst, size_t size) override + { + return esp_partition_read_raw(&partition, src_offset, dst, size); + } + + esp_err_t read(size_t src_offset, void* dst, size_t size) override + { + return esp_partition_read(&partition, src_offset, dst, size); + } + + esp_err_t write_raw(size_t dst_offset, const void* src, size_t size) override + { + return esp_partition_write_raw(&partition, dst_offset, src, size); + } + + esp_err_t write(size_t dst_offset, const void* src, size_t size) override + { + return esp_partition_write(&partition, dst_offset, src, size); + } + + esp_err_t erase_range(size_t dst_offset, size_t size) override + { + return esp_partition_erase_range(&partition, dst_offset, size); + } + + uint32_t get_address() override + { + return address; + } + + uint32_t get_size() override + { + return size; + } + + const esp_partition_t partition; + +private: + uint32_t address; + + uint32_t size; +}; + +#ifdef CONFIG_NVS_ENCRYPTION +struct EncryptedPartitionFixture { + EncryptedPartitionFixture(nvs_sec_cfg_t *cfg, + uint32_t start_sector = 0, + uint32_t sector_size = 1, + const char *partition_name = NVS_DEFAULT_PART_NAME) + : esp_partition(), emu(start_sector + sector_size), + part(partition_name, &esp_partition) { + esp_partition.address = start_sector * SPI_FLASH_SEC_SIZE; + esp_partition.size = sector_size * SPI_FLASH_SEC_SIZE; + assert(part.init(cfg) == ESP_OK); + } + + ~EncryptedPartitionFixture() { } + + esp_partition_t esp_partition; + + SpiFlashEmulator emu; + + nvs::NVSEncryptedPartition part; +}; +#endif + +struct PartitionMockFixture { + PartitionMockFixture(uint32_t start_sector = 0, + uint32_t sector_size = 1, + const char *partition_name = NVS_DEFAULT_PART_NAME) + : part_mock(start_sector * SPI_FLASH_SEC_SIZE, sector_size * SPI_FLASH_SEC_SIZE) { + std::fill_n(raw_header, sizeof(raw_header)/sizeof(raw_header[0]), UINT8_MAX); + + // This resets the mocks and prevents meeting accidental expectations from previous tests. + Mockesp_partition_Init(); + } + + ~PartitionMockFixture() { } + + uint8_t raw_header[512]; + + PartitionMock part_mock; +}; + +struct NVSPageFixture : public PartitionMockFixture { + NVSPageFixture(uint32_t start_sector = 0, + uint32_t sector_size = 1, + const char *partition_name = NVS_DEFAULT_PART_NAME) + : PartitionMockFixture(start_sector, sector_size, partition_name), page() + { + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 32); + + for (int i = 0; i < 8; i++) { + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 512); + } + + if (page.load(&part_mock, start_sector) != ESP_OK) throw FixtureException("couldn't setup page"); + } + + nvs::Page page; +}; + +struct NVSValidPageFlashFixture : public PartitionMockFixture { + const static uint8_t NS_INDEX = 1; + + // valid header + uint8_t raw_header_valid [32]; + + // entry table with one entry + uint8_t raw_entry_table [32]; + + uint8_t ns_entry [32]; + + uint8_t value_entry [32]; + + NVSValidPageFlashFixture(uint32_t start_sector = 0, + uint32_t sector_size = 1, + const char *partition_name = NVS_DEFAULT_PART_NAME) + : PartitionMockFixture(start_sector, sector_size, partition_name), + raw_header_valid {0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x16, 0xdd, 0xdc}, + ns_entry {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + value_entry {0x01, 0x01, 0x01, 0xff, 0x3d, 0xf3, 0x99, 0xe5, 't', 'e', 's', 't', '_', 'v', 'a', 'l', + 'u', 'e', '\0', '\0', '\0', '\0', '\0', '\0', 47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + { + std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0); + raw_entry_table[0] = 0xfa; + + // read page header + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_valid, 32); + + // read entry table + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_entry_table, 32); + + // read next free entry's header + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 4); + + // read namespace entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32); + + // read normal entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(value_entry, 32); + + // read normal entry second time during duplicated entry check + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(value_entry, 32); + } +}; + +struct NVSValidPageFixture : public NVSValidPageFlashFixture { + NVSValidPageFixture(uint32_t start_sector = 0, + uint32_t sector_size = 1, + const char *partition_name = NVS_DEFAULT_PART_NAME) + : NVSValidPageFlashFixture(start_sector, sector_size, partition_name), page() + { + if (page.load(&part_mock, start_sector) != ESP_OK) throw FixtureException("couldn't setup page"); + } + + nvs::Page page; +}; + +struct NVSValidStorageFixture : public PartitionMockFixture { + const static uint8_t NS_INDEX = 1; + + uint8_t ns_entry [32]; + + uint8_t empty_entry [32]; + + NVSValidStorageFixture(uint32_t start_sector = 0, + uint32_t sector_size = 3, + const char *partition_name = NVS_DEFAULT_PART_NAME) + : PartitionMockFixture(start_sector, sector_size, partition_name), + ns_entry {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + empty_entry(), + storage(&part_mock) + { + std::fill_n(empty_entry, sizeof(empty_entry)/sizeof(empty_entry[0]), 0xFF); + + // entry table with one entry + uint8_t raw_entry_table [32]; + + uint8_t header_full_page [] = { + 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x16, 0xdd, 0xdc}; + + uint8_t header_second_page [] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + uint8_t header_third_page [] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + // entry_table with all elements deleted except the namespace entry written and the last entry free + std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0); + raw_entry_table[0] = 0x02; + raw_entry_table[31] = 0xFC; + + // read full page header + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(header_full_page, 32); + + // read entry table + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_entry_table, 32); + + // reading entry table checks empty entry + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(empty_entry, 32); + + // read namespace entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32); + + // read last two pages' headers, which trigger an automatic full read each because each page is empty + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(header_second_page, 32); + for (int i = 0; i < 8; i++) { + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 512); + } + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(header_third_page, 32); + for (int i = 0; i < 8; i++) { + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 512); + } + + // read namespace entry in duplicated header item check of pagemanager::load + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32); + + // storage finally actually reads namespace + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32); + + // storage looks for blob index entries + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32); + + // Storage::eraseOrphanDataBlobs() also wants to take it's turn... + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32); + + if (storage.init(start_sector, sector_size) != ESP_OK) throw FixtureException("couldn't setup page"); + } + + nvs::Storage storage; +}; + +struct NVSValidBlobPageFixture : public PartitionMockFixture { + const static uint8_t NS_INDEX = 1; + const static size_t BLOB_DATA_SIZE = 32; + + // valid header + uint8_t raw_header_valid [32]; + + // entry table with one entry + uint8_t raw_entry_table [32]; + + uint8_t ns_entry [32]; + + uint8_t blob_entry [32]; + uint8_t blob_data [BLOB_DATA_SIZE]; + uint8_t blob_index [32]; + + NVSValidBlobPageFixture(uint32_t start_sector = 0, + uint32_t sector_size = 1, + const char *partition_name = NVS_DEFAULT_PART_NAME) + : PartitionMockFixture(start_sector, sector_size, partition_name), + raw_header_valid {0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x16, 0xdd, 0xdc}, + ns_entry {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + blob_entry {0x01, 0x42, 0x02, 0x00, 0xaa, 0xf3, 0x23, 0x87, 't', 'e', 's', 't', '_', 'b', 'l', 'o', + 'b', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 0x20, 0x00, 0xff, 0xff, 0xc6, 0x96, 0x86, 0xd9}, + blob_data {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef}, + blob_index {0x01, 0x48, 0x01, 0xff, 0x42, 0x6b, 0xdf, 0x66, 't', 'e', 's', 't', '_', 'b', 'l', 'o', + 'b', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff, 0xff}, + page() + { + std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0xFF); + raw_entry_table[0] = 0xaa; + + // read page header + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_valid, 32); + + // read entry table + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_entry_table, 32); + + // read next free entry's header + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 4); + + // read namespace entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32); + + // read normal blob entry + index, not the data + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(blob_entry, 32); + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(blob_index, 32); + + // read normal entry second time during duplicated entry check + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(blob_entry, 32); + + if (page.load(&part_mock, start_sector) != ESP_OK) throw FixtureException("couldn't setup page"); + } + + nvs::Page page; +}; + +struct NVSFullPageFixture : public PartitionMockFixture { + const static uint8_t NS_INDEX = 1; + + // valid header + uint8_t raw_header_valid [32]; + + // entry table with one entry + uint8_t raw_entry_table [32]; + + uint8_t ns_entry [32]; + + uint8_t value_entry [32]; + + NVSFullPageFixture(uint32_t start_sector = 0, + uint32_t sector_size = 1, + const char *partition_name = NVS_DEFAULT_PART_NAME, + bool load = true) + : PartitionMockFixture(start_sector, sector_size, partition_name), + raw_header_valid {0xfc, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa3, 0x48, 0x9f, 0x38}, + ns_entry {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + value_entry {0x01, 0x01, 0x01, 0xff, 0x3d, 0xf3, 0x99, 0xe5, 't', 'e', 's', 't', '_', 'v', 'a', 'l', + 'u', 'e', '\0', '\0', '\0', '\0', '\0', '\0', 47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + page() + { + // entry_table with all elements deleted except the namespace entry written and the last entry free + std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0); + raw_entry_table[0] = 0x0a; + raw_entry_table[31] = 0xFC; + + // read page header + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_valid, 32); + + // read entry table + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_entry_table, 32); + + // no next free entry check, only one entry written + + // read namespace entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32); + + // read normal entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(value_entry, 32); + + // no duplicated entry check + + if (load) { + if (page.load(&part_mock, start_sector) != ESP_OK) throw FixtureException("couldn't setup page"); + } + } + + nvs::Page page; +}; diff --git a/components/nvs_flash/host_test/nvs_page_test/CMakeLists.txt b/components/nvs_flash/host_test/nvs_page_test/CMakeLists.txt new file mode 100644 index 000000000..cafc7c699 --- /dev/null +++ b/components/nvs_flash/host_test/nvs_page_test/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(COMPONENTS main) +idf_build_set_property(CONFIG_SPI_FLASH_MOCK 1) +idf_build_set_property(COMPILE_DEFINITIONS "-DNO_DEBUG_STORAGE" APPEND) +project(host_nvs_page_test) + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/build/coverage.info" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build" + COMMAND lcov --capture --directory . --output-file coverage.info + COMMENT "Create coverage report" + ) + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/build/coverage_report/" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/build/coverage.info" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build" + COMMAND genhtml coverage.info --output-directory coverage_report/ + COMMENT "Turn coverage report into html-based visualization" + ) + +add_custom_target(coverage + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build" + DEPENDS "coverage_report/" + ) diff --git a/components/nvs_flash/host_test/nvs_page_test/README.rst b/components/nvs_flash/host_test/nvs_page_test/README.rst new file mode 100644 index 000000000..c005b3f48 --- /dev/null +++ b/components/nvs_flash/host_test/nvs_page_test/README.rst @@ -0,0 +1,23 @@ +NVS Page Test for Host +====================== + +Build +----- + +First, make sure that the target is set to linux. +Run ``idf.py --preview set-target linux`` to be sure. +Then do a normal IDF build: ``idf.py build``. + +Run +--- + +IDF monitor doesn't work yet for Linux. +You have to run the app manually: ``./build/host_nvs_page_test.elf``. + +Coverage +--- + +To generate the coverage, run: ``idf.py coverage``. +Afterwards, you can view the coverage by opening ``build/coverage_report/index.html`` with your browser. +Note that you need to run the application at least once before generating the coverage information. +If you run it multiple times, the coverage information adds up. diff --git a/components/nvs_flash/host_test/nvs_page_test/main/CMakeLists.txt b/components/nvs_flash/host_test/nvs_page_test/main/CMakeLists.txt new file mode 100644 index 000000000..d2af1b6a6 --- /dev/null +++ b/components/nvs_flash/host_test/nvs_page_test/main/CMakeLists.txt @@ -0,0 +1,10 @@ +idf_component_register(SRCS "nvs_page_test.cpp" + INCLUDE_DIRS + "." + "${CMAKE_CURRENT_SOURCE_DIR}/../../fixtures" + "${CMAKE_CURRENT_SOURCE_DIR}/../../../test_nvs_host" + "${CMAKE_CURRENT_SOURCE_DIR}/../../../src" + REQUIRES cmock nvs_flash spi_flash) + +target_compile_options(${COMPONENT_LIB} PUBLIC --coverage) +target_link_libraries(${COMPONENT_LIB} --coverage) diff --git a/components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp b/components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp new file mode 100644 index 000000000..e5ca9ed08 --- /dev/null +++ b/components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp @@ -0,0 +1,1000 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include "unity.h" +#include "test_fixtures.hpp" + +extern "C" { +#include "Mockesp_partition.h" +} + +using namespace std; +using namespace nvs; + +void test_Page_load_reading_header_fails() +{ + PartitionMock mock(0, 4096); + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_ERR_INVALID_ARG); + Page page; + + TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state()); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, page.load(&mock, 0)); + + Mockesp_partition_Verify(); +} + +void test_Page_load_reading_data_fails() +{ + uint8_t header[64]; + std::fill_n(header, sizeof(header)/sizeof(header[0]), UINT8_MAX); + PartitionMock mock(0, 4096); + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(header, 32); + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_FAIL); + Page page; + + TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state()); + TEST_ASSERT_EQUAL(ESP_FAIL, page.load(&mock, 0)); + + Mockesp_partition_Verify(); +} + +void test_Page_load__uninitialized_page_has_0xfe() +{ + PartitionMockFixture fix; + Page page; + + fix.raw_header[511] = 0xfe; + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 32); + + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 512); + + // Page::load() should return ESP_OK, but state has to be corrupt + TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0)); + + TEST_ASSERT_EQUAL(Page::PageState::CORRUPT, page.state()); + + Mockesp_partition_Verify(); +} + +void test_Page_load__initialized_corrupt_header() +{ + PartitionMockFixture fix; + Page page; + + uint8_t raw_header_corrupt [] = {0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x16, 0xdd, 0xdc}; + + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_corrupt, 32); + + // Page::load() should return ESP_OK, but state has to be corrupt + TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0)); + + TEST_ASSERT_EQUAL(Page::PageState::CORRUPT, page.state()); + + Mockesp_partition_Verify(); +} + +void test_Page_load__corrupt_entry_table() +{ + PartitionMockFixture fix; + + // valid header + uint8_t raw_header_valid [32] = {0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x16, 0xdd, 0xdc}; + + // entry table with one entry + uint8_t raw_entry_table [32]; + + uint8_t ns_entry [32] = {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + uint8_t raw_header[4] = {0xff, 0xff, 0xff, 0xff}; + std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0); + raw_entry_table[0] = 0xfa; + + // read page header + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_valid, 32); + + // read entry table + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_entry_table, 32); + + // read next free entry's header + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 4); + + // read namespace entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32); + + // we expect a raw word write from the partition in order to change the entry bits to erased (0) + esp_partition_write_raw_ExpectAndReturn(&fix.part_mock.partition, 32, nullptr, 4, ESP_OK); + esp_partition_write_raw_IgnoreArg_src(); + + // corrupt entry table as well as crc of corresponding item + raw_entry_table[0] = 0xf6; + + Page page; + + // Page::load() should return ESP_OK, but state has to be corrupt + TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0)); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, page.state()); + TEST_ASSERT_EQUAL(1, page.getUsedEntryCount()); + + Mockesp_partition_Verify(); +} + +void test_Page_load_success() +{ + PartitionMockFixture fix; + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 32); + for (int i = 0; i < 8; i++) { + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 512); + } + Page page; + + TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state()); + TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0)); + TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, page.state()); +} + +void test_Page_load_full_page() +{ + NVSFullPageFixture fix(0, 1, NVS_DEFAULT_PART_NAME, false); + + TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state()); + TEST_ASSERT_EQUAL(ESP_OK, fix.page.load(&fix.part_mock, 0)); + TEST_ASSERT_EQUAL(Page::PageState::FULL, fix.page.state()); +} +void test_Page_load__seq_number_0() +{ + NVSValidPageFixture fix; + + uint32_t seq_num; + fix.page.getSeqNumber(seq_num); + TEST_ASSERT_EQUAL(0, seq_num); +} + +void test_Page_erase__write_fail() +{ + NVSValidPageFixture fix; + + esp_partition_erase_range_ExpectAndReturn(&fix.part_mock.partition, 0, 4096, ESP_FAIL); + + TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.erase()); + TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state()); +} + +void test_Page_erase__success() +{ + NVSValidPageFixture fix; + + esp_partition_erase_range_ExpectAndReturn(&fix.part_mock.partition, 0, 4096, ESP_OK); + + TEST_ASSERT_EQUAL(ESP_OK, fix.page.erase()); + TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state()); +} + +void test_Page_write__initialize_write_failure() +{ + PartitionMockFixture fix; + uint8_t write_data = 47; + + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 32); + for (int i = 0; i < 8; i++) { + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 512); + } + esp_partition_write_raw_ExpectAnyArgsAndReturn(ESP_FAIL); + + Page page; + + TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0)); + TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, page.state()); + + TEST_ASSERT_EQUAL(ESP_FAIL, page.writeItem(1, nvs::ItemType::U8, "test", &write_data, sizeof(write_data))); + TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state()); +} + +void test_Page_write__write_data_fails() +{ + NVSPageFixture fix; + uint8_t write_data = 47; + esp_partition_write_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_write_ExpectAnyArgsAndReturn(ESP_FAIL); + + TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state()); + + TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.writeItem(1, nvs::ItemType::U8, "test", &write_data, sizeof(write_data))); + + TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state()); +} + +void test_page_write__write_correct_entry_state() +{ + NVSPageFixture fix; + uint8_t write_data = 47; + uint8_t raw_result [4]; + std::fill_n(raw_result, sizeof(raw_result)/sizeof(raw_result[0]), UINT8_MAX); + // mark first entry as written + raw_result[0] = 0xfe; + + // initialize page + esp_partition_write_raw_ExpectAnyArgsAndReturn(ESP_OK); + + // write entry + esp_partition_write_ExpectAnyArgsAndReturn(ESP_OK); + + // write entry state + esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_OK); + + TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state()); + + TEST_ASSERT_EQUAL(ESP_OK, fix.page.writeItem(1, nvs::ItemType::U8, "test_key", &write_data, sizeof(write_data))); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); +} + +void test_Page_write__write_correct_data() +{ + NVSPageFixture fix; + uint8_t write_data = 47; + uint8_t raw_result [32] = {0x01, 0x01, 0x01, 0xff, 0x98, 0x6f, 0x21, 0xfd, 't', 'e', 's', 't', '_', 'k', 'e', 'y', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + // initialize page + esp_partition_write_raw_ExpectAnyArgsAndReturn(ESP_OK); + + // write entry + esp_partition_write_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 64, raw_result, 32, 32, ESP_OK); + + // write entry state + esp_partition_write_raw_ExpectAnyArgsAndReturn(ESP_OK); + + TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state()); + + TEST_ASSERT_EQUAL(ESP_OK, fix.page.writeItem(1, nvs::ItemType::U8, "test_key", &write_data, sizeof(write_data))); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); +} + +void test_Page_readItem__read_entry_fails() +{ + NVSValidPageFixture fix; + + TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); + + uint8_t read_value = 0; + + esp_partition_read_ExpectAnyArgsAndReturn(ESP_FAIL); + + TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.readItem(NVSValidPageFixture::NS_INDEX, "test_value", read_value)); + + TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state()); + + TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount()); +} + +void test_Page_readItem__read_corrupted_entry() +{ + NVSValidPageFixture fix; + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); + TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount()); + + uint8_t read_value = 0; + + // corrupting entry + fix.value_entry[0] = 0x0; + + // first read the entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32); + + // Page::eraseEntryAndSpan() reads entry again + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32); + + // erasing entry by setting bit in entry table (0xfa -> 0xf2) + uint8_t raw_result [4] = {0xf2, 0x00, 0x00, 0x00}; + esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_OK); + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, fix.page.readItem(NVSValidPageFixture::NS_INDEX, "test_value", read_value)); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); + + TEST_ASSERT_EQUAL(1, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(123, fix.page.getErasedEntryCount()); +} + +void test_Page_readItem__read_corrupted_second_read_fail() +{ + NVSValidPageFixture fix; + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); + TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount()); + + uint8_t read_value = 0; + + // corrupting entry + fix.value_entry[0] = 0x0; + + // first read the entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32); + + // Page::eraseEntryAndSpan() reads entry again + esp_partition_read_ExpectAnyArgsAndReturn(ESP_FAIL); + + TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.readItem(NVSValidPageFixture::NS_INDEX, "test_value", read_value)); + + TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state()); +} + +void test_Page_readItem__read_corrupted_erase_fail() +{ + NVSValidPageFixture fix; + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); + TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount()); + + uint8_t read_value = 0; + + // corrupting entry + fix.value_entry[0] = 0x0; + + // first read the entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32); + + // Page::eraseEntryAndSpan() reads entry again + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32); + + // erasing entry by setting bit in entry table (0xfa -> 0xf2) + uint8_t raw_result [4] = {0xf2, 0x00, 0x00, 0x00}; + esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_FAIL); + + TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.readItem(NVSValidPageFixture::NS_INDEX, "test_value", read_value)); + + TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state()); +} + +void test_Page_readItem__read_entry_suceeds() +{ + NVSValidPageFixture fix; + TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); + + uint8_t read_value = 0; + + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32); + + TEST_ASSERT_EQUAL(ESP_OK, fix.page.readItem(NVSValidPageFixture::NS_INDEX, "test_value", read_value)); + + TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(47, read_value); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); +} + +void test_Page_readItem__blob_read_data_fails() +{ + NVSValidBlobPageFixture fix; + TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); + + uint8_t chunk_start = 0; + uint8_t read_data [32]; + + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32); + esp_partition_read_ExpectAnyArgsAndReturn(ESP_FAIL); + + TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.readItem(NVSValidPageFixture::NS_INDEX, + ItemType::BLOB_DATA, + "test_blob", + read_data, + 32, + chunk_start)); + + TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); +} + +void test_Page_readItem__corrupt_data_erase_failure() +{ + NVSValidBlobPageFixture fix; + TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); + + uint8_t chunk_start = 0; + uint8_t read_data [32]; + + fix.blob_data[16] = 0xdf; + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32); + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE); + + // Page::eraseEntryAndSpan() reads entry again + esp_partition_read_ExpectAnyArgsAndReturn(ESP_FAIL); + esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE); + + TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.readItem(NVSValidPageFixture::NS_INDEX, + ItemType::BLOB_DATA, + "test_blob", + read_data, + 32, + chunk_start)); + + TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); +} + +void test_Page_readItem__blob_corrupt_data() +{ + NVSValidBlobPageFixture fix; + TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); + + uint8_t chunk_start = 0; + uint8_t read_data [32]; + + fix.blob_data[16] = 0xdf; + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32); + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE); + + // Page::eraseEntryAndSpan() reads entry again + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE); + + // erasing entry by setting bit in entry table (0xfa -> 0xf2) + uint8_t raw_result [4] = {0xa2, 0xff, 0xff, 0xff}; + esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_OK); + + esp_partition_erase_range_ExpectAndReturn(&fix.part_mock.partition, 96, 64, ESP_OK); + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, fix.page.readItem(NVSValidPageFixture::NS_INDEX, + ItemType::BLOB_DATA, + "test_blob", + read_data, + 32, + chunk_start)); + + TEST_ASSERT_EQUAL(3, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(1, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); +} + +void test_Page_readItem__blob_read_entry_suceeds() +{ + NVSValidBlobPageFixture fix; + TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); + + uint8_t chunk_start = 0; + uint8_t read_data [32]; + + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32); + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE); + + TEST_ASSERT_EQUAL(ESP_OK, fix.page.readItem(NVSValidPageFixture::NS_INDEX, + ItemType::BLOB_DATA, + "test_blob", + read_data, + 32, + chunk_start)); + + TEST_ASSERT_EQUAL_MEMORY(fix.blob_data, read_data, fix.BLOB_DATA_SIZE); + + // make sure nothing was erased, i.e. checksums matched + TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); +} + +void test_Page_cmp__uninitialized() +{ + Page page; + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_INVALID_STATE, page.cmpItem(uint8_t(1) , "test", 47)); +} + +void test_Page_cmp__item_not_found() +{ + NVSValidPageFixture fix; + + // no expectations here since comparison uses the item hash list + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, fix.page.cmpItem(uint8_t(1), "different", 47)); +} + +void test_Page_cmp__item_type_mismatch() +{ + NVSValidPageFixture fix; + + // read normal entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32); + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_TYPE_MISMATCH, fix.page.cmpItem(uint8_t(1), "test_value", int(47))); +} + +void test_Page_cmp__item_content_mismatch() +{ + NVSValidPageFixture fix; + + // read normal entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32); + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_CONTENT_DIFFERS, fix.page.cmpItem(uint8_t(1), "test_value", uint8_t(46))); +} + +void test_Page_cmp__item_content_match() +{ + NVSValidPageFixture fix; + + // read normal entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32); + + TEST_ASSERT_EQUAL(ESP_OK, fix.page.cmpItem(NVSValidPageFixture::NS_INDEX, "test_value", uint8_t(47))); +} + +void test_Page_cmpItem__blob_data_mismatch() +{ + NVSValidBlobPageFixture fix; + + // read blob entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32); + + // read blob data + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE); + + + uint8_t blob_data_different [] = + {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xee}; + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_CONTENT_DIFFERS, + fix.page.cmpItem(uint8_t(1), + ItemType::BLOB_DATA, + "test_blob", + blob_data_different, + 32)); +} + +void test_Page_cmpItem__blob_data_match() +{ + NVSValidBlobPageFixture fix; + + // read blob entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32); + + // read blob data + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE); + + + uint8_t blob_data_same [] = + {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef}; + + TEST_ASSERT_EQUAL(ESP_OK, + fix.page.cmpItem(NVSValidPageFixture::NS_INDEX, + ItemType::BLOB_DATA, + "test_blob", + blob_data_same, + 32)); +} + +void test_Page_eraseItem__uninitialized() +{ + Page page; + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, page.eraseItem(NVSValidPageFixture::NS_INDEX, "test_value")); +} + +void test_Page_eraseItem__key_not_found() +{ + NVSValidPageFixture fix; + TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, fix.page.eraseItem(NVSValidPageFixture::NS_INDEX, "different")); + + TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); +} + +void test_Page_eraseItem__write_fail() +{ + NVSValidPageFixture fix; + TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); + + // first read the entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32); + + // Page::eraseEntryAndSpan() reads entry again + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32); + + // erasing entry by setting bit in entry table (0xfa -> 0xf2) + uint8_t raw_result [4] = {0xf2, 0x00, 0x00, 0x00}; + esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_FAIL); + + TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.eraseItem(NVSValidPageFixture::NS_INDEX, "test_value")); + + TEST_ASSERT_EQUAL(1, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(123, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state()); +} + +void test_Page_eraseItem__write_succeed() +{ + NVSValidPageFixture fix; + TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); + + // first read the entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32); + + // Page::eraseEntryAndSpan() reads entry again + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32); + + // erasing entry by setting bit in entry table (0xfa -> 0xf2) + uint8_t raw_result [4] = {0xf2, 0x00, 0x00, 0x00}; + esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_OK); + + TEST_ASSERT_EQUAL(ESP_OK, fix.page.eraseItem(NVSValidPageFixture::NS_INDEX, "test_value")); + + TEST_ASSERT_EQUAL(1, fix.page.getUsedEntryCount()); + TEST_ASSERT_EQUAL(123, fix.page.getErasedEntryCount()); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state()); +} + +void test_Page_findItem__uninitialized() +{ + Page page; + + size_t index = 0; + Item item; + TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, + page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::U8, "test_value", index, item)); +} + +void test_Page_find__wrong_ns() +{ + NVSValidPageFixture fix; + size_t index = 0; + Item item; + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, + fix.page.findItem(NVSValidPageFixture::NS_INDEX + 1, nvs::ItemType::U8, "test_value", index, item)); +} + +void test_Page_find__wrong_type() +{ + NVSValidPageFixture fix; + size_t index = 0; + Item item; + + // read normal entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32); + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_TYPE_MISMATCH, + fix.page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::I8, "test_value", index, item)); +} + +void test_Page_find__key_empty() +{ + NVSValidPageFixture fix; + size_t index = 0; + Item item; + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, + fix.page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::U8, "", index, item)); +} + +void test_Page_find__wrong_key() +{ + NVSValidPageFixture fix; + size_t index = 0; + Item item; + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, + fix.page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::U8, "different", index, item)); +} + +void test_Page_find__too_large_index() +{ + NVSValidPageFixture fix; + size_t index = 2; + Item item; + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, + fix.page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::U8, "test_value", index, item)); +} + +void test_Page_findItem__without_read() +{ + NVSValidPageFixture fix; + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, + fix.page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::U8, "different")); +} + +void test_Page_markFull__wrong_state() +{ + NVSPageFixture fix; + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_INVALID_STATE, fix.page.markFull()); + TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state()); +} + +void test_Page_markFull__success() +{ + NVSValidPageFixture fix; + Page::PageState expected_state = Page::PageState::FULL; + + esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, sizeof(fix.part_mock.partition), 0, &expected_state, sizeof(expected_state), 4, ESP_OK); + + TEST_ASSERT_EQUAL(ESP_OK, fix.page.markFull()); + TEST_ASSERT_EQUAL(Page::PageState::FULL, fix.page.state()); +} + +void test_Page_markFull__write_fail() +{ + NVSValidPageFixture fix; + Page::PageState expected_state = Page::PageState::FREEING; + + esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, sizeof(fix.part_mock.partition), 0, &expected_state, sizeof(expected_state), 4, ESP_FAIL); + + TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.markFreeing()); + TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state()); +} + +void test_Page_markFreeing__wrong_state() +{ + NVSPageFixture fix; + + TEST_ASSERT_EQUAL(ESP_ERR_NVS_INVALID_STATE, fix.page.markFreeing()); + TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state()); +} + +void test_Page_markFreeing__success() +{ + NVSValidPageFixture fix; + Page::PageState expected_state = Page::PageState::FREEING; + + esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, sizeof(fix.part_mock.partition), 0, &expected_state, sizeof(expected_state), 4, ESP_OK); + + TEST_ASSERT_EQUAL(ESP_OK, fix.page.markFreeing()); + TEST_ASSERT_EQUAL(Page::PageState::FREEING, fix.page.state()); +} + +void test_Page_getVarDataTailroom__uninitialized_page() +{ + NVSPageFixture fix; + + TEST_ASSERT_EQUAL(Page::CHUNK_MAX_SIZE, fix.page.getVarDataTailroom()); +} + +void test_Page_getVarDataTailroom__success() +{ + NVSValidPageFixture fix; + + // blob data item, written namespace item, written normal item: 3 items + TEST_ASSERT_EQUAL((Page::ENTRY_COUNT - 3) * Page::ENTRY_SIZE, fix.page.getVarDataTailroom()); +} + +void test_Page_calcEntries__uninit() +{ + NVSPageFixture fix; + TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state()); + + nvs_stats_t nvsStats = {0, 0, 0, 0}; + + TEST_ASSERT_EQUAL(ESP_OK, fix.page.calcEntries(nvsStats)); + TEST_ASSERT_EQUAL(0, nvsStats.used_entries); + TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.free_entries); + TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.total_entries); + TEST_ASSERT_EQUAL(0, nvsStats.namespace_count); +} + +void test_Page_calcEntries__corrupt() +{ + PartitionMockFixture fix; + Page page; + + uint8_t raw_header_corrupt [] = {0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x16, 0xdd, 0xdc}; + + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_corrupt, 32); + + // Page::load() should return ESP_OK, but state has to be corrupt + TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0)); + + TEST_ASSERT_EQUAL(Page::PageState::CORRUPT, page.state()); + + nvs_stats_t nvsStats = {0, 0, 0, 0}; + + TEST_ASSERT_EQUAL(ESP_OK, page.calcEntries(nvsStats)); + TEST_ASSERT_EQUAL(0, nvsStats.used_entries); + TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.free_entries); + TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.total_entries); + TEST_ASSERT_EQUAL(0, nvsStats.namespace_count); +} + +void test_Page_calcEntries__active_wo_blob() +{ + NVSValidPageFixture fix; + + nvs_stats_t nvsStats = {0, 0, 0, 0}; + + TEST_ASSERT_EQUAL(ESP_OK, fix.page.calcEntries(nvsStats)); + TEST_ASSERT_EQUAL(2, nvsStats.used_entries); + TEST_ASSERT_EQUAL(124, nvsStats.free_entries); + TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.total_entries); + TEST_ASSERT_EQUAL(0, nvsStats.namespace_count); +} + +void test_Page_calcEntries__active_with_blob() +{ + NVSValidBlobPageFixture fix; + + nvs_stats_t nvsStats = {0, 0, 0, 0}; + + TEST_ASSERT_EQUAL(ESP_OK, fix.page.calcEntries(nvsStats)); + TEST_ASSERT_EQUAL(4, nvsStats.used_entries); + TEST_ASSERT_EQUAL(122, nvsStats.free_entries); + TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.total_entries); + TEST_ASSERT_EQUAL(0, nvsStats.namespace_count); +} + +void test_Page_calcEntries__invalid() +{ + Page page; + + nvs_stats_t nvsStats = {0, 0, 0, 0}; + + TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state()); + + // total entries always get updated + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, page.calcEntries(nvsStats)); + TEST_ASSERT_EQUAL(0, nvsStats.used_entries); + TEST_ASSERT_EQUAL(0, nvsStats.free_entries); + TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.total_entries); + TEST_ASSERT_EQUAL(0, nvsStats.namespace_count); +} + +int main(int argc, char **argv) +{ + UNITY_BEGIN(); + RUN_TEST(test_Page_load_reading_header_fails); + RUN_TEST(test_Page_load_reading_data_fails); + RUN_TEST(test_Page_load__uninitialized_page_has_0xfe); + RUN_TEST(test_Page_load__initialized_corrupt_header); + RUN_TEST(test_Page_load__corrupt_entry_table); + RUN_TEST(test_Page_load_success); + RUN_TEST(test_Page_load_full_page); + RUN_TEST(test_Page_load__seq_number_0); + RUN_TEST(test_Page_erase__write_fail); + RUN_TEST(test_Page_erase__success); + RUN_TEST(test_Page_write__initialize_write_failure); + RUN_TEST(test_Page_write__write_data_fails); + RUN_TEST(test_page_write__write_correct_entry_state); + RUN_TEST(test_Page_write__write_correct_data); + RUN_TEST(test_Page_readItem__read_entry_fails); + RUN_TEST(test_Page_readItem__read_corrupted_entry); + RUN_TEST(test_Page_readItem__read_corrupted_second_read_fail); + RUN_TEST(test_Page_readItem__read_corrupted_erase_fail); + RUN_TEST(test_Page_readItem__read_entry_suceeds); + RUN_TEST(test_Page_readItem__blob_read_data_fails); + RUN_TEST(test_Page_readItem__blob_corrupt_data); + RUN_TEST(test_Page_readItem__blob_read_entry_suceeds); + RUN_TEST(test_Page_cmp__uninitialized); + RUN_TEST(test_Page_cmp__item_not_found); + RUN_TEST(test_Page_cmp__item_type_mismatch); + RUN_TEST(test_Page_cmp__item_content_mismatch); + RUN_TEST(test_Page_cmp__item_content_match); + RUN_TEST(test_Page_cmpItem__blob_data_mismatch); + RUN_TEST(test_Page_cmpItem__blob_data_match); + RUN_TEST(test_Page_eraseItem__uninitialized); + RUN_TEST(test_Page_eraseItem__key_not_found); + RUN_TEST(test_Page_eraseItem__write_fail); + RUN_TEST(test_Page_readItem__corrupt_data_erase_failure); + RUN_TEST(test_Page_eraseItem__write_succeed); + RUN_TEST(test_Page_findItem__uninitialized); + RUN_TEST(test_Page_find__wrong_ns); + RUN_TEST(test_Page_find__wrong_type); + RUN_TEST(test_Page_find__key_empty); + RUN_TEST(test_Page_find__wrong_key); + RUN_TEST(test_Page_find__too_large_index); + RUN_TEST(test_Page_findItem__without_read); + RUN_TEST(test_Page_markFull__wrong_state); + RUN_TEST(test_Page_markFreeing__wrong_state); + RUN_TEST(test_Page_markFull__success); + RUN_TEST(test_Page_markFreeing__success); + RUN_TEST(test_Page_markFull__write_fail); + RUN_TEST(test_Page_getVarDataTailroom__uninitialized_page); + RUN_TEST(test_Page_getVarDataTailroom__success); + RUN_TEST(test_Page_calcEntries__uninit); + RUN_TEST(test_Page_calcEntries__corrupt); + RUN_TEST(test_Page_calcEntries__active_wo_blob); + RUN_TEST(test_Page_calcEntries__active_with_blob); + RUN_TEST(test_Page_calcEntries__invalid); + int failures = UNITY_END(); + return failures; +} diff --git a/components/nvs_flash/host_test/nvs_page_test/sdkconfig.defaults b/components/nvs_flash/host_test/nvs_page_test/sdkconfig.defaults new file mode 100644 index 000000000..a05773334 --- /dev/null +++ b/components/nvs_flash/host_test/nvs_page_test/sdkconfig.defaults @@ -0,0 +1,3 @@ +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n +CONFIG_IDF_TARGET="linux" +CONFIG_CXX_EXCEPTIONS=y diff --git a/components/nvs_flash/include/nvs.h b/components/nvs_flash/include/nvs.h index dfdd18c92..26183853b 100644 --- a/components/nvs_flash/include/nvs.h +++ b/components/nvs_flash/include/nvs.h @@ -17,6 +17,7 @@ #include #include #include +#include "esp_attr.h" #include "esp_err.h" #ifdef __cplusplus @@ -26,34 +27,92 @@ extern "C" { /** * Opaque pointer type representing non-volatile storage handle */ -typedef uint32_t nvs_handle; - -#define ESP_ERR_NVS_BASE 0x1100 /*!< Starting number of error codes */ -#define ESP_ERR_NVS_NOT_INITIALIZED (ESP_ERR_NVS_BASE + 0x01) /*!< The storage driver is not initialized */ -#define ESP_ERR_NVS_NOT_FOUND (ESP_ERR_NVS_BASE + 0x02) /*!< Id namespace doesn’t exist yet and mode is NVS_READONLY */ -#define ESP_ERR_NVS_TYPE_MISMATCH (ESP_ERR_NVS_BASE + 0x03) /*!< The type of set or get operation doesn't match the type of value stored in NVS */ -#define ESP_ERR_NVS_READ_ONLY (ESP_ERR_NVS_BASE + 0x04) /*!< Storage handle was opened as read only */ -#define ESP_ERR_NVS_NOT_ENOUGH_SPACE (ESP_ERR_NVS_BASE + 0x05) /*!< There is not enough space in the underlying storage to save the value */ -#define ESP_ERR_NVS_INVALID_NAME (ESP_ERR_NVS_BASE + 0x06) /*!< Namespace name doesn’t satisfy constraints */ -#define ESP_ERR_NVS_INVALID_HANDLE (ESP_ERR_NVS_BASE + 0x07) /*!< Handle has been closed or is NULL */ -#define ESP_ERR_NVS_REMOVE_FAILED (ESP_ERR_NVS_BASE + 0x08) /*!< The value wasn’t updated because flash write operation has failed. The value was written however, and update will be finished after re-initialization of nvs, provided that flash operation doesn’t fail again. */ -#define ESP_ERR_NVS_KEY_TOO_LONG (ESP_ERR_NVS_BASE + 0x09) /*!< Key name is too long */ -#define ESP_ERR_NVS_PAGE_FULL (ESP_ERR_NVS_BASE + 0x0a) /*!< Internal error; never returned by nvs_ API functions */ -#define ESP_ERR_NVS_INVALID_STATE (ESP_ERR_NVS_BASE + 0x0b) /*!< NVS is in an inconsistent state due to a previous error. Call nvs_flash_init and nvs_open again, then retry. */ -#define ESP_ERR_NVS_INVALID_LENGTH (ESP_ERR_NVS_BASE + 0x0c) /*!< String or blob length is not sufficient to store data */ -#define ESP_ERR_NVS_NO_FREE_PAGES (ESP_ERR_NVS_BASE + 0x0d) /*!< NVS partition doesn't contain any empty pages. This may happen if NVS partition was truncated. Erase the whole partition and call nvs_flash_init again. */ -#define ESP_ERR_NVS_VALUE_TOO_LONG (ESP_ERR_NVS_BASE + 0x0e) /*!< String or blob length is longer than supported by the implementation */ -#define ESP_ERR_NVS_PART_NOT_FOUND (ESP_ERR_NVS_BASE + 0x0f) /*!< Partition with specified name is not found in the partition table */ - -#define NVS_DEFAULT_PART_NAME "nvs" /*!< Default partition name of the NVS partition in the partition table */ +typedef uint32_t nvs_handle_t; + +/* + * Pre-IDF V4.0 uses nvs_handle, so leaving the original typedef here for compatibility. + */ +typedef nvs_handle_t nvs_handle IDF_DEPRECATED("Replace with nvs_handle_t"); + +#define ESP_ERR_NVS_BASE 0x1100 /*!< Starting number of error codes */ +#define ESP_ERR_NVS_NOT_INITIALIZED (ESP_ERR_NVS_BASE + 0x01) /*!< The storage driver is not initialized */ +#define ESP_ERR_NVS_NOT_FOUND (ESP_ERR_NVS_BASE + 0x02) /*!< Id namespace doesn’t exist yet and mode is NVS_READONLY */ +#define ESP_ERR_NVS_TYPE_MISMATCH (ESP_ERR_NVS_BASE + 0x03) /*!< The type of set or get operation doesn't match the type of value stored in NVS */ +#define ESP_ERR_NVS_READ_ONLY (ESP_ERR_NVS_BASE + 0x04) /*!< Storage handle was opened as read only */ +#define ESP_ERR_NVS_NOT_ENOUGH_SPACE (ESP_ERR_NVS_BASE + 0x05) /*!< There is not enough space in the underlying storage to save the value */ +#define ESP_ERR_NVS_INVALID_NAME (ESP_ERR_NVS_BASE + 0x06) /*!< Namespace name doesn’t satisfy constraints */ +#define ESP_ERR_NVS_INVALID_HANDLE (ESP_ERR_NVS_BASE + 0x07) /*!< Handle has been closed or is NULL */ +#define ESP_ERR_NVS_REMOVE_FAILED (ESP_ERR_NVS_BASE + 0x08) /*!< The value wasn’t updated because flash write operation has failed. The value was written however, and update will be finished after re-initialization of nvs, provided that flash operation doesn’t fail again. */ +#define ESP_ERR_NVS_KEY_TOO_LONG (ESP_ERR_NVS_BASE + 0x09) /*!< Key name is too long */ +#define ESP_ERR_NVS_PAGE_FULL (ESP_ERR_NVS_BASE + 0x0a) /*!< Internal error; never returned by nvs API functions */ +#define ESP_ERR_NVS_INVALID_STATE (ESP_ERR_NVS_BASE + 0x0b) /*!< NVS is in an inconsistent state due to a previous error. Call nvs_flash_init and nvs_open again, then retry. */ +#define ESP_ERR_NVS_INVALID_LENGTH (ESP_ERR_NVS_BASE + 0x0c) /*!< String or blob length is not sufficient to store data */ +#define ESP_ERR_NVS_NO_FREE_PAGES (ESP_ERR_NVS_BASE + 0x0d) /*!< NVS partition doesn't contain any empty pages. This may happen if NVS partition was truncated. Erase the whole partition and call nvs_flash_init again. */ +#define ESP_ERR_NVS_VALUE_TOO_LONG (ESP_ERR_NVS_BASE + 0x0e) /*!< String or blob length is longer than supported by the implementation */ +#define ESP_ERR_NVS_PART_NOT_FOUND (ESP_ERR_NVS_BASE + 0x0f) /*!< Partition with specified name is not found in the partition table */ + +#define ESP_ERR_NVS_NEW_VERSION_FOUND (ESP_ERR_NVS_BASE + 0x10) /*!< NVS partition contains data in new format and cannot be recognized by this version of code */ +#define ESP_ERR_NVS_XTS_ENCR_FAILED (ESP_ERR_NVS_BASE + 0x11) /*!< XTS encryption failed while writing NVS entry */ +#define ESP_ERR_NVS_XTS_DECR_FAILED (ESP_ERR_NVS_BASE + 0x12) /*!< XTS decryption failed while reading NVS entry */ +#define ESP_ERR_NVS_XTS_CFG_FAILED (ESP_ERR_NVS_BASE + 0x13) /*!< XTS configuration setting failed */ +#define ESP_ERR_NVS_XTS_CFG_NOT_FOUND (ESP_ERR_NVS_BASE + 0x14) /*!< XTS configuration not found */ +#define ESP_ERR_NVS_ENCR_NOT_SUPPORTED (ESP_ERR_NVS_BASE + 0x15) /*!< NVS encryption is not supported in this version */ +#define ESP_ERR_NVS_KEYS_NOT_INITIALIZED (ESP_ERR_NVS_BASE + 0x16) /*!< NVS key partition is uninitialized */ +#define ESP_ERR_NVS_CORRUPT_KEY_PART (ESP_ERR_NVS_BASE + 0x17) /*!< NVS key partition is corrupt */ +#define ESP_ERR_NVS_WRONG_ENCRYPTION (ESP_ERR_NVS_BASE + 0x19) /*!< NVS partition is marked as encrypted with generic flash encryption. This is forbidden since the NVS encryption works differently. */ + +#define ESP_ERR_NVS_CONTENT_DIFFERS (ESP_ERR_NVS_BASE + 0x18) /*!< Internal error; never returned by nvs API functions. NVS key is different in comparison */ + +#define NVS_DEFAULT_PART_NAME "nvs" /*!< Default partition name of the NVS partition in the partition table */ + +#define NVS_PART_NAME_MAX_SIZE 16 /*!< maximum length of partition name (excluding null terminator) */ +#define NVS_KEY_NAME_MAX_SIZE 16 /*!< Maximal length of NVS key name (including null terminator) */ + /** * @brief Mode of opening the non-volatile storage - * */ typedef enum { NVS_READONLY, /*!< Read only */ NVS_READWRITE /*!< Read and write */ -} nvs_open_mode; +} nvs_open_mode_t; + +/* + * Pre-IDF V4.0 uses nvs_open_mode, so leaving the original typedef here for compatibility. + */ +typedef nvs_open_mode_t nvs_open_mode IDF_DEPRECATED("Replace with nvs_open_mode_t"); + + +/** + * @brief Types of variables + * + */ +typedef enum { + NVS_TYPE_U8 = 0x01, /*!< Type uint8_t */ + NVS_TYPE_I8 = 0x11, /*!< Type int8_t */ + NVS_TYPE_U16 = 0x02, /*!< Type uint16_t */ + NVS_TYPE_I16 = 0x12, /*!< Type int16_t */ + NVS_TYPE_U32 = 0x04, /*!< Type uint32_t */ + NVS_TYPE_I32 = 0x14, /*!< Type int32_t */ + NVS_TYPE_U64 = 0x08, /*!< Type uint64_t */ + NVS_TYPE_I64 = 0x18, /*!< Type int64_t */ + NVS_TYPE_STR = 0x21, /*!< Type string */ + NVS_TYPE_BLOB = 0x42, /*!< Type blob */ + NVS_TYPE_ANY = 0xff /*!< Must be last */ +} nvs_type_t; + +/** + * @brief information about entry obtained from nvs_entry_info function + */ +typedef struct { + char namespace_name[16]; /*!< Namespace to which key-value belong */ + char key[16]; /*!< Key of stored key-value pair */ + nvs_type_t type; /*!< Type of stored key-value pair */ +} nvs_entry_info_t; + +/** + * Opaque pointer type representing iterator to nvs entries + */ +typedef struct nvs_opaque_iterator_t *nvs_iterator_t; /** * @brief Open non-volatile storage with a given namespace from the default NVS partition @@ -64,12 +123,10 @@ typedef enum { * The default NVS partition is the one that is labelled "nvs" in the partition * table. * - * @param[in] name Namespace name. Maximal length is determined by the - * underlying implementation, but is guaranteed to be - * at least 15 characters. Shouldn't be empty. + * @param[in] name Namespace name. Maximal length is (NVS_KEY_NAME_MAX_SIZE-1) characters. Shouldn't be empty. * @param[in] open_mode NVS_READWRITE or NVS_READONLY. If NVS_READONLY, will * open a handle for reading only. All write requests will - * be rejected for this handle. + * be rejected for this handle. * @param[out] out_handle If successful (return code is zero), handle will be * returned in this argument. * @@ -80,9 +137,10 @@ typedef enum { * - ESP_ERR_NVS_NOT_FOUND id namespace doesn't exist yet and * mode is NVS_READONLY * - ESP_ERR_NVS_INVALID_NAME if namespace name doesn't satisfy constraints + * - ESP_ERR_NO_MEM in case memory could not be allocated for the internal structures * - other error codes from the underlying storage driver */ -esp_err_t nvs_open(const char* name, nvs_open_mode open_mode, nvs_handle *out_handle); +esp_err_t nvs_open(const char* name, nvs_open_mode_t open_mode, nvs_handle_t *out_handle); /** * @brief Open non-volatile storage with a given namespace from specified partition @@ -92,12 +150,10 @@ esp_err_t nvs_open(const char* name, nvs_open_mode open_mode, nvs_handle *out_ha * with NVS using nvs_flash_init_partition() API. * * @param[in] part_name Label (name) of the partition of interest for object read/write/erase - * @param[in] name Namespace name. Maximal length is determined by the - * underlying implementation, but is guaranteed to be - * at least 15 characters. Shouldn't be empty. - * @param[in] open_mode NVS_READWRITE or NVS_READONLY. If NVS_READONLY, will - * open a handle for reading only. All write requests will - * be rejected for this handle. + * @param[in] name Namespace name. Maximal length is (NVS_KEY_NAME_MAX_SIZE-1) characters. Shouldn't be empty. + * @param[in] open_mode NVS_READWRITE or NVS_READONLY. If NVS_READONLY, will + * open a handle for reading only. All write requests will + * be rejected for this handle. * @param[out] out_handle If successful (return code is zero), handle will be * returned in this argument. * @@ -108,25 +164,99 @@ esp_err_t nvs_open(const char* name, nvs_open_mode open_mode, nvs_handle *out_ha * - ESP_ERR_NVS_NOT_FOUND id namespace doesn't exist yet and * mode is NVS_READONLY * - ESP_ERR_NVS_INVALID_NAME if namespace name doesn't satisfy constraints + * - ESP_ERR_NO_MEM in case memory could not be allocated for the internal structures * - other error codes from the underlying storage driver */ -esp_err_t nvs_open_from_partition(const char *part_name, const char* name, nvs_open_mode open_mode, nvs_handle *out_handle); +esp_err_t nvs_open_from_partition(const char *part_name, const char* name, nvs_open_mode_t open_mode, nvs_handle_t *out_handle); /**@{*/ /** - * @brief set value for given key + * @brief set int8_t value for given key * - * This family of functions set value for the key, given its name. Note that - * actual storage will not be updated until nvs_commit function is called. + * Set value for the key, given its name. Note that the actual storage will not be updated + * until \c nvs_commit is called. + * + * @param[in] handle Handle obtained from nvs_open function. + * Handles that were opened read only cannot be used. + * @param[in] key Key name. Maximal length is (NVS_KEY_NAME_MAX_SIZE-1) characters. Shouldn't be empty. + * @param[in] value The value to set. + * + * @return + * - ESP_OK if value was set successfully + * - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL + * - ESP_ERR_NVS_READ_ONLY if storage handle was opened as read only + * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints + * - ESP_ERR_NVS_NOT_ENOUGH_SPACE if there is not enough space in the + * underlying storage to save the value + * - ESP_ERR_NVS_REMOVE_FAILED if the value wasn't updated because flash + * write operation has failed. The value was written however, and + * update will be finished after re-initialization of nvs, provided that + * flash operation doesn't fail again. + */ +esp_err_t nvs_set_i8 (nvs_handle_t handle, const char* key, int8_t value); + +/** + * @brief set uint8_t value for given key + * + * This function is the same as \c nvs_set_i8 except for the data type. + */ +esp_err_t nvs_set_u8 (nvs_handle_t handle, const char* key, uint8_t value); + +/** + * @brief set int16_t value for given key + * + * This function is the same as \c nvs_set_i8 except for the data type. + */ +esp_err_t nvs_set_i16 (nvs_handle_t handle, const char* key, int16_t value); + +/** + * @brief set uint16_t value for given key + * + * This function is the same as \c nvs_set_i8 except for the data type. + */ +esp_err_t nvs_set_u16 (nvs_handle_t handle, const char* key, uint16_t value); + +/** + * @brief set int32_t value for given key + * + * This function is the same as \c nvs_set_i8 except for the data type. + */ +esp_err_t nvs_set_i32 (nvs_handle_t handle, const char* key, int32_t value); + +/** + * @brief set uint32_t value for given key + * + * This function is the same as \c nvs_set_i8 except for the data type. + */ +esp_err_t nvs_set_u32 (nvs_handle_t handle, const char* key, uint32_t value); + +/** + * @brief set int64_t value for given key + * + * This function is the same as \c nvs_set_i8 except for the data type. + */ +esp_err_t nvs_set_i64 (nvs_handle_t handle, const char* key, int64_t value); + +/** + * @brief set uint64_t value for given key + * + * This function is the same as \c nvs_set_i8 except for the data type. + */ +esp_err_t nvs_set_u64 (nvs_handle_t handle, const char* key, uint64_t value); + +/** + * @brief set string for given key + * + * Set value for the key, given its name. Note that the actual storage will not be updated + * until \c nvs_commit is called. * * @param[in] handle Handle obtained from nvs_open function. * Handles that were opened read only cannot be used. - * @param[in] key Key name. Maximal length is determined by the underlying - * implementation, but is guaranteed to be at least - * 15 characters. Shouldn't be empty. + * @param[in] key Key name. Maximal length is (NVS_KEY_NAME_MAX_SIZE-1) characters. Shouldn't be empty. * @param[in] value The value to set. * For strings, the maximum length (including null character) is - * 1984 bytes. + * 4000 bytes, if there is one complete page free for writing. + * This decreases, however, if the free space is fragmented. * * @return * - ESP_OK if value was set successfully @@ -141,16 +271,8 @@ esp_err_t nvs_open_from_partition(const char *part_name, const char* name, nvs_o * flash operation doesn't fail again. * - ESP_ERR_NVS_VALUE_TOO_LONG if the string value is too long */ -esp_err_t nvs_set_i8 (nvs_handle handle, const char* key, int8_t value); -esp_err_t nvs_set_u8 (nvs_handle handle, const char* key, uint8_t value); -esp_err_t nvs_set_i16 (nvs_handle handle, const char* key, int16_t value); -esp_err_t nvs_set_u16 (nvs_handle handle, const char* key, uint16_t value); -esp_err_t nvs_set_i32 (nvs_handle handle, const char* key, int32_t value); -esp_err_t nvs_set_u32 (nvs_handle handle, const char* key, uint32_t value); -esp_err_t nvs_set_i64 (nvs_handle handle, const char* key, int64_t value); -esp_err_t nvs_set_u64 (nvs_handle handle, const char* key, uint64_t value); -esp_err_t nvs_set_str (nvs_handle handle, const char* key, const char* value); -/**@}*/ +esp_err_t nvs_set_str (nvs_handle_t handle, const char* key, const char* value); +/**@}*/ /** * @brief set variable length binary value for given key @@ -160,10 +282,11 @@ esp_err_t nvs_set_str (nvs_handle handle, const char* key, const char* value); * * @param[in] handle Handle obtained from nvs_open function. * Handles that were opened read only cannot be used. - * @param[in] key Key name. Maximal length is 15 characters. Shouldn't be empty. + * @param[in] key Key name. Maximal length is (NVS_KEY_NAME_MAX_SIZE-1) characters. Shouldn't be empty. * @param[in] value The value to set. * @param[in] length length of binary value to set, in bytes; Maximum length is - * 1984 bytes. + * 508000 bytes or (97.6% of the partition size - 4000) bytes + * whichever is lower. * * @return * - ESP_OK if value was set successfully @@ -178,20 +301,19 @@ esp_err_t nvs_set_str (nvs_handle handle, const char* key, const char* value); * flash operation doesn't fail again. * - ESP_ERR_NVS_VALUE_TOO_LONG if the value is too long */ -esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, size_t length); +esp_err_t nvs_set_blob(nvs_handle_t handle, const char* key, const void* value, size_t length); /**@{*/ /** - * @brief get value for given key + * @brief get int8_t value for given key * - * These functions retrieve value for the key, given its name. If key does not + * These functions retrieve value for the key, given its name. If \c key does not * exist, or the requested variable type doesn't match the type which was used * when setting a value, an error is returned. * * In case of any error, out_value is not modified. * - * All functions expect out_value to be a pointer to an already allocated variable - * of the given type. + * \c out_value has to be a pointer to an already allocated variable of the given type. * * \code{c} * // Example of using nvs_get_i32: @@ -204,9 +326,7 @@ esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, si * \endcode * * @param[in] handle Handle obtained from nvs_open function. - * @param[in] key Key name. Maximal length is determined by the underlying - * implementation, but is guaranteed to be at least - * 15 characters. Shouldn't be empty. + * @param[in] key Key name. Maximal length is (NVS_KEY_NAME_MAX_SIZE-1) characters. Shouldn't be empty. * @param out_value Pointer to the output value. * May be NULL for nvs_get_str and nvs_get_blob, in this * case required length will be returned in length argument. @@ -218,20 +338,63 @@ esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, si * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints * - ESP_ERR_NVS_INVALID_LENGTH if length is not sufficient to store data */ -esp_err_t nvs_get_i8 (nvs_handle handle, const char* key, int8_t* out_value); -esp_err_t nvs_get_u8 (nvs_handle handle, const char* key, uint8_t* out_value); -esp_err_t nvs_get_i16 (nvs_handle handle, const char* key, int16_t* out_value); -esp_err_t nvs_get_u16 (nvs_handle handle, const char* key, uint16_t* out_value); -esp_err_t nvs_get_i32 (nvs_handle handle, const char* key, int32_t* out_value); -esp_err_t nvs_get_u32 (nvs_handle handle, const char* key, uint32_t* out_value); -esp_err_t nvs_get_i64 (nvs_handle handle, const char* key, int64_t* out_value); -esp_err_t nvs_get_u64 (nvs_handle handle, const char* key, uint64_t* out_value); -/**@}*/ +esp_err_t nvs_get_i8 (nvs_handle_t handle, const char* key, int8_t* out_value); + +/** + * @brief get uint8_t value for given key + * + * This function is the same as \c nvs_get_i8 except for the data type. + */ +esp_err_t nvs_get_u8 (nvs_handle_t handle, const char* key, uint8_t* out_value); + +/** + * @brief get int16_t value for given key + * + * This function is the same as \c nvs_get_i8 except for the data type. + */ +esp_err_t nvs_get_i16 (nvs_handle_t handle, const char* key, int16_t* out_value); /** - * @brief get value for given key + * @brief get uint16_t value for given key * - * These functions retrieve value for the key, given its name. If key does not + * This function is the same as \c nvs_get_i8 except for the data type. + */ +esp_err_t nvs_get_u16 (nvs_handle_t handle, const char* key, uint16_t* out_value); + +/** + * @brief get int32_t value for given key + * + * This function is the same as \c nvs_get_i8 except for the data type. + */ +esp_err_t nvs_get_i32 (nvs_handle_t handle, const char* key, int32_t* out_value); + +/** + * @brief get uint32_t value for given key + * + * This function is the same as \c nvs_get_i8 except for the data type. + */ +esp_err_t nvs_get_u32 (nvs_handle_t handle, const char* key, uint32_t* out_value); + +/** + * @brief get int64_t value for given key + * + * This function is the same as \c nvs_get_i8 except for the data type. + */ +esp_err_t nvs_get_i64 (nvs_handle_t handle, const char* key, int64_t* out_value); + +/** + * @brief get uint64_t value for given key + * + * This function is the same as \c nvs_get_i8 except for the data type. + */ +esp_err_t nvs_get_u64 (nvs_handle_t handle, const char* key, uint64_t* out_value); +/**@}*/ + +/**@{*/ +/** + * @brief get string value for given key + * + * These functions retrieve the data of an entry, given its key. If key does not * exist, or the requested variable type doesn't match the type which was used * when setting a value, an error is returned. * @@ -239,7 +402,7 @@ esp_err_t nvs_get_u64 (nvs_handle handle, const char* key, uint64_t* out_value); * * All functions expect out_value to be a pointer to an already allocated variable * of the given type. - * + * * nvs_get_str and nvs_get_blob functions support WinAPI-style length queries. * To get the size necessary to store the value, call nvs_get_str or nvs_get_blob * with zero out_value and non-zero pointer to length. Variable pointed to @@ -265,10 +428,8 @@ esp_err_t nvs_get_u64 (nvs_handle handle, const char* key, uint64_t* out_value); * \endcode * * @param[in] handle Handle obtained from nvs_open function. - * @param[in] key Key name. Maximal length is determined by the underlying - * implementation, but is guaranteed to be at least - * 15 characters. Shouldn't be empty. - * @param out_value Pointer to the output value. + * @param[in] key Key name. Maximal length is (NVS_KEY_NAME_MAX_SIZE-1) characters. Shouldn't be empty. + * @param[out] out_value Pointer to the output value. * May be NULL for nvs_get_str and nvs_get_blob, in this * case required length will be returned in length argument. * @param[inout] length A non-zero pointer to the variable holding the length of out_value. @@ -282,11 +443,16 @@ esp_err_t nvs_get_u64 (nvs_handle handle, const char* key, uint64_t* out_value); * - ESP_ERR_NVS_NOT_FOUND if the requested key doesn't exist * - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints - * - ESP_ERR_NVS_INVALID_LENGTH if length is not sufficient to store data + * - ESP_ERR_NVS_INVALID_LENGTH if \c length is not sufficient to store data */ -/**@{*/ -esp_err_t nvs_get_str (nvs_handle handle, const char* key, char* out_value, size_t* length); -esp_err_t nvs_get_blob(nvs_handle handle, const char* key, void* out_value, size_t* length); +esp_err_t nvs_get_str (nvs_handle_t handle, const char* key, char* out_value, size_t* length); + +/** + * @brief get blob value for given key + * + * This function behaves the same as \c nvs_get_str, except for the data type. + */ +esp_err_t nvs_get_blob(nvs_handle_t handle, const char* key, void* out_value, size_t* length); /**@}*/ /** @@ -297,9 +463,7 @@ esp_err_t nvs_get_blob(nvs_handle handle, const char* key, void* out_value, size * @param[in] handle Storage handle obtained with nvs_open. * Handles that were opened read only cannot be used. * - * @param[in] key Key name. Maximal length is determined by the underlying - * implementation, but is guaranteed to be at least - * 15 characters. Shouldn't be empty. + * @param[in] key Key name. Maximal length is (NVS_KEY_NAME_MAX_SIZE-1) characters. Shouldn't be empty. * * @return * - ESP_OK if erase operation was successful @@ -308,7 +472,7 @@ esp_err_t nvs_get_blob(nvs_handle handle, const char* key, void* out_value, size * - ESP_ERR_NVS_NOT_FOUND if the requested key doesn't exist * - other error codes from the underlying storage driver */ -esp_err_t nvs_erase_key(nvs_handle handle, const char* key); +esp_err_t nvs_erase_key(nvs_handle_t handle, const char* key); /** * @brief Erase all key-value pairs in a namespace @@ -324,7 +488,7 @@ esp_err_t nvs_erase_key(nvs_handle handle, const char* key); * - ESP_ERR_NVS_READ_ONLY if handle was opened as read only * - other error codes from the underlying storage driver */ -esp_err_t nvs_erase_all(nvs_handle handle); +esp_err_t nvs_erase_all(nvs_handle_t handle); /** * @brief Write any pending changes to non-volatile storage @@ -341,7 +505,7 @@ esp_err_t nvs_erase_all(nvs_handle handle); * - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL * - other error codes from the underlying storage driver */ -esp_err_t nvs_commit(nvs_handle handle); +esp_err_t nvs_commit(nvs_handle_t handle); /** * @brief Close the storage handle and free any allocated resources @@ -354,7 +518,154 @@ esp_err_t nvs_commit(nvs_handle handle); * * @param[in] handle Storage handle to close */ -void nvs_close(nvs_handle handle); +void nvs_close(nvs_handle_t handle); + +/** + * @note Info about storage space NVS. + */ +typedef struct { + size_t used_entries; /**< Amount of used entries. */ + size_t free_entries; /**< Amount of free entries. */ + size_t total_entries; /**< Amount all available entries. */ + size_t namespace_count; /**< Amount name space. */ +} nvs_stats_t; + +/** + * @brief Fill structure nvs_stats_t. It provides info about used memory the partition. + * + * This function calculates to runtime the number of used entries, free entries, total entries, + * and amount namespace in partition. + * + * \code{c} + * // Example of nvs_get_stats() to get the number of used entries and free entries: + * nvs_stats_t nvs_stats; + * nvs_get_stats(NULL, &nvs_stats); + * printf("Count: UsedEntries = (%d), FreeEntries = (%d), AllEntries = (%d)\n", + nvs_stats.used_entries, nvs_stats.free_entries, nvs_stats.total_entries); + * \endcode + * + * @param[in] part_name Partition name NVS in the partition table. + * If pass a NULL than will use NVS_DEFAULT_PART_NAME ("nvs"). + * + * @param[out] nvs_stats Returns filled structure nvs_states_t. + * It provides info about used memory the partition. + * + * + * @return + * - ESP_OK if the changes have been written successfully. + * Return param nvs_stats will be filled. + * - ESP_ERR_NVS_PART_NOT_FOUND if the partition with label "name" is not found. + * Return param nvs_stats will be filled 0. + * - ESP_ERR_NVS_NOT_INITIALIZED if the storage driver is not initialized. + * Return param nvs_stats will be filled 0. + * - ESP_ERR_INVALID_ARG if nvs_stats equal to NULL. + * - ESP_ERR_INVALID_STATE if there is page with the status of INVALID. + * Return param nvs_stats will be filled not with correct values because + * not all pages will be counted. Counting will be interrupted at the first INVALID page. + */ +esp_err_t nvs_get_stats(const char *part_name, nvs_stats_t *nvs_stats); + +/** + * @brief Calculate all entries in a namespace. + * + * An entry represents the smallest storage unit in NVS. + * Strings and blobs may occupy more than one entry. + * Note that to find out the total number of entries occupied by the namespace, + * add one to the returned value used_entries (if err is equal to ESP_OK). + * Because the name space entry takes one entry. + * + * \code{c} + * // Example of nvs_get_used_entry_count() to get amount of all key-value pairs in one namespace: + * nvs_handle_t handle; + * nvs_open("namespace1", NVS_READWRITE, &handle); + * ... + * size_t used_entries; + * size_t total_entries_namespace; + * if(nvs_get_used_entry_count(handle, &used_entries) == ESP_OK){ + * // the total number of entries occupied by the namespace + * total_entries_namespace = used_entries + 1; + * } + * \endcode + * + * @param[in] handle Handle obtained from nvs_open function. + * + * @param[out] used_entries Returns amount of used entries from a namespace. + * + * + * @return + * - ESP_OK if the changes have been written successfully. + * Return param used_entries will be filled valid value. + * - ESP_ERR_NVS_NOT_INITIALIZED if the storage driver is not initialized. + * Return param used_entries will be filled 0. + * - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL. + * Return param used_entries will be filled 0. + * - ESP_ERR_INVALID_ARG if used_entries equal to NULL. + * - Other error codes from the underlying storage driver. + * Return param used_entries will be filled 0. + */ +esp_err_t nvs_get_used_entry_count(nvs_handle_t handle, size_t* used_entries); + +/** + * @brief Create an iterator to enumerate NVS entries based on one or more parameters + * + * \code{c} + * // Example of listing all the key-value pairs of any type under specified partition and namespace + * nvs_iterator_t it = nvs_entry_find(partition, namespace, NVS_TYPE_ANY); + * while (it != NULL) { + * nvs_entry_info_t info; + * nvs_entry_info(it, &info); + * it = nvs_entry_next(it); + * printf("key '%s', type '%d' \n", info.key, info.type); + * }; + * // Note: no need to release iterator obtained from nvs_entry_find function when + * // nvs_entry_find or nvs_entry_next function return NULL, indicating no other + * // element for specified criteria was found. + * } + * \endcode + * + * @param[in] part_name Partition name + * + * @param[in] namespace_name Set this value if looking for entries with + * a specific namespace. Pass NULL otherwise. + * + * @param[in] type One of nvs_type_t values. + * + * @return + * Iterator used to enumerate all the entries found, + * or NULL if no entry satisfying criteria was found. + * Iterator obtained through this function has to be released + * using nvs_release_iterator when not used any more. + */ +nvs_iterator_t nvs_entry_find(const char *part_name, const char *namespace_name, nvs_type_t type); + +/** + * @brief Returns next item matching the iterator criteria, NULL if no such item exists. + * + * Note that any copies of the iterator will be invalid after this call. + * + * @param[in] iterator Iterator obtained from nvs_entry_find function. Must be non-NULL. + * + * @return + * NULL if no entry was found, valid nvs_iterator_t otherwise. + */ +nvs_iterator_t nvs_entry_next(nvs_iterator_t iterator); + +/** + * @brief Fills nvs_entry_info_t structure with information about entry pointed to by the iterator. + * + * @param[in] iterator Iterator obtained from nvs_entry_find or nvs_entry_next function. Must be non-NULL. + * + * @param[out] out_info Structure to which entry information is copied. + */ +void nvs_entry_info(nvs_iterator_t iterator, nvs_entry_info_t *out_info); + +/** + * @brief Release iterator + * + * @param[in] iterator Release iterator obtained from nvs_entry_find function. NULL argument is allowed. + * + */ +void nvs_release_iterator(nvs_iterator_t iterator); #ifdef __cplusplus @@ -362,4 +673,3 @@ void nvs_close(nvs_handle handle); #endif #endif //ESP_NVS_H - diff --git a/components/nvs_flash/include/nvs_flash.h b/components/nvs_flash/include/nvs_flash.h index a7ef7f451..a5ad9ac28 100644 --- a/components/nvs_flash/include/nvs_flash.h +++ b/components/nvs_flash/include/nvs_flash.h @@ -19,6 +19,18 @@ extern "C" { #endif #include "nvs.h" +#include "esp_partition.h" + + +#define NVS_KEY_SIZE 32 // AES-256 + +/** + * @brief Key for encryption and decryption + */ +typedef struct { + uint8_t eky[NVS_KEY_SIZE]; /*!< XTS encryption and decryption key*/ + uint8_t tky[NVS_KEY_SIZE]; /*!< XTS tweak key */ +} nvs_sec_cfg_t; /** * @brief Initialize the default NVS partition. @@ -26,30 +38,62 @@ extern "C" { * This API initialises the default NVS partition. The default NVS partition * is the one that is labeled "nvs" in the partition table. * + * When "NVS_ENCRYPTION" is enabled in the menuconfig, this API enables + * the NVS encryption for the default NVS partition as follows + * 1. Read security configurations from the first NVS key + * partition listed in the partition table. (NVS key partition is + * any "data" type partition which has the subtype value set to "nvs_keys") + * 2. If the NVS key partiton obtained in the previous step is empty, + * generate and store new keys in that NVS key partiton. + * 3. Internally call "nvs_flash_secure_init()" with + * the security configurations obtained/generated in the previous steps. + * + * Post initialization NVS read/write APIs + * remain the same irrespective of NVS encryption. + * * @return * - ESP_OK if storage was successfully initialized. * - ESP_ERR_NVS_NO_FREE_PAGES if the NVS storage contains no empty pages * (which may happen if NVS partition was truncated) * - ESP_ERR_NOT_FOUND if no partition with label "nvs" is found in the partition table + * - ESP_ERR_NO_MEM in case memory could not be allocated for the internal structures * - one of the error codes from the underlying flash storage driver + * - error codes from nvs_flash_read_security_cfg API (when "NVS_ENCRYPTION" is enabled). + * - error codes from nvs_flash_generate_keys API (when "NVS_ENCRYPTION" is enabled). + * - error codes from nvs_flash_secure_init_partition API (when "NVS_ENCRYPTION" is enabled) . */ esp_err_t nvs_flash_init(void); /** * @brief Initialize NVS flash storage for the specified partition. * - * @param[in] partition_label Label of the partition. Note that internally a reference to - * passed value is kept and it should be accessible for future operations + * @param[in] partition_label Label of the partition. Must be no longer than 16 characters. * * @return * - ESP_OK if storage was successfully initialized. * - ESP_ERR_NVS_NO_FREE_PAGES if the NVS storage contains no empty pages * (which may happen if NVS partition was truncated) * - ESP_ERR_NOT_FOUND if specified partition is not found in the partition table + * - ESP_ERR_NO_MEM in case memory could not be allocated for the internal structures * - one of the error codes from the underlying flash storage driver */ esp_err_t nvs_flash_init_partition(const char *partition_label); +/** + * @brief Initialize NVS flash storage for the partition specified by partition pointer. + * + * @param[in] partition pointer to a partition obtained by the ESP partition API. + * + * @return + * - ESP_OK if storage was successfully initialized + * - ESP_ERR_NVS_NO_FREE_PAGES if the NVS storage contains no empty pages + * (which may happen if NVS partition was truncated) + * - ESP_ERR_INVALID_ARG in case partition is NULL + * - ESP_ERR_NO_MEM in case memory could not be allocated for the internal structures + * - one of the error codes from the underlying flash storage driver + */ +esp_err_t nvs_flash_init_partition_ptr(const esp_partition_t *partition); + /** * @brief Deinitialize NVS storage for the default NVS partition * @@ -76,29 +120,133 @@ esp_err_t nvs_flash_deinit_partition(const char* partition_label); /** * @brief Erase the default NVS partition * - * This function erases all contents of the default NVS partition (one with label "nvs") + * Erases all contents of the default NVS partition (one with label "nvs"). + * + * @note If the partition is initialized, this function first de-initializes it. Afterwards, the partition has to + * be initialized again to be used. * * @return * - ESP_OK on success * - ESP_ERR_NOT_FOUND if there is no NVS partition labeled "nvs" in the * partition table + * - different error in case de-initialization fails (shouldn't happen) */ esp_err_t nvs_flash_erase(void); /** * @brief Erase specified NVS partition * - * This function erases all contents of specified NVS partition + * Erase all content of a specified NVS partition * - * @param[in] part_name Name (label) of the partition to be erased + * @note If the partition is initialized, this function first de-initializes it. Afterwards, the partition has to + * be initialized again to be used. + * + * @param[in] part_name Name (label) of the partition which should be erased * * @return * - ESP_OK on success * - ESP_ERR_NOT_FOUND if there is no NVS partition with the specified name * in the partition table + * - different error in case de-initialization fails (shouldn't happen) */ esp_err_t nvs_flash_erase_partition(const char *part_name); +/** + * @brief Erase custom partition. + * + * Erase all content of specified custom partition. + * + * @note + * If the partition is initialized, this function first de-initializes it. + * Afterwards, the partition has to be initialized again to be used. + * + * @param[in] partition pointer to a partition obtained by the ESP partition API. + * + * @return + * - ESP_OK on success + * - ESP_ERR_NOT_FOUND if there is no partition with the specified + * parameters in the partition table + * - ESP_ERR_INVALID_ARG in case partition is NULL + * - one of the error codes from the underlying flash storage driver + */ +esp_err_t nvs_flash_erase_partition_ptr(const esp_partition_t *partition); + +/** + * @brief Initialize the default NVS partition. + * + * This API initialises the default NVS partition. The default NVS partition + * is the one that is labeled "nvs" in the partition table. + * + * @param[in] cfg Security configuration (keys) to be used for NVS encryption/decryption. + * If cfg is NULL, no encryption is used. + * + * @return + * - ESP_OK if storage was successfully initialized. + * - ESP_ERR_NVS_NO_FREE_PAGES if the NVS storage contains no empty pages + * (which may happen if NVS partition was truncated) + * - ESP_ERR_NOT_FOUND if no partition with label "nvs" is found in the partition table + * - ESP_ERR_NO_MEM in case memory could not be allocated for the internal structures + * - one of the error codes from the underlying flash storage driver + */ +esp_err_t nvs_flash_secure_init(nvs_sec_cfg_t* cfg); + +/** + * @brief Initialize NVS flash storage for the specified partition. + * + * @param[in] partition_label Label of the partition. Note that internally a reference to + * passed value is kept and it should be accessible for future operations + * + * @param[in] cfg Security configuration (keys) to be used for NVS encryption/decryption. + * If cfg is null, no encryption/decryption is used. + * @return + * - ESP_OK if storage was successfully initialized. + * - ESP_ERR_NVS_NO_FREE_PAGES if the NVS storage contains no empty pages + * (which may happen if NVS partition was truncated) + * - ESP_ERR_NOT_FOUND if specified partition is not found in the partition table + * - ESP_ERR_NO_MEM in case memory could not be allocated for the internal structures + * - one of the error codes from the underlying flash storage driver + */ +esp_err_t nvs_flash_secure_init_partition(const char *partition_label, nvs_sec_cfg_t* cfg); + +/** + * @brief Generate and store NVS keys in the provided esp partition + * + * @param[in] partition Pointer to partition structure obtained using + * esp_partition_find_first or esp_partition_get. + * Must be non-NULL. + * @param[out] cfg Pointer to nvs security configuration structure. + * Pointer must be non-NULL. + * Generated keys will be populated in this structure. + * + * + * @return + * -ESP_OK, if cfg was read successfully; + * -or error codes from esp_partition_write/erase APIs. + */ + +esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, nvs_sec_cfg_t* cfg); + + +/** + * @brief Read NVS security configuration from a partition. + * + * @param[in] partition Pointer to partition structure obtained using + * esp_partition_find_first or esp_partition_get. + * Must be non-NULL. + * @param[out] cfg Pointer to nvs security configuration structure. + * Pointer must be non-NULL. + * + * @note Provided parition is assumed to be marked 'encrypted'. + * + * @return + * -ESP_OK, if cfg was read successfully; + * -ESP_ERR_NVS_KEYS_NOT_INITIALIZED, if the partition is not yet written with keys. + * -ESP_ERR_NVS_CORRUPT_KEY_PART, if the partition containing keys is found to be corrupt + * -or error codes from esp_partition_read API. + */ + +esp_err_t nvs_flash_read_security_cfg(const esp_partition_t* partition, nvs_sec_cfg_t* cfg); + #ifdef __cplusplus } #endif diff --git a/components/nvs_flash/include/nvs_handle.hpp b/components/nvs_flash/include/nvs_handle.hpp new file mode 100644 index 000000000..287866fad --- /dev/null +++ b/components/nvs_flash/include/nvs_handle.hpp @@ -0,0 +1,280 @@ +#ifndef NVS_HANDLE_HPP_ +#define NVS_HANDLE_HPP_ + +#include +#include +#include + +#include "nvs.h" + +namespace nvs { + +/** + * The possible blob types. This is a helper definition for template functions. + */ +enum class ItemType : uint8_t { + U8 = NVS_TYPE_U8, + I8 = NVS_TYPE_I8, + U16 = NVS_TYPE_U16, + I16 = NVS_TYPE_I16, + U32 = NVS_TYPE_U32, + I32 = NVS_TYPE_I32, + U64 = NVS_TYPE_U64, + I64 = NVS_TYPE_I64, + SZ = NVS_TYPE_STR, + BLOB = 0x41, + BLOB_DATA = NVS_TYPE_BLOB, + BLOB_IDX = 0x48, + ANY = NVS_TYPE_ANY +}; + + +/** + * @brief A handle allowing nvs-entry related operations on the NVS. + * + * @note The scope of this handle may vary depending on the implementation, but normally would be the namespace of + * a particular partition. Outside that scope, nvs entries can't be accessed/altered. + */ +class NVSHandle { +public: + virtual ~NVSHandle() { } + + /** + * @brief set value for given key + * + * Sets value for key. Note that physical storage will not be updated until nvs_commit function is called. + * + * @param[in] key Key name. Maximal length is (NVS_KEY_NAME_MAX_SIZE-1) characters. Shouldn't be empty. + * @param[in] value The value to set. Allowed types are the ones declared in ItemType as well as enums. + * For strings, the maximum length (including null character) is + * 4000 bytes, if there is one complete page free for writing. + * This decreases, however, if the free space is fragmented. + * Note that enums loose their type information when stored in NVS. Ensure that the correct + * enum type is used during retrieval with \ref get_item! + * + * @return + * - ESP_OK if value was set successfully + * - ESP_ERR_NVS_READ_ONLY if storage handle was opened as read only + * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints + * - ESP_ERR_NVS_NOT_ENOUGH_SPACE if there is not enough space in the + * underlying storage to save the value + * - ESP_ERR_NVS_REMOVE_FAILED if the value wasn't updated because flash + * write operation has failed. The value was written however, and + * update will be finished after re-initialization of nvs, provided that + * flash operation doesn't fail again. + * - ESP_ERR_NVS_VALUE_TOO_LONG if the string value is too long + */ + template + esp_err_t set_item(const char *key, T value); + virtual + esp_err_t set_string(const char *key, const char* value) = 0; + + /** + * @brief get value for given key + * + * These functions retrieve value for the key, given its name. If key does not + * exist, or the requested variable type doesn't match the type which was used + * when setting a value, an error is returned. + * + * In case of any error, out_value is not modified. + * + * @param[in] key Key name. Maximal length is (NVS_KEY_NAME_MAX_SIZE-1) characters. Shouldn't be empty. + * @param value The output value. All integral types which are declared in ItemType as well as enums + * are allowed. Note however that enums lost their type information when stored in NVS. + * Ensure that the correct enum type is used during retrieval with \ref get_item! + * + * @return + * - ESP_OK if the value was retrieved successfully + * - ESP_ERR_NVS_NOT_FOUND if the requested key doesn't exist + * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints + * - ESP_ERR_NVS_INVALID_LENGTH if length is not sufficient to store data + */ + template + esp_err_t get_item(const char *key, T &value); + + /** + * @brief set variable length binary value for given key + * + * This family of functions set value for the key, given its name. Note that + * actual storage will not be updated until nvs_commit function is called. + * + * @param[in] key Key name. Maximal length is (NVS_KEY_NAME_MAX_SIZE-1) characters. Shouldn't be empty. + * @param[in] blob The blob value to set. + * @param[in] len length of binary value to set, in bytes; Maximum length is + * 508000 bytes or (97.6% of the partition size - 4000) bytes + * whichever is lower. + * + * @return + * - ESP_OK if value was set successfully + * - ESP_ERR_NVS_READ_ONLY if storage handle was opened as read only + * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints + * - ESP_ERR_NVS_NOT_ENOUGH_SPACE if there is not enough space in the + * underlying storage to save the value + * - ESP_ERR_NVS_REMOVE_FAILED if the value wasn't updated because flash + * write operation has failed. The value was written however, and + * update will be finished after re-initialization of nvs, provided that + * flash operation doesn't fail again. + * - ESP_ERR_NVS_VALUE_TOO_LONG if the value is too long + * + * @note compare to \ref nvs_set_blob in nvs.h + */ + virtual esp_err_t set_blob(const char *key, const void* blob, size_t len) = 0; + + /** + * @brief get value for given key + * + * These functions retrieve the data of an entry, given its key. If key does not + * exist, or the requested variable type doesn't match the type which was used + * when setting a value, an error is returned. + * + * In case of any error, out_value is not modified. + * + * Both functions expect out_value to be a pointer to an already allocated variable + * of the given type. + * + * It is suggested that nvs_get/set_str is used for zero-terminated short C strings, and + * nvs_get/set_blob is used for arbitrary data structures and long C strings. + * + * @param[in] key Key name. Maximum length is (NVS_KEY_NAME_MAX_SIZE-1) characters. Shouldn't be empty. + * @param out_str/ Pointer to the output value. + * out_blob + * @param[inout] len The length of the output buffer pointed to by out_str/out_blob. + * Use \c get_item_size to query the size of the item beforehand. + * + * @return + * - ESP_OK if the value was retrieved successfully + * - ESP_ERR_NVS_NOT_FOUND if the requested key doesn't exist + * - ESP_ERR_NVS_INVALID_NAME if key name doesn't satisfy constraints + * - ESP_ERR_NVS_INVALID_LENGTH if length is not sufficient to store data + */ + virtual esp_err_t get_string(const char *key, char* out_str, size_t len) = 0; + virtual esp_err_t get_blob(const char *key, void* out_blob, size_t len) = 0; + + /** + * @brief Look up the size of an entry's data. + * + * @param[in] datatype Data type to search for. + * @param[in] key Key name. Maximum length is (NVS_KEY_NAME_MAX_SIZE-1) characters. Shouldn't be empty. + * @param[out] size Size of the item, if it exists. + * For strings, this size includes the zero terminator. + * + * @return - ESP_OK if the item with specified type and key exists. Its size will be returned via \c size. + * - ESP_ERR_NVS_NOT_FOUND if an item with the requested key and type doesn't exist or any other + * error occurs. + */ + virtual esp_err_t get_item_size(ItemType datatype, const char *key, size_t &size) = 0; + + /** + * @brief Erases an entry. + */ + virtual esp_err_t erase_item(const char* key) = 0; + + /** + * Erases all entries in the scope of this handle. The scope may vary, depending on the implementation. + * + * @not If you want to erase the whole nvs flash (partition), refer to \ref + */ + virtual esp_err_t erase_all() = 0; + + /** + * Commits all changes done through this handle so far. + * Currently, NVS writes to storage right after the set and get functions, + * but this is not guaranteed. + */ + virtual esp_err_t commit() = 0; + + /** + * @brief Calculate all entries in the scope of the handle. + * + * @param[out] used_entries Returns amount of used entries from a namespace on success. + * + * + * @return + * - ESP_OK if the changes have been written successfully. + * Return param used_entries will be filled valid value. + * - ESP_ERR_NVS_NOT_INITIALIZED if the storage driver is not initialized. + * Return param used_entries will be filled 0. + * - ESP_ERR_INVALID_ARG if nvs_stats equal to NULL. + * - Other error codes from the underlying storage driver. + * Return param used_entries will be filled 0. + */ + virtual esp_err_t get_used_entry_count(size_t& usedEntries) = 0; + +protected: + virtual esp_err_t set_typed_item(ItemType datatype, const char *key, const void* data, size_t dataSize) = 0; + + virtual esp_err_t get_typed_item(ItemType datatype, const char *key, void* data, size_t dataSize) = 0; +}; + +/** + * @brief Opens non-volatile storage and returns a handle object. + * + * The handle is automatically closed on desctruction. The scope of the handle is the namespace ns_name + * in a particular partition partition_name. + * The parameters partition_name, ns_name and open_mode have the same meaning and restrictions as the parameters + * part_name, name and open_mode in \ref nvs_open_from_partition, respectively. + * + * @param err an optional pointer to an esp_err_t result of the open operation, having the same meaning as the return + * value in \ref nvs_open_from_partition: + * - ESP_OK if storage handle was opened successfully + * - ESP_ERR_NVS_NOT_INITIALIZED if the storage driver is not initialized + * - ESP_ERR_NVS_PART_NOT_FOUND if the partition with label "nvs" is not found + * - ESP_ERR_NVS_NOT_FOUND id namespace doesn't exist yet and + * mode is NVS_READONLY + * - ESP_ERR_NVS_INVALID_NAME if namespace name doesn't satisfy constraints + * - other error codes from the underlying storage driver + * + * @return shared pointer of an nvs handle on success, an empty shared pointer otherwise + */ +std::unique_ptr open_nvs_handle_from_partition(const char *partition_name, + const char *ns_name, + nvs_open_mode_t open_mode, + esp_err_t *err = nullptr); + +/** + * @brief This function does the same as \ref open_nvs_handle_from_partition but uses the default nvs partition + * instead of a partition_name parameter. + */ +std::unique_ptr open_nvs_handle(const char *ns_name, + nvs_open_mode_t open_mode, + esp_err_t *err = nullptr); + +// Helper functions for template usage +/** + * Help to translate all integral types into ItemType. + */ +template::value, void*>::type = nullptr> +constexpr ItemType itemTypeOf() +{ + return static_cast(((std::is_signed::value)?0x10:0x00) | sizeof(T)); +} + +/** + * Help to translate all enum types into integral ItemType. + */ +template::value, int>::type = 0> +constexpr ItemType itemTypeOf() +{ + return static_cast(((std::is_signed::value)?0x10:0x00) | sizeof(T)); +} + +template +constexpr ItemType itemTypeOf(const T&) +{ + return itemTypeOf(); +} + +// Template Implementations +template +esp_err_t NVSHandle::set_item(const char *key, T value) { + return set_typed_item(itemTypeOf(value), key, &value, sizeof(value)); +} + +template +esp_err_t NVSHandle::get_item(const char *key, T &value) { + return get_typed_item(itemTypeOf(value), key, &value, sizeof(value)); +} + +} // nvs + +#endif // NVS_HANDLE_HPP_ diff --git a/components/nvs_flash/test_nvs_host/crc.cpp b/components/nvs_flash/mock/int/crc.cpp similarity index 97% rename from components/nvs_flash/test_nvs_host/crc.cpp rename to components/nvs_flash/mock/int/crc.cpp index 4cbb9be9e..5098a1415 100644 --- a/components/nvs_flash/test_nvs_host/crc.cpp +++ b/components/nvs_flash/mock/int/crc.cpp @@ -31,7 +31,7 @@ static const unsigned int crc32_le_table[256] = { 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, - + 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, @@ -52,7 +52,7 @@ static const unsigned int crc32_le_table[256] = { -extern "C" unsigned int crc32_le(unsigned int crc, unsigned char const * buf,unsigned int len) +extern "C" uint32_t crc32_le(unsigned int crc, unsigned char const * buf,unsigned int len) { unsigned int i; crc = ~crc; @@ -61,4 +61,3 @@ extern "C" unsigned int crc32_le(unsigned int crc, unsigned char const * buf,uns } return ~crc; } - diff --git a/components/nvs_flash/test_nvs_host/crc.h b/components/nvs_flash/mock/int/crc.h similarity index 79% rename from components/nvs_flash/test_nvs_host/crc.h rename to components/nvs_flash/mock/int/crc.h index c752b3030..405295f8b 100644 --- a/components/nvs_flash/test_nvs_host/crc.h +++ b/components/nvs_flash/mock/int/crc.h @@ -20,6 +20,10 @@ extern "C" { #endif +/** + * Mock function to replace ESP ROM function used in IDF with a Linux implementation. + * Note: the name MUST have the prefix esp_rom_* since tools/ci/check_rom_apis.sh checks and complains otherwise. + */ uint32_t crc32_le(uint32_t crc, const uint8_t* buf, size_t len); #ifdef __cplusplus diff --git a/components/nvs_flash/nvs_partition_generator/README.rst b/components/nvs_flash/nvs_partition_generator/README.rst index 11f0a2ea6..3a78a109d 100644 --- a/components/nvs_flash/nvs_partition_generator/README.rst +++ b/components/nvs_flash/nvs_partition_generator/README.rst @@ -1,76 +1,312 @@ NVS Partition Generator Utility =============================== +:link_to_translation:`zh_CN:[中文]` + Introduction ------------ -:component_file:`nvs_flash/nvs_partition_generator/nvs_partition_gen.py` utility is designed to help create a binary file, compatible with NVS architecture defined in :doc:`Non-Volatile Storage `, based on user provided key-value pairs in a CSV file. -Utility is ideally suited for generating a binary blob, containing data specific to ODM/OEM, which can be flashed externally at the time of device manufacturing. This helps manufacturers set unique value for various parameters for each device, e.g. serial number, while using same application firmware for all devices. - -CSV file format ---------------- - -Each row of the .csv file should have 4 parameters, separated by comma. Below is the description of each of these parameters: +The utility :component_file:`nvs_flash/nvs_partition_generator/nvs_partition_gen.py` creates a binary file based on key-value pairs provided in a CSV file. The binary file is compatible with NVS architecture defined in :doc:`Non-Volatile Storage `. +This utility is ideally suited for generating a binary blob, containing data specific to ODM/OEM, which can be flashed externally at the time of device manufacturing. This allows manufacturers to generate many instances of the same application firmware with customized parameters for each device, such as a serial number. -Key - Key of the data. Data can later be accessed from an application via this key. +Prerequisites +------------- +To use this utility in encryption mode, install the following packages: + - cryptography package -Type - Supported values are ``file``, ``data`` and ``namespace``. +All the required packages are included in `requirements.txt` in the root of the esp-idf directory. -Encoding - Supported values are: ``u8``, ``i8``, ``u16``, ``u32``, ``i32``, ``string``, ``hex2bin``, ``base64`` and ``binary``. This specifies how actual data values are encoded in the resultant binary file. Difference between ``string`` and ``binary`` encoding is that ``string`` data is terminated with a NULL character, whereas ``binary`` data is not. - - .. note:: For ``file`` type, only ``hex2bin``, ``base64``, ``string`` and ``binary`` is supported as of now. +CSV file format +--------------- -Value - Data value. +Each line of a .csv file should contain 4 parameters, separated by a comma. The table below provides the description for each of these parameters. -.. note:: Encoding and Value cells for ``namespace`` field type should be empty. Encoding and Value of ``namespace`` is fixed and isn't configurable. Any value in these cells are ignored. ++-----+-----------+----------------------------------------------------------------------+-----------------------------------------------------+ +| No. | Parameter | Description | Notes | ++=====+===========+======================================================================+=====================================================+ +| 1 | Key | Key of the data. The data can be accessed later from | | +| | | an application using this key. | | ++-----+-----------+----------------------------------------------------------------------+-----------------------------------------------------+ +| 2 | Type | Supported values are ``file``, ``data`` and ``namespace``. | | ++-----+-----------+----------------------------------------------------------------------+-----------------------------------------------------+ +| 3 | Encoding | Supported values are: ``u8``, ``i8``, ``u16``, ``i16``, ``u32``, | As of now, for the ``file`` type, | +| | | ``i32``, ``u64``, ``i64``, ``string``, ``hex2bin``, ``base64`` | only ``hex2bin``, ``base64``, ``string``, | +| | | and ``binary``. | and ``binary`` encoding is supported. | +| | | This specifies how actual data values are encoded in the | | +| | | resulting binary file. The difference between the ``string`` | | +| | | and ``binary`` encoding is that ``string`` data is terminated | | +| | | with a NULL character, whereas ``binary`` data is not. | | ++-----+-----------+----------------------------------------------------------------------+-----------------------------------------------------+ +| 4 | Value | Data value. | Encoding and Value cells for the ``namespace`` | +| | | | field type should be empty. Encoding and Value | +| | | | of ``namespace`` is fixed and is not configurable. | +| | | | Any values in these cells are ignored. | ++-----+-----------+----------------------------------------------------------------------+-----------------------------------------------------+ -.. note:: First row of the CSV file should always be column header and isn't configurable. +.. note:: The first line of the CSV file should always be the column header and it is not configurable. -Below is an example dump of such CSV file:: +Below is an example dump of such a CSV file:: key,type,encoding,value <-- column header namespace_name,namespace,, <-- First entry should be of type "namespace" key1,data,u8,1 key2,file,string,/path/to/file -.. note:: Make sure there are no spaces before and after ',' in CSV file. +.. note:: + + Make sure there are **no spaces**: + - before and after ',' + - at the end of each line in a CSV file + NVS Entry and Namespace association ----------------------------------- -When a new namespace entry is encountered in the CSV file, each follow-up entries will be part of that namespace, until next namespace entry is found, in which case all the follow-up entries will be part of the new namespace. +When a namespace entry is encountered in a CSV file, each following entry will be treated as part of that namespace until the next namespace entry is found. At this point, all the following entries will be treated as part of the new namespace. + +.. note:: First entry in a CSV file should always be a ``namespace`` entry. + + +Multipage Blob Support +---------------------- + +By default, binary blobs are allowed to span over multiple pages and are written in the format mentioned in Section :ref:`structure_of_entry`. +If you intend to use an older format, the utility provides an option to disable this feature. + + +Encryption Support +------------------- -.. note:: First entry in a CSV file should always be ``namespace`` entry. +The NVS Partition Generator utility also allows you to create an encrypted binary file. The utility uses the AES-XTS encryption. Please refer to :ref:`nvs_encryption` for more details. + + +Decryption Support +------------------- +This utility allows you to decrypt an encrypted NVS binary file. The utility uses an NVS binary file encrypted using AES-XTS encryption. Please refer to :ref:`nvs_encryption` for more details. Running the utility ------------------- -python nvs_partition_gen.py [-h] [--input INPUT] [--output OUTPUT] [--size SIZE] +**Usage**:: + + python nvs_partition_gen.py [-h] {generate,generate-key,encrypt,decrypt} ... + + Optional Arguments: + +-----+------------+----------------------------------------------------------------------+ + | No. | Parameter | Description | + +=====+============+======================================================================+ + | 1 | -h, --help | show this help message and exit | + +-----+------------+----------------------------------------------------------------------+ + + Commands: + Run nvs_partition_gen.py {command} -h for additional help + +-----+--------------+--------------------------------------------------------------------+ + | No. | Parameter | Description | + +=====+==============+====================================================================+ + | 1 | generate | Generate NVS partition | + +-----+--------------+--------------------------------------------------------------------+ + | 2 | generate-key | Generate keys for encryption | + +-----+--------------+--------------------------------------------------------------------+ + | 3 | encrypt | Generate NVS encrypted partition | + +-----+--------------+--------------------------------------------------------------------+ + | 4 | decrypt | Decrypt NVS encrypted partition | + +-----+--------------+--------------------------------------------------------------------+ + + +To generate NVS partition (Default): +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + **Usage**:: + + python nvs_partition_gen.py generate [-h] [--version {1,2}] [--outdir OUTDIR] + input output size + + Positional Arguments: + +--------------+----------------------------------------------------------------------+ + | Parameter | Description | + +==============+======================================================================+ + | input | Path to CSV file to parse | + +--------------+----------------------------------------------------------------------+ + | output | Path to output NVS binary file | + +--------------+----------------------------------------------------------------------+ + | size | Size of NVS partition in bytes (must be multiple of 4096) | + +--------------+----------------------------------------------------------------------+ -+------------------------+----------------------------------------------------------------------------------------------+ -| Arguments | Description | -+========================+==============================================================================================+ -| --input INPUT | Path to CSV file to parse. | -+------------------------+----------------------------------------------------------------------------------------------+ -| --output OUTPUT | Path to output generated binary file. | -+------------------------+----------------------------------------------------------------------------------------------+ -| --size SIZE | Size of NVS Partition in bytes (must be multiple of 4096) | -+------------------------+----------------------------------------------------------------------------------------------+ + Optional Arguments: + +-----------------+--------------------------------------------------------------------+ + | Parameter | Description | + +=================+====================================================================+ + | -h, --help | show this help message and exit | + +-----------------+--------------------------------------------------------------------+ + | --version {1,2} | Set multipage blob version. | + | | Version 1 - Multipage blob support disabled. | + | | Version 2 - Multipage blob support enabled. | + | | Default: Version 2 | + | | | + +-----------------+--------------------------------------------------------------------+ + | --outdir OUTDIR | Output directory to store files created | + | | (Default: current directory) | + +-----------------+--------------------------------------------------------------------+ + + +You can run the utility to generate NVS partition using the command below: A sample CSV file is provided with the utility:: - python nvs_partition_gen.py --input sample.csv --output sample.bin --size 0x3000 + python nvs_partition_gen.py generate sample_singlepage_blob.csv sample.bin 0x3000 + + +To generate only encryption keys: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + **Usage**:: + + python nvs_partition_gen.py generate-key [-h] [--keyfile KEYFILE] + [--outdir OUTDIR] + + Optional Arguments: + +--------------------+----------------------------------------------------------------------+ + | Parameter | Description | + +====================+======================================================================+ + | -h, --help | show this help message and exit | + +--------------------+----------------------------------------------------------------------+ + | --keyfile KEYFILE | Path to output encryption keys file | + +--------------------+----------------------------------------------------------------------+ + | --outdir OUTDIR | Output directory to store files created. | + | | (Default: current directory) | + +--------------------+----------------------------------------------------------------------+ + +You can run the utility to generate only encryption keys using the command below:: + + python nvs_partition_gen.py generate-key + + +To generate encrypted NVS partition: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + **Usage**:: + + python nvs_partition_gen.py encrypt [-h] [--version {1,2}] [--keygen] + [--keyfile KEYFILE] [--inputkey INPUTKEY] + [--outdir OUTDIR] + input output size + + Positional Arguments: + +--------------+----------------------------------------------------------------------+ + | Parameter | Description | + +==============+======================================================================+ + | input | Path to CSV file to parse | + +--------------+----------------------------------------------------------------------+ + | output | Path to output NVS binary file | + +--------------+----------------------------------------------------------------------+ + | size | Size of NVS partition in bytes (must be multiple of 4096) | + +--------------+----------------------------------------------------------------------+ + + + Optional Arguments: + +---------------------+--------------------------------------------------------------------+ + | Parameter | Description | + +=====================+====================================================================+ + | -h, --help | show this help message and exit | + | | | + +---------------------+--------------------------------------------------------------------+ + | --version {1,2} | Set multipage blob version. | + | | Version 1 - Multipage blob support disabled. | + | | Version 2 - Multipage blob support enabled. | + | | Default: Version 2 | + +---------------------+--------------------------------------------------------------------+ + | --keygen | Generates key for encrypting NVS partition | + +---------------------+--------------------------------------------------------------------+ + | --keyfile KEYFILE | Path to output encryption keys file | + +---------------------+--------------------------------------------------------------------+ + | --inputkey INPUTKEY | File having key for encrypting NVS partition | + +---------------------+--------------------------------------------------------------------+ + | --outdir OUTDIR | Output directory to store files created | + | | (Default: current directory) | + +---------------------+--------------------------------------------------------------------+ + + +You can run the utility to encrypt NVS partition using the command below: +A sample CSV file is provided with the utility: + +- Encrypt by allowing the utility to generate encryption keys:: + + python nvs_partition_gen.py encrypt sample_singlepage_blob.csv sample_encr.bin 0x3000 --keygen + +.. note:: Encryption key of the following format ``/keys/keys-.bin`` is created. + +- Encrypt by allowing the utility to generate encryption keys and store it in provided custom filename:: + + python nvs_partition_gen.py encrypt sample_singlepage_blob.csv sample_encr.bin 0x3000 --keygen --keyfile sample_keys.bin + +.. note:: Encryption key of the following format ``/keys/sample_keys.bin`` is created. +.. note:: This newly created file having encryption keys in ``keys/`` directory is compatible with NVS key-partition structure. Refer to :ref:`nvs_key_partition` for more details. + +- Encrypt by providing the encryption keys as input binary file:: + + python nvs_partition_gen.py encrypt sample_singlepage_blob.csv sample_encr.bin 0x3000 --inputkey sample_keys.bin + +To decrypt encrypted NVS partition: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + **Usage**:: + + python nvs_partition_gen.py decrypt [-h] [--outdir OUTDIR] input key output + + Positional Arguments: + +--------------+----------------------------------------------------------------------+ + | Parameter | Description | + +==============+======================================================================+ + | input | Path to encrypted NVS partition file to parse | + +--------------+----------------------------------------------------------------------+ + | key | Path to file having keys for decryption | + +--------------+----------------------------------------------------------------------+ + | output | Path to output decrypted binary file | + +--------------+----------------------------------------------------------------------+ + + + Optional Arguments: + +---------------------+--------------------------------------------------------------------+ + | Parameter | Description | + +=====================+====================================================================+ + | -h, --help | show this help message and exit | + +---------------------+--------------------------------------------------------------------+ + | --outdir OUTDIR | Output directory to store files created | + | | (Default: current directory) | + +---------------------+--------------------------------------------------------------------+ + + +You can run the utility to decrypt encrypted NVS partition using the command below:: + + python nvs_partition_gen.py decrypt sample_encr.bin sample_keys.bin sample_decr.bin + +You can also provide the format version number: + - Multipage Blob Support Disabled (Version 1) + - Multipage Blob Support Enabled (Version 2) + + +Multipage Blob Support Disabled (Version 1): +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can run the utility in this format by setting the version parameter to 1, as shown below. +A sample CSV file is provided with the utility:: + + python nvs_partition_gen.py generate sample_singlepage_blob.csv sample.bin 0x3000 --version 1 + + +Multipage Blob Support Enabled (Version 2): +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can run the utility in this format by setting the version parameter to 2, as shown below. +A sample CSV file is provided with the utility:: + + python nvs_partition_gen.py generate sample_multipage_blob.csv sample.bin 0x4000 --version 2 + .. note:: *Minimum NVS Partition Size needed is 0x3000 bytes.* .. note:: *When flashing the binary onto the device, make sure it is consistent with the application's sdkconfig.* + Caveats ------- -- Utility doesn't check for duplicate keys and will write data pertaining to both keys. User needs to make sure keys are distinct. -- Once a new page is created, no data will be written in the space left in previous page. Fields in the CSV file need to be ordered in such a way so as to optimize memory. +- Utility does not check for duplicate keys and will write data pertaining to both keys. You need to make sure that the keys are distinct. +- Once a new page is created, no data will be written in the space left on the previous page. Fields in the CSV file need to be ordered in such a way as to optimize memory. - 64-bit datatype is not yet supported. + diff --git a/components/nvs_flash/nvs_partition_generator/README_CN.rst b/components/nvs_flash/nvs_partition_generator/README_CN.rst new file mode 100644 index 000000000..24094e993 --- /dev/null +++ b/components/nvs_flash/nvs_partition_generator/README_CN.rst @@ -0,0 +1,304 @@ +NVS 分区生æˆç¨‹åº +=============================== + +:link_to_translation:`en:[English]` + +ä»‹ç» +------------ + +NVS 分区生æˆç¨‹åº (:component_file:`nvs_flash/nvs_partition_generator/nvs_partition_gen.py`) æ ¹æ® CSV 文件中的键值对生æˆäºŒè¿›åˆ¶æ–‡ä»¶ã€‚该二进制文件与 :doc:`éžæ˜“失性存储器 (NVS) ` 中定义的 NVS 结构兼容。NVS 分区生æˆç¨‹åºé€‚åˆç”¨äºŽç”ŸæˆäºŒè¿›åˆ¶æ•°æ®ï¼ˆBlob),其中包括设备生产时å¯ä»Žå¤–部烧录的 ODM/OEM æ•°æ®ã€‚这也使得生产制造商在使用åŒä¸€ä¸ªå›ºä»¶çš„åŸºç¡€ä¸Šï¼Œé€šè¿‡è‡ªå®šä¹‰å‚æ•°ï¼Œå¦‚åºåˆ—å·ç­‰ï¼Œä¸ºæ¯ä¸ªè®¾å¤‡ç”Ÿæˆä¸åŒé…置。 + +准备工作 +------------- + +在加密模å¼ä¸‹ä½¿ç”¨è¯¥ç¨‹åºï¼Œéœ€å®‰è£…下列软件包: + - cryptography package + +根目录下的 `requirements.txt` 包å«å¿…需 python 包,请预先安装。 + + +CSV æ–‡ä»¶æ ¼å¼ +--------------- + +.csv 文件æ¯è¡Œéœ€åŒ…å«å››ä¸ªå‚数,以逗å·éš”å¼€ã€‚å…·ä½“å‚æ•°æè¿°è§ä¸‹è¡¨ï¼š + ++------+----------+--------------------------------------------------------------+-----------------------------------------------------------------+ +| åºå· | 傿•° | æè¿° | 说明 | ++======+==========+==============================================================+=================================================================+ +| 1 | Key | 主键,应用程åºå¯é€šè¿‡æŸ¥è¯¢æ­¤é”®æ¥èŽ·å–æ•°æ®ã€‚ | | ++------+----------+--------------------------------------------------------------+-----------------------------------------------------------------+ +| 2 | Type | æ”¯æŒ ``file``ã€``data`` å’Œ ``namespace``。 | | ++------+----------+--------------------------------------------------------------+-----------------------------------------------------------------+ +| 3 | Encoding | æ”¯æŒ ``u8``ã€``i8``ã€``u16``ã€``u32``〠| ``file`` | +| | | ``i32``ã€``string``ã€``hex2bin``ã€``base64`` å’Œ ``binary``。 | 类型当å‰ä»…æ”¯æŒ | +| | | 决定二进制 ``bin`` 文件中 value è¢«ç¼–ç æˆçš„类型。 | ``hex2bin``ã€``base64``〠| +| | | ``string`` å’Œ ``binary`` ç¼–ç çš„区别在于, | ``string`` å’Œ ``binary`` ç¼–ç ã€‚ | +| | | ``string`` æ•°æ®ä»¥ NULL 字符结尾,``binary`` æ•°æ®åˆ™ä¸æ˜¯ã€‚ | | ++------+----------+--------------------------------------------------------------+-----------------------------------------------------------------+ +| 4 | Value | Data value | ``namespace`` 字段的 ``encoding`` å’Œ ``value`` 应为空。 | +| | | | ``namespace`` çš„ ``encoding`` å’Œ ``value`` 为固定值,ä¸å¯è®¾ç½®ã€‚ | +| | | | 这些å•元格中的所有值都会被忽视。 | ++------+----------+--------------------------------------------------------------+-----------------------------------------------------------------+ + +.. note:: CSV 文件的第一行应为列标题,ä¸å¯è®¾ç½®ã€‚ + +此类 CSV 文件的 Dump 示例如下:: + + key,type,encoding,value <-- 列标题 + namespace_name,namespace,, <-- 第一个æ¡ç›®ä¸º "namespace" + key1,data,u8,1 + key2,file,string,/path/to/file + + +.. note:: + + 请确ä¿ï¼š + - é€—å· ',' å‰åŽæ— ç©ºæ ¼ï¼› + - CSV 文件æ¯è¡Œæœ«å°¾æ— ç©ºæ ¼ã€‚ + +NVS æ¡ç›®å’Œå‘½å空间 (namespace) +----------------------------------- + +如 CSV 文件中出现命å空间æ¡ç›®ï¼ŒåŽç»­æ¡ç›®å‡ä¼šè¢«è§†ä¸ºè¯¥å‘½å空间的一部分,直至找到下一个命å空间æ¡ç›®ã€‚找到新命å空间æ¡ç›®åŽï¼ŒåŽç»­æ‰€æœ‰æ¡ç›®éƒ½ä¼šè¢«è§†ä¸ºæ–°å‘½å空间的一部分。 + +.. note:: CSV 文件中第一个æ¡ç›®åº”始终为 ``namespace``。 + + +支æŒå¤šé¡µ Blob +---------------------- + +默认情况下,二进制 Blob å¯è·¨å¤šé¡µï¼Œæ ¼å¼å‚考 :ref:`structure_of_entry` 章节。如需使用旧版格å¼ï¼Œå¯åœ¨ç¨‹åºä¸­ç¦ç”¨è¯¥åŠŸèƒ½ã€‚ + + +支æŒåР坆 +------------------- + +NVS 分区生æˆç¨‹åºè¿˜å¯ä½¿ç”¨ AES-XTS 加密生æˆäºŒè¿›åˆ¶åŠ å¯†æ–‡ä»¶ã€‚æ›´å¤šä¿¡æ¯è¯¦è§ :ref:`nvs_encryption`。 + +支æŒè§£å¯† +------------------- +如果 NVS 二进制文件采用了 AES-XTS 加密,该程åºè¿˜å¯å¯¹æ­¤ç±»æ–‡ä»¶è¿›è¡Œè§£å¯†ï¼Œæ›´å¤šä¿¡æ¯è¯¦è§ :ref:`nvs_encryption`。 + +è¿è¡Œç¨‹åº +------------------- + +**使用方法**:: + + python nvs_partition_gen.py [-h] {generate,generate-key,encrypt,decrypt} ... + +**å¯é€‰å‚æ•°**: + ++------+------------+----------------------+ +| åºå· | 傿•° | æè¿° | ++------+------------+----------------------+ +| 1 | -h, --help | 显示帮助信æ¯å¹¶é€€å‡º | ++------+------------+----------------------+ + +**命令**:: + + è¿è¡Œ nvs_partition_gen.py {command} -h æŸ¥çœ‹æ›´å¤šå¸®åŠ©ä¿¡æ¯ + ++------+--------------+---------------+ +| åºå· | 傿•° | æè¿° | ++------+--------------+---------------+ +| 1 | generate | ç”Ÿæˆ NVS 分区 | ++------+--------------+---------------+ +| 2 | generate-key | 生æˆåР坆坆钥 | ++------+--------------+---------------+ +| 3 | encrypt | 加密 NVS 分区 | ++------+--------------+---------------+ +| 4 | decrypt | 解密 NVS 分区 | ++------+--------------+---------------+ + + +ç”Ÿæˆ NVS 分区(默认模å¼ï¼‰ +---------------------------------- + +**使用方法**:: + + python nvs_partition_gen.py generate [-h] [--version {1,2}] [--outdir OUTDIR] + input output size + +**ä½ç½®å‚æ•°**: + ++--------+--------------------------------------------------+ +| 傿•° | æè¿° | ++--------+--------------------------------------------------+ +| input | å¾…è§£æžçš„ CSV 文件路径 | ++--------+--------------------------------------------------+ +| output | NVS 二进制文件的输出路径 | ++--------+--------------------------------------------------+ +| size | NVS 分区大å°ï¼ˆä»¥å­—节为å•ä½ï¼Œä¸”为 4096 的整数å€ï¼‰ | ++--------+--------------------------------------------------+ + +**å¯é€‰å‚æ•°**: + ++-----------------+------------------------------------------------+ +| 傿•° | æè¿° | ++-----------------+------------------------------------------------+ +| -h, --help | 显示帮助信æ¯å¹¶é€€å‡º | ++-----------------+------------------------------------------------+ +| --version {1,2} | - 设置多页 Blob 版本。 | +| | - 版本 1:ç¦ç”¨å¤šé¡µ Blobï¼› | +| | - 版本 2:å¯ç”¨å¤šé¡µ Blobï¼› | +| | - 默认版本:版本 2。 | ++-----------------+------------------------------------------------+ +| --outdir OUTDIR | 输出目录,用于存储创建的文件。(默认当å‰ç›®å½•) | ++-----------------+------------------------------------------------+ + +è¿è¡Œå¦‚下命令创建 NVS 分区,该程åºåŒæ—¶ä¼šæä¾› CSV 示例文件:: + + python nvs_partition_gen.py generate sample_singlepage_blob.csv sample.bin 0x3000 + +仅生æˆåР坆坆钥 +----------------------- + +**使用方法**:: + + python nvs_partition_gen.py generate-key [-h] [--keyfile KEYFILE] + [--outdir OUTDIR] + +**å¯é€‰å‚æ•°**: + ++-------------------+------------------------------------------------+ +| 傿•° | æè¿° | ++-------------------+------------------------------------------------+ +| -h, --help | 显示帮助信æ¯å¹¶é€€å‡º | ++-------------------+------------------------------------------------+ +| --keyfile KEYFILE | 加密密钥文件的输出路径 | ++-------------------+------------------------------------------------+ +| --outdir OUTDIR | 输出目录,用于存储创建的文件。(默认当å‰ç›®å½•) | ++-------------------+------------------------------------------------+ + +è¿è¡Œä»¥ä¸‹å‘½ä»¤ä»…生æˆåР坆坆钥:: + + python nvs_partition_gen.py generate-key + +ç”Ÿæˆ NVS 加密分区 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**使用方法**:: + + python nvs_partition_gen.py encrypt [-h] [--version {1,2}] [--keygen] + [--keyfile KEYFILE] [--inputkey INPUTKEY] + [--outdir OUTDIR] + input output size + +**ä½ç½®å‚æ•°**: + ++--------+--------------------------------------+ +| 傿•° | æè¿° | ++--------+--------------------------------------+ +| input | å¾…è§£æž CSV 文件的路径 | ++--------+--------------------------------------+ +| output | NVS 二进制文件的输出路径 | ++--------+--------------------------------------+ +| size | NVS åˆ†åŒºå¤§å° | +| | (以字节为å•ä½ï¼Œä¸”为 4096 的整数å€ï¼‰ | ++--------+--------------------------------------+ + +**å¯é€‰å‚æ•°**: + ++---------------------+------------------------------+ +| 傿•° | æè¿° | ++---------------------+------------------------------+ +| -h, --help | 显示帮助信æ¯å¹¶é€€å‡º | ++---------------------+------------------------------+ +| --version {1,2} | - 设置多页 Blob 版本。 | +| | - 版本 1:ç¦ç”¨å¤šé¡µ Blobï¼› | +| | - 版本 2:å¯ç”¨å¤šé¡µ Blobï¼› | +| | - 默认版本:版本 2。 | ++---------------------+------------------------------+ +| --keygen | ç”Ÿæˆ NVS 分区加密密钥 | ++---------------------+------------------------------+ +| --keyfile KEYFILE | 密钥文件的输出路径 | ++---------------------+------------------------------+ +| --inputkey INPUTKEY | å†…å« NVS 分区加密密钥的文件 | ++---------------------+------------------------------+ +| --outdir OUTDIR | 输出目录,用于存储创建的文件 | +| | (默认当å‰ç›®å½•) | ++---------------------+------------------------------+ + +è¿è¡Œä»¥ä¸‹å‘½ä»¤åР坆 NVS 分区,该程åºåŒæ—¶ä¼šæä¾›ä¸€ä¸ª CSV 示例文件。 + +- 通过 NVS 分区生æˆç¨‹åºç”ŸæˆåР坆坆钥æ¥åР坆:: + + python nvs_partition_gen.py encrypt sample_singlepage_blob.csv sample_encr.bin 0x3000 --keygen + +.. note:: 创建的加密密钥格å¼ä¸º ``/keys/keys-.bin``。 + +- 通过 NVS 分区生æˆç¨‹åºç”ŸæˆåŠ å¯†å¯†é’¥ï¼Œå¹¶å°†å¯†é’¥å­˜å‚¨äºŽè‡ªå®šä¹‰çš„æ–‡ä»¶ä¸­:: + + python nvs_partition_gen.py encrypt sample_singlepage_blob.csv sample_encr.bin 0x3000 --keygen --keyfile sample_keys.bin + +.. note:: 创建的加密密钥格å¼ä¸º ``/keys/keys-.bin``。 +.. note:: 加密密钥存储于新建文件的 ``keys/`` 目录下,与 NVS 密钥分区结构兼容。更多信æ¯è¯·å‚考 :ref:`nvs_key_partition`。 + +- 将加密密钥用作二进制输入文件æ¥è¿›è¡ŒåР坆:: + + python nvs_partition_gen.py encrypt sample_singlepage_blob.csv sample_encr.bin 0x3000 --inputkey sample_keys.bin + +解密 NVS 分区 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**使用方法**:: + + python nvs_partition_gen.py decrypt [-h] [--outdir OUTDIR] input key output + +**ä½ç½®å‚æ•°**: + ++--------+-------------------------------+ +| 傿•° | æè¿° | ++--------+-------------------------------+ +| input | å¾…è§£æžçš„ NVS 加密分区文件路径 | ++--------+-------------------------------+ +| key | 嫿œ‰è§£å¯†å¯†é’¥çš„æ–‡ä»¶è·¯å¾„ | ++--------+-------------------------------+ +| output | 已解密的二进制文件输出路径 | ++--------+-------------------------------+ + +**å¯é€‰å‚æ•°**: + ++-----------------+------------------------------+ +| 傿•° | æè¿° | ++-----------------+------------------------------+ +| -h, --help | 显示帮助信æ¯å¹¶é€€å‡º | ++-----------------+------------------------------+ +| --outdir OUTDIR | 输出目录,用于存储创建的文件 | +| | (默认当å‰ç›®å½•) | ++-----------------+------------------------------+ + +è¿è¡Œä»¥ä¸‹å‘½ä»¤è§£å¯†å·²åŠ å¯†çš„ NVS 分区:: + + python nvs_partition_gen.py decrypt sample_encr.bin sample_keys.bin sample_decr.bin + +您å¯ä»¥è‡ªå®šä¹‰æ ¼å¼ç‰ˆæœ¬å·ï¼š + +- 版本 1:ç¦ç”¨å¤šé¡µ Blob +- 版本 2:å¯ç”¨å¤šé¡µ Blob + +版本 1:ç¦ç”¨å¤šé¡µ Blob +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +如需ç¦ç”¨å¤šé¡µ Blobï¼Œè¯·æŒ‰ç…§å¦‚ä¸‹å‘½ä»¤å°†ç‰ˆæœ¬å‚æ•°è®¾ç½®ä¸º 1,以此格å¼è¿è¡Œåˆ†åŒºç”Ÿæˆç¨‹åºã€‚该程åºåŒæ—¶ä¼šæä¾›ä¸€ä¸ª CSV 示例文件:: + + python nvs_partition_gen.py generate sample_singlepage_blob.csv sample.bin 0x3000 --version 1 + +版本 2:å¯ç”¨å¤šé¡µ Blob +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +如需å¯ç”¨å¤šé¡µ Blobï¼Œè¯·æŒ‰ç…§å¦‚ä¸‹å‘½ä»¤å°†ç‰ˆæœ¬å‚æ•°è®¾ç½®ä¸º 2,以此格å¼è¿è¡Œåˆ†åŒºç”Ÿæˆç¨‹åºã€‚该程åºåŒæ—¶ä¼šæä¾›ä¸€ä¸ª CSV 示例文件:: + + python nvs_partition_gen.py generate sample_multipage_blob.csv sample.bin 0x4000 --version 2 + +.. note:: NVS 分区最å°ä¸º 0x3000 字节。 + +.. note:: 将二进制文件烧录至设备时,请确ä¿ä¸Žåº”用的 sdkconfig 设置一致。 + + +说明 +------- + +- 分区生æˆç¨‹åºä¸ä¼šå¯¹é‡å¤é”®è¿›è¡Œæ£€æŸ¥ï¼Œè€Œå°†æ•°æ®åŒæ—¶å†™å…¥è¿™ä¸¤ä¸ªé‡å¤é”®ä¸­ã€‚请注æ„ä¸è¦ä½¿ç”¨åŒå的键; +- 新页é¢åˆ›å»ºåŽï¼Œå‰ä¸€é¡µçš„空白处ä¸ä¼šå†å†™å…¥æ•°æ®ã€‚CSV æ–‡ä»¶ä¸­çš„å­—æ®µé¡»æŒ‰æ¬¡åºæŽ’åˆ—ä»¥ä¼˜åŒ–å†…å­˜ï¼› +- æš‚ä¸æ”¯æŒ 64 使•°æ®ç±»åž‹ã€‚ diff --git a/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py b/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py index d5ddc55b0..890f5222b 100755 --- a/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py +++ b/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py @@ -19,32 +19,55 @@ # from __future__ import division, print_function -from builtins import int, range, bytes -from io import open -import sys + import argparse +import array import binascii +import codecs +import datetime +import distutils.dir_util +import os import random import struct -import os -import array -import csv +import sys import zlib -import codecs -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes -from cryptography.hazmat.backends import default_backend +from builtins import bytes, int, range +from io import open + +from future.moves.itertools import zip_longest -VERSION1_PRINT = "v1 - Multipage Blob Support Disabled" -VERSION2_PRINT = "v2 - Multipage Blob Support Enabled" +try: + from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +except ImportError: + print('The cryptography package is not installed.' + 'Please refer to the Get Started section of the ESP-IDF Programming Guide for ' + 'setting up the required packages.') + raise + +VERSION1_PRINT = 'V1 - Multipage Blob Support Disabled' +VERSION2_PRINT = 'V2 - Multipage Blob Support Enabled' + + +def reverse_hexbytes(addr_tmp): + addr = [] + reversed_bytes = '' + for i in range(0, len(addr_tmp), 2): + addr.append(addr_tmp[i:i + 2]) + reversed_bytes = ''.join(reversed(addr)) + + return reversed_bytes """ Class for standard NVS page structure """ + + class Page(object): PAGE_PARAMS = { - "max_size": 4096, - "max_old_blob_size": 1984, - "max_new_blob_size": 4000, - "max_entries": 126 + 'max_size': 4096, + 'max_old_blob_size': 1984, + 'max_new_blob_size': 4000, + 'max_entries': 126 } # Item type codes @@ -54,6 +77,8 @@ class Page(object): I16 = 0x12 U32 = 0x04 I32 = 0x14 + U64 = 0x08 + I64 = 0x18 SZ = 0x21 BLOB = 0x41 BLOB_DATA = 0x42 @@ -68,25 +93,21 @@ class Page(object): CHUNK_ANY = 0xFF ACTIVE = 0xFFFFFFFE FULL = 0xFFFFFFFC - VERSION1=0xFF - VERSION2=0xFE + VERSION1 = 0xFF + VERSION2 = 0xFE - def __init__(self, page_num, is_rsrv_page=False): + def __init__(self, page_num, version, is_rsrv_page=False): self.entry_num = 0 - self.is_encrypt = False - self.encr_key = None self.bitmap_array = array.array('B') - self.version = Page.VERSION2 - self.page_buf = bytearray(b'\xff')*Page.PAGE_PARAMS["max_size"] + self.version = version + self.page_buf = bytearray(b'\xff') * Page.PAGE_PARAMS['max_size'] if not is_rsrv_page: self.bitmap_array = self.create_bitmap_array() - self.set_header(page_num) - - def set_header(self, page_num): - global page_header + self.set_header(page_num, version) + def set_header(self, page_num, version): # set page state to active - page_header= bytearray(b'\xff') *32 + page_header = bytearray(b'\xff') * 32 page_state_active_seq = Page.ACTIVE struct.pack_into(' 2: if not addr_len % 2: addr_tmp = addr - tweak_tmp = self.reverse_hexbytes(addr_tmp) - tweak_val = tweak_tmp + (init_tweak_val * (tweak_len_needed - (len(tweak_tmp)))) else: addr_tmp = init_tweak_val + addr - tweak_tmp = self.reverse_hexbytes(addr_tmp) - tweak_val = tweak_tmp + (init_tweak_val * (tweak_len_needed - (len(tweak_tmp)))) + tweak_tmp = reverse_hexbytes(addr_tmp) + tweak_val = tweak_tmp + (init_tweak_val * (tweak_len_needed - (len(tweak_tmp)))) else: tweak_val = addr + (init_tweak_val * (tweak_len_needed - len(addr))) @@ -207,11 +212,10 @@ def encrypt_data(self, data_input, no_of_entries, nvs_obj): return encr_data_to_write - def write_entry_to_buf(self, data, entrycount,nvs_obj): encr_data = bytearray() - if self.is_encrypt: + if nvs_obj.encrypt: encr_data_ret = self.encrypt_data(data, entrycount,nvs_obj) encr_data[0:len(encr_data_ret)] = encr_data_ret data = encr_data @@ -226,7 +230,6 @@ def write_entry_to_buf(self, data, entrycount,nvs_obj): self.write_bitmaparray() self.entry_num += 1 - def set_crc_header(self, entry_struct): crc_data = bytearray(b'28') crc_data[0:4] = entry_struct[0:4] @@ -236,7 +239,6 @@ def set_crc_header(self, entry_struct): struct.pack_into('=0, "Page overflow!!" + tailroom = (Page.PAGE_PARAMS['max_entries'] - self.entry_num - 1) * Page.SINGLE_ENTRY_SIZE + assert tailroom >= 0, 'Page overflow!!' # Split the binary data into two and store a chunk of available size onto curr page if tailroom < remaining_size: @@ -266,7 +268,7 @@ def write_varlen_binary_data(self, entry_struct, ns_index, key, data, data_size, # Calculate no. of entries data chunk will require datachunk_rounded_size = (chunk_size + 31) & ~31 datachunk_entry_count = datachunk_rounded_size // 32 - datachunk_total_entry_count = datachunk_entry_count + 1 # +1 for the entry header + datachunk_total_entry_count = datachunk_entry_count + 1 # +1 for the entry header # Set Span entry_struct[2] = datachunk_total_entry_count @@ -276,7 +278,7 @@ def write_varlen_binary_data(self, entry_struct, ns_index, key, data, data_size, entry_struct[3] = chunk_index # Set data chunk - data_chunk = data[offset:offset + chunk_size] + data_chunk = data[offset:offset + chunk_size] # Compute CRC of data chunk struct.pack_into(' Page.PAGE_PARAMS["max_old_blob_size"]: - raise InputError("Version %s\n%s: Size exceeds max allowed length." % (VERSION1_PRINT,key)) - - if version == Page.VERSION2: - if encoding == "string": - if datalen > Page.PAGE_PARAMS["max_new_blob_size"]: - raise InputError("Version %s\n%s: Size exceeds max allowed length." % (VERSION2_PRINT,key)) + if datalen > Page.PAGE_PARAMS['max_old_blob_size']: + if self.version == Page.VERSION1: + raise InputError(' Input File: Size (%d) exceeds max allowed length `%s` bytes for key `%s`.' + % (datalen, Page.PAGE_PARAMS['max_old_blob_size'], key)) + else: + if encoding == 'string': + raise InputError(' Input File: Size (%d) exceeds max allowed length `%s` bytes for key `%s`.' + % (datalen, Page.PAGE_PARAMS['max_old_blob_size'], key)) # Calculate no. of entries data will require rounded_size = (datalen + 31) & ~31 data_entry_count = rounded_size // 32 - total_entry_count = data_entry_count + 1 # +1 for the entry header + total_entry_count = data_entry_count + 1 # +1 for the entry header # Check if page is already full and new page is needed to be created right away - if version == Page.VERSION1: - if encoding in ["string", "hex2bin", "binary", "base64"]: - if (self.entry_num + total_entry_count) >= Page.PAGE_PARAMS["max_entries"]: - raise PageFullError() - else: - if encoding == "string": - if (self.entry_num + total_entry_count) >= Page.PAGE_PARAMS["max_entries"]: - raise PageFullError() + if self.entry_num >= Page.PAGE_PARAMS['max_entries']: + raise PageFullError() + elif (self.entry_num + total_entry_count) >= Page.PAGE_PARAMS['max_entries']: + if not (self.version == Page.VERSION2 and encoding in ['hex2bin', 'binary', 'base64']): + raise PageFullError() # Entry header - entry_struct = bytearray(b'\xff')*32 + entry_struct = bytearray(b'\xff') * 32 # Set Namespace Index entry_struct[0] = ns_index # Set Span - if version == Page.VERSION2: - if encoding == "string": + if self.version == Page.VERSION2: + if encoding == 'string': entry_struct[2] = data_entry_count + 1 # Set Chunk Index chunk_index = Page.CHUNK_ANY @@ -408,51 +401,58 @@ def write_varlen_data(self, key, data, encoding, ns_index,nvs_obj): entry_struct[8:8 + len(key)] = key.encode() # set Type - if encoding == "string": + if encoding == 'string': entry_struct[1] = Page.SZ - elif encoding in ["hex2bin", "binary", "base64"]: + elif encoding in ['hex2bin', 'binary', 'base64']: entry_struct[1] = Page.BLOB - if version == Page.VERSION2 and (encoding in ["hex2bin", "binary", "base64"]): - entry_struct = self.write_varlen_binary_data(entry_struct,ns_index,key,data,\ - datalen,total_entry_count, encoding, nvs_obj) + if self.version == Page.VERSION2 and (encoding in ['hex2bin', 'binary', 'base64']): + entry_struct = self.write_varlen_binary_data(entry_struct,ns_index,key,data, + datalen,total_entry_count, encoding, nvs_obj) else: self.write_single_page_entry(entry_struct, data, datalen, data_entry_count, nvs_obj) - - """ Low-level function to write data of primitive type into page buffer. """ def write_primitive_data(self, key, data, encoding, ns_index,nvs_obj): # Check if entry exceeds max number of entries allowed per page - if self.entry_num >= Page.PAGE_PARAMS["max_entries"]: + if self.entry_num >= Page.PAGE_PARAMS['max_entries']: raise PageFullError() - entry_struct = bytearray(b'\xff')*32 - entry_struct[0] = ns_index # namespace index - entry_struct[2] = 0x01 # Span + entry_struct = bytearray(b'\xff') * 32 + entry_struct[0] = ns_index # namespace index + entry_struct[2] = 0x01 # Span chunk_index = Page.CHUNK_ANY entry_struct[3] = chunk_index # write key - key_array = b'\x00' *16 + key_array = b'\x00' * 16 entry_struct[8:24] = key_array entry_struct[8:8 + len(key)] = key.encode() - if encoding == "u8": + if encoding == 'u8': entry_struct[1] = Page.U8 struct.pack_into('/ + :param outdir: Target output dir to store files + :param filepath: Path of target file + ''' + bin_ext = '.bin' + # Expand if tilde(~) provided in path + outdir = os.path.expanduser(outdir) + + if filepath: + key_file_name, ext = os.path.splitext(filepath) + if not ext: + filepath = key_file_name + bin_ext + elif bin_ext not in ext: + sys.exit('Error: `%s`. Only `%s` extension allowed.' % (filepath, bin_ext)) + + # Create dir if does not exist + if not (os.path.isdir(outdir)): + distutils.dir_util.mkpath(outdir) + + filedir, filename = os.path.split(filepath) + filedir = os.path.join(outdir,filedir,'') + if filedir and not os.path.isdir(filedir): + distutils.dir_util.mkpath(filedir) + + if os.path.isabs(filepath): + if not outdir == os.getcwd(): + print('\nWarning: `%s` \n\t==> absolute path given so outdir is ignored for this file.' % filepath) + # Set to empty as outdir is ignored here + outdir = '' + + # Set full path - outdir + filename + filepath = os.path.join(outdir, '') + filepath + + return outdir, filepath + + +def encrypt(args): + ''' + Generate encrypted NVS Partition + :param args: Command line arguments given + ''' + key = None + bin_ext = '.bin' + + check_size(args.size) + if (args.keygen is False) and (not args.inputkey): + sys.exit('Error. --keygen or --inputkey argument needed.') + elif args.keygen and args.inputkey: + sys.exit('Error. --keygen and --inputkey both are not allowed.') + elif not args.keygen and args.keyfile: + print('\nWarning:','--inputkey argument is given. --keyfile argument will be ignored...') + + if args.inputkey: + # Check if key file has .bin extension + filename, ext = os.path.splitext(args.inputkey) + if bin_ext not in ext: + sys.exit('Error: `%s`. Only `%s` extension allowed.' % (args.inputkey, bin_ext)) + key = bytearray() + with open(args.inputkey, 'rb') as key_f: + key = key_f.read(64) + + # Generate encrypted NVS Partition + generate(args, is_encr_enabled=True, encr_key=key) + + +def decrypt_data(data_input, decr_key, page_num, entry_no, entry_size): + ''' + Decrypt NVS data entry + ''' + page_max_size = 4096 + first_entry_offset = 64 + init_tweak_val = '0' + tweak_len_needed = 32 # in hex + tweak_tmp = '' + + data_input = binascii.hexlify(data_input) + rel_addr = page_num * page_max_size + first_entry_offset + + # Set tweak value + offset = entry_no * entry_size + addr = hex(rel_addr + offset)[2:] + addr_len = len(addr) + if addr_len > 2: + if not addr_len % 2: + addr_tmp = addr + else: + addr_tmp = init_tweak_val + addr + tweak_tmp = reverse_hexbytes(addr_tmp) + tweak_val = tweak_tmp + (init_tweak_val * (tweak_len_needed - (len(tweak_tmp)))) + else: + tweak_val = addr + (init_tweak_val * (tweak_len_needed - len(addr))) + + if type(data_input) == bytes: + data_input = data_input.decode() + + # Decrypt 32 bytes of data using AES-XTS decryption + backend = default_backend() + plain_text = codecs.decode(data_input, 'hex') + tweak = codecs.decode(tweak_val, 'hex') + cipher = Cipher(algorithms.AES(decr_key), modes.XTS(tweak), backend=backend) + decryptor = cipher.decryptor() + decrypted_data = decryptor.update(plain_text) + + return decrypted_data + + +def decrypt(args): + ''' + Decrypt encrypted NVS Partition + :param args: Command line arguments given + ''' + bin_ext = '.bin' + nvs_read_bytes = 32 + decrypted_entry_no = 0 + file_entry_no = 0 + page_num = 0 + page_max_size = 4096 + start_entry_offset = 0 + empty_data_entry = bytearray(b'\xff') * nvs_read_bytes + + # Check if key file has .bin extension + input_files = [args.input, args.key, args.output] + for filepath in input_files: + filename, ext = os.path.splitext(filepath) + if bin_ext not in ext: + sys.exit('Error: `%s`. Only `%s` extension allowed.' % (filepath, bin_ext)) + with open(args.key,'rb') as decr_key_file: + decr_key = decr_key_file.read(64) + + args.outdir, args.output = set_target_filepath(args.outdir, args.output) + + output_buf = bytearray(b'\xff') + + with open(args.input, 'rb') as input_file, open(args.output,'wb') as output_file: + while True: + if file_entry_no == 128: + decrypted_entry_no = 0 + file_entry_no = 0 + page_num += 1 + data_entry = input_file.read(nvs_read_bytes) + if not data_entry: + break + if data_entry != empty_data_entry and file_entry_no not in [0,1]: + data_entry = decrypt_data(data_entry, decr_key, page_num, decrypted_entry_no, nvs_read_bytes) + decrypted_entry_no += 1 + write_entry_no = ((page_num * page_max_size) + file_entry_no) + start_idx = start_entry_offset + (write_entry_no * nvs_read_bytes) + end_idx = nvs_read_bytes + output_buf[start_idx:end_idx] = data_entry + file_entry_no += 1 + start_entry_offset += nvs_read_bytes + output_file.write(output_buf) + + print('\nCreated NVS decrypted binary: ===>', args.output) + + +def generate_key(args): + ''' + Generate encryption keys + :param args: Command line arguments given + ''' + page_max_size = 4096 + keys_dir = 'keys' + output_keyfile = None + bin_ext = '.bin' + + if not args.keyfile: + timestamp = datetime.datetime.now().strftime('%m-%d_%H-%M') + args.keyfile = 'keys-' + timestamp + bin_ext + + keys_outdir = os.path.join(args.outdir,keys_dir, '') + # Create keys/ dir in if does not exist + if not (os.path.isdir(keys_outdir)): + distutils.dir_util.mkpath(keys_outdir) + keys_outdir, output_keyfile = set_target_filepath(keys_outdir, args.keyfile) + + key = ''.join(random.choice('0123456789abcdef') for _ in range(128)).strip() + encr_key_bytes = codecs.decode(key, 'hex') + key_len = len(encr_key_bytes) + + keys_buf = bytearray(b'\xff') * page_max_size + keys_buf[0:key_len] = encr_key_bytes + crc_data = keys_buf[0:key_len] + crc_data = bytes(crc_data) + crc = zlib.crc32(crc_data, 0xFFFFFFFF) + struct.pack_into(' ', output_keyfile) + + return key + + +def generate(args, is_encr_enabled=False, encr_key=None): + ''' + Generate NVS Partition + :param args: Command line arguments given + :param is_encr_enabled: Encryption enabled/disabled + :param encr_key: Key to encrypt NVS partition + ''' + is_dir_new = False + bin_ext = '.bin' + + input_size = check_size(args.size) + if args.version == 1: + args.version = Page.VERSION1 + elif args.version == 2: + args.version = Page.VERSION2 + + # Check if key file has .bin extension + filename, ext = os.path.splitext(args.output) + if bin_ext not in ext: + sys.exit('Error: `%s`. Only `.bin` extension allowed.' % args.output) + args.outdir, args.output = set_target_filepath(args.outdir, args.output) + + if is_encr_enabled and not encr_key: + encr_key = generate_key(args) + + input_file = open(args.input, 'rt', encoding='utf8') + output_file = open(args.output, 'wb') + + with open(args.input, 'rt', encoding='utf8') as input_file,\ + open(args.output, 'wb') as output_file,\ + nvs_open(output_file, input_size, args.version, is_encrypt=is_encr_enabled, key=encr_key) as nvs_obj: + + if nvs_obj.version == Page.VERSION1: + version_set = VERSION1_PRINT + else: + version_set = VERSION2_PRINT -def nvs_part_gen(input_filename=None, output_filename=None, input_part_size=None, is_key_gen=None, encrypt_mode=None, key_file=None, version_no=None): - """ Wrapper to generate nvs partition binary + print('\nCreating NVS binary with version:', version_set) - :param input_filename: Name of input file containing data - :param output_filename: Name of output file to store generated binary - :param input_part_size: Size of partition in bytes (must be multiple of 4096) - :param is_key_gen: Enable encryption key generation in encryption mode - :param encrypt_mode: Enable/Disable encryption mode - :param key_file: Input file having encryption keys in encryption mode - :param version_no: Format Version number - :return: None - """ + line = input_file.readline().strip() - global key_input, key_len_needed + # Comments are skipped + while line.startswith('#'): + line = input_file.readline().strip() + if not isinstance(line, str): + line = line.encode('utf-8') - key_len_needed = 64 - key_input = bytearray() + header = line.split(',') - if key_gen: - key_input = ''.join(random.choice('0123456789abcdef') for _ in range(128)).strip() - elif key_file: - with open(key_file, 'rb') as key_f: - key_input = key_f.read(64) + while True: + line = input_file.readline().strip() + if not isinstance(line, str): + line = line.encode('utf-8') - if all(arg is not None for arg in [input_filename, output_filename, input_size]): - input_file = open(input_filename, 'rt', encoding='utf8') - output_file = open(output_filename, 'wb') + value = line.split(',') + if len(value) == 1 and '' in value: + break - with nvs_open(output_file, input_size) as nvs_obj: - reader = csv.DictReader(input_file, delimiter=',') - for row in reader: - try: - write_entry(nvs_obj, row["key"], row["type"], row["encoding"], row["value"]) - except (InputError) as e: - print(e) - input_file.close() - output_file.close() - sys.exit(-2) - - input_file.close() - output_file.close() - - - if key_gen: - keys_page_buf = bytearray(b'\xff')*Page.PAGE_PARAMS["max_size"] - key_bytes = bytearray() - if len(key_input) == key_len_needed: - key_bytes = key_input - else: - key_bytes = codecs.decode(key_input, 'hex') - key_len = len(key_bytes) - keys_page_buf[0:key_len] = key_bytes - crc_data = keys_page_buf[0:key_len] - crc_data = bytes(crc_data) - crc = zlib.crc32(crc_data, 0xFFFFFFFF) - struct.pack_into(' 15: + raise InputError('Length of key `{}` should be <= 15 characters.'.format(data['key'])) + write_entry(nvs_obj, data['key'], data['type'], data['encoding'], data['value']) + except InputError as e: + print(e) + filedir, filename = os.path.split(args.output) + if filename: + print('\nWarning: NVS binary not created...') + os.remove(args.output) + if is_dir_new and not filedir == os.getcwd(): + print('\nWarning: Output dir not created...') + os.rmdir(filedir) + sys.exit(-2) + + print('\nCreated NVS binary: ===>', args.output) def main(): - parser = argparse.ArgumentParser(description="ESP32 NVS partition generation utility") - nvs_part_gen_group = parser.add_argument_group('To generate NVS partition') - nvs_part_gen_group.add_argument( - "--input", - help="Path to CSV file to parse.", - default=None) - - nvs_part_gen_group.add_argument( - "--output", - help='Path to output converted binary file.', - default=None) - - nvs_part_gen_group.add_argument( - "--size", - help='Size of NVS Partition in bytes (must be multiple of 4096)') - + parser = argparse.ArgumentParser(description='\nESP NVS partition generation utility', formatter_class=argparse.RawTextHelpFormatter) + subparser = parser.add_subparsers(title='Commands', + dest='command', + help='\nRun nvs_partition_gen.py {command} -h for additional help\n\n') + + parser_gen = subparser.add_parser('generate', + help='Generate NVS partition', + formatter_class=argparse.RawTextHelpFormatter) + parser_gen.set_defaults(func=generate) + parser_gen.add_argument('input', + default=None, + help='Path to CSV file to parse') + parser_gen.add_argument('output', + default=None, + help='Path to output NVS binary file') + parser_gen.add_argument('size', + default=None, + help='Size of NVS partition in bytes\ + \n(must be multiple of 4096)') + parser_gen.add_argument('--version', + choices=[1,2], + default=2, + type=int, + help='''Set multipage blob version.\ + \nVersion 1 - Multipage blob support disabled.\ + \nVersion 2 - Multipage blob support enabled.\ + \nDefault: Version 2''') + parser_gen.add_argument('--outdir', + default=os.getcwd(), + help='Output directory to store files created\ + \n(Default: current directory)') + parser_gen_key = subparser.add_parser('generate-key', + help='Generate keys for encryption', + formatter_class=argparse.RawTextHelpFormatter) + parser_gen_key.set_defaults(func=generate_key) + parser_gen_key.add_argument('--keyfile', + default=None, + help='Path to output encryption keys file') + parser_gen_key.add_argument('--outdir', + default=os.getcwd(), + help='Output directory to store files created.\ + \n(Default: current directory)') + parser_encr = subparser.add_parser('encrypt', + help='Generate NVS encrypted partition', + formatter_class=argparse.RawTextHelpFormatter) + parser_encr.set_defaults(func=encrypt) + parser_encr.add_argument('input', + default=None, + help='Path to CSV file to parse') + parser_encr.add_argument('output', + default=None, + help='Path to output NVS binary file') + parser_encr.add_argument('size', + default=None, + help='Size of NVS partition in bytes\ + \n(must be multiple of 4096)') + parser_encr.add_argument('--version', + choices=[1,2], + default=2, + type=int, + help='''Set multipage blob version.\ + \nVersion 1 - Multipage blob support disabled.\ + \nVersion 2 - Multipage blob support enabled.\ + \nDefault: Version 2''') + parser_encr.add_argument('--keygen', + action='store_true', + default=False, + help='Generates key for encrypting NVS partition') + parser_encr.add_argument('--keyfile', + default=None, + help='Path to output encryption keys file') + parser_encr.add_argument('--inputkey', + default=None, + help='File having key for encrypting NVS partition') + parser_encr.add_argument('--outdir', + default=os.getcwd(), + help='Output directory to store files created.\ + \n(Default: current directory)') + parser_decr = subparser.add_parser('decrypt', + help='Decrypt NVS encrypted partition', + formatter_class=argparse.RawTextHelpFormatter) + parser_decr.set_defaults(func=decrypt) + parser_decr.add_argument('input', + default=None, + help='Path to encrypted NVS partition file to parse') + parser_decr.add_argument('key', + default=None, + help='Path to file having keys for decryption') + parser_decr.add_argument('output', + default=None, + help='Path to output decrypted binary file') + parser_decr.add_argument('--outdir', + default=os.getcwd(), + help='Output directory to store files created.\ + \n(Default: current directory)') args = parser.parse_args() - input_filename = args.input - output_filename = args.output - part_size = args.size - version_no = 'v1' - is_key_gen = 'false' - is_encrypt_data = 'false' - key_file = None - - print_arg_str = "Invalid.\nTo generate nvs partition binary --input, --output and --size arguments are mandatory." - - check_input_args(input_filename,output_filename, part_size, is_key_gen, is_encrypt_data, key_file, version_no, print_arg_str) - nvs_part_gen(input_filename, output_filename, part_size, is_key_gen, is_encrypt_data, key_file, version_no) + args.func(args) -if __name__ == "__main__": +if __name__ == '__main__': main() diff --git a/components/nvs_flash/nvs_partition_generator/sample_multipage_blob.csv b/components/nvs_flash/nvs_partition_generator/sample_multipage_blob.csv index 384ac6919..e9546cb41 100644 --- a/components/nvs_flash/nvs_partition_generator/sample_multipage_blob.csv +++ b/components/nvs_flash/nvs_partition_generator/sample_multipage_blob.csv @@ -1,3 +1,4 @@ +# Sample csv file key,type,encoding,value dummyNamespace,namespace,, dummyU8Key,data,u8,127 diff --git a/components/nvs_flash/nvs_partition_generator/sample_singlepage_blob.csv b/components/nvs_flash/nvs_partition_generator/sample_singlepage_blob.csv index c99f513cf..10d3cc635 100644 --- a/components/nvs_flash/nvs_partition_generator/sample_singlepage_blob.csv +++ b/components/nvs_flash/nvs_partition_generator/sample_singlepage_blob.csv @@ -1,3 +1,4 @@ +# Sample csv file key,type,encoding,value dummyNamespace,namespace,, dummyU8Key,data,u8,127 diff --git a/components/nvs_flash/src/compressed_enum_table.hpp b/components/nvs_flash/src/compressed_enum_table.hpp index 319d86a45..dcf9d0999 100644 --- a/components/nvs_flash/src/compressed_enum_table.hpp +++ b/components/nvs_flash/src/compressed_enum_table.hpp @@ -35,7 +35,7 @@ class CompressedEnumTable Tenum get(size_t index) const { - assert(index >= 0 && index < Nitems); + assert(index < Nitems); size_t wordIndex = index / ITEMS_PER_WORD; size_t offset = (index % ITEMS_PER_WORD) * Nbits; @@ -44,7 +44,7 @@ class CompressedEnumTable void set(size_t index, Tenum val) { - assert(index >= 0 && index < Nitems); + assert(index < Nitems); size_t wordIndex = index / ITEMS_PER_WORD; size_t offset = (index % ITEMS_PER_WORD) * Nbits; diff --git a/components/nvs_flash/src/intrusive_list.h b/components/nvs_flash/src/intrusive_list.h index fc92442cd..bb580502e 100644 --- a/components/nvs_flash/src/intrusive_list.h +++ b/components/nvs_flash/src/intrusive_list.h @@ -15,6 +15,7 @@ #define intrusive_list_h #include +#include template class intrusive_list; @@ -229,8 +230,7 @@ class intrusive_list { return mSize == 0; } - - + void clear() { while (mFirst) { @@ -238,6 +238,16 @@ class intrusive_list } } + void clearAndFreeNodes() + { + while (mFirst) { + auto tmp = mFirst; + erase(mFirst); + delete tmp; + } + } + + protected: T* mFirst = nullptr; T* mLast = nullptr; diff --git a/components/nvs_flash/src/nvs_api.cpp b/components/nvs_flash/src/nvs_api.cpp index 15f76d1dd..8d0848c48 100644 --- a/components/nvs_flash/src/nvs_api.cpp +++ b/components/nvs_flash/src/nvs_api.cpp @@ -11,64 +11,64 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +#include "sdkconfig.h" #include "nvs.hpp" #include "nvs_flash.h" #include "nvs_storage.hpp" #include "intrusive_list.h" #include "nvs_platform.hpp" +#include "nvs_partition_manager.hpp" #include "esp_partition.h" -#include "sdkconfig.h" +#include +#include "nvs_handle_simple.hpp" +#include "esp_err.h" + +#ifdef LINUX_TARGET +#include "crc.h" +#define ESP_LOGD(...) +#else // LINUX_TARGET +#include -#ifdef ESP_PLATFORM // Uncomment this line to force output from this module // #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG #include "esp_log.h" static const char* TAG = "nvs"; -#else -#define ESP_LOGD(...) -#endif +#endif // ! LINUX_TARGET -class HandleEntry : public intrusive_list_node -{ - static uint32_t s_nvs_next_handle; +class NVSHandleEntry : public intrusive_list_node { public: - HandleEntry() {} + NVSHandleEntry(nvs::NVSHandleSimple *handle, const char* part_name) + : nvs_handle(handle), + mHandle(++s_nvs_next_handle), + handle_part_name(part_name) { } - HandleEntry(bool readOnly, uint8_t nsIndex, nvs::Storage* StoragePtr) : - mHandle(++s_nvs_next_handle), // Begin the handle value with 1 - mReadOnly(readOnly), - mNsIndex(nsIndex), - mStoragePtr(StoragePtr) - { + ~NVSHandleEntry() { + delete nvs_handle; } - nvs_handle mHandle; - uint8_t mReadOnly; - uint8_t mNsIndex; - nvs::Storage* mStoragePtr; + nvs::NVSHandleSimple *nvs_handle; + nvs_handle_t mHandle; + const char* handle_part_name; +private: + static uint32_t s_nvs_next_handle; }; -#ifdef ESP_PLATFORM -SemaphoreHandle_t nvs::Lock::mSemaphore = NULL; -#endif +uint32_t NVSHandleEntry::s_nvs_next_handle; + +extern "C" void nvs_dump(const char *partName); + +#ifndef LINUX_TARGET +SemaphoreHandle_t nvs::Lock::mSemaphore = nullptr; +#endif // ! LINUX_TARGET using namespace std; using namespace nvs; -static intrusive_list s_nvs_handles; -uint32_t HandleEntry::s_nvs_next_handle; -static intrusive_list s_nvs_storage_list; +static intrusive_list s_nvs_handles; static nvs::Storage* lookup_storage_from_name(const char *name) { - auto it = find_if(begin(s_nvs_storage_list), end(s_nvs_storage_list), [=](Storage& e) -> bool { - return (strcmp(e.getPartName(), name) == 0); - }); - - if (it == end(s_nvs_storage_list)) { - return NULL; - } - return it; + return NVSPartitionManager::get_instance()->lookup_storage_from_name(name); } extern "C" void nvs_dump(const char *partName) @@ -77,359 +77,415 @@ extern "C" void nvs_dump(const char *partName) nvs::Storage* pStorage; pStorage = lookup_storage_from_name(partName); - if (pStorage == NULL) { + if (pStorage == nullptr) { return; } pStorage->debugDump(); - return; } -extern "C" esp_err_t nvs_flash_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount) +static esp_err_t close_handles_and_deinit(const char* part_name) { - ESP_LOGD(TAG, "nvs_flash_init_custom partition=%s start=%d count=%d", partName, baseSector, sectorCount); - nvs::Storage* new_storage = NULL; - nvs::Storage* storage = lookup_storage_from_name(partName); - if (storage == NULL) { - new_storage = new nvs::Storage((const char *)partName); - storage = new_storage; - } + auto belongs_to_part = [=](NVSHandleEntry& e) -> bool { + return strncmp(e.nvs_handle->get_partition_name(), part_name, NVS_PART_NAME_MAX_SIZE) == 0; + }; - esp_err_t err = storage->init(baseSector, sectorCount); - if (new_storage != NULL) { - if (err == ESP_OK) { - s_nvs_storage_list.push_back(new_storage); - } else { - delete new_storage; - } + auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), belongs_to_part); + + while (it != end(s_nvs_handles)) { + s_nvs_handles.erase(it); + it = find_if(begin(s_nvs_handles), end(s_nvs_handles), belongs_to_part); } - return err; + + // Deinit partition + return NVSPartitionManager::get_instance()->deinit_partition(part_name); } -#ifdef ESP_PLATFORM -extern "C" esp_err_t nvs_flash_init_partition(const char *part_name) +extern "C" esp_err_t nvs_flash_init_partition_ptr(const esp_partition_t *partition) { Lock::init(); Lock lock; - nvs::Storage* mStorage; - mStorage = lookup_storage_from_name(part_name); - if (mStorage) { - return ESP_OK; + if (partition == nullptr) { + return ESP_ERR_INVALID_ARG; } - const esp_partition_t* partition = esp_partition_find_first( - ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name); - if (partition == NULL) { - return ESP_ERR_NOT_FOUND; + NVSPartition *part = new (std::nothrow) NVSPartition(partition); + if (part == nullptr) { + return ESP_ERR_NO_MEM; } - return nvs_flash_init_custom(part_name, partition->address / SPI_FLASH_SEC_SIZE, + esp_err_t init_res = NVSPartitionManager::get_instance()->init_custom(part, + partition->address / SPI_FLASH_SEC_SIZE, partition->size / SPI_FLASH_SEC_SIZE); -} -extern "C" esp_err_t nvs_flash_init(void) -{ - return nvs_flash_init_partition(NVS_DEFAULT_PART_NAME); + if (init_res != ESP_OK) { + delete part; + } + + return init_res; } -extern "C" esp_err_t nvs_flash_deinit_partition(const char* partition_name) +#ifndef LINUX_TARGET +extern "C" esp_err_t nvs_flash_init_partition(const char *part_name) { Lock::init(); Lock lock; - nvs::Storage* storage = lookup_storage_from_name(partition_name); - if (!storage) { - return ESP_ERR_NVS_NOT_INITIALIZED; + return NVSPartitionManager::get_instance()->init_partition(part_name); +} + +extern "C" esp_err_t nvs_flash_init(void) +{ +#ifdef CONFIG_NVS_ENCRYPTION + esp_err_t ret = ESP_FAIL; + const esp_partition_t *key_part = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS, NULL); + if (key_part == NULL) { + ESP_LOGE(TAG, "CONFIG_NVS_ENCRYPTION is enabled, but no partition with subtype nvs_keys found in the partition table."); + return ret; } - /* Clean up handles related to the storage being deinitialized */ - auto it = s_nvs_handles.begin(); - auto next = it; - while(it != s_nvs_handles.end()) { - next++; - if (it->mStoragePtr == storage) { - ESP_LOGD(TAG, "Deleting handle %d (ns=%d) related to partition \"%s\" (missing call to nvs_close?)", - it->mHandle, it->mNsIndex, partition_name); - s_nvs_handles.erase(it); - delete static_cast(it); + nvs_sec_cfg_t cfg = {}; + ret = nvs_flash_read_security_cfg(key_part, &cfg); + if (ret == ESP_ERR_NVS_KEYS_NOT_INITIALIZED) { + ESP_LOGI(TAG, "NVS key partition empty, generating keys"); + ret = nvs_flash_generate_keys(key_part, &cfg); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to generate keys: [0x%02X] (%s)", ret, esp_err_to_name(ret)); + return ret; } - it = next; + } else if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to read NVS security cfg: [0x%02X] (%s)", ret, esp_err_to_name(ret)); + return ret; } - /* Finally delete the storage itself */ - s_nvs_storage_list.erase(storage); - delete storage; + ret = nvs_flash_secure_init_partition(NVS_DEFAULT_PART_NAME, &cfg); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_LOGE(TAG, "Failed to initialize NVS partition: [0x%02X] (%s)", ret, esp_err_to_name(ret)); + return ret; + } + ESP_LOGI(TAG, "NVS partition \"%s\" is encrypted.", NVS_DEFAULT_PART_NAME); + return ret; +#else // CONFIG_NVS_ENCRYPTION + return nvs_flash_init_partition(NVS_DEFAULT_PART_NAME); +#endif +} - return ESP_OK; +#ifdef CONFIG_NVS_ENCRYPTION +extern "C" esp_err_t nvs_flash_secure_init_partition(const char *part_name, nvs_sec_cfg_t* cfg) +{ + Lock::init(); + Lock lock; + + return NVSPartitionManager::get_instance()->secure_init_partition(part_name, cfg); } -extern "C" esp_err_t nvs_flash_deinit(void) +extern "C" esp_err_t nvs_flash_secure_init(nvs_sec_cfg_t* cfg) { - return nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME); + return nvs_flash_secure_init_partition(NVS_DEFAULT_PART_NAME, cfg); } +#endif extern "C" esp_err_t nvs_flash_erase_partition(const char *part_name) { + Lock::init(); + Lock lock; + + // if the partition is initialized, uninitialize it first + if (NVSPartitionManager::get_instance()->lookup_storage_from_name(part_name)) { + esp_err_t err = close_handles_and_deinit(part_name); + + // only hypothetical/future case, deinit_partition() only fails if partition is uninitialized + if (err != ESP_OK) { + return err; + } + } + const esp_partition_t* partition = esp_partition_find_first( ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name); - if (partition == NULL) { + if (partition == nullptr) { return ESP_ERR_NOT_FOUND; } return esp_partition_erase_range(partition, 0, partition->size); } -extern "C" esp_err_t nvs_flash_erase() +extern "C" esp_err_t nvs_flash_erase_partition_ptr(const esp_partition_t *partition) +{ + Lock::init(); + Lock lock; + + if (partition == nullptr) { + return ESP_ERR_INVALID_ARG; + } + + // if the partition is initialized, uninitialize it first + if (NVSPartitionManager::get_instance()->lookup_storage_from_name(partition->label)) { + const esp_err_t err = close_handles_and_deinit(partition->label); + + // only hypothetical/future case, deinit_partition() only fails if partition is uninitialized + if (err != ESP_OK) { + return err; + } + } + + return esp_partition_erase_range(partition, 0, partition->size); +} + +extern "C" esp_err_t nvs_flash_erase(void) { return nvs_flash_erase_partition(NVS_DEFAULT_PART_NAME); } -#endif +#endif // ! LINUX_TARGET -static esp_err_t nvs_find_ns_handle(nvs_handle handle, HandleEntry& entry) +extern "C" esp_err_t nvs_flash_deinit_partition(const char* partition_name) { - auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](HandleEntry& e) -> bool { - return e.mHandle == handle; + Lock::init(); + Lock lock; + + return close_handles_and_deinit(partition_name); +} + +extern "C" esp_err_t nvs_flash_deinit(void) +{ + return nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME); +} + +static esp_err_t nvs_find_ns_handle(nvs_handle_t c_handle, NVSHandleSimple** handle) +{ + auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](NVSHandleEntry& e) -> bool { + return e.mHandle == c_handle; }); if (it == end(s_nvs_handles)) { return ESP_ERR_NVS_INVALID_HANDLE; } - entry = *it; + *handle = it->nvs_handle; return ESP_OK; } -extern "C" esp_err_t nvs_open_from_partition(const char *part_name, const char* name, nvs_open_mode open_mode, nvs_handle *out_handle) +extern "C" esp_err_t nvs_open_from_partition(const char *part_name, const char* name, nvs_open_mode_t open_mode, nvs_handle_t *out_handle) { Lock lock; ESP_LOGD(TAG, "%s %s %d", __func__, name, open_mode); - uint8_t nsIndex; - nvs::Storage* sHandle; - - sHandle = lookup_storage_from_name(part_name); - if (sHandle == NULL) { - return ESP_ERR_NVS_PART_NOT_FOUND; - } - esp_err_t err = sHandle->createOrOpenNamespace(name, open_mode == NVS_READWRITE, nsIndex); - if (err != ESP_OK) { - return err; + NVSHandleSimple *handle; + esp_err_t result = NVSPartitionManager::get_instance()->open_handle(part_name, name, open_mode, &handle); + if (result == ESP_OK) { + NVSHandleEntry *entry = new (std::nothrow) NVSHandleEntry(handle, part_name); + if (entry) { + s_nvs_handles.push_back(entry); + *out_handle = entry->mHandle; + } else { + delete handle; + return ESP_ERR_NO_MEM; + } } - HandleEntry *handle_entry = new HandleEntry(open_mode==NVS_READONLY, nsIndex, sHandle); - s_nvs_handles.push_back(handle_entry); - - *out_handle = handle_entry->mHandle; - - return ESP_OK; + return result; } -extern "C" esp_err_t nvs_open(const char* name, nvs_open_mode open_mode, nvs_handle *out_handle) +extern "C" esp_err_t nvs_open(const char* name, nvs_open_mode_t open_mode, nvs_handle_t *out_handle) { - if (s_nvs_storage_list.size() == 0) { - return ESP_ERR_NVS_NOT_INITIALIZED; - } - return nvs_open_from_partition(NVS_DEFAULT_PART_NAME, name, open_mode, out_handle); } -extern "C" void nvs_close(nvs_handle handle) +extern "C" void nvs_close(nvs_handle_t handle) { Lock lock; ESP_LOGD(TAG, "%s %d", __func__, handle); - auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](HandleEntry& e) -> bool { + auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](NVSHandleEntry& e) -> bool { return e.mHandle == handle; }); if (it == end(s_nvs_handles)) { return; } s_nvs_handles.erase(it); - delete static_cast(it); + delete static_cast(it); } -extern "C" esp_err_t nvs_erase_key(nvs_handle handle, const char* key) +extern "C" esp_err_t nvs_erase_key(nvs_handle_t c_handle, const char* key) { Lock lock; ESP_LOGD(TAG, "%s %s\r\n", __func__, key); - HandleEntry entry; - auto err = nvs_find_ns_handle(handle, entry); + NVSHandleSimple *handle; + auto err = nvs_find_ns_handle(c_handle, &handle); if (err != ESP_OK) { return err; } - if (entry.mReadOnly) { - return ESP_ERR_NVS_READ_ONLY; - } - return entry.mStoragePtr->eraseItem(entry.mNsIndex, key); + + return handle->erase_item(key); } -extern "C" esp_err_t nvs_erase_all(nvs_handle handle) +extern "C" esp_err_t nvs_erase_all(nvs_handle_t c_handle) { Lock lock; ESP_LOGD(TAG, "%s\r\n", __func__); - HandleEntry entry; - auto err = nvs_find_ns_handle(handle, entry); + NVSHandleSimple *handle; + auto err = nvs_find_ns_handle(c_handle, &handle); if (err != ESP_OK) { return err; } - if (entry.mReadOnly) { - return ESP_ERR_NVS_READ_ONLY; - } - return entry.mStoragePtr->eraseNamespace(entry.mNsIndex); + + return handle->erase_all(); } template -static esp_err_t nvs_set(nvs_handle handle, const char* key, T value) +static esp_err_t nvs_set(nvs_handle_t c_handle, const char* key, T value) { Lock lock; ESP_LOGD(TAG, "%s %s %d %d", __func__, key, sizeof(T), (uint32_t) value); - HandleEntry entry; - auto err = nvs_find_ns_handle(handle, entry); + NVSHandleSimple *handle; + auto err = nvs_find_ns_handle(c_handle, &handle); if (err != ESP_OK) { return err; } - if (entry.mReadOnly) { - return ESP_ERR_NVS_READ_ONLY; - } - return entry.mStoragePtr->writeItem(entry.mNsIndex, key, value); + + return handle->set_item(key, value); } -extern "C" esp_err_t nvs_set_i8 (nvs_handle handle, const char* key, int8_t value) +extern "C" esp_err_t nvs_set_i8 (nvs_handle_t handle, const char* key, int8_t value) { return nvs_set(handle, key, value); } -extern "C" esp_err_t nvs_set_u8 (nvs_handle handle, const char* key, uint8_t value) +extern "C" esp_err_t nvs_set_u8 (nvs_handle_t handle, const char* key, uint8_t value) { return nvs_set(handle, key, value); } -extern "C" esp_err_t nvs_set_i16 (nvs_handle handle, const char* key, int16_t value) +extern "C" esp_err_t nvs_set_i16 (nvs_handle_t handle, const char* key, int16_t value) { return nvs_set(handle, key, value); } -extern "C" esp_err_t nvs_set_u16 (nvs_handle handle, const char* key, uint16_t value) +extern "C" esp_err_t nvs_set_u16 (nvs_handle_t handle, const char* key, uint16_t value) { return nvs_set(handle, key, value); } -extern "C" esp_err_t nvs_set_i32 (nvs_handle handle, const char* key, int32_t value) +extern "C" esp_err_t nvs_set_i32 (nvs_handle_t handle, const char* key, int32_t value) { return nvs_set(handle, key, value); } -extern "C" esp_err_t nvs_set_u32 (nvs_handle handle, const char* key, uint32_t value) +extern "C" esp_err_t nvs_set_u32 (nvs_handle_t handle, const char* key, uint32_t value) { return nvs_set(handle, key, value); } -extern "C" esp_err_t nvs_set_i64 (nvs_handle handle, const char* key, int64_t value) +extern "C" esp_err_t nvs_set_i64 (nvs_handle_t handle, const char* key, int64_t value) { return nvs_set(handle, key, value); } -extern "C" esp_err_t nvs_set_u64 (nvs_handle handle, const char* key, uint64_t value) +extern "C" esp_err_t nvs_set_u64 (nvs_handle_t handle, const char* key, uint64_t value) { return nvs_set(handle, key, value); } -extern "C" esp_err_t nvs_commit(nvs_handle handle) +extern "C" esp_err_t nvs_commit(nvs_handle_t c_handle) { Lock lock; // no-op for now, to be used when intermediate cache is added - HandleEntry entry; - return nvs_find_ns_handle(handle, entry); + NVSHandleSimple *handle; + auto err = nvs_find_ns_handle(c_handle, &handle); + if (err != ESP_OK) { + return err; + } + return handle->commit(); } -extern "C" esp_err_t nvs_set_str(nvs_handle handle, const char* key, const char* value) +extern "C" esp_err_t nvs_set_str(nvs_handle_t c_handle, const char* key, const char* value) { Lock lock; ESP_LOGD(TAG, "%s %s %s", __func__, key, value); - HandleEntry entry; - auto err = nvs_find_ns_handle(handle, entry); + NVSHandleSimple *handle; + auto err = nvs_find_ns_handle(c_handle, &handle); if (err != ESP_OK) { return err; } - return entry.mStoragePtr->writeItem(entry.mNsIndex, nvs::ItemType::SZ, key, value, strlen(value) + 1); + return handle->set_string(key, value); } -extern "C" esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, size_t length) +extern "C" esp_err_t nvs_set_blob(nvs_handle_t c_handle, const char* key, const void* value, size_t length) { Lock lock; ESP_LOGD(TAG, "%s %s %d", __func__, key, length); - HandleEntry entry; - auto err = nvs_find_ns_handle(handle, entry); + NVSHandleSimple *handle; + auto err = nvs_find_ns_handle(c_handle, &handle); if (err != ESP_OK) { return err; } - return entry.mStoragePtr->writeItem(entry.mNsIndex, nvs::ItemType::BLOB, key, value, length); + return handle->set_blob(key, value, length); } template -static esp_err_t nvs_get(nvs_handle handle, const char* key, T* out_value) +static esp_err_t nvs_get(nvs_handle_t c_handle, const char* key, T* out_value) { Lock lock; ESP_LOGD(TAG, "%s %s %d", __func__, key, sizeof(T)); - HandleEntry entry; - auto err = nvs_find_ns_handle(handle, entry); + NVSHandleSimple *handle; + auto err = nvs_find_ns_handle(c_handle, &handle); if (err != ESP_OK) { return err; } - return entry.mStoragePtr->readItem(entry.mNsIndex, key, *out_value); + return handle->get_item(key, *out_value); } -extern "C" esp_err_t nvs_get_i8 (nvs_handle handle, const char* key, int8_t* out_value) +extern "C" esp_err_t nvs_get_i8 (nvs_handle_t c_handle, const char* key, int8_t* out_value) { - return nvs_get(handle, key, out_value); + return nvs_get(c_handle, key, out_value); } -extern "C" esp_err_t nvs_get_u8 (nvs_handle handle, const char* key, uint8_t* out_value) +extern "C" esp_err_t nvs_get_u8 (nvs_handle_t c_handle, const char* key, uint8_t* out_value) { - return nvs_get(handle, key, out_value); + return nvs_get(c_handle, key, out_value); } -extern "C" esp_err_t nvs_get_i16 (nvs_handle handle, const char* key, int16_t* out_value) +extern "C" esp_err_t nvs_get_i16 (nvs_handle_t c_handle, const char* key, int16_t* out_value) { - return nvs_get(handle, key, out_value); + return nvs_get(c_handle, key, out_value); } -extern "C" esp_err_t nvs_get_u16 (nvs_handle handle, const char* key, uint16_t* out_value) +extern "C" esp_err_t nvs_get_u16 (nvs_handle_t c_handle, const char* key, uint16_t* out_value) { - return nvs_get(handle, key, out_value); + return nvs_get(c_handle, key, out_value); } -extern "C" esp_err_t nvs_get_i32 (nvs_handle handle, const char* key, int32_t* out_value) +extern "C" esp_err_t nvs_get_i32 (nvs_handle_t c_handle, const char* key, int32_t* out_value) { - return nvs_get(handle, key, out_value); + return nvs_get(c_handle, key, out_value); } -extern "C" esp_err_t nvs_get_u32 (nvs_handle handle, const char* key, uint32_t* out_value) +extern "C" esp_err_t nvs_get_u32 (nvs_handle_t c_handle, const char* key, uint32_t* out_value) { - return nvs_get(handle, key, out_value); + return nvs_get(c_handle, key, out_value); } -extern "C" esp_err_t nvs_get_i64 (nvs_handle handle, const char* key, int64_t* out_value) +extern "C" esp_err_t nvs_get_i64 (nvs_handle_t c_handle, const char* key, int64_t* out_value) { - return nvs_get(handle, key, out_value); + return nvs_get(c_handle, key, out_value); } -extern "C" esp_err_t nvs_get_u64 (nvs_handle handle, const char* key, uint64_t* out_value) +extern "C" esp_err_t nvs_get_u64 (nvs_handle_t c_handle, const char* key, uint64_t* out_value) { - return nvs_get(handle, key, out_value); + return nvs_get(c_handle, key, out_value); } -static esp_err_t nvs_get_str_or_blob(nvs_handle handle, nvs::ItemType type, const char* key, void* out_value, size_t* length) +static esp_err_t nvs_get_str_or_blob(nvs_handle_t c_handle, nvs::ItemType type, const char* key, void* out_value, size_t* length) { Lock lock; ESP_LOGD(TAG, "%s %s", __func__, key); - HandleEntry entry; - auto err = nvs_find_ns_handle(handle, entry); + NVSHandleSimple *handle; + auto err = nvs_find_ns_handle(c_handle, &handle); if (err != ESP_OK) { return err; } size_t dataSize; - err = entry.mStoragePtr->getItemDataSize(entry.mNsIndex, type, key, dataSize); + err = handle->get_item_size(type, key, dataSize); if (err != ESP_OK) { return err; } @@ -445,16 +501,254 @@ static esp_err_t nvs_get_str_or_blob(nvs_handle handle, nvs::ItemType type, cons } *length = dataSize; - return entry.mStoragePtr->readItem(entry.mNsIndex, type, key, out_value, dataSize); + return handle->get_typed_item(type, key, out_value, dataSize); } -extern "C" esp_err_t nvs_get_str(nvs_handle handle, const char* key, char* out_value, size_t* length) +extern "C" esp_err_t nvs_get_str(nvs_handle_t c_handle, const char* key, char* out_value, size_t* length) { - return nvs_get_str_or_blob(handle, nvs::ItemType::SZ, key, out_value, length); + return nvs_get_str_or_blob(c_handle, nvs::ItemType::SZ, key, out_value, length); } -extern "C" esp_err_t nvs_get_blob(nvs_handle handle, const char* key, void* out_value, size_t* length) +extern "C" esp_err_t nvs_get_blob(nvs_handle_t c_handle, const char* key, void* out_value, size_t* length) { - return nvs_get_str_or_blob(handle, nvs::ItemType::BLOB, key, out_value, length); + return nvs_get_str_or_blob(c_handle, nvs::ItemType::BLOB, key, out_value, length); } +extern "C" esp_err_t nvs_get_stats(const char* part_name, nvs_stats_t* nvs_stats) +{ + Lock lock; + nvs::Storage* pStorage; + + if (nvs_stats == nullptr) { + return ESP_ERR_INVALID_ARG; + } + nvs_stats->used_entries = 0; + nvs_stats->free_entries = 0; + nvs_stats->total_entries = 0; + nvs_stats->namespace_count = 0; + + pStorage = lookup_storage_from_name((part_name == nullptr) ? NVS_DEFAULT_PART_NAME : part_name); + if (pStorage == nullptr) { + return ESP_ERR_NVS_NOT_INITIALIZED; + } + + if(!pStorage->isValid()){ + return ESP_ERR_NVS_INVALID_STATE; + } + + return pStorage->fillStats(*nvs_stats); +} + +extern "C" esp_err_t nvs_get_used_entry_count(nvs_handle_t c_handle, size_t* used_entries) +{ + Lock lock; + if(used_entries == nullptr){ + return ESP_ERR_INVALID_ARG; + } + *used_entries = 0; + + NVSHandleSimple *handle; + auto err = nvs_find_ns_handle(c_handle, &handle); + if (err != ESP_OK) { + return err; + } + + size_t used_entry_count; + err = handle->get_used_entry_count(used_entry_count); + if(err == ESP_OK){ + *used_entries = used_entry_count; + } + return err; +} + +#if (defined CONFIG_NVS_ENCRYPTION) && (!defined LINUX_TARGET) + +extern "C" esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, nvs_sec_cfg_t* cfg) +{ + auto err = esp_partition_erase_range(partition, 0, partition->size); + if(err != ESP_OK) { + return err; + } + + for(uint8_t cnt = 0; cnt < NVS_KEY_SIZE; cnt++) { + /* Adjacent 16-byte blocks should be different */ + if (((cnt / 16) & 1) == 0) { + cfg->eky[cnt] = 0xff; + cfg->tky[cnt] = 0xee; + } else { + cfg->eky[cnt] = 0x99; + cfg->tky[cnt] = 0x88; + } + } + + /** + * Write key configuration without encryption engine (using raw partition write APIs). + * But the read is decrypted through flash encryption engine. This allows unique NVS encryption configuration, + * as flash encryption key is randomly generated per device. + */ + err = esp_partition_write(partition, 0, cfg->eky, NVS_KEY_SIZE); + if(err != ESP_OK) { + return err; + } + + /* Write without encryption, see note above */ + err = esp_partition_write(partition, NVS_KEY_SIZE, cfg->tky, NVS_KEY_SIZE); + if(err != ESP_OK) { + return err; + } + + err = esp_partition_read(partition, 0, cfg->eky, NVS_KEY_SIZE); + if(err != ESP_OK) { + return err; + } + + err = esp_partition_read(partition, NVS_KEY_SIZE, cfg->tky, NVS_KEY_SIZE); + if(err != ESP_OK) { + return err; + } + + uint32_t crc_calc = crc32_le(0xffffffff, cfg->eky, NVS_KEY_SIZE); + crc_calc = crc32_le(crc_calc, cfg->tky, NVS_KEY_SIZE); + + uint8_t crc_wr[16]; + memset(crc_wr, 0xff, sizeof(crc_wr)); + memcpy(crc_wr, &crc_calc, 4); + + err = esp_partition_write(partition, 2 * NVS_KEY_SIZE, crc_wr, sizeof(crc_wr)); + if(err != ESP_OK) { + return err; + } + + return ESP_OK; + +} + +extern "C" esp_err_t nvs_flash_read_security_cfg(const esp_partition_t* partition, nvs_sec_cfg_t* cfg) +{ + uint8_t eky_raw[NVS_KEY_SIZE], tky_raw[NVS_KEY_SIZE]; + uint32_t crc_raw, crc_read, crc_calc; + + auto check_if_initialized = [](uint8_t* eky, uint8_t* tky, uint32_t crc) { + uint8_t cnt = 0; + while(cnt < NVS_KEY_SIZE && eky[cnt] == 0xff && tky[cnt] == 0xff) cnt++; + + if(cnt == NVS_KEY_SIZE && crc == 0xffffffff) { + return false; + } + return true; + }; + + auto err = esp_partition_read(partition, 0, eky_raw, NVS_KEY_SIZE); + if(err != ESP_OK) { + return err; + } + + err = esp_partition_read(partition, NVS_KEY_SIZE, tky_raw, NVS_KEY_SIZE); + if(err != ESP_OK) { + return err; + } + + err = esp_partition_read(partition, 2 * NVS_KEY_SIZE, &crc_raw, 4); + if(err != ESP_OK) { + return err; + } + + if(!check_if_initialized(eky_raw, tky_raw, crc_raw)) { + /* This is an uninitialized key partition*/ + return ESP_ERR_NVS_KEYS_NOT_INITIALIZED; + } + + err = esp_partition_read(partition, 0, cfg->eky, NVS_KEY_SIZE); + + if(err != ESP_OK) { + return err; + } + + err = esp_partition_read(partition, NVS_KEY_SIZE, cfg->tky, NVS_KEY_SIZE); + + if(err != ESP_OK) { + return err; + } + + err = esp_partition_read(partition, 2 * NVS_KEY_SIZE, &crc_read, 4); + + if(err != ESP_OK) { + return err; + } + + crc_calc = crc32_le(0xffffffff, cfg->eky, NVS_KEY_SIZE); + crc_calc = crc32_le(crc_calc, cfg->tky, NVS_KEY_SIZE); + + if(crc_calc != crc_read) { + if(!check_if_initialized(cfg->eky, cfg->tky, crc_read)) { + /* This is an uninitialized key partition*/ + return ESP_ERR_NVS_KEYS_NOT_INITIALIZED; + } + return ESP_ERR_NVS_CORRUPT_KEY_PART; + } + + return ESP_OK; +} + +#endif + +static nvs_iterator_t create_iterator(nvs::Storage *storage, nvs_type_t type) +{ + nvs_iterator_t it = (nvs_iterator_t)calloc(1, sizeof(nvs_opaque_iterator_t)); + if (it == nullptr) { + return nullptr; + } + + it->storage = storage; + it->type = type; + + return it; +} + +extern "C" nvs_iterator_t nvs_entry_find(const char *part_name, const char *namespace_name, nvs_type_t type) +{ + Lock lock; + nvs::Storage *pStorage; + + pStorage = lookup_storage_from_name(part_name); + if (pStorage == nullptr) { + return nullptr; + } + + nvs_iterator_t it = create_iterator(pStorage, type); + if (it == nullptr) { + return nullptr; + } + + bool entryFound = pStorage->findEntry(it, namespace_name); + if (!entryFound) { + free(it); + return nullptr; + } + + return it; +} + +extern "C" nvs_iterator_t nvs_entry_next(nvs_iterator_t it) +{ + Lock lock; + assert(it); + + bool entryFound = it->storage->nextEntry(it); + if (!entryFound) { + free(it); + return nullptr; + } + + return it; +} + +extern "C" void nvs_entry_info(nvs_iterator_t it, nvs_entry_info_t *out_info) +{ + *out_info = it->entry_info; +} + +extern "C" void nvs_release_iterator(nvs_iterator_t it) +{ + free(it); +} diff --git a/components/nvs_flash/src/nvs_cxx_api.cpp b/components/nvs_flash/src/nvs_cxx_api.cpp new file mode 100644 index 000000000..65fb1128b --- /dev/null +++ b/components/nvs_flash/src/nvs_cxx_api.cpp @@ -0,0 +1,68 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "nvs_partition_manager.hpp" +#include "nvs_handle.hpp" +#include "nvs_handle_simple.hpp" +#include "nvs_handle_locked.hpp" +#include "nvs_platform.hpp" + +namespace nvs { + +std::unique_ptr open_nvs_handle_from_partition(const char *partition_name, + const char *ns_name, + nvs_open_mode_t open_mode, + esp_err_t *err) +{ + if (partition_name == nullptr || ns_name == nullptr) { + if (err) { + *err = ESP_ERR_INVALID_ARG; + } + return nullptr; + } + + Lock lock; + + NVSHandleSimple *handle_simple; + esp_err_t result = nvs::NVSPartitionManager::get_instance()-> + open_handle(partition_name, ns_name, open_mode, &handle_simple); + + if (err) { + *err = result; + } + + if (result != ESP_OK) { + return nullptr; + } + + NVSHandleLocked *locked_handle = new (nothrow) NVSHandleLocked(handle_simple); + + if (!locked_handle) { + if (err) { + *err = ESP_ERR_NO_MEM; + } + delete handle_simple; + return nullptr; + } + + return std::unique_ptr(locked_handle); +} + +std::unique_ptr open_nvs_handle(const char *ns_name, + nvs_open_mode_t open_mode, + esp_err_t *err) +{ + return open_nvs_handle_from_partition(NVS_DEFAULT_PART_NAME, ns_name, open_mode, err); +} + +} // namespace nvs diff --git a/components/nvs_flash/src/nvs_encrypted_partition.cpp b/components/nvs_flash/src/nvs_encrypted_partition.cpp new file mode 100644 index 000000000..26e8a3314 --- /dev/null +++ b/components/nvs_flash/src/nvs_encrypted_partition.cpp @@ -0,0 +1,121 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "nvs_encrypted_partition.hpp" +#include "nvs_types.hpp" + +namespace nvs { + +NVSEncryptedPartition::NVSEncryptedPartition(const esp_partition_t *partition) + : NVSPartition(partition) { } + +esp_err_t NVSEncryptedPartition::init(nvs_sec_cfg_t* cfg) +{ + uint8_t* eky = reinterpret_cast(cfg); + + mbedtls_aes_xts_init(&mEctxt); + mbedtls_aes_xts_init(&mDctxt); + + if (mbedtls_aes_xts_setkey_enc(&mEctxt, eky, 2 * NVS_KEY_SIZE * 8) != 0) { + return ESP_ERR_NVS_XTS_CFG_FAILED; + } + + if (mbedtls_aes_xts_setkey_dec(&mDctxt, eky, 2 * NVS_KEY_SIZE * 8) != 0) { + return ESP_ERR_NVS_XTS_CFG_FAILED; + } + + return ESP_OK; +} + +esp_err_t NVSEncryptedPartition::read(size_t src_offset, void* dst, size_t size) +{ + /** Currently upper layer of NVS reads entries one by one even for variable size + * multi-entry data types. So length should always be equal to size of an entry.*/ + if (size != sizeof(Item)) return ESP_ERR_INVALID_SIZE; + + // read data + esp_err_t read_result = esp_partition_read(mESPPartition, src_offset, dst, size); + if (read_result != ESP_OK) { + return read_result; + } + + // decrypt data + //sector num required as an arr by mbedtls. Should have been just uint64/32. + uint8_t data_unit[16]; + + uint32_t relAddr = src_offset; + + memset(data_unit, 0, sizeof(data_unit)); + + memcpy(data_unit, &relAddr, sizeof(relAddr)); + + uint8_t *destination = reinterpret_cast(dst); + + if (mbedtls_aes_crypt_xts(&mDctxt, MBEDTLS_AES_DECRYPT, size, data_unit, destination, destination) != 0) { + return ESP_ERR_NVS_XTS_DECR_FAILED; + } + + return ESP_OK; +} + +esp_err_t NVSEncryptedPartition::write(size_t addr, const void* src, size_t size) +{ + if (size % ESP_ENCRYPT_BLOCK_SIZE != 0) return ESP_ERR_INVALID_SIZE; + + // copy data to buffer for encryption + uint8_t* buf = new (std::nothrow) uint8_t [size]; + + if (!buf) return ESP_ERR_NO_MEM; + + memcpy(buf, src, size); + + // encrypt data + uint8_t entrySize = sizeof(Item); + + //sector num required as an arr by mbedtls. Should have been just uint64/32. + uint8_t data_unit[16]; + + /* Use relative address instead of absolute address (relocatable), so that host-generated + * encrypted nvs images can be used*/ + uint32_t relAddr = addr; + + memset(data_unit, 0, sizeof(data_unit)); + + for(uint8_t entry = 0; entry < (size/entrySize); entry++) + { + uint32_t offset = entry * entrySize; + uint32_t *addr_loc = (uint32_t*) &data_unit[0]; + + *addr_loc = relAddr + offset; + if (mbedtls_aes_crypt_xts(&mEctxt, + MBEDTLS_AES_ENCRYPT, + entrySize, + data_unit, + buf + offset, + buf + offset) != 0) { + delete buf; + return ESP_ERR_NVS_XTS_ENCR_FAILED; + } + } + + // write data + esp_err_t result = esp_partition_write(mESPPartition, addr, buf, size); + + delete buf; + + return result; +} + +} // nvs diff --git a/components/nvs_flash/src/nvs_encrypted_partition.hpp b/components/nvs_flash/src/nvs_encrypted_partition.hpp new file mode 100644 index 000000000..76c0607a0 --- /dev/null +++ b/components/nvs_flash/src/nvs_encrypted_partition.hpp @@ -0,0 +1,43 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef NVS_ENCRYPTED_PARTITION_HPP_ +#define NVS_ENCRYPTED_PARTITION_HPP_ + +#include "mbedtls/aes.h" +#include "nvs_flash.h" +#include "nvs_partition.hpp" + +namespace nvs { + +class NVSEncryptedPartition : public NVSPartition { +public: + NVSEncryptedPartition(const esp_partition_t *partition); + + virtual ~NVSEncryptedPartition() { } + + esp_err_t init(nvs_sec_cfg_t* cfg); + + esp_err_t read(size_t src_offset, void* dst, size_t size) override; + + esp_err_t write(size_t dst_offset, const void* src, size_t size) override; + +protected: + mbedtls_aes_xts_context mEctxt; + mbedtls_aes_xts_context mDctxt; +}; + +} // nvs + +#endif // NVS_ENCRYPTED_PARTITION_HPP_ diff --git a/components/nvs_flash/src/nvs_handle_locked.cpp b/components/nvs_flash/src/nvs_handle_locked.cpp new file mode 100644 index 000000000..89e5cbbca --- /dev/null +++ b/components/nvs_flash/src/nvs_handle_locked.cpp @@ -0,0 +1,82 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "nvs_handle_locked.hpp" + +namespace nvs { + +NVSHandleLocked::NVSHandleLocked(NVSHandleSimple *handle) : handle(handle) { + Lock::init(); +} + +NVSHandleLocked::~NVSHandleLocked() { + Lock lock; + delete handle; +} + +esp_err_t NVSHandleLocked::set_string(const char *key, const char* str) { + Lock lock; + return handle->set_string(key, str); +} + +esp_err_t NVSHandleLocked::set_blob(const char *key, const void* blob, size_t len) { + Lock lock; + return handle->set_blob(key, blob, len); +} + +esp_err_t NVSHandleLocked::get_string(const char *key, char* out_str, size_t len) { + Lock lock; + return handle->get_string(key, out_str, len); +} + +esp_err_t NVSHandleLocked::get_blob(const char *key, void* out_blob, size_t len) { + Lock lock; + return handle->get_blob(key, out_blob, len); +} + +esp_err_t NVSHandleLocked::get_item_size(ItemType datatype, const char *key, size_t &size) { + Lock lock; + return handle->get_item_size(datatype, key, size); +} + +esp_err_t NVSHandleLocked::erase_item(const char* key) { + Lock lock; + return handle->erase_item(key); +} + +esp_err_t NVSHandleLocked::erase_all() { + Lock lock; + return handle->erase_all(); +} + +esp_err_t NVSHandleLocked::commit() { + Lock lock; + return handle->commit(); +} + +esp_err_t NVSHandleLocked::get_used_entry_count(size_t& usedEntries) { + Lock lock; + return handle->get_used_entry_count(usedEntries); +} + +esp_err_t NVSHandleLocked::set_typed_item(ItemType datatype, const char *key, const void* data, size_t dataSize) { + Lock lock; + return handle->set_typed_item(datatype, key, data, dataSize); +} + +esp_err_t NVSHandleLocked::get_typed_item(ItemType datatype, const char *key, void* data, size_t dataSize) { + Lock lock; + return handle->get_typed_item(datatype, key, data, dataSize); +} + +} // namespace nvs diff --git a/components/nvs_flash/src/nvs_handle_locked.hpp b/components/nvs_flash/src/nvs_handle_locked.hpp new file mode 100644 index 000000000..39d514c7a --- /dev/null +++ b/components/nvs_flash/src/nvs_handle_locked.hpp @@ -0,0 +1,66 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef NVS_HANDLE_LOCKED_HPP_ +#define NVS_HANDLE_LOCKED_HPP_ + +#include "nvs_handle_simple.hpp" + +namespace nvs { + +/** + * @brief A class which behaves the same as NVSHandleSimple, except that all public member functions are locked. + * + * This class follows the decorator design pattern. The reason why we don't want locks in NVSHandleSimple is that + * NVSHandleSimple can also be used by the C-API which locks its public functions already. + * Thus, we avoid double-locking. + * + * @note this class becomes responsible for its internal NVSHandleSimple object, i.e. it deletes the handle object on + * destruction + */ +class NVSHandleLocked : public NVSHandle { +public: + NVSHandleLocked(NVSHandleSimple *handle); + + virtual ~NVSHandleLocked(); + + esp_err_t set_string(const char *key, const char* str) override; + + esp_err_t set_blob(const char *key, const void* blob, size_t len) override; + + esp_err_t get_string(const char *key, char* out_str, size_t len) override; + + esp_err_t get_blob(const char *key, void* out_blob, size_t len) override; + + esp_err_t get_item_size(ItemType datatype, const char *key, size_t &size) override; + + esp_err_t erase_item(const char* key) override; + + esp_err_t erase_all() override; + + esp_err_t commit() override; + + esp_err_t get_used_entry_count(size_t& usedEntries) override; + +protected: + esp_err_t set_typed_item(ItemType datatype, const char *key, const void* data, size_t dataSize) override; + + esp_err_t get_typed_item(ItemType datatype, const char *key, void* data, size_t dataSize) override; + +private: + NVSHandleSimple *handle; +}; + +} // namespace nvs + +#endif // NVS_HANDLE_LOCKED_HPP_ diff --git a/components/nvs_flash/src/nvs_handle_simple.cpp b/components/nvs_flash/src/nvs_handle_simple.cpp new file mode 100644 index 000000000..348e197b7 --- /dev/null +++ b/components/nvs_flash/src/nvs_handle_simple.cpp @@ -0,0 +1,137 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include "nvs_handle.hpp" +#include "nvs_partition_manager.hpp" + +namespace nvs { + +NVSHandleSimple::~NVSHandleSimple() { + NVSPartitionManager::get_instance()->close_handle(this); +} + +esp_err_t NVSHandleSimple::set_typed_item(ItemType datatype, const char *key, const void* data, size_t dataSize) +{ + if (!valid) return ESP_ERR_NVS_INVALID_HANDLE; + if (mReadOnly) return ESP_ERR_NVS_READ_ONLY; + + return mStoragePtr->writeItem(mNsIndex, datatype, key, data, dataSize); +} + +esp_err_t NVSHandleSimple::get_typed_item(ItemType datatype, const char *key, void* data, size_t dataSize) +{ + if (!valid) return ESP_ERR_NVS_INVALID_HANDLE; + + return mStoragePtr->readItem(mNsIndex, datatype, key, data, dataSize); +} + +esp_err_t NVSHandleSimple::set_string(const char *key, const char* str) +{ + if (!valid) return ESP_ERR_NVS_INVALID_HANDLE; + if (mReadOnly) return ESP_ERR_NVS_READ_ONLY; + + return mStoragePtr->writeItem(mNsIndex, nvs::ItemType::SZ, key, str, strlen(str) + 1); +} + +esp_err_t NVSHandleSimple::set_blob(const char *key, const void* blob, size_t len) +{ + if (!valid) return ESP_ERR_NVS_INVALID_HANDLE; + if (mReadOnly) return ESP_ERR_NVS_READ_ONLY; + + return mStoragePtr->writeItem(mNsIndex, nvs::ItemType::BLOB, key, blob, len); +} + +esp_err_t NVSHandleSimple::get_string(const char *key, char* out_str, size_t len) +{ + if (!valid) return ESP_ERR_NVS_INVALID_HANDLE; + + return mStoragePtr->readItem(mNsIndex, nvs::ItemType::SZ, key, out_str, len); +} + +esp_err_t NVSHandleSimple::get_blob(const char *key, void* out_blob, size_t len) +{ + if (!valid) return ESP_ERR_NVS_INVALID_HANDLE; + + return mStoragePtr->readItem(mNsIndex, nvs::ItemType::BLOB, key, out_blob, len); +} + +esp_err_t NVSHandleSimple::get_item_size(ItemType datatype, const char *key, size_t &size) +{ + if (!valid) return ESP_ERR_NVS_INVALID_HANDLE; + + return mStoragePtr->getItemDataSize(mNsIndex, datatype, key, size); +} + +esp_err_t NVSHandleSimple::erase_item(const char* key) +{ + if (!valid) return ESP_ERR_NVS_INVALID_HANDLE; + if (mReadOnly) return ESP_ERR_NVS_READ_ONLY; + + return mStoragePtr->eraseItem(mNsIndex, key); +} + +esp_err_t NVSHandleSimple::erase_all() +{ + if (!valid) return ESP_ERR_NVS_INVALID_HANDLE; + if (mReadOnly) return ESP_ERR_NVS_READ_ONLY; + + return mStoragePtr->eraseNamespace(mNsIndex); +} + +esp_err_t NVSHandleSimple::commit() +{ + if (!valid) return ESP_ERR_NVS_INVALID_HANDLE; + + return ESP_OK; +} + +esp_err_t NVSHandleSimple::get_used_entry_count(size_t& used_entries) +{ + used_entries = 0; + + if (!valid) return ESP_ERR_NVS_INVALID_HANDLE; + + size_t used_entry_count; + esp_err_t err = mStoragePtr->calcEntriesInNamespace(mNsIndex, used_entry_count); + if(err == ESP_OK){ + used_entries = used_entry_count; + } + return err; +} + +void NVSHandleSimple::debugDump() { + return mStoragePtr->debugDump(); +} + +esp_err_t NVSHandleSimple::fillStats(nvs_stats_t& nvsStats) { + return mStoragePtr->fillStats(nvsStats); +} + +esp_err_t NVSHandleSimple::calcEntriesInNamespace(size_t& usedEntries) { + return mStoragePtr->calcEntriesInNamespace(mNsIndex, usedEntries); +} + +bool NVSHandleSimple::findEntry(nvs_opaque_iterator_t* it, const char* name) { + return mStoragePtr->findEntry(it, name); +} + +bool NVSHandleSimple::nextEntry(nvs_opaque_iterator_t* it) { + return mStoragePtr->nextEntry(it); +} + +const char *NVSHandleSimple::get_partition_name() const { + return mStoragePtr->getPartName(); +} + +} diff --git a/components/nvs_flash/src/nvs_handle_simple.hpp b/components/nvs_flash/src/nvs_handle_simple.hpp new file mode 100644 index 000000000..0a20aa4e8 --- /dev/null +++ b/components/nvs_flash/src/nvs_handle_simple.hpp @@ -0,0 +1,107 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef NVS_HANDLE_SIMPLE_HPP_ +#define NVS_HANDLE_SIMPLE_HPP_ + +#include "intrusive_list.h" +#include "nvs_storage.hpp" +#include "nvs_platform.hpp" + +#include "nvs_handle.hpp" + +namespace nvs { + +/** + * @brief This class implements NVSHandle according to the ESP32's flash and partitioning scheme. + * + * It is used by both the C API and the C++ API. The main responsibility is to check whether the handle is valid + * and in the right read/write mode and then forward the calls to the storage object. + * + * For more details about the general member functions, see nvs_handle.hpp. + */ +class NVSHandleSimple : public intrusive_list_node, public NVSHandle { + friend class NVSPartitionManager; +public: + NVSHandleSimple(bool readOnly, uint8_t nsIndex, Storage *StoragePtr) : + mStoragePtr(StoragePtr), + mNsIndex(nsIndex), + mReadOnly(readOnly), + valid(1) + { } + + ~NVSHandleSimple(); + + esp_err_t set_typed_item(ItemType datatype, const char *key, const void *data, size_t dataSize) override; + + esp_err_t get_typed_item(ItemType datatype, const char *key, void *data, size_t dataSize) override; + + esp_err_t set_string(const char *key, const char *str) override; + + esp_err_t set_blob(const char *key, const void *blob, size_t len) override; + + esp_err_t get_string(const char *key, char *out_str, size_t len) override; + + esp_err_t get_blob(const char *key, void *out_blob, size_t len) override; + + esp_err_t get_item_size(ItemType datatype, const char *key, size_t &size) override; + + esp_err_t erase_item(const char *key) override; + + esp_err_t erase_all() override; + + esp_err_t commit() override; + + esp_err_t get_used_entry_count(size_t &usedEntries) override; + + esp_err_t getItemDataSize(ItemType datatype, const char *key, size_t &dataSize); + + void debugDump(); + + esp_err_t fillStats(nvs_stats_t &nvsStats); + + esp_err_t calcEntriesInNamespace(size_t &usedEntries); + + bool findEntry(nvs_opaque_iterator_t *it, const char *name); + + bool nextEntry(nvs_opaque_iterator_t *it); + + const char *get_partition_name() const; + +private: + /** + * The underlying storage's object. + */ + Storage *mStoragePtr; + + /** + * Numeric representation of the namespace as it is saved in flash (see README.rst for further details). + */ + uint8_t mNsIndex; + + /** + * Whether this handle is marked as read-only or read-write. + * 0 indicates read-only, any other value read-write. + */ + uint8_t mReadOnly; + + /** + * Indicates the validity of this handle. + * Upon opening, a handle is valid. It becomes invalid if the underlying storage is de-initialized. + */ + uint8_t valid; +}; + +} // nvs + +#endif // NVS_HANDLE_SIMPLE_HPP_ diff --git a/components/nvs_flash/src/nvs_item_hash_list.cpp b/components/nvs_flash/src/nvs_item_hash_list.cpp index 845dd0910..21bf8b315 100644 --- a/components/nvs_flash/src/nvs_item_hash_list.cpp +++ b/components/nvs_flash/src/nvs_item_hash_list.cpp @@ -20,7 +20,7 @@ namespace nvs HashList::HashList() { } - + void HashList::clear() { for (auto it = mBlockList.begin(); it != mBlockList.end();) { @@ -30,7 +30,7 @@ void HashList::clear() delete static_cast(tmp); } } - + HashList::~HashList() { clear(); @@ -42,7 +42,7 @@ HashList::HashListBlock::HashListBlock() "cache block size calculation incorrect"); } -void HashList::insert(const Item& item, size_t index) +esp_err_t HashList::insert(const Item& item, size_t index) { const uint32_t hash_24 = item.calculateCrc32WithoutValue() & 0xffffff; // add entry to the end of last block if possible @@ -50,29 +50,41 @@ void HashList::insert(const Item& item, size_t index) auto& block = mBlockList.back(); if (block.mCount < HashListBlock::ENTRY_COUNT) { block.mNodes[block.mCount++] = HashListNode(hash_24, index); - return; + return ESP_OK; } } // if the above failed, create a new block and add entry to it - HashListBlock* newBlock = new HashListBlock; + HashListBlock* newBlock = new (std::nothrow) HashListBlock; + + if (!newBlock) return ESP_ERR_NO_MEM; + mBlockList.push_back(newBlock); newBlock->mNodes[0] = HashListNode(hash_24, index); newBlock->mCount++; + + return ESP_OK; } -void HashList::erase(size_t index, bool itemShouldExist) +bool HashList::erase(size_t index) { for (auto it = mBlockList.begin(); it != mBlockList.end();) { bool haveEntries = false; + bool foundIndex = false; for (size_t i = 0; i < it->mCount; ++i) { if (it->mNodes[i].mIndex == index) { it->mNodes[i].mIndex = 0xff; - return; + foundIndex = true; + /* found the item and removed it */ } if (it->mNodes[i].mIndex != 0xff) { haveEntries = true; } + if (haveEntries && foundIndex) { + /* item was found, and HashListBlock still has some items */ + return true; + } } + /* no items left in HashListBlock, can remove */ if (!haveEntries) { auto tmp = it; ++it; @@ -81,10 +93,14 @@ void HashList::erase(size_t index, bool itemShouldExist) } else { ++it; } + if (foundIndex) { + /* item was found and empty HashListBlock was removed */ + return true; + } } - if (itemShouldExist) { - assert(false && "item should have been present in cache"); - } + + // item hasn't been present in cache"); + return false; } size_t HashList::find(size_t start, const Item& item) diff --git a/components/nvs_flash/src/nvs_item_hash_list.hpp b/components/nvs_flash/src/nvs_item_hash_list.hpp index e759cd818..e724c4f02 100644 --- a/components/nvs_flash/src/nvs_item_hash_list.hpp +++ b/components/nvs_flash/src/nvs_item_hash_list.hpp @@ -27,16 +27,16 @@ class HashList public: HashList(); ~HashList(); - - void insert(const Item& item, size_t index); - void erase(const size_t index, bool itemShouldExist=true); + + esp_err_t insert(const Item& item, size_t index); + bool erase(const size_t index); size_t find(size_t start, const Item& item); void clear(); - + private: HashList(const HashList& other); const HashList& operator= (const HashList& rhs); - + protected: struct HashListNode { diff --git a/components/nvs_flash/src/nvs_page.cpp b/components/nvs_flash/src/nvs_page.cpp index acbae5358..0be9960f5 100644 --- a/components/nvs_flash/src/nvs_page.cpp +++ b/components/nvs_flash/src/nvs_page.cpp @@ -12,13 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. #include "nvs_page.hpp" -#include +#if defined(LINUX_TARGET) +#include "crc.h" +#else +#include +#endif #include #include namespace nvs { +Page::Page() : mPartition(nullptr) { } + uint32_t Page::Header::calculateCrc32() { return crc32_le(0xffffffff, @@ -26,14 +32,19 @@ uint32_t Page::Header::calculateCrc32() offsetof(Header, mCrc32) - offsetof(Header, mSeqNumber)); } -esp_err_t Page::load(uint32_t sectorNumber) +esp_err_t Page::load(Partition *partition, uint32_t sectorNumber) { + if (partition == nullptr) { + return ESP_ERR_INVALID_ARG; + } + + mPartition = partition; mBaseAddress = sectorNumber * SEC_SIZE; mUsedEntryCount = 0; mErasedEntryCount = 0; Header header; - auto rc = spi_flash_read(mBaseAddress, &header, sizeof(header)); + auto rc = mPartition->read_raw(mBaseAddress, &header, sizeof(header)); if (rc != ESP_OK) { mState = PageState::INVALID; return rc; @@ -42,24 +53,35 @@ esp_err_t Page::load(uint32_t sectorNumber) mState = header.mState; // check if the whole page is really empty // reading the whole page takes ~40 times less than erasing it - uint32_t line[8]; - for (uint32_t i = 0; i < SPI_FLASH_SEC_SIZE; i += sizeof(line)) { - rc = spi_flash_read(mBaseAddress + i, line, sizeof(line)); + const int BLOCK_SIZE = 128; + uint32_t* block = new (std::nothrow) uint32_t[BLOCK_SIZE]; + + if (!block) return ESP_ERR_NO_MEM; + + for (uint32_t i = 0; i < SPI_FLASH_SEC_SIZE; i += 4 * BLOCK_SIZE) { + rc = mPartition->read_raw(mBaseAddress + i, block, 4 * BLOCK_SIZE); if (rc != ESP_OK) { mState = PageState::INVALID; + delete[] block; return rc; } - if (std::any_of(line, line + 4, [](uint32_t val) -> bool { return val != 0xffffffff; })) { + if (std::any_of(block, block + BLOCK_SIZE, [](uint32_t val) -> bool { return val != 0xffffffff; })) { // page isn't as empty after all, mark it as corrupted mState = PageState::CORRUPT; break; } } + delete[] block; } else if (header.mCrc32 != header.calculateCrc32()) { header.mState = PageState::CORRUPT; } else { mState = header.mState; mSeqNumber = header.mSeqNumber; + if(header.mVersion < NVS_VERSION) { + return ESP_ERR_NVS_NEW_VERSION_FOUND; + } else { + mVersion = header.mVersion; + } } switch (mState) { @@ -82,13 +104,16 @@ esp_err_t Page::load(uint32_t sectorNumber) esp_err_t Page::writeEntry(const Item& item) { - auto rc = spi_flash_write(getEntryAddress(mNextFreeEntry), &item, sizeof(item)); - if (rc != ESP_OK) { + esp_err_t err; + + err = mPartition->write(getEntryAddress(mNextFreeEntry), &item, sizeof(item)); + + if (err != ESP_OK) { mState = PageState::INVALID; - return rc; + return err; } - auto err = alterEntryState(mNextFreeEntry, EntryState::WRITTEN); + err = alterEntryState(mNextFreeEntry, EntryState::WRITTEN); if (err != ESP_OK) { return err; } @@ -102,17 +127,18 @@ esp_err_t Page::writeEntry(const Item& item) return ESP_OK; } - + esp_err_t Page::writeEntryData(const uint8_t* data, size_t size) { assert(size % ENTRY_SIZE == 0); assert(mNextFreeEntry != INVALID_ENTRY); assert(mFirstUsedEntry != INVALID_ENTRY); const uint16_t count = size / ENTRY_SIZE; - + const uint8_t* buf = data; - -#ifdef ESP_PLATFORM + +#if !defined LINUX_TARGET + // TODO: check whether still necessary with esp_partition* API /* On the ESP32, data can come from DROM, which is not accessible by spi_flash_write * function. To work around this, we copy the data to heap if it came from DROM. * Hopefully this won't happen very often in practice. For data from DRAM, we should @@ -127,13 +153,15 @@ esp_err_t Page::writeEntryData(const uint8_t* data, size_t size) } memcpy((void*)buf, data, size); } -#endif //ESP_PLATFORM - auto rc = spi_flash_write(getEntryAddress(mNextFreeEntry), buf, size); -#ifdef ESP_PLATFORM +#endif // ! LINUX_TARGET + + auto rc = mPartition->write(getEntryAddress(mNextFreeEntry), buf, size); + +#if !defined LINUX_TARGET if (buf != data) { free((void*)buf); } -#endif //ESP_PLATFORM +#endif // ! LINUX_TARGET if (rc != ESP_OK) { mState = PageState::INVALID; return rc; @@ -147,15 +175,15 @@ esp_err_t Page::writeEntryData(const uint8_t* data, size_t size) return ESP_OK; } -esp_err_t Page::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize) +esp_err_t Page::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize, uint8_t chunkIdx) { Item item; esp_err_t err; - + if (mState == PageState::INVALID) { return ESP_ERR_NVS_INVALID_STATE; } - + if (mState == PageState::UNINITIALIZED) { err = initialize(); if (err != ESP_OK) { @@ -171,21 +199,22 @@ esp_err_t Page::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, c if (keySize > Item::MAX_KEY_LENGTH) { return ESP_ERR_NVS_KEY_TOO_LONG; } - - if (dataSize > Page::BLOB_MAX_SIZE) { + + if (dataSize > Page::CHUNK_MAX_SIZE) { return ESP_ERR_NVS_VALUE_TOO_LONG; } size_t totalSize = ENTRY_SIZE; size_t entriesCount = 1; - if (datatype == ItemType::SZ || datatype == ItemType::BLOB) { + if (isVariableLengthType(datatype)) { size_t roundedSize = (dataSize + ENTRY_SIZE - 1) & ~(ENTRY_SIZE - 1); totalSize += roundedSize; entriesCount += roundedSize / ENTRY_SIZE; } // primitive types should fit into one entry - assert(totalSize == ENTRY_SIZE || datatype == ItemType::BLOB || datatype == ItemType::SZ); + assert(totalSize == ENTRY_SIZE || + isVariableLengthType(datatype)); if (mNextFreeEntry == INVALID_ENTRY || mNextFreeEntry + entriesCount > ENTRY_COUNT) { // page will not fit this amount of data @@ -194,10 +223,14 @@ esp_err_t Page::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, c // write first item size_t span = (totalSize + ENTRY_SIZE - 1) / ENTRY_SIZE; - item = Item(nsIndex, datatype, span, key); - mHashList.insert(item, mNextFreeEntry); + item = Item(nsIndex, datatype, span, key, chunkIdx); + err = mHashList.insert(item, mNextFreeEntry); - if (datatype != ItemType::SZ && datatype != ItemType::BLOB) { + if (err != ESP_OK) { + return err; + } + + if (!isVariableLengthType(datatype)) { memcpy(item.data, data, dataSize); item.crc32 = item.calculateCrc32(); err = writeEntry(item); @@ -208,7 +241,7 @@ esp_err_t Page::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, c const uint8_t* src = reinterpret_cast(data); item.varLength.dataCrc32 = Item::calculateCrc32(src, dataSize); item.varLength.dataSize = dataSize; - item.varLength.reserved2 = 0xffff; + item.varLength.reserved = 0xffff; item.crc32 = item.calculateCrc32(); err = writeEntry(item); if (err != ESP_OK) { @@ -222,36 +255,36 @@ esp_err_t Page::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, c return err; } } - + size_t tail = dataSize - left; if (tail > 0) { - std::fill_n(item.rawData, ENTRY_SIZE / 4, 0xffffffff); + std::fill_n(item.rawData, ENTRY_SIZE, 0xff); memcpy(item.rawData, static_cast(data) + left, tail); err = writeEntry(item); if (err != ESP_OK) { return err; } } - + } return ESP_OK; } -esp_err_t Page::readItem(uint8_t nsIndex, ItemType datatype, const char* key, void* data, size_t dataSize) +esp_err_t Page::readItem(uint8_t nsIndex, ItemType datatype, const char* key, void* data, size_t dataSize, uint8_t chunkIdx, VerOffset chunkStart) { size_t index = 0; Item item; - + if (mState == PageState::INVALID) { return ESP_ERR_NVS_INVALID_STATE; } - - esp_err_t rc = findItem(nsIndex, datatype, key, index, item); + + esp_err_t rc = findItem(nsIndex, datatype, key, index, item, chunkIdx, chunkStart); if (rc != ESP_OK) { return rc; } - if (datatype != ItemType::SZ && datatype != ItemType::BLOB) { + if (!isVariableLengthType(datatype)) { if (dataSize != getAlignmentForType(datatype)) { return ESP_ERR_NVS_TYPE_MISMATCH; } @@ -288,28 +321,81 @@ esp_err_t Page::readItem(uint8_t nsIndex, ItemType datatype, const char* key, vo return ESP_OK; } -esp_err_t Page::eraseItem(uint8_t nsIndex, ItemType datatype, const char* key) +esp_err_t Page::cmpItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize, uint8_t chunkIdx, VerOffset chunkStart) +{ + size_t index = 0; + Item item; + + if (mState == PageState::INVALID) { + return ESP_ERR_NVS_INVALID_STATE; + } + + esp_err_t rc = findItem(nsIndex, datatype, key, index, item, chunkIdx, chunkStart); + if (rc != ESP_OK) { + return rc; + } + + if (!isVariableLengthType(datatype)) { + if (dataSize != getAlignmentForType(datatype)) { + return ESP_ERR_NVS_TYPE_MISMATCH; + } + + if (memcmp(data, item.data, dataSize)) { + return ESP_ERR_NVS_CONTENT_DIFFERS; + } + return ESP_OK; + } + + if (dataSize < static_cast(item.varLength.dataSize)) { + return ESP_ERR_NVS_INVALID_LENGTH; + } + + const uint8_t* dst = reinterpret_cast(data); + size_t left = item.varLength.dataSize; + for (size_t i = index + 1; i < index + item.span; ++i) { + Item ditem; + rc = readEntry(i, ditem); + if (rc != ESP_OK) { + return rc; + } + size_t willCopy = ENTRY_SIZE; + willCopy = (left < willCopy)?left:willCopy; + if (memcmp(dst, ditem.rawData, willCopy)) { + return ESP_ERR_NVS_CONTENT_DIFFERS; + } + left -= willCopy; + dst += willCopy; + } + if (Item::calculateCrc32(reinterpret_cast(data), item.varLength.dataSize) != item.varLength.dataCrc32) { + return ESP_ERR_NVS_NOT_FOUND; + } + + return ESP_OK; +} + +esp_err_t Page::eraseItem(uint8_t nsIndex, ItemType datatype, const char* key, uint8_t chunkIdx, VerOffset chunkStart) { size_t index = 0; Item item; - esp_err_t rc = findItem(nsIndex, datatype, key, index, item); + esp_err_t rc = findItem(nsIndex, datatype, key, index, item, chunkIdx, chunkStart); if (rc != ESP_OK) { return rc; } return eraseEntryAndSpan(index); } -esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key) +esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, uint8_t chunkIdx, VerOffset chunkStart) { size_t index = 0; Item item; - return findItem(nsIndex, datatype, key, index, item); + return findItem(nsIndex, datatype, key, index, item, chunkIdx, chunkStart); } esp_err_t Page::eraseEntryAndSpan(size_t index) { + uint32_t seq_num; + getSeqNumber(seq_num); auto state = mEntryTable.get(index); - assert(state == EntryState::WRITTEN || state == EntryState::EMPTY); size_t span = 1; if (state == EntryState::WRITTEN) { @@ -319,7 +405,7 @@ esp_err_t Page::eraseEntryAndSpan(size_t index) return rc; } if (item.calculateCrc32() != item.crc32) { - mHashList.erase(index, false); + mHashList.erase(index); rc = alterEntryState(index, EntryState::ERASED); --mUsedEntryCount; ++mErasedEntryCount; @@ -406,7 +492,11 @@ esp_err_t Page::copyItems(Page& other) return err; } - other.mHashList.insert(entry, other.mNextFreeEntry); + err = other.mHashList.insert(entry, other.mNextFreeEntry); + if (err != ESP_OK) { + return err; + } + err = other.writeEntry(entry); if (err != ESP_OK) { return err; @@ -435,7 +525,7 @@ esp_err_t Page::mLoadEntryTable() if (mState == PageState::ACTIVE || mState == PageState::FULL || mState == PageState::FREEING) { - auto rc = spi_flash_read(mBaseAddress + ENTRY_TABLE_OFFSET, mEntryTable.data(), + auto rc = mPartition->read_raw(mBaseAddress + ENTRY_TABLE_OFFSET, mEntryTable.data(), mEntryTable.byteSize()); if (rc != ESP_OK) { mState = PageState::INVALID; @@ -474,7 +564,7 @@ esp_err_t Page::mLoadEntryTable() while (mNextFreeEntry < ENTRY_COUNT) { uint32_t entryAddress = getEntryAddress(mNextFreeEntry); uint32_t header; - auto rc = spi_flash_read(entryAddress, &header, sizeof(header)); + auto rc = mPartition->read_raw(entryAddress, &header, sizeof(header)); if (rc != ESP_OK) { mState = PageState::INVALID; return rc; @@ -512,6 +602,16 @@ esp_err_t Page::mLoadEntryTable() continue; } + if (mEntryTable.get(i) == static_cast(0x1)) { + lastItemIndex = INVALID_ENTRY; + auto err = eraseEntryAndSpan(i); + if (err != ESP_OK) { + mState = PageState::INVALID; + return err; + } + continue; + } + lastItemIndex = i; auto err = readEntry(i, item); @@ -519,7 +619,7 @@ esp_err_t Page::mLoadEntryTable() mState = PageState::INVALID; return err; } - + if (item.crc32 != item.calculateCrc32()) { err = eraseEntryAndSpan(i); if (err != ESP_OK) { @@ -529,12 +629,16 @@ esp_err_t Page::mLoadEntryTable() continue; } - mHashList.insert(item, i); + err = mHashList.insert(item, i); + if (err != ESP_OK) { + mState = PageState::INVALID; + return err; + } // search for potential duplicate item size_t duplicateIndex = mHashList.find(0, item); - - if (item.datatype == ItemType::BLOB || item.datatype == ItemType::SZ) { + + if (isVariableLengthType(item.datatype)) { span = item.span; bool needErase = false; for (size_t j = i; j < i + span; ++j) { @@ -549,7 +653,11 @@ esp_err_t Page::mLoadEntryTable() continue; } } - + + /* Note that logic for duplicate detections works fine even + * when old-format blob is present along with new-format blob-index + * for same key on active page. Since datatype is not used in hash calculation, + * old-format blob will be removed.*/ if (duplicateIndex < i) { eraseEntryAndSpan(duplicateIndex); } @@ -592,12 +700,18 @@ esp_err_t Page::mLoadEntryTable() } continue; } + assert(item.span > 0); - mHashList.insert(item, i); + err = mHashList.insert(item, i); + if (err != ESP_OK) { + mState = PageState::INVALID; + return err; + } + size_t span = item.span; - if (item.datatype == ItemType::BLOB || item.datatype == ItemType::SZ) { + if (isVariableLengthType(item.datatype)) { for (size_t j = i + 1; j < i + span; ++j) { if (mEntryTable.get(j) != EntryState::WRITTEN) { eraseEntryAndSpan(i); @@ -622,9 +736,10 @@ esp_err_t Page::initialize() Header header; header.mState = mState; header.mSeqNumber = mSeqNumber; + header.mVersion = mVersion; header.mCrc32 = header.calculateCrc32(); - auto rc = spi_flash_write(mBaseAddress, &header, sizeof(header)); + auto rc = mPartition->write_raw(mBaseAddress, &header, sizeof(header)); if (rc != ESP_OK) { mState = PageState::INVALID; return rc; @@ -641,7 +756,7 @@ esp_err_t Page::alterEntryState(size_t index, EntryState state) mEntryTable.set(index, state); size_t wordToWrite = mEntryTable.getWordIndex(index); uint32_t word = mEntryTable.data()[wordToWrite]; - auto rc = spi_flash_write(mBaseAddress + ENTRY_TABLE_OFFSET + static_cast(wordToWrite) * 4, + auto rc = mPartition->write_raw(mBaseAddress + ENTRY_TABLE_OFFSET + static_cast(wordToWrite) * 4, &word, sizeof(word)); if (rc != ESP_OK) { mState = PageState::INVALID; @@ -665,7 +780,7 @@ esp_err_t Page::alterEntryRangeState(size_t begin, size_t end, EntryState state) } if (nextWordIndex != wordIndex) { uint32_t word = mEntryTable.data()[wordIndex]; - auto rc = spi_flash_write(mBaseAddress + ENTRY_TABLE_OFFSET + static_cast(wordIndex) * 4, + auto rc = mPartition->write_raw(mBaseAddress + ENTRY_TABLE_OFFSET + static_cast(wordIndex) * 4, &word, 4); if (rc != ESP_OK) { return rc; @@ -679,7 +794,7 @@ esp_err_t Page::alterEntryRangeState(size_t begin, size_t end, EntryState state) esp_err_t Page::alterPageState(PageState state) { uint32_t state_val = static_cast(state); - auto rc = spi_flash_write(mBaseAddress, &state_val, sizeof(state)); + auto rc = mPartition->write_raw(mBaseAddress, &state_val, sizeof(state)); if (rc != ESP_OK) { mState = PageState::INVALID; return rc; @@ -690,19 +805,19 @@ esp_err_t Page::alterPageState(PageState state) esp_err_t Page::readEntry(size_t index, Item& dst) const { - auto rc = spi_flash_read(getEntryAddress(index), &dst, sizeof(dst)); + auto rc = mPartition->read(getEntryAddress(index), &dst, sizeof(dst)); if (rc != ESP_OK) { return rc; } return ESP_OK; } -esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, size_t &itemIndex, Item& item) +esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, size_t &itemIndex, Item& item, uint8_t chunkIdx, VerOffset chunkStart) { if (mState == PageState::CORRUPT || mState == PageState::INVALID || mState == PageState::UNINITIALIZED) { return ESP_ERR_NVS_NOT_FOUND; } - + size_t findBeginIndex = itemIndex; if (findBeginIndex >= ENTRY_COUNT) { return ESP_ERR_NVS_NOT_FOUND; @@ -719,7 +834,7 @@ esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, si } if (nsIndex != NS_ANY && datatype != ItemType::ANY && key != NULL) { - size_t cachedIndex = mHashList.find(start, Item(nsIndex, datatype, 0, key)); + size_t cachedIndex = mHashList.find(start, Item(nsIndex, datatype, 0, key, chunkIdx)); if (cachedIndex < ENTRY_COUNT) { start = cachedIndex; } else { @@ -750,7 +865,7 @@ esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, si continue; } - if (item.datatype == ItemType::BLOB || item.datatype == ItemType::SZ) { + if (isVariableLengthType(item.datatype)) { next = i + item.span; } @@ -761,8 +876,31 @@ esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, si if (key != nullptr && strncmp(key, item.key, Item::MAX_KEY_LENGTH) != 0) { continue; } + /* For blob data, chunkIndex should match*/ + if (chunkIdx != CHUNK_ANY + && datatype == ItemType::BLOB_DATA + && item.chunkIndex != chunkIdx) { + continue; + } + /* Blob-index will match the with blob data. + * Skip data chunks when searching for blob index*/ + if (datatype == ItemType::BLOB_IDX + && item.chunkIndex != CHUNK_ANY) { + continue; + } + /* Match the version for blob-index*/ + if (datatype == ItemType::BLOB_IDX + && chunkStart != VerOffset::VER_ANY + && item.blobIndex.chunkStart != chunkStart) { + continue; + } + if (datatype != ItemType::ANY && item.datatype != datatype) { + if (key == nullptr && nsIndex == NS_ANY && chunkIdx == CHUNK_ANY) { + continue; // continue for bruteforce search on blob indices. + } + itemIndex = i; return ESP_ERR_NVS_TYPE_MISMATCH; } @@ -793,10 +931,18 @@ esp_err_t Page::setSeqNumber(uint32_t seqNumber) return ESP_OK; } +esp_err_t Page::setVersion(uint8_t ver) +{ + if (mState != PageState::UNINITIALIZED) { + return ESP_ERR_NVS_INVALID_STATE; + } + mVersion = ver; + return ESP_OK; +} + esp_err_t Page::erase() { - auto sector = mBaseAddress / SPI_FLASH_SEC_SIZE; - auto rc = spi_flash_erase_sector(sector); + auto rc = mPartition->erase_range(mBaseAddress, SPI_FLASH_SEC_SIZE); if (rc != ESP_OK) { mState = PageState::INVALID; return rc; @@ -825,28 +971,39 @@ esp_err_t Page::markFull() } return alterPageState(PageState::FULL); } - + +size_t Page::getVarDataTailroom() const +{ + if (mState == PageState::UNINITIALIZED) { + return CHUNK_MAX_SIZE; + } else if (mState == PageState::FULL) { + return 0; + } + /* Skip one entry for blob data item precessing the data */ + return ((mNextFreeEntry < (ENTRY_COUNT-1)) ? ((ENTRY_COUNT - mNextFreeEntry - 1) * ENTRY_SIZE): 0); +} + const char* Page::pageStateToName(PageState ps) { switch (ps) { case PageState::CORRUPT: return "CORRUPT"; - + case PageState::ACTIVE: return "ACTIVE"; - + case PageState::FREEING: return "FREEING"; - + case PageState::FULL: return "FULL"; - + case PageState::INVALID: return "INVALID"; - + case PageState::UNINITIALIZED: return "UNINITIALIZED"; - + default: assert(0 && "invalid state value"); return ""; @@ -868,7 +1025,7 @@ void Page::debugDump() const Item item; readEntry(i, item); if (skip == 0) { - printf("W ns=%2u type=%2u span=%3u key=\"%s\" len=%d\n", item.nsIndex, static_cast(item.datatype), item.span, item.key, (item.span != 1)?((int)item.varLength.dataSize):-1); + printf("W ns=%2u type=%2u span=%3u key=\"%s\" chunkIdx=%d len=%d\n", item.nsIndex, static_cast(item.datatype), item.span, item.key, item.chunkIndex, (item.span != 1)?((int)item.varLength.dataSize):-1); if (item.span > 0 && item.span <= ENTRY_COUNT - i) { skip = item.span - 1; } else { @@ -882,4 +1039,33 @@ void Page::debugDump() const } } +esp_err_t Page::calcEntries(nvs_stats_t &nvsStats) +{ + assert(mState != PageState::FREEING); + + nvsStats.total_entries += ENTRY_COUNT; + + switch (mState) { + case PageState::UNINITIALIZED: + case PageState::CORRUPT: + nvsStats.free_entries += ENTRY_COUNT; + break; + + case PageState::FULL: + case PageState::ACTIVE: + nvsStats.used_entries += mUsedEntryCount; + nvsStats.free_entries += ENTRY_COUNT - mUsedEntryCount; // it's equivalent free + erase entries. + break; + + case PageState::INVALID: + return ESP_ERR_INVALID_STATE; + break; + + default: + assert(false && "Unhandled state"); + break; + } + return ESP_OK; +} + } // namespace nvs diff --git a/components/nvs_flash/src/nvs_page.hpp b/components/nvs_flash/src/nvs_page.hpp index 413da4589..5857f1ffe 100644 --- a/components/nvs_flash/src/nvs_page.hpp +++ b/components/nvs_flash/src/nvs_page.hpp @@ -24,6 +24,7 @@ #include "compressed_enum_table.hpp" #include "intrusive_list.h" #include "nvs_item_hash_list.hpp" +#include "partition.hpp" namespace nvs { @@ -45,12 +46,16 @@ class Page : public intrusive_list_node static const size_t ENTRY_SIZE = 32; static const size_t ENTRY_COUNT = 126; static const uint32_t INVALID_ENTRY = 0xffffffff; - - static const size_t BLOB_MAX_SIZE = ENTRY_SIZE * (ENTRY_COUNT / 2 - 1); + + static const size_t CHUNK_MAX_SIZE = ENTRY_SIZE * (ENTRY_COUNT - 1); static const uint8_t NS_INDEX = 0; static const uint8_t NS_ANY = 255; + static const uint8_t CHUNK_ANY = Item::CHUNK_ANY; + + static const uint8_t NVS_VERSION = 0xfe; // Decrement to upgrade + enum class PageState : uint32_t { // All bits set, default state after flash erase. Page has not been initialized yet. UNINITIALIZED = 0xffffffff, @@ -73,26 +78,32 @@ class Page : public intrusive_list_node INVALID = 0 }; + Page(); + PageState state() const { return mState; } - esp_err_t load(uint32_t sectorNumber); + esp_err_t load(Partition *partition, uint32_t sectorNumber); esp_err_t getSeqNumber(uint32_t& seqNumber) const; esp_err_t setSeqNumber(uint32_t seqNumber); - esp_err_t writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize); + esp_err_t setVersion(uint8_t version); - esp_err_t readItem(uint8_t nsIndex, ItemType datatype, const char* key, void* data, size_t dataSize); + esp_err_t writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize, uint8_t chunkIdx = CHUNK_ANY); - esp_err_t eraseItem(uint8_t nsIndex, ItemType datatype, const char* key); + esp_err_t readItem(uint8_t nsIndex, ItemType datatype, const char* key, void* data, size_t dataSize, uint8_t chunkIdx = CHUNK_ANY, VerOffset chunkStart = VerOffset::VER_ANY); - esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key); + esp_err_t cmpItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize, uint8_t chunkIdx = CHUNK_ANY, VerOffset chunkStart = VerOffset::VER_ANY); - esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key, size_t &itemIndex, Item& item); + esp_err_t eraseItem(uint8_t nsIndex, ItemType datatype, const char* key, uint8_t chunkIdx = CHUNK_ANY, VerOffset chunkStart = VerOffset::VER_ANY); + + esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key, uint8_t chunkIdx = CHUNK_ANY, VerOffset chunkStart = VerOffset::VER_ANY); + + esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key, size_t &itemIndex, Item& item, uint8_t chunkIdx = CHUNK_ANY, VerOffset chunkStart = VerOffset::VER_ANY); template esp_err_t writeItem(uint8_t nsIndex, const char* key, const T& value) @@ -106,6 +117,12 @@ class Page : public intrusive_list_node return readItem(nsIndex, itemTypeOf(value), key, &value, sizeof(value)); } + template + esp_err_t cmpItem(uint8_t nsIndex, const char* key, const T& value) + { + return cmpItem(nsIndex, itemTypeOf(value), key, &value, sizeof(value)); + } + template esp_err_t eraseItem(uint8_t nsIndex, const char* key) { @@ -121,7 +138,7 @@ class Page : public intrusive_list_node { return mErasedEntryCount; } - + size_t getVarDataTailroom() const ; esp_err_t markFull(); @@ -133,6 +150,8 @@ class Page : public intrusive_list_node void debugDump() const; + esp_err_t calcEntries(nvs_stats_t &nvsStats); + protected: class Header @@ -140,12 +159,13 @@ class Page : public intrusive_list_node public: Header() { - std::fill_n(mReserved, sizeof(mReserved)/sizeof(mReserved[0]), UINT32_MAX); + std::fill_n(mReserved, sizeof(mReserved)/sizeof(mReserved[0]), UINT8_MAX); } PageState mState; // page state uint32_t mSeqNumber; // sequence number of this page - uint32_t mReserved[5]; // unused, must be 0xffffffff + uint8_t mVersion; // nvs format version + uint8_t mReserved[19]; // unused, must be 0xff uint32_t mCrc32; // crc of everything except mState uint32_t calculateCrc32(); @@ -171,7 +191,7 @@ class Page : public intrusive_list_node esp_err_t readEntry(size_t index, Item& dst) const; esp_err_t writeEntry(const Item& item); - + esp_err_t writeEntryData(const uint8_t* data, size_t size); esp_err_t eraseEntryAndSpan(size_t index); @@ -188,7 +208,7 @@ class Page : public intrusive_list_node assert(entry < ENTRY_COUNT); return mBaseAddress + ENTRY_DATA_OFFSET + static_cast(entry) * ENTRY_SIZE; } - + static const char* pageStateToName(PageState ps); @@ -196,6 +216,7 @@ class Page : public intrusive_list_node uint32_t mBaseAddress = 0; PageState mState = PageState::INVALID; uint32_t mSeqNumber = UINT32_MAX; + uint8_t mVersion = NVS_VERSION; typedef CompressedEnumTable TEntryTable; TEntryTable mEntryTable; size_t mNextFreeEntry = INVALID_ENTRY; @@ -203,8 +224,13 @@ class Page : public intrusive_list_node uint16_t mUsedEntryCount = 0; uint16_t mErasedEntryCount = 0; + /** + * This hash list stores hashes of namespace index, key, and ChunkIndex for quick lookup when searching items. + */ HashList mHashList; + Partition *mPartition; + static const uint32_t HEADER_OFFSET = 0; static const uint32_t ENTRY_TABLE_OFFSET = HEADER_OFFSET + 32; static const uint32_t ENTRY_DATA_OFFSET = ENTRY_TABLE_OFFSET + 32; diff --git a/components/nvs_flash/src/nvs_pagemanager.cpp b/components/nvs_flash/src/nvs_pagemanager.cpp index 31240d98b..88a830bd0 100644 --- a/components/nvs_flash/src/nvs_pagemanager.cpp +++ b/components/nvs_flash/src/nvs_pagemanager.cpp @@ -15,16 +15,22 @@ namespace nvs { -esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount) +esp_err_t PageManager::load(Partition *partition, uint32_t baseSector, uint32_t sectorCount) { + if (partition == nullptr) { + return ESP_ERR_INVALID_ARG; + } + mBaseSector = baseSector; mPageCount = sectorCount; mPageList.clear(); mFreePageList.clear(); - mPages.reset(new Page[sectorCount]); + mPages.reset(new (nothrow) Page[sectorCount]); + + if (!mPages) return ESP_ERR_NO_MEM; for (uint32_t i = 0; i < sectorCount; ++i) { - auto err = mPages[i].load(baseSector + i); + auto err = mPages[i].load(partition, baseSector + i); if (err != ESP_OK) { return err; } @@ -66,13 +72,26 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount) if (lastItemIndex != SIZE_MAX) { auto last = PageManager::TPageListIterator(&lastPage); - for (auto it = begin(); it != last; ++it) { + TPageListIterator it; + + for (it = begin(); it != last; ++it) { if ((it->state() != Page::PageState::FREEING) && - (it->eraseItem(item.nsIndex, item.datatype, item.key) == ESP_OK)) { + (it->eraseItem(item.nsIndex, item.datatype, item.key, item.chunkIndex) == ESP_OK)) { break; } } + if ((it == last) && (item.datatype == ItemType::BLOB_IDX)) { + /* Rare case in which the blob was stored using old format, but power went just after writing + * blob index during modification. Loop again and delete the old version blob*/ + for (it = begin(); it != last; ++it) { + + if ((it->state() != Page::PageState::FREEING) && + (it->eraseItem(item.nsIndex, ItemType::BLOB, item.key, item.chunkIndex) == ESP_OK)) { + break; + } + } + } } // check if power went out while page was being freed @@ -111,7 +130,7 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount) } // partition should have at least one free page - if (mFreePageList.size() == 0) { + if (mFreePageList.empty()) { return ESP_ERR_NVS_NO_FREE_PAGES; } @@ -200,4 +219,26 @@ esp_err_t PageManager::activatePage() return ESP_OK; } +esp_err_t PageManager::fillStats(nvs_stats_t& nvsStats) +{ + nvsStats.used_entries = 0; + nvsStats.free_entries = 0; + nvsStats.total_entries = 0; + esp_err_t err = ESP_OK; + + // list of used pages + for (auto p = mPageList.begin(); p != mPageList.end(); ++p) { + err = p->calcEntries(nvsStats); + if (err != ESP_OK) { + return err; + } + } + + // free pages + nvsStats.total_entries += mFreePageList.size() * Page::ENTRY_COUNT; + nvsStats.free_entries += mFreePageList.size() * Page::ENTRY_COUNT; + + return err; +} + } // namespace nvs diff --git a/components/nvs_flash/src/nvs_pagemanager.hpp b/components/nvs_flash/src/nvs_pagemanager.hpp index 10c545f0f..4a1c19f7e 100644 --- a/components/nvs_flash/src/nvs_pagemanager.hpp +++ b/components/nvs_flash/src/nvs_pagemanager.hpp @@ -18,7 +18,7 @@ #include #include "nvs_types.hpp" #include "nvs_page.hpp" -#include "nvs_pagemanager.hpp" +#include "partition.hpp" #include "intrusive_list.h" namespace nvs @@ -31,7 +31,7 @@ class PageManager PageManager() {} - esp_err_t load(uint32_t baseSector, uint32_t sectorCount); + esp_err_t load(Partition *partition, uint32_t baseSector, uint32_t sectorCount); TPageListIterator begin() { @@ -48,8 +48,19 @@ class PageManager return mPageList.back(); } + uint32_t getPageCount() { + return mPageCount; + } + esp_err_t requestNewPage(); + esp_err_t fillStats(nvs_stats_t& nvsStats); + + uint32_t getBaseSector() + { + return mBaseSector; + } + protected: friend class Iterator; diff --git a/components/nvs_flash/src/nvs_partition.cpp b/components/nvs_flash/src/nvs_partition.cpp new file mode 100644 index 000000000..9ee8d378c --- /dev/null +++ b/components/nvs_flash/src/nvs_partition.cpp @@ -0,0 +1,77 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "nvs_partition.hpp" + +namespace nvs { + +NVSPartition::NVSPartition(const esp_partition_t* partition) + : mESPPartition(partition) +{ + // ensure the class is in a valid state + if (partition == nullptr) { + std::abort(); + } +} + +const char *NVSPartition::get_partition_name() +{ + return mESPPartition->label; +} + +esp_err_t NVSPartition::read_raw(size_t src_offset, void* dst, size_t size) +{ + return esp_partition_read(mESPPartition, src_offset, dst, size); +} + +esp_err_t NVSPartition::read(size_t src_offset, void* dst, size_t size) +{ + if (size % ESP_ENCRYPT_BLOCK_SIZE != 0) { + return ESP_ERR_INVALID_ARG; + } + + return esp_partition_read(mESPPartition, src_offset, dst, size); +} + +esp_err_t NVSPartition::write_raw(size_t dst_offset, const void* src, size_t size) +{ + return esp_partition_write(mESPPartition, dst_offset, src, size); +} + +esp_err_t NVSPartition::write(size_t dst_offset, const void* src, size_t size) +{ + if (size % ESP_ENCRYPT_BLOCK_SIZE != 0) { + return ESP_ERR_INVALID_ARG; + } + + return esp_partition_write(mESPPartition, dst_offset, src, size); +} + +esp_err_t NVSPartition::erase_range(size_t dst_offset, size_t size) +{ + return esp_partition_erase_range(mESPPartition, dst_offset, size); +} + +uint32_t NVSPartition::get_address() +{ + return mESPPartition->address; +} + +uint32_t NVSPartition::get_size() +{ + return mESPPartition->size; +} + +} // nvs diff --git a/components/nvs_flash/src/nvs_partition.hpp b/components/nvs_flash/src/nvs_partition.hpp new file mode 100644 index 000000000..d5259cdb5 --- /dev/null +++ b/components/nvs_flash/src/nvs_partition.hpp @@ -0,0 +1,115 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ESP_PARTITION_HPP_ +#define ESP_PARTITION_HPP_ + +#include "esp_partition.h" +#include "intrusive_list.h" +#include "partition.hpp" + +#define ESP_ENCRYPT_BLOCK_SIZE 16 + +#define PART_NAME_MAX_SIZE 16 /*!< maximum length of partition name (excluding null terminator) */ + +namespace nvs { + +/** + * Implementation of Partition for NVS. + * + * It is implemented as an intrusive_list_node to easily store instances of it. NVSStorage and NVSPage take pointer + * references of this class to abstract their partition operations. + */ +class NVSPartition : public Partition, public intrusive_list_node { +public: + /** + * Copy partition_name to mPartitionName and initialize mESPPartition. + * + * @param partition_name the name of the partition as in the partition table, must be non-NULL! + * @param partition an already initialized partition structure + */ + NVSPartition(const esp_partition_t* partition); + + /** + * No need to de-initialize mESPPartition here, if you used esp_partition_find_first. + * Otherwise, the user is responsible for de-initializing it. + */ + virtual ~NVSPartition() { } + + const char *get_partition_name() override; + + /** + * Look into \c esp_partition_read for more details. + * + * @return + * - ESP_OK on success + * - other error codes from the esp_partition API + */ + esp_err_t read_raw(size_t src_offset, void* dst, size_t size) override; + + /** + * Look into \c esp_partition_read for more details. + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if size isn't a multiple of ESP_ENCRYPT_BLOCK_SIZE + * - other error codes from the esp_partition API + */ + esp_err_t read(size_t src_offset, void* dst, size_t size) override; + + /** + * Look into \c esp_partition_write for more details. + * + * @return + * - ESP_OK on success + * - error codes from the esp_partition API + */ + esp_err_t write_raw(size_t dst_offset, const void* src, size_t size) override; + + /** + * Look into \c esp_partition_write for more details. + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if size isn't a multiple of ESP_ENCRYPT_BLOCK_SIZE + * - other error codes from the esp_partition API + */ + esp_err_t write(size_t dst_offset, const void* src, size_t size) override; + + /** + * Look into \c esp_partition_erase_range for more details. + * + * @return + * - ESP_OK on success + * - error codes from the esp_partition API + */ + esp_err_t erase_range(size_t dst_offset, size_t size) override; + + /** + * @return the base address of the partition. + */ + uint32_t get_address() override; + + /** + * @return the size of the partition in bytes. + */ + uint32_t get_size() override; + +protected: + const esp_partition_t* mESPPartition; +}; + +} // nvs + +#endif // ESP_PARTITION_HPP_ diff --git a/components/nvs_flash/src/nvs_partition_lookup.cpp b/components/nvs_flash/src/nvs_partition_lookup.cpp new file mode 100644 index 000000000..e9d27256f --- /dev/null +++ b/components/nvs_flash/src/nvs_partition_lookup.cpp @@ -0,0 +1,69 @@ +#include "esp_partition.h" +#include "nvs_partition_lookup.hpp" + +#ifdef CONFIG_NVS_ENCRYPTION +#include "nvs_encrypted_partition.hpp" +#endif // CONFIG_NVS_ENCRYPTION + +namespace nvs { + +namespace partition_lookup { + +esp_err_t lookup_nvs_partition(const char* label, NVSPartition **p) +{ + const esp_partition_t* esp_partition = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, label); + + if (esp_partition == nullptr) { + return ESP_ERR_NOT_FOUND; + } + + if (esp_partition->encrypted) { + return ESP_ERR_NVS_WRONG_ENCRYPTION; + } + + NVSPartition *partition = new (std::nothrow) NVSPartition(esp_partition); + if (partition == nullptr) { + return ESP_ERR_NO_MEM; + } + + *p = partition; + + return ESP_OK; +} + +#ifdef CONFIG_NVS_ENCRYPTION +esp_err_t lookup_nvs_encrypted_partition(const char* label, nvs_sec_cfg_t* cfg, NVSPartition **p) +{ + const esp_partition_t* esp_partition = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, label); + + if (esp_partition == nullptr) { + return ESP_ERR_NOT_FOUND; + } + + if (esp_partition->encrypted) { + return ESP_ERR_NVS_WRONG_ENCRYPTION; + } + + NVSEncryptedPartition *enc_p = new (std::nothrow) NVSEncryptedPartition(esp_partition); + if (enc_p == nullptr) { + return ESP_ERR_NO_MEM; + } + + esp_err_t result = enc_p->init(cfg); + if (result != ESP_OK) { + delete enc_p; + return result; + } + + *p = enc_p; + + return ESP_OK; +} + +#endif // CONFIG_NVS_ENCRYPTION + +} // partition_lookup + +} // nvs diff --git a/components/nvs_flash/src/nvs_partition_lookup.hpp b/components/nvs_flash/src/nvs_partition_lookup.hpp new file mode 100644 index 000000000..62a8e8b6f --- /dev/null +++ b/components/nvs_flash/src/nvs_partition_lookup.hpp @@ -0,0 +1,22 @@ +#include "esp_err.h" +#include "nvs_partition.hpp" +#include "nvs_flash.h" + +#ifndef NVS_PARTITION_LOOKUP_HPP_ +#define NVS_PARTITION_LOOKUP_HPP_ + +namespace nvs { + +namespace partition_lookup { + +esp_err_t lookup_nvs_partition(const char* label, NVSPartition **p); + +#ifdef CONFIG_NVS_ENCRYPTION +esp_err_t lookup_nvs_encrypted_partition(const char* label, nvs_sec_cfg_t* cfg, NVSPartition **p); +#endif // CONFIG_NVS_ENCRYPTION + +} // partition_lookup + +} // nvs + +#endif // NVS_PARTITION_LOOKUP_HPP_ diff --git a/components/nvs_flash/src/nvs_partition_manager.cpp b/components/nvs_flash/src/nvs_partition_manager.cpp new file mode 100644 index 000000000..b95db7e81 --- /dev/null +++ b/components/nvs_flash/src/nvs_partition_manager.cpp @@ -0,0 +1,244 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "esp_partition.h" +#include "nvs_partition_manager.hpp" +#include "nvs_partition_lookup.hpp" + +#ifdef CONFIG_NVS_ENCRYPTION +#include "nvs_encrypted_partition.hpp" +#endif // CONFIG_NVS_ENCRYPTION + +namespace nvs { + +NVSPartitionManager* NVSPartitionManager::instance = nullptr; + +NVSPartitionManager* NVSPartitionManager::get_instance() +{ + if (!instance) { + instance = new (std::nothrow) NVSPartitionManager(); + } + + return instance; +} + +#ifdef ESP_PLATFORM +esp_err_t NVSPartitionManager::init_partition(const char *partition_label) +{ + if (strlen(partition_label) > NVS_PART_NAME_MAX_SIZE) { + return ESP_ERR_INVALID_ARG; + } + + uint32_t size; + Storage* mStorage; + + mStorage = lookup_storage_from_name(partition_label); + if (mStorage) { + return ESP_OK; + } + + assert(SPI_FLASH_SEC_SIZE != 0); + + NVSPartition *p = nullptr; + esp_err_t result = partition_lookup::lookup_nvs_partition(partition_label, &p); + + if (result != ESP_OK) { + goto error; + } + + size = p->get_size(); + + result = init_custom(p, 0, size / SPI_FLASH_SEC_SIZE); + if (result != ESP_OK) { + goto error; + } + + nvs_partition_list.push_back(p); + + return ESP_OK; + +error: + delete p; + return result; +} +#endif // ESP_PLATFORM + +esp_err_t NVSPartitionManager::init_custom(Partition *partition, uint32_t baseSector, uint32_t sectorCount) +{ + Storage* new_storage = nullptr; + Storage* storage = lookup_storage_from_name(partition->get_partition_name()); + if (storage == nullptr) { + new_storage = new (std::nothrow) Storage(partition); + + if (new_storage == nullptr) { + return ESP_ERR_NO_MEM; + } + + storage = new_storage; + } else { + // if storage was initialized already, we don't need partition and hence delete it + for (auto it = nvs_partition_list.begin(); it != nvs_partition_list.end(); ++it) { + if (partition == it) { + nvs_partition_list.erase(it); + delete partition; + break; + } + } + } + + esp_err_t err = storage->init(baseSector, sectorCount); + if (new_storage != nullptr) { + if (err == ESP_OK) { + nvs_storage_list.push_back(new_storage); + } else { + delete new_storage; + } + } + return err; +} + +#ifdef CONFIG_NVS_ENCRYPTION +#ifdef ESP_PLATFORM +esp_err_t NVSPartitionManager::secure_init_partition(const char *part_name, nvs_sec_cfg_t* cfg) +{ + if (strlen(part_name) > NVS_PART_NAME_MAX_SIZE) { + return ESP_ERR_INVALID_ARG; + } + + Storage* mStorage; + + mStorage = lookup_storage_from_name(part_name); + if (mStorage != nullptr) { + return ESP_OK; + } + + NVSPartition *p; + esp_err_t result; + if (cfg != nullptr) { + result = partition_lookup::lookup_nvs_encrypted_partition(part_name, cfg, &p); + } else { + result = partition_lookup::lookup_nvs_partition(part_name, &p); + } + + if (result != ESP_OK) { + return result; + } + + uint32_t size = p->get_size(); + + result = init_custom(p, 0, size / SPI_FLASH_SEC_SIZE); + if (result != ESP_OK) { + delete p; + return result; + } + + nvs_partition_list.push_back(p); + + return ESP_OK; +} +#endif // ESP_PLATFORM +#endif // CONFIG_NVS_ENCRYPTION + +esp_err_t NVSPartitionManager::deinit_partition(const char *partition_label) +{ + Storage* storage = lookup_storage_from_name(partition_label); + if (!storage) { + return ESP_ERR_NVS_NOT_INITIALIZED; + } + + /* Clean up handles related to the storage being deinitialized */ + for (auto it = nvs_handles.begin(); it != nvs_handles.end(); ++it) { + if (it->mStoragePtr == storage) { + it->valid = false; + nvs_handles.erase(it); + } + } + + /* Finally delete the storage and its partition */ + nvs_storage_list.erase(storage); + delete storage; + + for (auto it = nvs_partition_list.begin(); it != nvs_partition_list.end(); ++it) { + if (strcmp(it->get_partition_name(), partition_label) == 0) { + NVSPartition *p = it; + nvs_partition_list.erase(it); + delete p; + break; + } + } + + return ESP_OK; +} + +esp_err_t NVSPartitionManager::open_handle(const char *part_name, + const char *ns_name, + nvs_open_mode_t open_mode, + NVSHandleSimple** handle) +{ + uint8_t nsIndex; + Storage* sHandle; + + if (nvs_storage_list.empty()) { + return ESP_ERR_NVS_NOT_INITIALIZED; + } + + sHandle = lookup_storage_from_name(part_name); + if (sHandle == nullptr) { + return ESP_ERR_NVS_PART_NOT_FOUND; + } + + esp_err_t err = sHandle->createOrOpenNamespace(ns_name, open_mode == NVS_READWRITE, nsIndex); + if (err != ESP_OK) { + return err; + } + + *handle = new (std::nothrow) NVSHandleSimple(open_mode==NVS_READONLY, nsIndex, sHandle); + + if (handle == nullptr) { + return ESP_ERR_NO_MEM; + } + + nvs_handles.push_back(*handle); + + return ESP_OK; +} + +esp_err_t NVSPartitionManager::close_handle(NVSHandleSimple* handle) { + for (auto it = nvs_handles.begin(); it != nvs_handles.end(); ++it) { + if (it == intrusive_list::iterator(handle)) { + nvs_handles.erase(it); + return ESP_OK; + } + } + + return ESP_ERR_NVS_INVALID_HANDLE; +} + +size_t NVSPartitionManager::open_handles_size() +{ + return nvs_handles.size(); +} + +Storage* NVSPartitionManager::lookup_storage_from_name(const char* name) +{ + auto it = find_if(begin(nvs_storage_list), end(nvs_storage_list), [=](Storage& e) -> bool { + return (strcmp(e.getPartName(), name) == 0); + }); + + if (it == end(nvs_storage_list)) { + return nullptr; + } + return it; +} + +} // nvs diff --git a/components/nvs_flash/src/nvs_partition_manager.hpp b/components/nvs_flash/src/nvs_partition_manager.hpp new file mode 100644 index 000000000..885787de4 --- /dev/null +++ b/components/nvs_flash/src/nvs_partition_manager.hpp @@ -0,0 +1,62 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef NVS_PARTITION_MANAGER_HPP_ +#define NVS_PARTITION_MANAGER_HPP_ + +#include "nvs_handle_simple.hpp" +#include "nvs_storage.hpp" +#include "nvs_partition.hpp" +#include "nvs_flash.h" + +namespace nvs { + +class NVSPartitionManager { +public: + virtual ~NVSPartitionManager() { } + + static NVSPartitionManager* get_instance(); + + esp_err_t init_partition(const char *partition_label); + + esp_err_t init_custom(Partition *partition, uint32_t baseSector, uint32_t sectorCount); + +#ifdef CONFIG_NVS_ENCRYPTION + esp_err_t secure_init_partition(const char *part_name, nvs_sec_cfg_t* cfg); +#endif + + esp_err_t deinit_partition(const char *partition_label); + + Storage* lookup_storage_from_name(const char* name); + + esp_err_t open_handle(const char *part_name, const char *ns_name, nvs_open_mode_t open_mode, NVSHandleSimple** handle); + + esp_err_t close_handle(NVSHandleSimple* handle); + + size_t open_handles_size(); + +protected: + NVSPartitionManager() { } + + static NVSPartitionManager* instance; + + intrusive_list nvs_handles; + + intrusive_list nvs_storage_list; + + intrusive_list nvs_partition_list; +}; + +} // nvs + +#endif // NVS_PARTITION_MANAGER_HPP_ diff --git a/components/nvs_flash/src/nvs_platform.hpp b/components/nvs_flash/src/nvs_platform.hpp index 0973c4875..5c6b5b8b2 100644 --- a/components/nvs_flash/src/nvs_platform.hpp +++ b/components/nvs_flash/src/nvs_platform.hpp @@ -11,11 +11,23 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -#ifndef nvs_platform_h -#define nvs_platform_h +#pragma once +#ifdef LINUX_TARGET +namespace nvs +{ +class Lock +{ +public: + Lock() { } + ~Lock() { } + static void init() {} + static void uninit() {} +}; +} // namespace nvs + +#else // LINUX_TARGET -#ifdef ESP_PLATFORM #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" @@ -63,19 +75,4 @@ class Lock }; } // namespace nvs -#else // ESP_PLATFORM -namespace nvs -{ -class Lock -{ -public: - Lock() { } - ~Lock() { } - static void init() {} - static void uninit() {} -}; -} // namespace nvs -#endif // ESP_PLATFORM - - -#endif /* nvs_platform_h */ +#endif // LINUX_TARGET diff --git a/components/nvs_flash/src/nvs_storage.cpp b/components/nvs_flash/src/nvs_storage.cpp index f8da28fa2..52952b7a3 100644 --- a/components/nvs_flash/src/nvs_storage.cpp +++ b/components/nvs_flash/src/nvs_storage.cpp @@ -14,9 +14,15 @@ #include "nvs_storage.hpp" #ifndef ESP_PLATFORM +// We need NO_DEBUG_STORAGE here since the integration tests on the host add some debug code. +// The unit tests, however, don't want debug code since they check the behavior via data in/output and disturb +// the order of calling mocked functions. +#ifndef NO_DEBUG_STORAGE #include #include +#define DEBUG_STORAGE #endif +#endif // !ESP_PLATFORM namespace nvs { @@ -28,17 +34,69 @@ Storage::~Storage() void Storage::clearNamespaces() { - for (auto it = std::begin(mNamespaces); it != std::end(mNamespaces); ) { - auto tmp = it; - ++it; - mNamespaces.erase(tmp); - delete static_cast(tmp); + mNamespaces.clearAndFreeNodes(); +} + +esp_err_t Storage::populateBlobIndices(TBlobIndexList& blobIdxList) +{ + for (auto it = mPageManager.begin(); it != mPageManager.end(); ++it) { + Page& p = *it; + size_t itemIndex = 0; + Item item; + + /* If the power went off just after writing a blob index, the duplicate detection + * logic in pagemanager will remove the earlier index. So we should never find a + * duplicate index at this point */ + + while (p.findItem(Page::NS_ANY, ItemType::BLOB_IDX, nullptr, itemIndex, item) == ESP_OK) { + BlobIndexNode* entry = new (std::nothrow) BlobIndexNode; + + if (!entry) return ESP_ERR_NO_MEM; + + item.getKey(entry->key, sizeof(entry->key)); + entry->nsIndex = item.nsIndex; + entry->chunkStart = item.blobIndex.chunkStart; + entry->chunkCount = item.blobIndex.chunkCount; + + blobIdxList.push_back(entry); + itemIndex += item.span; + } + } + + return ESP_OK; +} + +void Storage::eraseOrphanDataBlobs(TBlobIndexList& blobIdxList) +{ + for (auto it = mPageManager.begin(); it != mPageManager.end(); ++it) { + Page& p = *it; + size_t itemIndex = 0; + Item item; + /* Chunks with same and with chunkIndex in the following ranges + * belong to same family. + * 1) VER_0_OFFSET <= chunkIndex < VER_1_OFFSET-1 => Version0 chunks + * 2) VER_1_OFFSET <= chunkIndex < VER_ANY => Version1 chunks + */ + while (p.findItem(Page::NS_ANY, ItemType::BLOB_DATA, nullptr, itemIndex, item) == ESP_OK) { + + auto iter = std::find_if(blobIdxList.begin(), + blobIdxList.end(), + [=] (const BlobIndexNode& e) -> bool + {return (strncmp(item.key, e.key, sizeof(e.key) - 1) == 0) + && (item.nsIndex == e.nsIndex) + && (item.chunkIndex >= static_cast (e.chunkStart)) + && (item.chunkIndex < static_cast (e.chunkStart) + e.chunkCount);}); + if (iter == std::end(blobIdxList)) { + p.eraseItem(item.nsIndex, item.datatype, item.key, item.chunkIndex); + } + itemIndex += item.span; + } } } esp_err_t Storage::init(uint32_t baseSector, uint32_t sectorCount) { - auto err = mPageManager.load(baseSector, sectorCount); + auto err = mPageManager.load(mPartition, baseSector, sectorCount); if (err != ESP_OK) { mState = StorageState::INVALID; return err; @@ -52,8 +110,14 @@ esp_err_t Storage::init(uint32_t baseSector, uint32_t sectorCount) size_t itemIndex = 0; Item item; while (p.findItem(Page::NS_INDEX, ItemType::U8, nullptr, itemIndex, item) == ESP_OK) { - NamespaceEntry* entry = new NamespaceEntry; - item.getKey(entry->mName, sizeof(entry->mName) - 1); + NamespaceEntry* entry = new (std::nothrow) NamespaceEntry; + + if (!entry) { + mState = StorageState::INVALID; + return ESP_ERR_NO_MEM; + } + + item.getKey(entry->mName, sizeof(entry->mName)); item.getValue(entry->mIndex); mNamespaces.push_back(entry); mNamespaceUsage.set(entry->mIndex, true); @@ -63,7 +127,22 @@ esp_err_t Storage::init(uint32_t baseSector, uint32_t sectorCount) mNamespaceUsage.set(0, true); mNamespaceUsage.set(255, true); mState = StorageState::ACTIVE; -#ifndef ESP_PLATFORM + + // Populate list of multi-page index entries. + TBlobIndexList blobIdxList; + err = populateBlobIndices(blobIdxList); + if (err != ESP_OK) { + mState = StorageState::INVALID; + return ESP_ERR_NO_MEM; + } + + // Remove the entries for which there is no parent multi-page index. + eraseOrphanDataBlobs(blobIdxList); + + // Purge the blob index list + blobIdxList.clearAndFreeNodes(); + +#ifdef DEBUG_STORAGE debugCheck(); #endif return ESP_OK; @@ -74,11 +153,11 @@ bool Storage::isValid() const return mState == StorageState::ACTIVE; } -esp_err_t Storage::findItem(uint8_t nsIndex, ItemType datatype, const char* key, Page* &page, Item& item) +esp_err_t Storage::findItem(uint8_t nsIndex, ItemType datatype, const char* key, Page* &page, Item& item, uint8_t chunkIdx, VerOffset chunkStart) { for (auto it = std::begin(mPageManager); it != std::end(mPageManager); ++it) { size_t itemIndex = 0; - auto err = it->findItem(nsIndex, datatype, key, itemIndex, item); + auto err = it->findItem(nsIndex, datatype, key, itemIndex, item, chunkIdx, chunkStart); if (err == ESP_OK) { page = it; return ESP_OK; @@ -87,6 +166,109 @@ esp_err_t Storage::findItem(uint8_t nsIndex, ItemType datatype, const char* key, return ESP_ERR_NVS_NOT_FOUND; } +esp_err_t Storage::writeMultiPageBlob(uint8_t nsIndex, const char* key, const void* data, size_t dataSize, VerOffset chunkStart) +{ + uint8_t chunkCount = 0; + TUsedPageList usedPages; + size_t remainingSize = dataSize; + size_t offset = 0; + esp_err_t err = ESP_OK; + + /* Check how much maximum data can be accommodated**/ + uint32_t max_pages = mPageManager.getPageCount() - 1; + + if(max_pages > (Page::CHUNK_ANY-1)/2) { + max_pages = (Page::CHUNK_ANY-1)/2; + } + + if (dataSize > max_pages * Page::CHUNK_MAX_SIZE) { + return ESP_ERR_NVS_VALUE_TOO_LONG; + } + + do { + Page& page = getCurrentPage(); + size_t tailroom = page.getVarDataTailroom(); + size_t chunkSize = 0; + if (chunkCount == 0U && ((tailroom < dataSize) || (tailroom == 0 && dataSize == 0)) && tailroom < Page::CHUNK_MAX_SIZE/10) { + /** This is the first chunk and tailroom is too small ***/ + if (page.state() != Page::PageState::FULL) { + err = page.markFull(); + if (err != ESP_OK) { + return err; + } + } + err = mPageManager.requestNewPage(); + if (err != ESP_OK) { + return err; + } else if(getCurrentPage().getVarDataTailroom() == tailroom) { + /* We got the same page or we are not improving.*/ + return ESP_ERR_NVS_NOT_ENOUGH_SPACE; + } else { + continue; + } + } else if (!tailroom) { + err = ESP_ERR_NVS_NOT_ENOUGH_SPACE; + break; + } + + /* Split the blob into two and store the chunk of available size onto the current page */ + assert(tailroom != 0); + chunkSize = (remainingSize > tailroom)? tailroom : remainingSize; + remainingSize -= chunkSize; + + err = page.writeItem(nsIndex, ItemType::BLOB_DATA, key, + static_cast (data) + offset, chunkSize, static_cast (chunkStart) + chunkCount); + chunkCount++; + assert(err != ESP_ERR_NVS_PAGE_FULL); + if (err != ESP_OK) { + break; + } else { + UsedPageNode* node = new (std::nothrow) UsedPageNode(); + if (!node) { + err = ESP_ERR_NO_MEM; + break; + } + node->mPage = &page; + usedPages.push_back(node); + if (remainingSize || (tailroom - chunkSize) < Page::ENTRY_SIZE) { + if (page.state() != Page::PageState::FULL) { + err = page.markFull(); + if (err != ESP_OK) { + break; + } + } + err = mPageManager.requestNewPage(); + if (err != ESP_OK) { + break; + } + } + } + offset += chunkSize; + if (!remainingSize) { + /* All pages are stored. Now store the index.*/ + Item item; + std::fill_n(item.data, sizeof(item.data), 0xff); + item.blobIndex.dataSize = dataSize; + item.blobIndex.chunkCount = chunkCount; + item.blobIndex.chunkStart = chunkStart; + + err = getCurrentPage().writeItem(nsIndex, ItemType::BLOB_IDX, key, item.data, sizeof(item.data)); + assert(err != ESP_ERR_NVS_PAGE_FULL); + break; + } + } while (1); + + if (err != ESP_OK) { + /* Anything failed, then we should erase all the written chunks*/ + int ii=0; + for (auto it = std::begin(usedPages); it != std::end(usedPages); it++) { + it->mPage->eraseItem(nsIndex, ItemType::BLOB_DATA, key, ii++); + } + } + usedPages.clearAndFreeNodes(); + return err; +} + esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize) { if (mState != StorageState::ACTIVE) { @@ -95,40 +277,109 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key Page* findPage = nullptr; Item item; - auto err = findItem(nsIndex, datatype, key, findPage, item); + + esp_err_t err; + if (datatype == ItemType::BLOB) { + err = findItem(nsIndex, ItemType::BLOB_IDX, key, findPage, item); + } else { + err = findItem(nsIndex, datatype, key, findPage, item); + } + if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) { return err; } - Page& page = getCurrentPage(); - err = page.writeItem(nsIndex, datatype, key, data, dataSize); - if (err == ESP_ERR_NVS_PAGE_FULL) { - if (page.state() != Page::PageState::FULL) { - err = page.markFull(); - if (err != ESP_OK) { - return err; + if (datatype == ItemType::BLOB) { + VerOffset prevStart, nextStart; + prevStart = nextStart = VerOffset::VER_0_OFFSET; + if (findPage) { + // Do a sanity check that the item in question is actually being modified. + // If it isn't, it is cheaper to purposefully not write out new data. + // since it may invoke an erasure of flash. + if (cmpMultiPageBlob(nsIndex, key, data, dataSize) == ESP_OK) { + return ESP_OK; } + + if (findPage->state() == Page::PageState::UNINITIALIZED || + findPage->state() == Page::PageState::INVALID) { + ESP_ERROR_CHECK(findItem(nsIndex, datatype, key, findPage, item)); + } + /* Get the version of the previous index with same */ + prevStart = item.blobIndex.chunkStart; + assert(prevStart == VerOffset::VER_0_OFFSET || prevStart == VerOffset::VER_1_OFFSET); + + /* Toggle the version by changing the offset */ + nextStart + = (prevStart == VerOffset::VER_1_OFFSET) ? VerOffset::VER_0_OFFSET : VerOffset::VER_1_OFFSET; } - err = mPageManager.requestNewPage(); - if (err != ESP_OK) { - return err; - } + /* Write the blob with new version*/ + err = writeMultiPageBlob(nsIndex, key, data, dataSize, nextStart); - err = getCurrentPage().writeItem(nsIndex, datatype, key, data, dataSize); if (err == ESP_ERR_NVS_PAGE_FULL) { return ESP_ERR_NVS_NOT_ENOUGH_SPACE; } if (err != ESP_OK) { return err; } - } else if (err != ESP_OK) { - return err; + + if (findPage) { + /* Erase the blob with earlier version*/ + err = eraseMultiPageBlob(nsIndex, key, prevStart); + + if (err == ESP_ERR_FLASH_OP_FAIL) { + return ESP_ERR_NVS_REMOVE_FAILED; + } + if (err != ESP_OK) { + return err; + } + + findPage = nullptr; + } else { + /* Support for earlier versions where BLOBS were stored without index */ + err = findItem(nsIndex, datatype, key, findPage, item); + if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) { + return err; + } + } + } else { + // Do a sanity check that the item in question is actually being modified. + // If it isn't, it is cheaper to purposefully not write out new data. + // since it may invoke an erasure of flash. + if (findPage != nullptr && + findPage->cmpItem(nsIndex, datatype, key, data, dataSize) == ESP_OK) { + return ESP_OK; + } + + Page& page = getCurrentPage(); + err = page.writeItem(nsIndex, datatype, key, data, dataSize); + if (err == ESP_ERR_NVS_PAGE_FULL) { + if (page.state() != Page::PageState::FULL) { + err = page.markFull(); + if (err != ESP_OK) { + return err; + } + } + err = mPageManager.requestNewPage(); + if (err != ESP_OK) { + return err; + } + + err = getCurrentPage().writeItem(nsIndex, datatype, key, data, dataSize); + if (err == ESP_ERR_NVS_PAGE_FULL) { + return ESP_ERR_NVS_NOT_ENOUGH_SPACE; + } + if (err != ESP_OK) { + return err; + } + } else if (err != ESP_OK) { + return err; + } } if (findPage) { if (findPage->state() == Page::PageState::UNINITIALIZED || findPage->state() == Page::PageState::INVALID) { - ESP_ERROR_CHECK( findItem(nsIndex, datatype, key, findPage, item) ); + ESP_ERROR_CHECK(findItem(nsIndex, datatype, key, findPage, item)); } err = findPage->eraseItem(nsIndex, datatype, key); if (err == ESP_ERR_FLASH_OP_FAIL) { @@ -138,7 +389,7 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key return err; } } -#ifndef ESP_PLATFORM +#ifdef DEBUG_STORAGE debugCheck(); #endif return ESP_OK; @@ -168,6 +419,11 @@ esp_err_t Storage::createOrOpenNamespace(const char* nsName, bool canCreate, uin return ESP_ERR_NVS_NOT_ENOUGH_SPACE; } + NamespaceEntry* entry = new (std::nothrow) NamespaceEntry; + if (!entry) { + return ESP_ERR_NO_MEM; + } + auto err = writeItem(Page::NS_INDEX, ItemType::U8, nsName, &ns, sizeof(ns)); if (err != ESP_OK) { return err; @@ -175,7 +431,6 @@ esp_err_t Storage::createOrOpenNamespace(const char* nsName, bool canCreate, uin mNamespaceUsage.set(ns, true); nsIndex = ns; - NamespaceEntry* entry = new NamespaceEntry; entry->mIndex = ns; strncpy(entry->mName, nsName, sizeof(entry->mName) - 1); entry->mName[sizeof(entry->mName) - 1] = 0; @@ -187,6 +442,91 @@ esp_err_t Storage::createOrOpenNamespace(const char* nsName, bool canCreate, uin return ESP_OK; } +esp_err_t Storage::readMultiPageBlob(uint8_t nsIndex, const char* key, void* data, size_t dataSize) +{ + Item item; + Page* findPage = nullptr; + + /* First read the blob index */ + auto err = findItem(nsIndex, ItemType::BLOB_IDX, key, findPage, item); + if (err != ESP_OK) { + return err; + } + + uint8_t chunkCount = item.blobIndex.chunkCount; + VerOffset chunkStart = item.blobIndex.chunkStart; + size_t readSize = item.blobIndex.dataSize; + size_t offset = 0; + + assert(dataSize == readSize); + + /* Now read corresponding chunks */ + for (uint8_t chunkNum = 0; chunkNum < chunkCount; chunkNum++) { + err = findItem(nsIndex, ItemType::BLOB_DATA, key, findPage, item, static_cast (chunkStart) + chunkNum); + if (err != ESP_OK) { + if (err == ESP_ERR_NVS_NOT_FOUND) { + break; + } + return err; + } + err = findPage->readItem(nsIndex, ItemType::BLOB_DATA, key, static_cast(data) + offset, item.varLength.dataSize, static_cast (chunkStart) + chunkNum); + if (err != ESP_OK) { + return err; + } + assert(static_cast (chunkStart) + chunkNum == item.chunkIndex); + offset += item.varLength.dataSize; + } + if (err == ESP_OK) { + assert(offset == dataSize); + } + if (err == ESP_ERR_NVS_NOT_FOUND) { + eraseMultiPageBlob(nsIndex, key); // cleanup if a chunk is not found + } + return err; +} + +esp_err_t Storage::cmpMultiPageBlob(uint8_t nsIndex, const char* key, const void* data, size_t dataSize) +{ + Item item; + Page* findPage = nullptr; + + /* First read the blob index */ + auto err = findItem(nsIndex, ItemType::BLOB_IDX, key, findPage, item); + if (err != ESP_OK) { + return err; + } + + uint8_t chunkCount = item.blobIndex.chunkCount; + VerOffset chunkStart = item.blobIndex.chunkStart; + size_t readSize = item.blobIndex.dataSize; + size_t offset = 0; + + if (dataSize != readSize) { + return ESP_ERR_NVS_CONTENT_DIFFERS; + } + + /* Now read corresponding chunks */ + for (uint8_t chunkNum = 0; chunkNum < chunkCount; chunkNum++) { + err = findItem(nsIndex, ItemType::BLOB_DATA, key, findPage, item, static_cast (chunkStart) + chunkNum); + if (err != ESP_OK) { + if (err == ESP_ERR_NVS_NOT_FOUND) { + break; + } + return err; + } + err = findPage->cmpItem(nsIndex, ItemType::BLOB_DATA, key, static_cast(data) + offset, item.varLength.dataSize, static_cast (chunkStart) + chunkNum); + if (err != ESP_OK) { + return err; + } + assert(static_cast (chunkStart) + chunkNum == item.chunkIndex); + offset += item.varLength.dataSize; + } + if (err == ESP_OK) { + assert(offset == dataSize); + } + return err; +} + esp_err_t Storage::readItem(uint8_t nsIndex, ItemType datatype, const char* key, void* data, size_t dataSize) { if (mState != StorageState::ACTIVE) { @@ -195,12 +535,64 @@ esp_err_t Storage::readItem(uint8_t nsIndex, ItemType datatype, const char* key, Item item; Page* findPage = nullptr; + if (datatype == ItemType::BLOB) { + auto err = readMultiPageBlob(nsIndex, key, data, dataSize); + if (err != ESP_ERR_NVS_NOT_FOUND) { + return err; + } // else check if the blob is stored with earlier version format without index + } + auto err = findItem(nsIndex, datatype, key, findPage, item); if (err != ESP_OK) { return err; } - return findPage->readItem(nsIndex, datatype, key, data, dataSize); + +} + +esp_err_t Storage::eraseMultiPageBlob(uint8_t nsIndex, const char* key, VerOffset chunkStart) +{ + if (mState != StorageState::ACTIVE) { + return ESP_ERR_NVS_NOT_INITIALIZED; + } + Item item; + Page* findPage = nullptr; + + auto err = findItem(nsIndex, ItemType::BLOB_IDX, key, findPage, item, Page::CHUNK_ANY, chunkStart); + if (err != ESP_OK) { + return err; + } + /* Erase the index first and make children blobs orphan*/ + err = findPage->eraseItem(nsIndex, ItemType::BLOB_IDX, key, Page::CHUNK_ANY, chunkStart); + if (err != ESP_OK) { + return err; + } + + uint8_t chunkCount = item.blobIndex.chunkCount; + + if (chunkStart == VerOffset::VER_ANY) { + chunkStart = item.blobIndex.chunkStart; + } else { + assert(chunkStart == item.blobIndex.chunkStart); + } + + /* Now erase corresponding chunks*/ + for (uint8_t chunkNum = 0; chunkNum < chunkCount; chunkNum++) { + err = findItem(nsIndex, ItemType::BLOB_DATA, key, findPage, item, static_cast (chunkStart) + chunkNum); + + if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) { + return err; + } else if (err == ESP_ERR_NVS_NOT_FOUND) { + continue; // Keep erasing other chunks + } + err = findPage->eraseItem(nsIndex, ItemType::BLOB_DATA, key, static_cast (chunkStart) + chunkNum); + if (err != ESP_OK) { + return err; + } + + } + + return ESP_OK; } esp_err_t Storage::eraseItem(uint8_t nsIndex, ItemType datatype, const char* key) @@ -209,6 +601,10 @@ esp_err_t Storage::eraseItem(uint8_t nsIndex, ItemType datatype, const char* key return ESP_ERR_NVS_NOT_INITIALIZED; } + if (datatype == ItemType::BLOB) { + return eraseMultiPageBlob(nsIndex, key); + } + Item item; Page* findPage = nullptr; auto err = findItem(nsIndex, datatype, key, findPage, item); @@ -216,6 +612,10 @@ esp_err_t Storage::eraseItem(uint8_t nsIndex, ItemType datatype, const char* key return err; } + if (item.datatype == ItemType::BLOB_DATA || item.datatype == ItemType::BLOB_IDX) { + return eraseMultiPageBlob(nsIndex, key); + } + return findPage->eraseItem(nsIndex, datatype, key); } @@ -250,7 +650,15 @@ esp_err_t Storage::getItemDataSize(uint8_t nsIndex, ItemType datatype, const cha Page* findPage = nullptr; auto err = findItem(nsIndex, datatype, key, findPage, item); if (err != ESP_OK) { - return err; + if (datatype != ItemType::BLOB) { + return err; + } + err = findItem(nsIndex, ItemType::BLOB_IDX, key, findPage, item); + if (err != ESP_OK) { + return err; + } + dataSize = item.blobIndex.dataSize; + return ESP_OK; } dataSize = item.varLength.dataSize; @@ -264,18 +672,18 @@ void Storage::debugDump() } } -#ifndef ESP_PLATFORM +#ifdef DEBUG_STORAGE void Storage::debugCheck() { std::map keys; - + for (auto p = mPageManager.begin(); p != mPageManager.end(); ++p) { size_t itemIndex = 0; size_t usedCount = 0; Item item; while (p->findItem(Page::NS_ANY, ItemType::ANY, nullptr, itemIndex, item) == ESP_OK) { std::stringstream keyrepr; - keyrepr << static_cast(item.nsIndex) << "_" << static_cast(item.datatype) << "_" << item.key; + keyrepr << static_cast(item.nsIndex) << "_" << static_cast(item.datatype) << "_" << item.key <<"_"<(item.chunkIndex); std::string keystr = keyrepr.str(); if (keys.find(keystr) != std::end(keys)) { printf("Duplicate key: %s\n", keystr.c_str()); @@ -289,6 +697,104 @@ void Storage::debugCheck() assert(usedCount == p->getUsedEntryCount()); } } -#endif //ESP_PLATFORM +#endif //DEBUG_STORAGE + +esp_err_t Storage::fillStats(nvs_stats_t& nvsStats) +{ + nvsStats.namespace_count = mNamespaces.size(); + return mPageManager.fillStats(nvsStats); +} + +esp_err_t Storage::calcEntriesInNamespace(uint8_t nsIndex, size_t& usedEntries) +{ + usedEntries = 0; + + if (mState != StorageState::ACTIVE) { + return ESP_ERR_NVS_NOT_INITIALIZED; + } + + for (auto it = std::begin(mPageManager); it != std::end(mPageManager); ++it) { + size_t itemIndex = 0; + Item item; + while (true) { + auto err = it->findItem(nsIndex, ItemType::ANY, nullptr, itemIndex, item); + if (err == ESP_ERR_NVS_NOT_FOUND) { + break; + } + else if (err != ESP_OK) { + return err; + } + usedEntries += item.span; + itemIndex += item.span; + if (itemIndex >= it->ENTRY_COUNT) break; + } + } + return ESP_OK; +} + +void Storage::fillEntryInfo(Item &item, nvs_entry_info_t &info) +{ + info.type = static_cast(item.datatype); + strncpy(info.key, item.key, sizeof(info.key)); + + for (auto &name : mNamespaces) { + if(item.nsIndex == name.mIndex) { + strncpy(info.namespace_name, name.mName, sizeof(info.namespace_name)); + break; + } + } +} + +bool Storage::findEntry(nvs_opaque_iterator_t* it, const char* namespace_name) +{ + it->entryIndex = 0; + it->nsIndex = Page::NS_ANY; + it->page = mPageManager.begin(); + + if (namespace_name != nullptr) { + if(createOrOpenNamespace(namespace_name, false, it->nsIndex) != ESP_OK) { + return false; + } + } + + return nextEntry(it); +} + +inline bool isIterableItem(Item& item) +{ + return (item.nsIndex != 0 && + item.datatype != ItemType::BLOB && + item.datatype != ItemType::BLOB_IDX); +} + +inline bool isMultipageBlob(Item& item) +{ + return (item.datatype == ItemType::BLOB_DATA && + !(item.chunkIndex == static_cast(VerOffset::VER_0_OFFSET) + || item.chunkIndex == static_cast(VerOffset::VER_1_OFFSET))); +} + +bool Storage::nextEntry(nvs_opaque_iterator_t* it) +{ + Item item; + esp_err_t err; + + for (auto page = it->page; page != mPageManager.end(); ++page) { + do { + err = page->findItem(it->nsIndex, (ItemType)it->type, nullptr, it->entryIndex, item); + it->entryIndex += item.span; + if(err == ESP_OK && isIterableItem(item) && !isMultipageBlob(item)) { + fillEntryInfo(item, it->entry_info); + it->page = page; + return true; + } + } while (err != ESP_ERR_NVS_NOT_FOUND); + + it->entryIndex = 0; + } + + return false; +} + } diff --git a/components/nvs_flash/src/nvs_storage.hpp b/components/nvs_flash/src/nvs_storage.hpp index 3c0e0c85a..fd6eb1cc9 100644 --- a/components/nvs_flash/src/nvs_storage.hpp +++ b/components/nvs_flash/src/nvs_storage.hpp @@ -15,12 +15,12 @@ #define nvs_storage_hpp #include -#include #include #include "nvs.hpp" #include "nvs_types.hpp" #include "nvs_page.hpp" #include "nvs_pagemanager.hpp" +#include "partition.hpp" //extern void dumpBytes(const uint8_t* data, size_t count); @@ -42,10 +42,30 @@ class Storage : public intrusive_list_node typedef intrusive_list TNamespaces; + struct UsedPageNode: public intrusive_list_node { + public: Page* mPage; + }; + + typedef intrusive_list TUsedPageList; + + struct BlobIndexNode: public intrusive_list_node { + public: + char key[Item::MAX_KEY_LENGTH + 1]; + uint8_t nsIndex; + uint8_t chunkCount; + VerOffset chunkStart; + }; + + typedef intrusive_list TBlobIndexList; + public: ~Storage(); - Storage(const char *pName = NVS_DEFAULT_PART_NAME) : mPartitionName(pName) { }; + Storage(Partition *partition) : mPartition(partition) { + if (partition == nullptr) { + abort(); + } + }; esp_err_t init(uint32_t baseSector, uint32_t sectorCount); @@ -77,18 +97,43 @@ class Storage : public intrusive_list_node { return eraseItem(nsIndex, ItemType::ANY, key); } - + esp_err_t eraseNamespace(uint8_t nsIndex); + const Partition *getPart() const + { + return mPartition; + } + const char *getPartName() const { - return mPartitionName; + return mPartition->get_partition_name(); + } + + uint32_t getBaseSector() + { + return mPageManager.getBaseSector(); } + esp_err_t writeMultiPageBlob(uint8_t nsIndex, const char* key, const void* data, size_t dataSize, VerOffset chunkStart); + + esp_err_t readMultiPageBlob(uint8_t nsIndex, const char* key, void* data, size_t dataSize); + + esp_err_t cmpMultiPageBlob(uint8_t nsIndex, const char* key, const void* data, size_t dataSize); + + esp_err_t eraseMultiPageBlob(uint8_t nsIndex, const char* key, VerOffset chunkStart = VerOffset::VER_ANY); + void debugDump(); - + void debugCheck(); + esp_err_t fillStats(nvs_stats_t& nvsStats); + + esp_err_t calcEntriesInNamespace(uint8_t nsIndex, size_t& usedEntries); + + bool findEntry(nvs_opaque_iterator_t*, const char* name); + + bool nextEntry(nvs_opaque_iterator_t* it); protected: @@ -99,10 +144,16 @@ class Storage : public intrusive_list_node void clearNamespaces(); - esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key, Page* &page, Item& item); + esp_err_t populateBlobIndices(TBlobIndexList&); + + void eraseOrphanDataBlobs(TBlobIndexList&); + + void fillEntryInfo(Item &item, nvs_entry_info_t &info); + + esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key, Page* &page, Item& item, uint8_t chunkIdx = Page::CHUNK_ANY, VerOffset chunkStart = VerOffset::VER_ANY); protected: - const char *mPartitionName; + Partition *mPartition; size_t mPageCount; PageManager mPageManager; TNamespaces mNamespaces; @@ -112,6 +163,14 @@ class Storage : public intrusive_list_node } // namespace nvs - +struct nvs_opaque_iterator_t +{ + nvs_type_t type; + uint8_t nsIndex; + size_t entryIndex; + nvs::Storage *storage; + intrusive_list::iterator page; + nvs_entry_info_t entry_info; +}; #endif /* nvs_storage_hpp */ diff --git a/components/nvs_flash/src/nvs_test_api.h b/components/nvs_flash/src/nvs_test_api.h index 3cf3e7fa1..8ba2c4faa 100644 --- a/components/nvs_flash/src/nvs_test_api.h +++ b/components/nvs_flash/src/nvs_test_api.h @@ -17,22 +17,38 @@ #ifdef __cplusplus extern "C" { #endif - + #include "nvs_flash.h" /** * @brief Initialize NVS flash storage with custom flash sector layout * * @note This API is intended to be used in unit tests. - * + * * @param partName Partition name of the NVS partition as per partition table * @param baseSector Flash sector (units of 4096 bytes) offset to start NVS - * @param sectorCount Length (in flash sectors) of NVS region. + * @param sectorCount Length (in flash sectors) of NVS region. NVS partition must be at least 3 sectors long. * @return ESP_OK if flash was successfully initialized */ esp_err_t nvs_flash_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount); +#ifdef CONFIG_NVS_ENCRYPTION +/** + * @brief Initialize NVS flash storage with custom flash sector layout + * + * @note This API is intended to be used in unit tests. + * + * @param partName Partition name of the NVS partition as per partition table + * @param baseSector Flash sector (units of 4096 bytes) offset to start NVS + * @param sectorCount Length (in flash sectors) of NVS region. + NVS partition must be at least 3 sectors long. + * @param[in] cfg Security configuration (keys) to be used for NVS encryption/decryption. + * If cfg is null, no encryption/decryption is used. + * @return ESP_OK if flash was successfully initialized + */ +esp_err_t nvs_flash_secure_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount, nvs_sec_cfg_t* cfg); +#endif /** * @brief Dump contents of NVS storage to stdout diff --git a/components/nvs_flash/src/nvs_types.cpp b/components/nvs_flash/src/nvs_types.cpp index 8a1a42fb2..127e24b88 100644 --- a/components/nvs_flash/src/nvs_types.cpp +++ b/components/nvs_flash/src/nvs_types.cpp @@ -13,7 +13,11 @@ // limitations under the License. #include "nvs_types.hpp" -#include +#if defined(LINUX_TARGET) +#include "crc.h" +#else +#include +#endif namespace nvs { @@ -35,6 +39,7 @@ uint32_t Item::calculateCrc32WithoutValue() const result = crc32_le(result, p + offsetof(Item, nsIndex), offsetof(Item, datatype) - offsetof(Item, nsIndex)); result = crc32_le(result, p + offsetof(Item, key), sizeof(key)); + result = crc32_le(result, p + offsetof(Item, chunkIndex), sizeof(chunkIndex)); return result; } diff --git a/components/nvs_flash/src/nvs_types.hpp b/components/nvs_flash/src/nvs_types.hpp index 5306744b5..d05d4d94b 100644 --- a/components/nvs_flash/src/nvs_types.hpp +++ b/components/nvs_flash/src/nvs_types.hpp @@ -15,41 +15,36 @@ #define nvs_types_h #include -#include #include #include #include #include "nvs.h" +#include "nvs_handle.hpp" #include "compressed_enum_table.hpp" +#include "string.h" +using namespace std; namespace nvs { -enum class ItemType : uint8_t { - U8 = 0x01, - I8 = 0x11, - U16 = 0x02, - I16 = 0x12, - U32 = 0x04, - I32 = 0x14, - U64 = 0x08, - I64 = 0x18, - SZ = 0x21, - BLOB = 0x41, - ANY = 0xff +/** + * Used to recognize transient states of a blob. Once a blob is modified, new chunks with the new data are written + * with a new version. The version is saved in the highest bit of Item::chunkIndex as well as in + * Item::blobIndex::chunkStart. + * If a chunk is modified and hence re-written, the version swaps: 0x0 -> 0x80 or 0x80 -> 0x0. + */ +enum class VerOffset: uint8_t { + VER_0_OFFSET = 0x0, + VER_1_OFFSET = 0x80, + VER_ANY = 0xff, }; -template::value, void*>::type = nullptr> -constexpr ItemType itemTypeOf() +inline bool isVariableLengthType(ItemType type) { - return static_cast(((std::is_signed::value)?0x10:0x00) | sizeof(T)); -} - -template -constexpr ItemType itemTypeOf(const T&) -{ - return itemTypeOf(); + return (type == ItemType::BLOB || + type == ItemType::SZ || + type == ItemType::BLOB_DATA); } class Item @@ -60,15 +55,21 @@ class Item uint8_t nsIndex; ItemType datatype; uint8_t span; - uint8_t reserved; + uint8_t chunkIndex; uint32_t crc32; - char key[16]; + char key[NVS_KEY_NAME_MAX_SIZE]; union { struct { uint16_t dataSize; - uint16_t reserved2; + uint16_t reserved; uint32_t dataCrc32; } varLength; + struct { + uint32_t dataSize; + uint8_t chunkCount; // Number of children data blobs. + VerOffset chunkStart; // Offset from which the chunkIndex for children blobs starts + uint16_t reserved; + } blobIndex; uint8_t data[8]; }; }; @@ -77,8 +78,12 @@ class Item static const size_t MAX_KEY_LENGTH = sizeof(key) - 1; - Item(uint8_t nsIndex, ItemType datatype, uint8_t span, const char* key_) - : nsIndex(nsIndex), datatype(datatype), span(span), reserved(0xff) + // 0xff cannot be used as a valid chunkIndex for blob datatype. + static const uint8_t CHUNK_ANY = 0xff; + + + Item(uint8_t nsIndex, ItemType datatype, uint8_t span, const char* key_, uint8_t chunkIdx = CHUNK_ANY) + : nsIndex(nsIndex), datatype(datatype), span(span), chunkIndex(chunkIdx) { std::fill_n(reinterpret_cast(key), sizeof(key) / 4, 0xffffffff); std::fill_n(reinterpret_cast(data), sizeof(data) / 4, 0xffffffff); @@ -100,7 +105,8 @@ class Item void getKey(char* dst, size_t dstSize) { - strncpy(dst, key, (dstSize @@ -113,6 +119,4 @@ class Item } // namespace nvs - - #endif /* nvs_types_h */ diff --git a/components/nvs_flash/src/partition.hpp b/components/nvs_flash/src/partition.hpp new file mode 100644 index 000000000..4cbfb6d9d --- /dev/null +++ b/components/nvs_flash/src/partition.hpp @@ -0,0 +1,59 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef PARTITION_HPP_ +#define PARTITION_HPP_ + +#include "esp_err.h" + +namespace nvs { + +/** + * @brief Abstract interface for partition related operations, currently in NVS. + * + * It resembles the main operations according to esp_partition.h. + */ +class Partition { +public: + virtual ~Partition() { } + + /** + * Return the partition name as in the partition table. + */ + virtual const char *get_partition_name() = 0; + + virtual esp_err_t read_raw(size_t src_offset, void* dst, size_t size) = 0; + + virtual esp_err_t read(size_t src_offset, void* dst, size_t size) = 0; + + virtual esp_err_t write_raw(size_t dst_offset, const void* src, size_t size) = 0; + + virtual esp_err_t write(size_t dst_offset, const void* src, size_t size) = 0; + + virtual esp_err_t erase_range(size_t dst_offset, size_t size) = 0; + + /** + * Return the address of the beginning of the partition. + */ + virtual uint32_t get_address() = 0; + + /** + * Return the partition size in bytes. + */ + virtual uint32_t get_size() = 0; +}; + +} // nvs + +#endif // PARTITION_HPP_ diff --git a/components/nvs_flash/test/CMakeLists.txt b/components/nvs_flash/test/CMakeLists.txt new file mode 100644 index 000000000..f69580398 --- /dev/null +++ b/components/nvs_flash/test/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRC_DIRS "." + PRIV_INCLUDE_DIRS "." + PRIV_REQUIRES cmock test_utils nvs_flash bootloader_support + EMBED_TXTFILES encryption_keys.bin partition_encrypted.bin sample.bin) diff --git a/components/nvs_flash/test/component.mk b/components/nvs_flash/test/component.mk index 5dd172bdb..a0ea7a406 100644 --- a/components/nvs_flash/test/component.mk +++ b/components/nvs_flash/test/component.mk @@ -3,3 +3,4 @@ # COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive +COMPONENT_EMBED_TXTFILES += encryption_keys.bin partition_encrypted.bin sample.bin diff --git a/components/nvs_flash/test/encryption_keys.bin b/components/nvs_flash/test/encryption_keys.bin new file mode 100644 index 000000000..9ef4439d8 --- /dev/null +++ b/components/nvs_flash/test/encryption_keys.bin @@ -0,0 +1 @@ +"""""""""""""""""""""""""""""""",ïÏ<ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file diff --git a/components/nvs_flash/test/partition_encrypted.bin b/components/nvs_flash/test/partition_encrypted.bin new file mode 100644 index 000000000..93c900ff4 Binary files /dev/null and b/components/nvs_flash/test/partition_encrypted.bin differ diff --git a/components/nvs_flash/test/sample.bin b/components/nvs_flash/test/sample.bin new file mode 100644 index 000000000..fe69eca4f --- /dev/null +++ b/components/nvs_flash/test/sample.bin @@ -0,0 +1 @@ +start0000000000000000000000start0123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef00000000000000000123456789abcdef0000000000000000end00000000000000000000000000end \ No newline at end of file diff --git a/components/nvs_flash/test/test_nvs.c b/components/nvs_flash/test/test_nvs.c index ed0884a7d..7e172f5ac 100644 --- a/components/nvs_flash/test/test_nvs.c +++ b/components/nvs_flash/test/test_nvs.c @@ -9,26 +9,75 @@ #include "esp_partition.h" #include "esp_log.h" #include +#include "esp_system.h" + +#ifdef CONFIG_NVS_ENCRYPTION +#include "mbedtls/aes.h" +#endif static const char* TAG = "test_nvs"; +TEST_CASE("Partition name no longer than 16 characters", "[nvs]") +{ + const char *TOO_LONG_NAME = "0123456789abcdefg"; + + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, nvs_flash_init_partition(TOO_LONG_NAME)); + + nvs_flash_deinit_partition(TOO_LONG_NAME); // just in case +} + +TEST_CASE("flash erase deinitializes initialized partition", "[nvs]") +{ + nvs_handle_t handle; + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + nvs_flash_erase(); + err = nvs_flash_init(); + } + TEST_ESP_OK( err ); + + TEST_ESP_OK(nvs_flash_init()); + TEST_ESP_OK(nvs_open("uninit_ns", NVS_READWRITE, &handle)); + nvs_close(handle); + TEST_ESP_OK(nvs_flash_erase()); + + // exptected: no partition is initialized since nvs_flash_erase() deinitialized the partition again + TEST_ESP_ERR(ESP_ERR_NVS_NOT_INITIALIZED, nvs_open("uninit_ns", NVS_READWRITE, &handle)); + + // just to be sure it's deinitialized in case of error and not affecting other tests + nvs_flash_deinit(); +} + +// test could have different output on host tests +TEST_CASE("nvs deinit with open handle", "[nvs]") +{ + nvs_handle_t handle_1; + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_LOGW(TAG, "nvs_flash_init failed (0x%x), erasing partition and retrying", err); + ESP_ERROR_CHECK(nvs_flash_erase()); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK( err ); + + TEST_ESP_OK(nvs_open("deinit_ns", NVS_READWRITE, &handle_1)); + nvs_flash_deinit(); +} + TEST_CASE("various nvs tests", "[nvs]") { - nvs_handle handle_1; + nvs_handle_t handle_1; esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_LOGW(TAG, "nvs_flash_init failed (0x%x), erasing partition and retrying", err); - const esp_partition_t* nvs_partition = esp_partition_find_first( - ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL); - assert(nvs_partition && "partition table must have an NVS partition"); - ESP_ERROR_CHECK( esp_partition_erase_range(nvs_partition, 0, nvs_partition->size) ); + ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); } ESP_ERROR_CHECK( err ); - TEST_ESP_ERR(nvs_open("test_namespace1", NVS_READONLY, &handle_1), ESP_ERR_NVS_NOT_FOUND); + TEST_ESP_ERR(ESP_ERR_NVS_NOT_FOUND, nvs_open("test_namespace1", NVS_READONLY, &handle_1)); - TEST_ESP_ERR(nvs_set_i32(handle_1, "foo", 0x12345678), ESP_ERR_NVS_INVALID_HANDLE); + TEST_ESP_ERR(ESP_ERR_NVS_INVALID_HANDLE, nvs_set_i32(handle_1, "foo", 0x12345678)); nvs_close(handle_1); TEST_ESP_OK(nvs_open("test_namespace2", NVS_READWRITE, &handle_1)); @@ -36,7 +85,7 @@ TEST_CASE("various nvs tests", "[nvs]") TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x12345678)); TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x23456789)); - nvs_handle handle_2; + nvs_handle_t handle_2; TEST_ESP_OK(nvs_open("test_namespace3", NVS_READWRITE, &handle_2)); TEST_ESP_OK(nvs_erase_all(handle_2)); TEST_ESP_OK(nvs_set_i32(handle_2, "foo", 0x3456789a)); @@ -65,3 +114,430 @@ TEST_CASE("various nvs tests", "[nvs]") nvs_close(handle_2); } + +TEST_CASE("calculate used and free space", "[nvs]") +{ + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, nvs_get_stats(NULL, NULL)); + nvs_stats_t stat1; + nvs_stats_t stat2; + TEST_ESP_ERR(ESP_ERR_NVS_NOT_INITIALIZED, nvs_get_stats(NULL, &stat1)); + TEST_ASSERT_TRUE(stat1.free_entries == 0); + TEST_ASSERT_TRUE(stat1.namespace_count == 0); + TEST_ASSERT_TRUE(stat1.total_entries == 0); + TEST_ASSERT_TRUE(stat1.used_entries == 0); + + nvs_handle_t handle = 0; + size_t h_count_entries; + TEST_ESP_ERR(ESP_ERR_NVS_INVALID_HANDLE, nvs_get_used_entry_count(handle, &h_count_entries)); + TEST_ASSERT_TRUE(h_count_entries == 0); + + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_LOGW(TAG, "nvs_flash_init failed (0x%x), erasing partition and retrying", err); + const esp_partition_t* nvs_partition = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL); + assert(nvs_partition && "partition table must have an NVS partition"); + ESP_ERROR_CHECK(nvs_flash_erase()); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK( err ); + + // erase if have any namespace + TEST_ESP_OK(nvs_get_stats(NULL, &stat1)); + if(stat1.namespace_count != 0) { + TEST_ESP_OK(nvs_flash_deinit()); + TEST_ESP_OK(nvs_flash_erase()); + TEST_ESP_OK(nvs_flash_init()); + } + + // after erase. empty partition + TEST_ESP_OK(nvs_get_stats(NULL, &stat1)); + TEST_ASSERT_TRUE(stat1.free_entries != 0); + TEST_ASSERT_TRUE(stat1.namespace_count == 0); + TEST_ASSERT_TRUE(stat1.total_entries != 0); + TEST_ASSERT_TRUE(stat1.used_entries == 0); + + // create namespace test_k1 + nvs_handle_t handle_1; + TEST_ESP_OK(nvs_open("test_k1", NVS_READWRITE, &handle_1)); + TEST_ESP_OK(nvs_get_stats(NULL, &stat2)); + TEST_ASSERT_TRUE(stat2.free_entries + 1 == stat1.free_entries); + TEST_ASSERT_TRUE(stat2.namespace_count == 1); + TEST_ASSERT_TRUE(stat2.total_entries == stat1.total_entries); + TEST_ASSERT_TRUE(stat2.used_entries == 1); + + // create pair key-value com + TEST_ESP_OK(nvs_set_i32(handle_1, "com", 0x12345678)); + TEST_ESP_OK(nvs_get_stats(NULL, &stat1)); + TEST_ASSERT_TRUE(stat1.free_entries + 1 == stat2.free_entries); + TEST_ASSERT_TRUE(stat1.namespace_count == 1); + TEST_ASSERT_TRUE(stat1.total_entries == stat2.total_entries); + TEST_ASSERT_TRUE(stat1.used_entries == 2); + + // change value in com + TEST_ESP_OK(nvs_set_i32(handle_1, "com", 0x01234567)); + TEST_ESP_OK(nvs_get_stats(NULL, &stat2)); + TEST_ASSERT_TRUE(stat2.free_entries == stat1.free_entries); + TEST_ASSERT_TRUE(stat2.namespace_count == 1); + TEST_ASSERT_TRUE(stat2.total_entries != 0); + TEST_ASSERT_TRUE(stat2.used_entries == 2); + + // create pair key-value ru + TEST_ESP_OK(nvs_set_i32(handle_1, "ru", 0x00FF00FF)); + TEST_ESP_OK(nvs_get_stats(NULL, &stat1)); + TEST_ASSERT_TRUE(stat1.free_entries + 1 == stat2.free_entries); + TEST_ASSERT_TRUE(stat1.namespace_count == 1); + TEST_ASSERT_TRUE(stat1.total_entries != 0); + TEST_ASSERT_TRUE(stat1.used_entries == 3); + + // amount valid pair in namespace 1 + size_t h1_count_entries; + TEST_ESP_OK(nvs_get_used_entry_count(handle_1, &h1_count_entries)); + TEST_ASSERT_TRUE(h1_count_entries == 2); + + nvs_handle_t handle_2; + // create namespace test_k2 + TEST_ESP_OK(nvs_open("test_k2", NVS_READWRITE, &handle_2)); + TEST_ESP_OK(nvs_get_stats(NULL, &stat2)); + TEST_ASSERT_TRUE(stat2.free_entries + 1 == stat1.free_entries); + TEST_ASSERT_TRUE(stat2.namespace_count == 2); + TEST_ASSERT_TRUE(stat2.total_entries == stat1.total_entries); + TEST_ASSERT_TRUE(stat2.used_entries == 4); + + // create pair key-value + TEST_ESP_OK(nvs_set_i32(handle_2, "su1", 0x00000001)); + TEST_ESP_OK(nvs_set_i32(handle_2, "su2", 0x00000002)); + TEST_ESP_OK(nvs_set_i32(handle_2, "sus", 0x00000003)); + TEST_ESP_OK(nvs_get_stats(NULL, &stat1)); + TEST_ASSERT_TRUE(stat1.free_entries + 3 == stat2.free_entries); + TEST_ASSERT_TRUE(stat1.namespace_count == 2); + TEST_ASSERT_TRUE(stat1.total_entries == stat2.total_entries); + TEST_ASSERT_TRUE(stat1.used_entries == 7); + + TEST_ASSERT_TRUE(stat1.total_entries == (stat1.used_entries + stat1.free_entries)); + + // amount valid pair in namespace 2 + size_t h2_count_entries; + TEST_ESP_OK(nvs_get_used_entry_count(handle_2, &h2_count_entries)); + TEST_ASSERT_TRUE(h2_count_entries == 3); + + TEST_ASSERT_TRUE(stat1.used_entries == (h1_count_entries + h2_count_entries + stat1.namespace_count)); + + nvs_close(handle_1); + nvs_close(handle_2); + + size_t temp = h2_count_entries; + TEST_ESP_ERR(ESP_ERR_NVS_INVALID_HANDLE, nvs_get_used_entry_count(handle_1, &h2_count_entries)); + TEST_ASSERT_TRUE(h2_count_entries == 0); + h2_count_entries = temp; + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, nvs_get_used_entry_count(handle_1, NULL)); + + nvs_handle_t handle_3; + // create namespace test_k3 + TEST_ESP_OK(nvs_open("test_k3", NVS_READWRITE, &handle_3)); + TEST_ESP_OK(nvs_get_stats(NULL, &stat2)); + TEST_ASSERT_TRUE(stat2.free_entries + 1 == stat1.free_entries); + TEST_ASSERT_TRUE(stat2.namespace_count == 3); + TEST_ASSERT_TRUE(stat2.total_entries == stat1.total_entries); + TEST_ASSERT_TRUE(stat2.used_entries == 8); + + // create pair blobs + uint32_t blob[12]; + TEST_ESP_OK(nvs_set_blob(handle_3, "bl1", &blob, sizeof(blob))); + TEST_ESP_OK(nvs_get_stats(NULL, &stat1)); + TEST_ASSERT_TRUE(stat1.free_entries + 4 == stat2.free_entries); + TEST_ASSERT_TRUE(stat1.namespace_count == 3); + TEST_ASSERT_TRUE(stat1.total_entries == stat2.total_entries); + TEST_ASSERT_TRUE(stat1.used_entries == 12); + + // amount valid pair in namespace 2 + size_t h3_count_entries; + TEST_ESP_OK(nvs_get_used_entry_count(handle_3, &h3_count_entries)); + TEST_ASSERT_TRUE(h3_count_entries == 4); + + TEST_ASSERT_TRUE(stat1.used_entries == (h1_count_entries + h2_count_entries + h3_count_entries + stat1.namespace_count)); + + nvs_close(handle_3); + + TEST_ESP_OK(nvs_flash_deinit()); + TEST_ESP_OK(nvs_flash_erase()); +} + +TEST_CASE("check for memory leaks in nvs_set_blob", "[nvs]") +{ + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + err = nvs_flash_init(); + } + TEST_ESP_OK( err ); + + for (int i = 0; i < 500; ++i) { + nvs_handle_t my_handle; + uint8_t key[20] = {0}; + + TEST_ESP_OK( nvs_open("leak_check_ns", NVS_READWRITE, &my_handle) ); + TEST_ESP_OK( nvs_set_blob(my_handle, "key", key, sizeof(key)) ); + TEST_ESP_OK( nvs_commit(my_handle) ); + nvs_close(my_handle); + printf("%d\n", esp_get_free_heap_size()); + } + + nvs_flash_deinit(); + printf("%d\n", esp_get_free_heap_size()); + /* heap leaks will be checked in unity_platform.c */ +} + +#ifdef CONFIG_NVS_ENCRYPTION +TEST_CASE("check underlying xts code for 32-byte size sector encryption", "[nvs]") +{ + uint8_t eky_hex[2 * NVS_KEY_SIZE] = { 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + /* Tweak key below*/ + 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, + 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, + 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, + 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22 }; + + uint8_t ba_hex[16] = { 0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + + uint8_t ptxt_hex[32] = { 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44 }; + + + uint8_t ctxt_hex[32] = { 0xe6,0x22,0x33,0x4f,0x18,0x4b,0xbc,0xe1, + 0x29,0xa2,0x5b,0x2a,0xc7,0x6b,0x3d,0x92, + 0xab,0xf9,0x8e,0x22,0xdf,0x5b,0xdd,0x15, + 0xaf,0x47,0x1f,0x3d,0xb8,0x94,0x6a,0x85 }; + + mbedtls_aes_xts_context ectx[1]; + mbedtls_aes_xts_context dctx[1]; + + mbedtls_aes_xts_init(ectx); + mbedtls_aes_xts_init(dctx); + + TEST_ASSERT_TRUE(!mbedtls_aes_xts_setkey_enc(ectx, eky_hex, 2 * NVS_KEY_SIZE * 8)); + TEST_ASSERT_TRUE(!mbedtls_aes_xts_setkey_enc(dctx, eky_hex, 2 * NVS_KEY_SIZE * 8)); + + TEST_ASSERT_TRUE(!mbedtls_aes_crypt_xts(ectx, MBEDTLS_AES_ENCRYPT, 32, ba_hex, ptxt_hex, ptxt_hex)); + + TEST_ASSERT_TRUE(!memcmp(ptxt_hex, ctxt_hex, 32)); +} + +TEST_CASE("Check nvs key partition APIs (read and generate keys)", "[nvs]") +{ + nvs_sec_cfg_t cfg, cfg2; + + const esp_partition_t* key_part = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS, NULL); + + if (!esp_flash_encryption_enabled()) { + TEST_IGNORE_MESSAGE("flash encryption disabled, skipping nvs_key partition related tests"); + } + + TEST_ESP_OK(esp_partition_erase_range(key_part, 0, key_part->size)); + TEST_ESP_ERR(ESP_ERR_NVS_KEYS_NOT_INITIALIZED, nvs_flash_read_security_cfg(key_part, &cfg)); + + TEST_ESP_OK(nvs_flash_generate_keys(key_part, &cfg)); + + TEST_ESP_OK(nvs_flash_read_security_cfg(key_part, &cfg2)); + + TEST_ASSERT_TRUE(!memcmp(&cfg, &cfg2, sizeof(nvs_sec_cfg_t))); +} + + +TEST_CASE("test nvs apis with encryption enabled", "[nvs]") +{ + if (!esp_flash_encryption_enabled()) { + TEST_IGNORE_MESSAGE("flash encryption disabled, skipping nvs_api tests with encryption enabled"); + } + const esp_partition_t* key_part = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS, NULL); + + assert(key_part && "partition table must have an NVS Key partition"); + + const esp_partition_t* nvs_partition = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL); + assert(nvs_partition && "partition table must have an NVS partition"); + + ESP_ERROR_CHECK( esp_partition_erase_range(key_part, 0, key_part->size) ); + + bool done = false; + + do { + ESP_ERROR_CHECK( esp_partition_erase_range(nvs_partition, 0, nvs_partition->size) ); + + nvs_sec_cfg_t cfg; + esp_err_t err = nvs_flash_read_security_cfg(key_part, &cfg); + + if(err == ESP_ERR_NVS_KEYS_NOT_INITIALIZED) { + uint8_t value[4096] = {[0 ... 4095] = 0xff}; + TEST_ESP_OK(esp_partition_write(key_part, 0, value, sizeof(value))); + + TEST_ESP_ERR(ESP_ERR_NVS_KEYS_NOT_INITIALIZED, nvs_flash_read_security_cfg(key_part, &cfg)); + + TEST_ESP_OK(nvs_flash_generate_keys(key_part, &cfg)); + } else { + /* Second time key_partition exists already*/ + ESP_ERROR_CHECK(err); + done = true; + } + TEST_ESP_OK(nvs_flash_secure_init(&cfg)); + + nvs_handle_t handle_1; + + TEST_ESP_ERR(ESP_ERR_NVS_NOT_FOUND, nvs_open("namespace1", NVS_READONLY, &handle_1)); + + + TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle_1)); + + TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x12345678)); + TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x23456789)); + + nvs_handle_t handle_2; + TEST_ESP_OK(nvs_open("namespace2", NVS_READWRITE, &handle_2)); + TEST_ESP_OK(nvs_set_i32(handle_2, "foo", 0x3456789a)); + const char* str = "value 0123456789abcdef0123456789abcdef"; + TEST_ESP_OK(nvs_set_str(handle_2, "key", str)); + + int32_t v1; + TEST_ESP_OK(nvs_get_i32(handle_1, "foo", &v1)); + TEST_ASSERT_TRUE(0x23456789 == v1); + + int32_t v2; + TEST_ESP_OK(nvs_get_i32(handle_2, "foo", &v2)); + TEST_ASSERT_TRUE(0x3456789a == v2); + + char buf[strlen(str) + 1]; + size_t buf_len = sizeof(buf); + + size_t buf_len_needed; + TEST_ESP_OK(nvs_get_str(handle_2, "key", NULL, &buf_len_needed)); + TEST_ASSERT_TRUE(buf_len_needed == buf_len); + + size_t buf_len_short = buf_len - 1; + TEST_ESP_ERR(ESP_ERR_NVS_INVALID_LENGTH, nvs_get_str(handle_2, "key", buf, &buf_len_short)); + TEST_ASSERT_TRUE(buf_len_short == buf_len); + + size_t buf_len_long = buf_len + 1; + TEST_ESP_OK(nvs_get_str(handle_2, "key", buf, &buf_len_long)); + TEST_ASSERT_TRUE(buf_len_long == buf_len); + + TEST_ESP_OK(nvs_get_str(handle_2, "key", buf, &buf_len)); + + TEST_ASSERT_TRUE(0 == strcmp(buf, str)); + + nvs_close(handle_1); + nvs_close(handle_2); + + TEST_ESP_OK(nvs_flash_deinit()); + } while(!done); +} + +TEST_CASE("test nvs apis for nvs partition generator utility with encryption enabled", "[nvs_part_gen]") +{ + + if (!esp_flash_encryption_enabled()) { + TEST_IGNORE_MESSAGE("flash encryption disabled, skipping nvs_api tests with encryption enabled"); + } + + nvs_handle_t handle; + nvs_sec_cfg_t xts_cfg; + + extern const char nvs_key_start[] asm("_binary_encryption_keys_bin_start"); + extern const char nvs_key_end[] asm("_binary_encryption_keys_bin_end"); + + extern const char nvs_data_start[] asm("_binary_partition_encrypted_bin_start"); + + extern const char sample_bin_start[] asm("_binary_sample_bin_start"); + + const esp_partition_t* key_part = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS, NULL); + + const esp_partition_t* nvs_part = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL); + + assert(key_part && "partition table must have a KEY partition"); + TEST_ASSERT_TRUE((nvs_key_end - nvs_key_start - 1) == SPI_FLASH_SEC_SIZE); + + assert(nvs_part && "partition table must have an NVS partition"); + printf("\n nvs_part size:%d\n", nvs_part->size); + + ESP_ERROR_CHECK(esp_partition_erase_range(key_part, 0, key_part->size)); + ESP_ERROR_CHECK( esp_partition_erase_range(nvs_part, 0, nvs_part->size) ); + + for (int i = 0; i < key_part->size; i+= SPI_FLASH_SEC_SIZE) { + ESP_ERROR_CHECK( esp_partition_write(key_part, i, nvs_key_start + i, SPI_FLASH_SEC_SIZE) ); + } + + for (int i = 0; i < nvs_part->size; i+= SPI_FLASH_SEC_SIZE) { + ESP_ERROR_CHECK( esp_partition_write(nvs_part, i, nvs_data_start + i, SPI_FLASH_SEC_SIZE) ); + } + + esp_err_t err = nvs_flash_read_security_cfg(key_part, &xts_cfg); + ESP_ERROR_CHECK(err); + + TEST_ESP_OK(nvs_flash_secure_init(&xts_cfg)); + + TEST_ESP_OK(nvs_open("dummyNamespace", NVS_READONLY, &handle)); + uint8_t u8v; + TEST_ESP_OK( nvs_get_u8(handle, "dummyU8Key", &u8v)); + TEST_ASSERT_TRUE(u8v == 127); + int8_t i8v; + TEST_ESP_OK( nvs_get_i8(handle, "dummyI8Key", &i8v)); + TEST_ASSERT_TRUE(i8v == -128); + uint16_t u16v; + TEST_ESP_OK( nvs_get_u16(handle, "dummyU16Key", &u16v)); + TEST_ASSERT_TRUE(u16v == 32768); + uint32_t u32v; + TEST_ESP_OK( nvs_get_u32(handle, "dummyU32Key", &u32v)); + TEST_ASSERT_TRUE(u32v == 4294967295); + int32_t i32v; + TEST_ESP_OK( nvs_get_i32(handle, "dummyI32Key", &i32v)); + TEST_ASSERT_TRUE(i32v == -2147483648); + + char buf[64] = {0}; + size_t buflen = 64; + TEST_ESP_OK( nvs_get_str(handle, "dummyStringKey", buf, &buflen)); + TEST_ASSERT_TRUE(strncmp(buf, "0A:0B:0C:0D:0E:0F", buflen) == 0); + + uint8_t hexdata[] = {0x01, 0x02, 0x03, 0xab, 0xcd, 0xef}; + buflen = 64; + TEST_ESP_OK( nvs_get_blob(handle, "dummyHex2BinKey", buf, &buflen)); + TEST_ASSERT_TRUE(memcmp(buf, hexdata, buflen) == 0); + + uint8_t base64data[] = {'1', '2', '3', 'a', 'b', 'c'}; + buflen = 64; + TEST_ESP_OK( nvs_get_blob(handle, "dummyBase64Key", buf, &buflen)); + TEST_ASSERT_TRUE(memcmp(buf, base64data, buflen) == 0); + + uint8_t hexfiledata[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}; + buflen = 64; + TEST_ESP_OK( nvs_get_blob(handle, "hexFileKey", buf, &buflen)); + TEST_ASSERT_TRUE(memcmp(buf, hexfiledata, buflen) == 0); + + uint8_t base64filedata[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xab, 0xcd, 0xef}; + buflen = 64; + TEST_ESP_OK( nvs_get_blob(handle, "base64FileKey", buf, &buflen)); + TEST_ASSERT_TRUE(memcmp(buf, base64filedata, buflen) == 0); + + uint8_t strfiledata[64] = "abcdefghijklmnopqrstuvwxyz\0"; + buflen = 64; + TEST_ESP_OK( nvs_get_str(handle, "stringFileKey", buf, &buflen)); + TEST_ASSERT_TRUE(memcmp(buf, strfiledata, buflen) == 0); + + char bin_data[5120]; + size_t bin_len = sizeof(bin_data); + TEST_ESP_OK( nvs_get_blob(handle, "binFileKey", bin_data, &bin_len)); + TEST_ASSERT_TRUE(memcmp(bin_data, sample_bin_start, bin_len) == 0); + + nvs_close(handle); + TEST_ESP_OK(nvs_flash_deinit()); + +} +#endif diff --git a/components/nvs_flash/test_nvs_host/Makefile b/components/nvs_flash/test_nvs_host/Makefile index f1f5b52f2..5031de6a8 100644 --- a/components/nvs_flash/test_nvs_host/Makefile +++ b/components/nvs_flash/test_nvs_host/Makefile @@ -3,6 +3,7 @@ all: $(TEST_PROGRAM) SOURCE_FILES = \ esp_error_check_stub.cpp \ + ../mock/int/crc.cpp \ $(addprefix ../src/, \ nvs_types.cpp \ nvs_api.cpp \ @@ -10,37 +11,61 @@ SOURCE_FILES = \ nvs_pagemanager.cpp \ nvs_storage.cpp \ nvs_item_hash_list.cpp \ + nvs_handle_simple.cpp \ + nvs_handle_locked.cpp \ + nvs_partition_manager.cpp \ + nvs_partition.cpp \ + nvs_encrypted_partition.cpp \ + nvs_cxx_api.cpp \ ) \ spi_flash_emulation.cpp \ test_compressed_enum_table.cpp \ test_spi_flash_emulation.cpp \ test_intrusive_list.cpp \ test_nvs.cpp \ - crc.cpp \ + test_partition_manager.cpp \ + test_nvs_handle.cpp \ + test_nvs_storage.cpp \ + test_nvs_partition.cpp \ + test_nvs_cxx_api.cpp \ + test_nvs_initialization.cpp \ main.cpp -CPPFLAGS += -I../include -I../src -I./ -I../../esp32/include -I ../../spi_flash/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage -CFLAGS += -fprofile-arcs -ftest-coverage -CXXFLAGS += -std=c++11 -Wall -Werror +ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1) +COMPILER := clang +else +COMPILER := gcc +endif + +CPPFLAGS += -I../include -I../src -I../mock/int -I./ -I../../esp_common/include -I../../esp32/include -I ../../mbedtls/mbedtls/include -I ../../spi_flash/include -I ../../hal/include -I ../../xtensa/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage -g2 -ggdb +CFLAGS += -fprofile-arcs -ftest-coverage -DLINUX_TARGET +CXXFLAGS += -std=c++11 -Wall -Werror -DLINUX_TARGET LDFLAGS += -lstdc++ -Wall -fprofile-arcs -ftest-coverage +ifeq ($(COMPILER),clang) +CFLAGS += -fsanitize=address +CXXFLAGS += -fsanitize=address +LDFLAGS += -fsanitize=address +endif + OBJ_FILES = $(SOURCE_FILES:.cpp=.o) COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(OBJ_FILES): %.o: %.cpp -$(TEST_PROGRAM): $(OBJ_FILES) - g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) +$(TEST_PROGRAM): clean-coverage $(OBJ_FILES) + $(MAKE) -C ../../mbedtls/mbedtls/ lib + g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) ../../mbedtls/mbedtls/library/libmbedcrypto.a $(OUTPUT_DIR): mkdir -p $(OUTPUT_DIR) test: $(TEST_PROGRAM) - ./$(TEST_PROGRAM) + ./$(TEST_PROGRAM) -d yes exclude:[long] long-test: $(TEST_PROGRAM) - ./$(TEST_PROGRAM) [list],[enumtable],[spi_flash_emu],[nvs],[long] + ./$(TEST_PROGRAM) -d yes $(COVERAGE_FILES): $(TEST_PROGRAM) long-test @@ -52,10 +77,26 @@ coverage_report: coverage.info genhtml coverage.info --output-directory coverage_report @echo "Coverage report is in coverage_report/index.html" -clean: - rm -f $(OBJ_FILES) $(TEST_PROGRAM) +clean-coverage: rm -f $(COVERAGE_FILES) *.gcov rm -rf coverage_report/ rm -f coverage.info -.PHONY: clean all test +clean: clean-coverage + $(MAKE) -C ../../mbedtls/mbedtls/ clean + rm -f $(OBJ_FILES) $(TEST_PROGRAM) + rm -f ../nvs_partition_generator/partition_single_page.bin + rm -f ../nvs_partition_generator/partition_multipage_blob.bin + rm -f ../nvs_partition_generator/partition_encrypted.bin + rm -f ../nvs_partition_generator/partition_encrypted_using_keygen.bin + rm -f ../nvs_partition_generator/partition_encrypted_using_keyfile.bin + rm -f ../nvs_partition_generator/partition_decrypted.bin + rm -f ../nvs_partition_generator/partition_encoded.bin + rm -f ../nvs_partition_generator/Test-1-partition-encrypted.bin + rm -f ../nvs_partition_generator/Test-1-partition.bin + rm -f ../../../tools/mass_mfg/samples/sample_values_multipage_blob_created.csv + rm -f ../../../tools/mass_mfg/samples/sample_values_singlepage_blob_created.csv + + + +.PHONY: clean clean-coverage all test long-test diff --git a/components/nvs_flash/test_nvs_host/README.md b/components/nvs_flash/test_nvs_host/README.md new file mode 100644 index 000000000..bad5b08cd --- /dev/null +++ b/components/nvs_flash/test_nvs_host/README.md @@ -0,0 +1,22 @@ +# Build + +```bash +make -j 6 +``` + +# Run +* Run particular test case: +```bash +./test_nvs "" + +``` +* Run all quick tests: +```bash +./test_nvs -d yes exclude:[long] +``` + +* Run all tests (takes several hours) +```bash +./test_nvs -d yes +``` + diff --git a/components/nvs_flash/test_nvs_host/esp_error_check_stub.cpp b/components/nvs_flash/test_nvs_host/esp_error_check_stub.cpp index 9cff4af31..34d8704e7 100644 --- a/components/nvs_flash/test_nvs_host/esp_error_check_stub.cpp +++ b/components/nvs_flash/test_nvs_host/esp_error_check_stub.cpp @@ -1,9 +1,14 @@ #include "catch.hpp" #include "esp_err.h" +#include "sdkconfig.h" void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) { - printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x at %p\n", rc, __builtin_return_address(0)); + printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x", rc); +#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP + printf(" (%s)", esp_err_to_name(rc)); +#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP + printf(" at %p\n", __builtin_return_address(0)); printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression); abort(); } diff --git a/components/nvs_flash/test_nvs_host/sdkconfig.h b/components/nvs_flash/test_nvs_host/sdkconfig.h index e69de29bb..a38e0a10d 100644 --- a/components/nvs_flash/test_nvs_host/sdkconfig.h +++ b/components/nvs_flash/test_nvs_host/sdkconfig.h @@ -0,0 +1,3 @@ +#define CONFIG_NVS_ENCRYPTION 1 +//currently use the legacy implementation, since the stubs for new HAL are not done yet +#define CONFIG_SPI_FLASH_USE_LEGACY_IMPL 1 diff --git a/components/nvs_flash/test_nvs_host/spi_flash_emulation.cpp b/components/nvs_flash/test_nvs_host/spi_flash_emulation.cpp index 914efc145..e5b9ae071 100644 --- a/components/nvs_flash/test_nvs_host/spi_flash_emulation.cpp +++ b/components/nvs_flash/test_nvs_host/spi_flash_emulation.cpp @@ -11,7 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -#include "esp_spi_flash.h" +#include "esp_partition.h" #include "spi_flash_emulation.h" @@ -22,39 +22,82 @@ void spi_flash_emulator_set(SpiFlashEmulator* e) s_emulator = e; } -esp_err_t spi_flash_erase_sector(size_t sec) +esp_err_t esp_partition_erase_range(const esp_partition_t* partition, + size_t offset, size_t size) { if (!s_emulator) { return ESP_ERR_FLASH_OP_TIMEOUT; } - if (!s_emulator->erase(sec)) { + if (size % SPI_FLASH_SEC_SIZE != 0) { + return ESP_ERR_INVALID_SIZE; + } + + if (offset % SPI_FLASH_SEC_SIZE != 0) { + return ESP_ERR_INVALID_ARG; + } + + size_t start_sector = offset / SPI_FLASH_SEC_SIZE; + size_t num_sectors = size / SPI_FLASH_SEC_SIZE; + for (size_t sector = start_sector; sector < (start_sector + num_sectors); sector++) { + if (!s_emulator->erase(sector)) { + return ESP_ERR_FLASH_OP_FAIL; + } + } + + return ESP_OK; +} + +esp_err_t esp_partition_read(const esp_partition_t* partition, + size_t src_offset, void* dst, size_t size) +{ + if (!s_emulator) { + return ESP_ERR_FLASH_OP_TIMEOUT; + } + + if (!s_emulator->read(reinterpret_cast(dst), src_offset, size)) { return ESP_ERR_FLASH_OP_FAIL; } return ESP_OK; } -esp_err_t spi_flash_write(size_t des_addr, const void *src_addr, size_t size) +esp_err_t esp_partition_read(const esp_partition_t* partition, + size_t src_offset, void* dst, size_t size) { if (!s_emulator) { return ESP_ERR_FLASH_OP_TIMEOUT; } - if (!s_emulator->write(des_addr, reinterpret_cast(src_addr), size)) { + if (!s_emulator->read(reinterpret_cast(dst), src_offset, size)) { return ESP_ERR_FLASH_OP_FAIL; } return ESP_OK; } -esp_err_t spi_flash_read(size_t src_addr, void *des_addr, size_t size) +esp_err_t esp_partition_write(const esp_partition_t* partition, + size_t dst_offset, const void* src, size_t size) { if (!s_emulator) { return ESP_ERR_FLASH_OP_TIMEOUT; } - if (!s_emulator->read(reinterpret_cast(des_addr), src_addr, size)) { + if (!s_emulator->write(dst_offset, reinterpret_cast(src), size)) { + return ESP_ERR_FLASH_OP_FAIL; + } + + return ESP_OK; +} + +esp_err_t esp_partition_write(const esp_partition_t* partition, + size_t dst_offset, const void* src, size_t size) +{ + if (!s_emulator) { + return ESP_ERR_FLASH_OP_TIMEOUT; + } + + if (!s_emulator->write(dst_offset, reinterpret_cast(src), size)) { return ESP_ERR_FLASH_OP_FAIL; } @@ -71,10 +114,11 @@ static size_t blockEraseTime = 37142; static size_t timeInterp(uint32_t bytes, size_t* lut) { + const int lut_size = sizeof(readTimes)/sizeof(readTimes[0]); int lz = __builtin_clz(bytes / 4); int log_size = 32 - lz; size_t x2 = 1 << (log_size + 2); - size_t y2 = lut[log_size]; + size_t y2 = lut[std::min(log_size, lut_size - 1)]; size_t x1 = 1 << (log_size + 1); size_t y1 = lut[log_size - 1]; return (bytes - x1) * (y2 - y1) / (x2 - x1) + y1; @@ -94,4 +138,3 @@ size_t SpiFlashEmulator::getEraseOpTime() { return blockEraseTime; } - diff --git a/components/nvs_flash/test_nvs_host/spi_flash_emulation.h b/components/nvs_flash/test_nvs_host/spi_flash_emulation.h index d8099322d..f2aef6a01 100644 --- a/components/nvs_flash/test_nvs_host/spi_flash_emulation.h +++ b/components/nvs_flash/test_nvs_host/spi_flash_emulation.h @@ -36,6 +36,16 @@ class SpiFlashEmulator SpiFlashEmulator(size_t sectorCount) : mUpperSectorBound(sectorCount) { mData.resize(sectorCount * SPI_FLASH_SEC_SIZE / 4, 0xffffffff); + mEraseCnt.resize(sectorCount); + spi_flash_emulator_set(this); + } + + SpiFlashEmulator(const char *filename) + { + load(filename); + // Atleast one page should be free, hence we create mData of size of 2 sectors. + mData.resize(mData.size() + SPI_FLASH_SEC_SIZE / 4, 0xffffffff); + mUpperSectorBound = mData.size() * 4 / SPI_FLASH_SEC_SIZE; spi_flash_emulator_set(this); } @@ -67,13 +77,13 @@ class SpiFlashEmulator WARN("invalid flash operation detected: erase sector=" << sectorNumber); return false; } - + if (dstAddr % 4 != 0 || size % 4 != 0 || dstAddr + size > mData.size() * 4) { return false; } - + for (size_t i = 0; i < size / 4; ++i) { if (mFailCountdown != SIZE_MAX && mFailCountdown-- == 0) { return false; @@ -102,12 +112,12 @@ class SpiFlashEmulator if (offset > mData.size()) { return false; } - + if (sectorNumber < mLowerSectorBound || sectorNumber >= mUpperSectorBound) { WARN("invalid flash operation detected: erase sector=" << sectorNumber); return false; } - + if (mFailCountdown != SIZE_MAX && mFailCountdown-- == 0) { return false; } @@ -115,10 +125,11 @@ class SpiFlashEmulator std::fill_n(begin(mData) + offset, SPI_FLASH_SEC_SIZE / 4, 0xffffffff); ++mEraseOps; + mEraseCnt[sectorNumber]++; mTotalTime += getEraseOpTime(); return true; } - + void randomize(uint32_t seed) { std::random_device rd; @@ -141,7 +152,7 @@ class SpiFlashEmulator { return reinterpret_cast(mData.data()); } - + void load(const char* filename) { FILE* f = fopen(filename, "rb"); @@ -154,7 +165,7 @@ class SpiFlashEmulator assert(s == static_cast(size / SPI_FLASH_SEC_SIZE)); fclose(f); } - + void save(const char* filename) { FILE* f = fopen(filename, "wb"); @@ -198,16 +209,20 @@ class SpiFlashEmulator { return mTotalTime; } - + void setBounds(uint32_t lowerSector, uint32_t upperSector) { mLowerSectorBound = lowerSector; mUpperSectorBound = upperSector; } - + void failAfter(uint32_t count) { mFailCountdown = count; } + size_t getSectorEraseCount(uint32_t sector) const { + return mEraseCnt[sector]; + } + protected: static size_t getReadOpTime(uint32_t bytes); static size_t getWriteOpTime(uint32_t bytes); @@ -215,6 +230,7 @@ class SpiFlashEmulator std::vector mData; + std::vector mEraseCnt; mutable size_t mReadOps = 0; mutable size_t mWriteOps = 0; @@ -224,7 +240,7 @@ class SpiFlashEmulator mutable size_t mTotalTime = 0; size_t mLowerSectorBound = 0; size_t mUpperSectorBound = 0; - + size_t mFailCountdown = SIZE_MAX; }; diff --git a/components/nvs_flash/test_nvs_host/test_compressed_enum_table.cpp b/components/nvs_flash/test_nvs_host/test_compressed_enum_table.cpp index 225a11c27..a404545c7 100644 --- a/components/nvs_flash/test_nvs_host/test_compressed_enum_table.cpp +++ b/components/nvs_flash/test_nvs_host/test_compressed_enum_table.cpp @@ -53,4 +53,4 @@ TEST_CASE("test if CompressedEnumTable works as expected", "[enumtable]") CHECK(table.data()[0] == 0x93909249); -} \ No newline at end of file +} diff --git a/components/nvs_flash/test_nvs_host/test_fixtures.hpp b/components/nvs_flash/test_nvs_host/test_fixtures.hpp new file mode 100644 index 000000000..473f1da97 --- /dev/null +++ b/components/nvs_flash/test_nvs_host/test_fixtures.hpp @@ -0,0 +1,149 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "nvs_partition.hpp" +#include "nvs_encrypted_partition.hpp" +#include "spi_flash_emulation.h" +#include "nvs.h" + +class PartitionEmulation : public nvs::Partition { +public: + PartitionEmulation(SpiFlashEmulator *spi_flash_emulator, + uint32_t address, + uint32_t size, + const char *partition_name = NVS_DEFAULT_PART_NAME) + : partition_name(partition_name), flash_emu(spi_flash_emulator), address(address), size(size) + { + assert(partition_name); + assert(flash_emu); + assert(size); + } + + const char *get_partition_name() override + { + return partition_name; + } + + esp_err_t read_raw(size_t src_offset, void* dst, size_t size) override + { + if (!flash_emu->read(reinterpret_cast(dst), src_offset, size)) { + return ESP_ERR_FLASH_OP_FAIL; + } + + return ESP_OK; + } + + esp_err_t read(size_t src_offset, void* dst, size_t size) override + { + if (!flash_emu->read(reinterpret_cast(dst), src_offset, size)) { + return ESP_ERR_FLASH_OP_FAIL; + } + + return ESP_OK; + } + + esp_err_t write_raw(size_t dst_offset, const void* src, size_t size) override + { + if (!flash_emu->write(dst_offset, reinterpret_cast(src), size)) { + return ESP_ERR_FLASH_OP_FAIL; + } + + return ESP_OK; + } + + esp_err_t write(size_t dst_offset, const void* src, size_t size) override + { + if (!flash_emu->write(dst_offset, reinterpret_cast(src), size)) { + return ESP_ERR_FLASH_OP_FAIL; + } + + return ESP_OK; + } + + esp_err_t erase_range(size_t dst_offset, size_t size) override + { + if (size % SPI_FLASH_SEC_SIZE != 0) { + return ESP_ERR_INVALID_SIZE; + } + + if (dst_offset % SPI_FLASH_SEC_SIZE != 0) { + return ESP_ERR_INVALID_ARG; + } + + size_t start_sector = dst_offset / SPI_FLASH_SEC_SIZE; + size_t num_sectors = size / SPI_FLASH_SEC_SIZE; + for (size_t sector = start_sector; sector < (start_sector + num_sectors); sector++) { + if (!flash_emu->erase(sector)) { + return ESP_ERR_FLASH_OP_FAIL; + } + } + + return ESP_OK; + } + + uint32_t get_address() override + { + return address; + } + + uint32_t get_size() override + { + return size; + } + +private: + const char *partition_name; + + SpiFlashEmulator *flash_emu; + + uint32_t address; + + uint32_t size; +}; + +struct PartitionEmulationFixture { + PartitionEmulationFixture(uint32_t start_sector = 0, + uint32_t sector_size = 1, + const char *partition_name = NVS_DEFAULT_PART_NAME) + : emu(start_sector + sector_size), + part(&emu, start_sector * SPI_FLASH_SEC_SIZE, sector_size * SPI_FLASH_SEC_SIZE, partition_name) { + } + + ~PartitionEmulationFixture() { } + + SpiFlashEmulator emu; + + PartitionEmulation part; +}; + +struct EncryptedPartitionFixture { + EncryptedPartitionFixture(nvs_sec_cfg_t *cfg, + uint32_t start_sector = 0, + uint32_t sector_size = 1, + const char *partition_name = NVS_DEFAULT_PART_NAME) + : esp_partition(), emu(start_sector + sector_size), + part(&esp_partition) { + esp_partition.address = start_sector * SPI_FLASH_SEC_SIZE; + esp_partition.size = sector_size * SPI_FLASH_SEC_SIZE; + strncpy(esp_partition.label, partition_name, PART_NAME_MAX_SIZE); + assert(part.init(cfg) == ESP_OK); + } + + ~EncryptedPartitionFixture() { } + + esp_partition_t esp_partition; + + SpiFlashEmulator emu; + + nvs::NVSEncryptedPartition part; +}; diff --git a/components/nvs_flash/test_nvs_host/test_intrusive_list.cpp b/components/nvs_flash/test_nvs_host/test_intrusive_list.cpp index 979438a0b..dea63f3c3 100644 --- a/components/nvs_flash/test_nvs_host/test_intrusive_list.cpp +++ b/components/nvs_flash/test_nvs_host/test_intrusive_list.cpp @@ -197,8 +197,8 @@ TEST_CASE("can erase all items in the list using clear method", "[list]") TestNode n4("four", 4); TestNode n5("five", 5); TestNode n6("six", 6); - - + + list.push_back(&n1); list.push_back(&n2); list.insert(++list.begin(), &n3); @@ -207,7 +207,6 @@ TEST_CASE("can erase all items in the list using clear method", "[list]") list.insert(list.begin(), &n6); list.clear(); - + REQUIRE(std::begin(list) == std::end(list)); } - diff --git a/components/nvs_flash/test_nvs_host/test_nvs.cpp b/components/nvs_flash/test_nvs_host/test_nvs.cpp index c23f5d661..b7a2110a2 100644 --- a/components/nvs_flash/test_nvs_host/test_nvs.cpp +++ b/components/nvs_flash/test_nvs_host/test_nvs.cpp @@ -14,9 +14,21 @@ #include "catch.hpp" #include "nvs.hpp" #include "nvs_test_api.h" +#include "sdkconfig.h" #include "spi_flash_emulation.h" +#include "nvs_partition_manager.hpp" +#include "nvs_partition.hpp" +#include "mbedtls/aes.h" #include #include +#include +#include +#include +#include +#include +#include + +#include "test_fixtures.hpp" #define TEST_ESP_ERR(rc, res) CHECK((rc) == (res)) #define TEST_ESP_OK(rc) CHECK((rc) == ESP_OK) @@ -45,7 +57,7 @@ TEST_CASE("crc32 behaves as expected", "[nvs]") item1.datatype = ItemType::I32; item1.nsIndex = 1; item1.crc32 = 0; - item1.reserved = 0xff; + item1.chunkIndex = 0xff; fill_n(item1.key, sizeof(item1.key), 0xbb); fill_n(item1.data, sizeof(item1.data), 0xaa); @@ -69,20 +81,20 @@ TEST_CASE("crc32 behaves as expected", "[nvs]") CHECK(crc32_1 != item2.calculateCrc32()); } -TEST_CASE("starting with empty flash, page is in uninitialized state", "[nvs]") +TEST_CASE("Page starting with empty flash is in uninitialized state", "[nvs]") { - SpiFlashEmulator emu(1); + PartitionEmulationFixture f; Page page; CHECK(page.state() == Page::PageState::INVALID); - CHECK(page.load(0) == ESP_OK); + CHECK(page.load(&f.part, 0) == ESP_OK); CHECK(page.state() == Page::PageState::UNINITIALIZED); } -TEST_CASE("can distinguish namespaces", "[nvs]") +TEST_CASE("Page can distinguish namespaces", "[nvs]") { - SpiFlashEmulator emu(1); + PartitionEmulationFixture f; Page page; - CHECK(page.load(0) == ESP_OK); + CHECK(page.load(&f.part, 0) == ESP_OK); int32_t val1 = 0x12345678; CHECK(page.writeItem(1, ItemType::I32, "intval1", &val1, sizeof(val1)) == ESP_OK); int32_t val2 = 0x23456789; @@ -94,32 +106,32 @@ TEST_CASE("can distinguish namespaces", "[nvs]") } -TEST_CASE("reading with different type causes type mismatch error", "[nvs]") +TEST_CASE("Page reading with different type causes type mismatch error", "[nvs]") { - SpiFlashEmulator emu(1); + PartitionEmulationFixture f; Page page; - CHECK(page.load(0) == ESP_OK); + CHECK(page.load(&f.part, 0) == ESP_OK); int32_t val = 0x12345678; CHECK(page.writeItem(1, ItemType::I32, "intval1", &val, sizeof(val)) == ESP_OK); CHECK(page.readItem(1, ItemType::U32, "intval1", &val, sizeof(val)) == ESP_ERR_NVS_TYPE_MISMATCH); } -TEST_CASE("when page is erased, it's state becomes UNITIALIZED", "[nvs]") +TEST_CASE("Page when erased, it's state becomes UNITIALIZED", "[nvs]") { - SpiFlashEmulator emu(1); + PartitionEmulationFixture f; Page page; - CHECK(page.load(0) == ESP_OK); + CHECK(page.load(&f.part, 0) == ESP_OK); int32_t val = 0x12345678; CHECK(page.writeItem(1, ItemType::I32, "intval1", &val, sizeof(val)) == ESP_OK); CHECK(page.erase() == ESP_OK); CHECK(page.state() == Page::PageState::UNINITIALIZED); } -TEST_CASE("when writing and erasing, used/erased counts are updated correctly", "[nvs]") +TEST_CASE("Page when writing and erasing, used/erased counts are updated correctly", "[nvs]") { - SpiFlashEmulator emu(1); + PartitionEmulationFixture f; Page page; - CHECK(page.load(0) == ESP_OK); + CHECK(page.load(&f.part, 0) == ESP_OK); CHECK(page.getUsedEntryCount() == 0); CHECK(page.getErasedEntryCount() == 0); uint32_t foo1 = 0; @@ -146,11 +158,11 @@ TEST_CASE("when writing and erasing, used/erased counts are updated correctly", CHECK(page.getErasedEntryCount() == Page::ENTRY_COUNT - 1); } -TEST_CASE("when page is full, adding an element fails", "[nvs]") +TEST_CASE("Page when page is full, adding an element fails", "[nvs]") { - SpiFlashEmulator emu(1); + PartitionEmulationFixture f; Page page; - CHECK(page.load(0) == ESP_OK); + CHECK(page.load(&f.part, 0) == ESP_OK); for (size_t i = 0; i < Page::ENTRY_COUNT; ++i) { char name[16]; snprintf(name, sizeof(name), "i%ld", (long int)i); @@ -159,30 +171,30 @@ TEST_CASE("when page is full, adding an element fails", "[nvs]") CHECK(page.writeItem(1, "foo", 64UL) == ESP_ERR_NVS_PAGE_FULL); } -TEST_CASE("page maintains its seq number") +TEST_CASE("Page maintains its seq number") { - SpiFlashEmulator emu(1); + PartitionEmulationFixture f; { Page page; - CHECK(page.load(0) == ESP_OK); + CHECK(page.load(&f.part, 0) == ESP_OK); CHECK(page.setSeqNumber(123) == ESP_OK); int32_t val = 42; CHECK(page.writeItem(1, ItemType::I32, "dummy", &val, sizeof(val)) == ESP_OK); } { Page page; - CHECK(page.load(0) == ESP_OK); + CHECK(page.load(&f.part, 0) == ESP_OK); uint32_t seqno; CHECK(page.getSeqNumber(seqno) == ESP_OK); CHECK(seqno == 123); } } -TEST_CASE("can write and read variable length data", "[nvs]") +TEST_CASE("Page can write and read variable length data", "[nvs]") { - SpiFlashEmulator emu(1); + PartitionEmulationFixture f; Page page; - CHECK(page.load(0) == ESP_OK); + CHECK(page.load(&f.part, 0) == ESP_OK); const char str[] = "foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234"; size_t len = strlen(str); CHECK(page.writeItem(1, "stuff1", 42) == ESP_OK); @@ -212,11 +224,11 @@ TEST_CASE("can write and read variable length data", "[nvs]") CHECK(memcmp(buf, str, strlen(str)) == 0); } -TEST_CASE("different key names are distinguished even if the pointer is the same", "[nvs]") +TEST_CASE("Page different key names are distinguished even if the pointer is the same", "[nvs]") { - SpiFlashEmulator emu(1); + PartitionEmulationFixture f; Page page; - TEST_ESP_OK(page.load(0)); + TEST_ESP_OK(page.load(&f.part, 0)); TEST_ESP_OK(page.writeItem(1, "i1", 1)); TEST_ESP_OK(page.writeItem(1, "i2", 2)); int32_t value; @@ -233,9 +245,9 @@ TEST_CASE("different key names are distinguished even if the pointer is the same TEST_CASE("Page validates key size", "[nvs]") { - SpiFlashEmulator emu(4); + PartitionEmulationFixture f(0, 4); Page page; - TEST_ESP_OK(page.load(0)); + TEST_ESP_OK(page.load(&f.part, 0)); // 16-character key fails TEST_ESP_ERR(page.writeItem(1, "0123456789123456", 1), ESP_ERR_NVS_KEY_TOO_LONG); // 15-character key is okay @@ -244,56 +256,98 @@ TEST_CASE("Page validates key size", "[nvs]") TEST_CASE("Page validates blob size", "[nvs]") { - SpiFlashEmulator emu(4); + PartitionEmulationFixture f(0, 4); Page page; - TEST_ESP_OK(page.load(0)); + TEST_ESP_OK(page.load(&f.part, 0)); - char buf[2048] = { 0 }; + char buf[4096] = { 0 }; // There are two potential errors here: // - not enough space in the page (because one value has been written already) // - value is too long // Check that the second one is actually returned. TEST_ESP_ERR(page.writeItem(1, ItemType::BLOB, "2", buf, Page::ENTRY_COUNT * Page::ENTRY_SIZE), ESP_ERR_NVS_VALUE_TOO_LONG); // Should fail as well - TEST_ESP_ERR(page.writeItem(1, ItemType::BLOB, "2", buf, Page::BLOB_MAX_SIZE + 1), ESP_ERR_NVS_VALUE_TOO_LONG); - TEST_ESP_OK(page.writeItem(1, ItemType::BLOB, "2", buf, Page::BLOB_MAX_SIZE)); + TEST_ESP_ERR(page.writeItem(1, ItemType::BLOB, "2", buf, Page::CHUNK_MAX_SIZE + 1), ESP_ERR_NVS_VALUE_TOO_LONG); + TEST_ESP_OK(page.writeItem(1, ItemType::BLOB, "2", buf, Page::CHUNK_MAX_SIZE)); } TEST_CASE("Page handles invalid CRC of variable length items", "[nvs][cur]") { - SpiFlashEmulator emu(4); + PartitionEmulationFixture f(0, 4); { Page page; - TEST_ESP_OK(page.load(0)); + TEST_ESP_OK(page.load(&f.part, 0)); char buf[128] = {0}; TEST_ESP_OK(page.writeItem(1, ItemType::BLOB, "1", buf, sizeof(buf))); } // corrupt header of the item (64 is the offset of the first item in page) uint32_t overwrite_buf = 0; - emu.write(64, &overwrite_buf, 4); + f.emu.write(64, &overwrite_buf, 4); // load page again { Page page; - TEST_ESP_OK(page.load(0)); + TEST_ESP_OK(page.load(&f.part, 0)); + } +} + +class HashListTestHelper : public HashList +{ + public: + size_t getBlockCount() + { + return mBlockList.size(); + } +}; + +TEST_CASE("HashList is cleaned up as soon as items are erased", "[nvs]") +{ + HashListTestHelper hashlist; + // Add items + const size_t count = 128; + for (size_t i = 0; i < count; ++i) { + char key[16]; + snprintf(key, sizeof(key), "i%ld", (long int)i); + Item item(1, ItemType::U32, 1, key); + hashlist.insert(item, i); + } + INFO("Added " << count << " items, " << hashlist.getBlockCount() << " blocks"); + // Remove them in reverse order + for (size_t i = count; i > 0; --i) { + // Make sure that the element existed before it's erased + CHECK(hashlist.erase(i - 1) == true); + } + CHECK(hashlist.getBlockCount() == 0); + // Add again + for (size_t i = 0; i < count; ++i) { + char key[16]; + snprintf(key, sizeof(key), "i%ld", (long int)i); + Item item(1, ItemType::U32, 1, key); + hashlist.insert(item, i); + } + INFO("Added " << count << " items, " << hashlist.getBlockCount() << " blocks"); + // Remove them in the same order + for (size_t i = 0; i < count; ++i) { + CHECK(hashlist.erase(i) == true); } + CHECK(hashlist.getBlockCount() == 0); } TEST_CASE("can init PageManager in empty flash", "[nvs]") { - SpiFlashEmulator emu(4); + PartitionEmulationFixture f(0, 4); PageManager pm; - CHECK(pm.load(0, 4) == ESP_OK); + CHECK(pm.load(&f.part, 0, 4) == ESP_OK); } TEST_CASE("PageManager adds page in the correct order", "[nvs]") { const size_t pageCount = 8; - SpiFlashEmulator emu(pageCount); + PartitionEmulationFixture f(0, pageCount); uint32_t pageNo[pageCount] = { -1U, 50, 11, -1U, 23, 22, 24, 49}; for (uint32_t i = 0; i < pageCount; ++i) { Page p; - p.load(i); + p.load(&f.part, i); if (pageNo[i] != -1U) { p.setSeqNumber(pageNo[i]); p.writeItem(1, "foo", 10U); @@ -301,7 +355,7 @@ TEST_CASE("PageManager adds page in the correct order", "[nvs]") } PageManager pageManager; - CHECK(pageManager.load(0, pageCount) == ESP_OK); + CHECK(pageManager.load(&f.part, 0, pageCount) == ESP_OK); uint32_t lastSeqNo = 0; for (auto it = std::begin(pageManager); it != std::end(pageManager); ++it) { @@ -313,76 +367,77 @@ TEST_CASE("PageManager adds page in the correct order", "[nvs]") TEST_CASE("can init storage in empty flash", "[nvs]") { - SpiFlashEmulator emu(8); - Storage storage; - emu.setBounds(4, 8); + PartitionEmulationFixture f(0, 8); + Storage storage(&f.part); + f.emu.setBounds(4, 8); + cout << "before check" << endl; CHECK(storage.init(4, 4) == ESP_OK); - s_perf << "Time to init empty storage (4 sectors): " << emu.getTotalTime() << " us" << std::endl; + s_perf << "Time to init empty storage (4 sectors): " << f.emu.getTotalTime() << " us" << std::endl; } TEST_CASE("storage doesn't add duplicates within one page", "[nvs]") { - SpiFlashEmulator emu(8); - Storage storage; - emu.setBounds(4, 8); + PartitionEmulationFixture f(0, 8); + Storage storage(&f.part); + f.emu.setBounds(4, 8); CHECK(storage.init(4, 4) == ESP_OK); int bar = 0; - CHECK(storage.writeItem(1, "bar", bar) == ESP_OK); - CHECK(storage.writeItem(1, "bar", bar) == ESP_OK); + CHECK(storage.writeItem(1, "bar", ++bar) == ESP_OK); + CHECK(storage.writeItem(1, "bar", ++bar) == ESP_OK); Page page; - page.load(4); + page.load(&f.part, 4); CHECK(page.getUsedEntryCount() == 1); CHECK(page.getErasedEntryCount() == 1); } TEST_CASE("can write one item a thousand times", "[nvs]") { - SpiFlashEmulator emu(8); - Storage storage; - emu.setBounds(4, 8); + PartitionEmulationFixture f(0, 8); + Storage storage(&f.part); + f.emu.setBounds(4, 8); CHECK(storage.init(4, 4) == ESP_OK); for (size_t i = 0; i < Page::ENTRY_COUNT * 4 * 2; ++i) { REQUIRE(storage.writeItem(1, "i", static_cast(i)) == ESP_OK); } - s_perf << "Time to write one item a thousand times: " << emu.getTotalTime() << " us (" << emu.getEraseOps() << " " << emu.getWriteOps() << " " << emu.getReadOps() << " " << emu.getWriteBytes() << " " << emu.getReadBytes() << ")" << std::endl; + s_perf << "Time to write one item a thousand times: " << f.emu.getTotalTime() << " us (" << f.emu.getEraseOps() << " " << f.emu.getWriteOps() << " " << f.emu.getReadOps() << " " << f.emu.getWriteBytes() << " " << f.emu.getReadBytes() << ")" << std::endl; } TEST_CASE("storage doesn't add duplicates within multiple pages", "[nvs]") { - SpiFlashEmulator emu(8); - Storage storage; - emu.setBounds(4, 8); + PartitionEmulationFixture f(0, 8); + Storage storage(&f.part); + f.emu.setBounds(4, 8); CHECK(storage.init(4, 4) == ESP_OK); int bar = 0; - CHECK(storage.writeItem(1, "bar", bar) == ESP_OK); + CHECK(storage.writeItem(1, "bar", ++bar) == ESP_OK); for (size_t i = 0; i < Page::ENTRY_COUNT; ++i) { - CHECK(storage.writeItem(1, "foo", static_cast(bar)) == ESP_OK); + CHECK(storage.writeItem(1, "foo", static_cast(++bar)) == ESP_OK); } - CHECK(storage.writeItem(1, "bar", bar) == ESP_OK); + CHECK(storage.writeItem(1, "bar", ++bar) == ESP_OK); Page page; - page.load(4); + page.load(&f.part, 4); CHECK(page.findItem(1, itemTypeOf(), "bar") == ESP_ERR_NVS_NOT_FOUND); - page.load(5); + page.load(&f.part, 5); CHECK(page.findItem(1, itemTypeOf(), "bar") == ESP_OK); } TEST_CASE("storage can find items on second page if first is not fully written and has cached search data", "[nvs]") { - SpiFlashEmulator emu(3); - Storage storage; + PartitionEmulationFixture f(0, 3); + Storage storage(&f.part); CHECK(storage.init(0, 3) == ESP_OK); int bar = 0; - uint8_t bigdata[Page::BLOB_MAX_SIZE] = {0}; + uint8_t bigdata[(Page::CHUNK_MAX_SIZE - Page::ENTRY_SIZE)/2] = {0}; // write one big chunk of data ESP_ERROR_CHECK(storage.writeItem(0, ItemType::BLOB, "1", bigdata, sizeof(bigdata))); // write another big chunk of data ESP_ERROR_CHECK(storage.writeItem(0, ItemType::BLOB, "2", bigdata, sizeof(bigdata))); - + // write third one; it will not fit into the first page ESP_ERROR_CHECK(storage.writeItem(0, ItemType::BLOB, "3", bigdata, sizeof(bigdata))); - + size_t size; ESP_ERROR_CHECK(storage.getItemDataSize(0, ItemType::BLOB, "1", size)); CHECK(size == sizeof(bigdata)); @@ -393,9 +448,9 @@ TEST_CASE("storage can find items on second page if first is not fully written a TEST_CASE("can write and read variable length data lots of times", "[nvs]") { - SpiFlashEmulator emu(8); - Storage storage; - emu.setBounds(4, 8); + PartitionEmulationFixture f(0, 8); + Storage storage(&f.part); + f.emu.setBounds(4, 8); CHECK(storage.init(4, 4) == ESP_OK); const char str[] = "foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234"; char buf[sizeof(str) + 16]; @@ -413,16 +468,16 @@ TEST_CASE("can write and read variable length data lots of times", "[nvs]") CHECK(storage.readItem(1, ItemType::SZ, "foobaar", buf, sizeof(buf)) == ESP_OK); CHECK(memcmp(buf, str, strlen(str) + 1) == 0); } - s_perf << "Time to write one string and one integer a thousand times: " << emu.getTotalTime() << " us (" << emu.getEraseOps() << " " << emu.getWriteOps() << " " << emu.getReadOps() << " " << emu.getWriteBytes() << " " << emu.getReadBytes() << ")" << std::endl; + s_perf << "Time to write one string and one integer a thousand times: " << f.emu.getTotalTime() << " us (" << f.emu.getEraseOps() << " " << f.emu.getWriteOps() << " " << f.emu.getReadOps() << " " << f.emu.getWriteBytes() << " " << f.emu.getReadBytes() << ")" << std::endl; } TEST_CASE("can get length of variable length data", "[nvs]") { - SpiFlashEmulator emu(8); - emu.randomize(200); - Storage storage; - emu.setBounds(4, 8); + PartitionEmulationFixture f(0, 8); + f.emu.randomize(200); + Storage storage(&f.part); + f.emu.setBounds(4, 8); CHECK(storage.init(4, 4) == ESP_OK); const char str[] = "foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234foobar1234"; size_t len = strlen(str); @@ -439,24 +494,24 @@ TEST_CASE("can get length of variable length data", "[nvs]") TEST_CASE("can create namespaces", "[nvs]") { - SpiFlashEmulator emu(8); - Storage storage; - emu.setBounds(4, 8); + PartitionEmulationFixture f(0, 8); + Storage storage(&f.part); + f.emu.setBounds(4, 8); CHECK(storage.init(4, 4) == ESP_OK); uint8_t nsi; CHECK(storage.createOrOpenNamespace("wifi", false, nsi) == ESP_ERR_NVS_NOT_FOUND); CHECK(storage.createOrOpenNamespace("wifi", true, nsi) == ESP_OK); Page page; - page.load(4); + page.load(&f.part, 4); CHECK(page.findItem(Page::NS_INDEX, ItemType::U8, "wifi") == ESP_OK); } TEST_CASE("storage may become full", "[nvs]") { - SpiFlashEmulator emu(8); - Storage storage; - emu.setBounds(4, 8); + PartitionEmulationFixture f(0, 8); + Storage storage(&f.part); + f.emu.setBounds(4, 8); CHECK(storage.init(4, 4) == ESP_OK); for (size_t i = 0; i < Page::ENTRY_COUNT * 3; ++i) { char name[Item::MAX_KEY_LENGTH + 1]; @@ -468,19 +523,48 @@ TEST_CASE("storage may become full", "[nvs]") TEST_CASE("can modify an item on a page which will be erased", "[nvs]") { - SpiFlashEmulator emu(2); - Storage storage; + PartitionEmulationFixture f(0, 8); + Storage storage(&f.part); CHECK(storage.init(0, 2) == ESP_OK); for (size_t i = 0; i < Page::ENTRY_COUNT * 3 + 1; ++i) { REQUIRE(storage.writeItem(1, "foo", 42U) == ESP_OK); } } +TEST_CASE("erase operations are distributed among sectors", "[nvs]") +{ + const size_t sectors = 6; + PartitionEmulationFixture f(0, sectors); + Storage storage(&f.part); + CHECK(storage.init(0, sectors) == ESP_OK); + + /* Fill some part of storage with static values */ + const size_t static_sectors = 2; + for (size_t i = 0; i < static_sectors * Page::ENTRY_COUNT; ++i) { + char name[Item::MAX_KEY_LENGTH]; + snprintf(name, sizeof(name), "static%d", (int) i); + REQUIRE(storage.writeItem(1, name, i) == ESP_OK); + } + + /* Now perform many write operations */ + const size_t write_ops = 2000; + for (size_t i = 0; i < write_ops; ++i) { + REQUIRE(storage.writeItem(1, "value", i) == ESP_OK); + } + + /* Check that erase counts are distributed between the remaining sectors */ + const size_t max_erase_cnt = write_ops / Page::ENTRY_COUNT / (sectors - static_sectors) + 1; + for (size_t i = 0; i < sectors; ++i) { + auto erase_cnt = f.emu.getSectorEraseCount(i); + INFO("Sector " << i << " erased " << erase_cnt); + CHECK(erase_cnt <= max_erase_cnt); + } +} TEST_CASE("can erase items", "[nvs]") { - SpiFlashEmulator emu(3); - Storage storage; + PartitionEmulationFixture f(0, 8); + Storage storage(&f.part); CHECK(storage.init(0, 3) == ESP_OK); for (size_t i = 0; i < Page::ENTRY_COUNT * 2 - 3; ++i) { char name[Item::MAX_KEY_LENGTH + 1]; @@ -498,22 +582,82 @@ TEST_CASE("can erase items", "[nvs]") CHECK(storage.readItem(3, "key00222", val) == ESP_ERR_NVS_NOT_FOUND); } +TEST_CASE("namespace name is deep copy", "[nvs]") +{ + char ns_name[16]; + strcpy(ns_name, "const_name"); + + nvs_handle_t handle_1; + nvs_handle_t handle_2; + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + PartitionEmulationFixture f(NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN); + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + + TEST_ESP_OK(nvs_open("const_name", NVS_READWRITE, &handle_1)); + strcpy(ns_name, "just_kidding"); + + CHECK(nvs_open("just_kidding", NVS_READONLY, &handle_2) == ESP_ERR_NVS_NOT_FOUND); + + nvs_close(handle_1); + nvs_close(handle_2); + + nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME); +} + +TEST_CASE("readonly handle fails on writing", "[nvs]") +{ + PartitionEmulationFixture f(0, 10); + const char* str = "value 0123456789abcdef0123456789abcdef"; + const uint8_t blob[8] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}; + + nvs_handle_t handle_1; + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + + // first, creating namespace... + TEST_ESP_OK(nvs_open("ro_ns", NVS_READWRITE, &handle_1)); + nvs_close(handle_1); + + TEST_ESP_OK(nvs_open("ro_ns", NVS_READONLY, &handle_1)); + TEST_ESP_ERR(nvs_set_i32(handle_1, "key", 47), ESP_ERR_NVS_READ_ONLY); + TEST_ESP_ERR(nvs_set_str(handle_1, "key", str), ESP_ERR_NVS_READ_ONLY); + TEST_ESP_ERR(nvs_set_blob(handle_1, "key", blob, 8), ESP_ERR_NVS_READ_ONLY); + + nvs_close(handle_1); + + // without deinit it affects "nvs api tests" + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); +} + TEST_CASE("nvs api tests", "[nvs]") { - SpiFlashEmulator emu(10); - emu.randomize(100); - - nvs_handle handle_1; + PartitionEmulationFixture f(0, 10); + f.emu.randomize(100); + + nvs_handle_t handle_1; const uint32_t NVS_FLASH_SECTOR = 6; const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; - emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); TEST_ESP_ERR(nvs_open("namespace1", NVS_READWRITE, &handle_1), ESP_ERR_NVS_NOT_INITIALIZED); for (uint16_t i = NVS_FLASH_SECTOR; i init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); TEST_ESP_ERR(nvs_open("namespace1", NVS_READONLY, &handle_1), ESP_ERR_NVS_NOT_FOUND); @@ -524,7 +668,7 @@ TEST_CASE("nvs api tests", "[nvs]") TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x12345678)); TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x23456789)); - nvs_handle handle_2; + nvs_handle_t handle_2; TEST_ESP_OK(nvs_open("namespace2", NVS_READWRITE, &handle_2)); TEST_ESP_OK(nvs_set_i32(handle_2, "foo", 0x3456789a)); const char* str = "value 0123456789abcdef0123456789abcdef"; @@ -544,11 +688,11 @@ TEST_CASE("nvs api tests", "[nvs]") size_t buf_len_needed; TEST_ESP_OK(nvs_get_str(handle_2, "key", NULL, &buf_len_needed)); CHECK(buf_len_needed == buf_len); - + size_t buf_len_short = buf_len - 1; TEST_ESP_ERR(ESP_ERR_NVS_INVALID_LENGTH, nvs_get_str(handle_2, "key", buf, &buf_len_short)); CHECK(buf_len_short == buf_len); - + size_t buf_len_long = buf_len + 1; TEST_ESP_OK(nvs_get_str(handle_2, "key", buf, &buf_len_long)); CHECK(buf_len_long == buf_len); @@ -556,51 +700,294 @@ TEST_CASE("nvs api tests", "[nvs]") TEST_ESP_OK(nvs_get_str(handle_2, "key", buf, &buf_len)); CHECK(0 == strcmp(buf, str)); + nvs_close(handle_1); + nvs_close(handle_2); + + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); +} + +TEST_CASE("deinit partition doesn't affect other partition's open handles", "[nvs]") +{ + const char *OTHER_PARTITION_NAME = "other_part"; + PartitionEmulationFixture f(0, 10); + PartitionEmulationFixture f_other(0, 10, OTHER_PARTITION_NAME); + const char* str = "value 0123456789abcdef0123456789abcdef"; + const uint8_t blob[8] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}; + + nvs_handle_t handle_1; + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + f_other.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f_other.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + + TEST_ESP_OK(nvs_open_from_partition(OTHER_PARTITION_NAME, "ns", NVS_READWRITE, &handle_1)); + + // Deinitializing must not interfere with the open handle from the other partition. + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); + + TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x3456789a)); + nvs_close(handle_1); + + TEST_ESP_OK(nvs_flash_deinit_partition(OTHER_PARTITION_NAME)); +} + +TEST_CASE("nvs iterators tests", "[nvs]") +{ + PartitionEmulationFixture f(0, 5); + + const uint32_t NVS_FLASH_SECTOR = 0; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 5; + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + for (uint16_t i = NVS_FLASH_SECTOR; i < NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN; ++i) { + f.emu.erase(i); + } + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + + nvs_iterator_t it; + nvs_entry_info_t info; + nvs_handle handle_1; + nvs_handle handle_2; + const uint32_t blob = 0x11223344; + const char *name_1 = "namespace1"; + const char *name_2 = "namespace2"; + TEST_ESP_OK(nvs_open(name_1, NVS_READWRITE, &handle_1)); + TEST_ESP_OK(nvs_open(name_2, NVS_READWRITE, &handle_2)); + + TEST_ESP_OK(nvs_set_i8(handle_1, "value1", -11)); + TEST_ESP_OK(nvs_set_u8(handle_1, "value2", 11)); + TEST_ESP_OK(nvs_set_i16(handle_1, "value3", 1234)); + TEST_ESP_OK(nvs_set_u16(handle_1, "value4", -1234)); + TEST_ESP_OK(nvs_set_i32(handle_1, "value5", -222)); + TEST_ESP_OK(nvs_set_i32(handle_1, "value6", -222)); + TEST_ESP_OK(nvs_set_i32(handle_1, "value7", -222)); + TEST_ESP_OK(nvs_set_u32(handle_1, "value8", 222)); + TEST_ESP_OK(nvs_set_u32(handle_1, "value9", 222)); + TEST_ESP_OK(nvs_set_str(handle_1, "value10", "foo")); + TEST_ESP_OK(nvs_set_blob(handle_1, "value11", &blob, sizeof(blob))); + TEST_ESP_OK(nvs_set_i32(handle_2, "value1", -111)); + TEST_ESP_OK(nvs_set_i32(handle_2, "value2", -111)); + TEST_ESP_OK(nvs_set_i64(handle_2, "value3", -555)); + TEST_ESP_OK(nvs_set_u64(handle_2, "value4", 555)); + + auto entry_count = [](const char *part, const char *name, nvs_type_t type)-> int { + int count; + nvs_iterator_t it = nvs_entry_find(part, name, type); + for (count = 0; it != nullptr; count++) { + it = nvs_entry_next(it); + } + return count; + }; + + SECTION("Number of entries found for specified namespace and type is correct") + { + CHECK(nvs_entry_find("", NULL, NVS_TYPE_ANY) == NULL); + CHECK(entry_count(NVS_DEFAULT_PART_NAME, NULL, NVS_TYPE_ANY) == 15); + CHECK(entry_count(NVS_DEFAULT_PART_NAME, name_1, NVS_TYPE_ANY) == 11); + CHECK(entry_count(NVS_DEFAULT_PART_NAME, name_1, NVS_TYPE_I32) == 3); + CHECK(entry_count(NVS_DEFAULT_PART_NAME, NULL, NVS_TYPE_I32) == 5); + CHECK(entry_count(NVS_DEFAULT_PART_NAME, NULL, NVS_TYPE_U64) == 1); + } + + SECTION("New entry is not created when existing key-value pair is set") + { + CHECK(entry_count(NVS_DEFAULT_PART_NAME, name_2, NVS_TYPE_ANY) == 4); + TEST_ESP_OK(nvs_set_i32(handle_2, "value1", -222)); + CHECK(entry_count(NVS_DEFAULT_PART_NAME, name_2, NVS_TYPE_ANY) == 4); + } + + SECTION("Number of entries found decrease when entry is erased") + { + CHECK(entry_count(NVS_DEFAULT_PART_NAME, NULL, NVS_TYPE_U64) == 1); + TEST_ESP_OK(nvs_erase_key(handle_2, "value4")); + CHECK(entry_count(NVS_DEFAULT_PART_NAME, "", NVS_TYPE_U64) == 0); + } + + SECTION("All fields of nvs_entry_info_t structure are correct") + { + it = nvs_entry_find(NVS_DEFAULT_PART_NAME, name_1, NVS_TYPE_I32); + CHECK(it != nullptr); + string key = "value5"; + do { + nvs_entry_info(it, &info); + + CHECK(string(name_1) == info.namespace_name); + CHECK(key == info.key); + CHECK(info.type == NVS_TYPE_I32); + + it = nvs_entry_next(it); + key[5]++; + } while (it != NULL); + nvs_release_iterator(it); + } + + SECTION("Entry info is not affected by subsequent erase") + { + nvs_entry_info_t info_after_erase; + + it = nvs_entry_find(NVS_DEFAULT_PART_NAME, name_1, NVS_TYPE_ANY); + nvs_entry_info(it, &info); + TEST_ESP_OK(nvs_erase_key(handle_1, "value1")); + nvs_entry_info(it, &info_after_erase); + CHECK(memcmp(&info, &info_after_erase, sizeof(info)) == 0); + nvs_release_iterator(it); + } + + SECTION("Entry info is not affected by subsequent set") + { + nvs_entry_info_t info_after_set; + + it = nvs_entry_find(NVS_DEFAULT_PART_NAME, name_1, NVS_TYPE_ANY); + nvs_entry_info(it, &info); + TEST_ESP_OK(nvs_set_u8(handle_1, info.key, 44)); + nvs_entry_info(it, &info_after_set); + CHECK(memcmp(&info, &info_after_set, sizeof(info)) == 0); + nvs_release_iterator(it); + } + + + SECTION("Iterating over multiple pages works correctly") + { + nvs_handle handle_3; + const char *name_3 = "namespace3"; + const int entries_created = 250; + + TEST_ESP_OK(nvs_open(name_3, NVS_READWRITE, &handle_3)); + for (size_t i = 0; i < entries_created; i++) { + TEST_ESP_OK(nvs_set_u8(handle_3, to_string(i).c_str(), 123)); + } + + int entries_found = 0; + it = nvs_entry_find(NVS_DEFAULT_PART_NAME, name_3, NVS_TYPE_ANY); + while(it != nullptr) { + entries_found++; + it = nvs_entry_next(it); + } + CHECK(entries_created == entries_found); + + nvs_release_iterator(it); + nvs_close(handle_3); + } + + SECTION("Iterating over multi-page blob works correctly") + { + nvs_handle handle_3; + const char *name_3 = "namespace3"; + const uint8_t multipage_blob[4096 * 2] = { 0 }; + const int NUMBER_OF_ENTRIES_PER_PAGE = 125; + size_t occupied_entries; + + TEST_ESP_OK(nvs_open(name_3, NVS_READWRITE, &handle_3)); + nvs_set_blob(handle_3, "blob", multipage_blob, sizeof(multipage_blob)); + TEST_ESP_OK(nvs_get_used_entry_count(handle_3, &occupied_entries)); + CHECK(occupied_entries > NUMBER_OF_ENTRIES_PER_PAGE * 2); + + CHECK(entry_count(NVS_DEFAULT_PART_NAME, name_3, NVS_TYPE_BLOB) == 1); + + nvs_close(handle_3); + } + + nvs_close(handle_1); + nvs_close(handle_2); + + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); +} + +TEST_CASE("Iterator with not matching type iterates correctly", "[nvs]") +{ + PartitionEmulationFixture f(0, 5); + nvs_iterator_t it; + nvs_handle_t my_handle; + const char* NAMESPACE = "test_ns_4"; + + const uint32_t NVS_FLASH_SECTOR = 0; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 5; + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + for (uint16_t i = NVS_FLASH_SECTOR; i < NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN; ++i) { + f.emu.erase(i); + } + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + + // writing string to namespace (a type which spans multiple entries) + TEST_ESP_OK(nvs_open(NAMESPACE, NVS_READWRITE, &my_handle)); + TEST_ESP_OK(nvs_set_str(my_handle, "test-string", "InitString0")); + TEST_ESP_OK(nvs_commit(my_handle)); + nvs_close(my_handle); + + it = nvs_entry_find(NVS_DEFAULT_PART_NAME, NAMESPACE, NVS_TYPE_I32); + CHECK(it == NULL); + + // re-init to trigger cleaning up of broken items -> a corrupted string will be erased + nvs_flash_deinit(); + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + + it = nvs_entry_find(NVS_DEFAULT_PART_NAME, NAMESPACE, NVS_TYPE_STR); + CHECK(it != NULL); + nvs_release_iterator(it); + + // without deinit it affects "nvs api tests" + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); } TEST_CASE("wifi test", "[nvs]") { - SpiFlashEmulator emu(10); - emu.randomize(10); - - + PartitionEmulationFixture f(0, 10); + f.emu.randomize(10); + + const uint32_t NVS_FLASH_SECTOR = 5; const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; - emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); - TEST_ESP_OK(nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)); - - nvs_handle misc_handle; + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + + nvs_handle_t misc_handle; TEST_ESP_OK(nvs_open("nvs.net80211", NVS_READWRITE, &misc_handle)); char log[33]; size_t log_size = sizeof(log); TEST_ESP_ERR(nvs_get_str(misc_handle, "log", log, &log_size), ESP_ERR_NVS_NOT_FOUND); strcpy(log, "foobarbazfizzz"); TEST_ESP_OK(nvs_set_str(misc_handle, "log", log)); - - nvs_handle net80211_handle; + + nvs_handle_t net80211_handle; TEST_ESP_OK(nvs_open("nvs.net80211", NVS_READWRITE, &net80211_handle)); - + uint8_t opmode = 2; TEST_ESP_ERR(nvs_get_u8(net80211_handle, "wifi.opmode", &opmode), ESP_ERR_NVS_NOT_FOUND); - + TEST_ESP_OK(nvs_set_u8(net80211_handle, "wifi.opmode", opmode)); - + uint8_t country = 0; TEST_ESP_ERR(nvs_get_u8(net80211_handle, "wifi.country", &opmode), ESP_ERR_NVS_NOT_FOUND); TEST_ESP_OK(nvs_set_u8(net80211_handle, "wifi.country", opmode)); - + char ssid[36]; size_t size = sizeof(ssid); TEST_ESP_ERR(nvs_get_blob(net80211_handle, "sta.ssid", ssid, &size), ESP_ERR_NVS_NOT_FOUND); strcpy(ssid, "my android AP"); TEST_ESP_OK(nvs_set_blob(net80211_handle, "sta.ssid", ssid, size)); - + char mac[6]; size = sizeof(mac); TEST_ESP_ERR(nvs_get_blob(net80211_handle, "sta.mac", mac, &size), ESP_ERR_NVS_NOT_FOUND); memset(mac, 0xab, 6); TEST_ESP_OK(nvs_set_blob(net80211_handle, "sta.mac", mac, size)); - + uint8_t authmode = 1; TEST_ESP_ERR(nvs_get_u8(net80211_handle, "sta.authmode", &authmode), ESP_ERR_NVS_NOT_FOUND); TEST_ESP_OK(nvs_set_u8(net80211_handle, "sta.authmode", authmode)); @@ -616,11 +1003,11 @@ TEST_CASE("wifi test", "[nvs]") TEST_ESP_ERR(nvs_get_blob(net80211_handle, "sta.pmk", pmk, &size), ESP_ERR_NVS_NOT_FOUND); memset(pmk, 1, size); TEST_ESP_OK(nvs_set_blob(net80211_handle, "sta.pmk", pmk, size)); - + uint8_t chan = 1; TEST_ESP_ERR(nvs_get_u8(net80211_handle, "sta.chan", &chan), ESP_ERR_NVS_NOT_FOUND); TEST_ESP_OK(nvs_set_u8(net80211_handle, "sta.chan", chan)); - + uint8_t autoconn = 1; TEST_ESP_ERR(nvs_get_u8(net80211_handle, "auto.conn", &autoconn), ESP_ERR_NVS_NOT_FOUND); TEST_ESP_OK(nvs_set_u8(net80211_handle, "auto.conn", autoconn)); @@ -638,43 +1025,43 @@ TEST_CASE("wifi test", "[nvs]") uint8_t phym = 3; TEST_ESP_ERR(nvs_get_u8(net80211_handle, "sta.phym", &phym), ESP_ERR_NVS_NOT_FOUND); TEST_ESP_OK(nvs_set_u8(net80211_handle, "sta.phym", phym)); - + uint8_t phybw = 2; TEST_ESP_ERR(nvs_get_u8(net80211_handle, "sta.phybw", &phybw), ESP_ERR_NVS_NOT_FOUND); TEST_ESP_OK(nvs_set_u8(net80211_handle, "sta.phybw", phybw)); - + char apsw[2]; size = sizeof(apsw); TEST_ESP_ERR(nvs_get_blob(net80211_handle, "sta.apsw", apsw, &size), ESP_ERR_NVS_NOT_FOUND); memset(apsw, 0x2, size); TEST_ESP_OK(nvs_set_blob(net80211_handle, "sta.apsw", apsw, size)); - + char apinfo[700]; size = sizeof(apinfo); TEST_ESP_ERR(nvs_get_blob(net80211_handle, "sta.apinfo", apinfo, &size), ESP_ERR_NVS_NOT_FOUND); memset(apinfo, 0, size); TEST_ESP_OK(nvs_set_blob(net80211_handle, "sta.apinfo", apinfo, size)); - + size = sizeof(ssid); TEST_ESP_ERR(nvs_get_blob(net80211_handle, "ap.ssid", ssid, &size), ESP_ERR_NVS_NOT_FOUND); strcpy(ssid, "ESP_A2F340"); TEST_ESP_OK(nvs_set_blob(net80211_handle, "ap.ssid", ssid, size)); - + size = sizeof(mac); TEST_ESP_ERR(nvs_get_blob(net80211_handle, "ap.mac", mac, &size), ESP_ERR_NVS_NOT_FOUND); memset(mac, 0xac, 6); TEST_ESP_OK(nvs_set_blob(net80211_handle, "ap.mac", mac, size)); - + size = sizeof(pswd); TEST_ESP_ERR(nvs_get_blob(net80211_handle, "ap.passwd", pswd, &size), ESP_ERR_NVS_NOT_FOUND); strcpy(pswd, ""); TEST_ESP_OK(nvs_set_blob(net80211_handle, "ap.passwd", pswd, size)); - + size = sizeof(pmk); TEST_ESP_ERR(nvs_get_blob(net80211_handle, "ap.pmk", pmk, &size), ESP_ERR_NVS_NOT_FOUND); memset(pmk, 1, size); TEST_ESP_OK(nvs_set_blob(net80211_handle, "ap.pmk", pmk, size)); - + chan = 6; TEST_ESP_ERR(nvs_get_u8(net80211_handle, "ap.chan", &chan), ESP_ERR_NVS_NOT_FOUND); TEST_ESP_OK(nvs_set_u8(net80211_handle, "ap.chan", chan)); @@ -682,63 +1069,133 @@ TEST_CASE("wifi test", "[nvs]") authmode = 0; TEST_ESP_ERR(nvs_get_u8(net80211_handle, "ap.authmode", &authmode), ESP_ERR_NVS_NOT_FOUND); TEST_ESP_OK(nvs_set_u8(net80211_handle, "ap.authmode", authmode)); - + uint8_t hidden = 0; TEST_ESP_ERR(nvs_get_u8(net80211_handle, "ap.hidden", &hidden), ESP_ERR_NVS_NOT_FOUND); TEST_ESP_OK(nvs_set_u8(net80211_handle, "ap.hidden", hidden)); - + uint8_t max_conn = 4; TEST_ESP_ERR(nvs_get_u8(net80211_handle, "ap.max.conn", &max_conn), ESP_ERR_NVS_NOT_FOUND); TEST_ESP_OK(nvs_set_u8(net80211_handle, "ap.max.conn", max_conn)); - + uint8_t bcn_interval = 2; TEST_ESP_ERR(nvs_get_u8(net80211_handle, "bcn_interval", &bcn_interval), ESP_ERR_NVS_NOT_FOUND); TEST_ESP_OK(nvs_set_u8(net80211_handle, "bcn_interval", bcn_interval)); - - s_perf << "Time to simulate nvs init with wifi libs: " << emu.getTotalTime() << " us (" << emu.getEraseOps() << "E " << emu.getWriteOps() << "W " << emu.getReadOps() << "R " << emu.getWriteBytes() << "Wb " << emu.getReadBytes() << "Rb)" << std::endl; + s_perf << "Time to simulate nvs init with wifi libs: " << f.emu.getTotalTime() << " us (" << f.emu.getEraseOps() << "E " << f.emu.getWriteOps() << "W " << f.emu.getReadOps() << "R " << f.emu.getWriteBytes() << "Wb " << f.emu.getReadBytes() << "Rb)" << std::endl; + + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); } +TEST_CASE("writing the identical content does not write or erase", "[nvs]") +{ + PartitionEmulationFixture f(0, 20); + + const uint32_t NVS_FLASH_SECTOR = 5; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 10; + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + + nvs_handle misc_handle; + TEST_ESP_OK(nvs_open("test", NVS_READWRITE, &misc_handle)); + + // Test writing a u8 twice, then changing it + nvs_set_u8(misc_handle, "test_u8", 8); + f.emu.clearStats(); + nvs_set_u8(misc_handle, "test_u8", 8); + CHECK(f.emu.getWriteOps() == 0); + CHECK(f.emu.getEraseOps() == 0); + CHECK(f.emu.getReadOps() != 0); + f.emu.clearStats(); + nvs_set_u8(misc_handle, "test_u8", 9); + CHECK(f.emu.getWriteOps() != 0); + CHECK(f.emu.getReadOps() != 0); + + // Test writing a string twice, then changing it + static const char *test[2] = {"Hello world.", "Hello world!"}; + nvs_set_str(misc_handle, "test_str", test[0]); + f.emu.clearStats(); + nvs_set_str(misc_handle, "test_str", test[0]); + CHECK(f.emu.getWriteOps() == 0); + CHECK(f.emu.getEraseOps() == 0); + CHECK(f.emu.getReadOps() != 0); + f.emu.clearStats(); + nvs_set_str(misc_handle, "test_str", test[1]); + CHECK(f.emu.getWriteOps() != 0); + CHECK(f.emu.getReadOps() != 0); + + // Test writing a multi-page blob, then changing it + uint8_t blob[Page::CHUNK_MAX_SIZE * 3] = {0}; + memset(blob, 1, sizeof(blob)); + nvs_set_blob(misc_handle, "test_blob", blob, sizeof(blob)); + f.emu.clearStats(); + nvs_set_blob(misc_handle, "test_blob", blob, sizeof(blob)); + CHECK(f.emu.getWriteOps() == 0); + CHECK(f.emu.getEraseOps() == 0); + CHECK(f.emu.getReadOps() != 0); + blob[sizeof(blob) - 1]++; + f.emu.clearStats(); + nvs_set_blob(misc_handle, "test_blob", blob, sizeof(blob)); + CHECK(f.emu.getWriteOps() != 0); + CHECK(f.emu.getReadOps() != 0); + + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); +} TEST_CASE("can init storage from flash with random contents", "[nvs]") { - SpiFlashEmulator emu(10); - emu.randomize(42); - - nvs_handle handle; + PartitionEmulationFixture f(0, 10); + f.emu.randomize(42); + + nvs_handle_t handle; const uint32_t NVS_FLASH_SECTOR = 5; const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; - emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); - TEST_ESP_OK(nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)); - + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + TEST_ESP_OK(nvs_open("nvs.net80211", NVS_READWRITE, &handle)); - + uint8_t opmode = 2; if (nvs_get_u8(handle, "wifi.opmode", &opmode) != ESP_OK) { TEST_ESP_OK(nvs_set_u8(handle, "wifi.opmode", opmode)); } + + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); } -TEST_CASE("nvs api tests, starting with random data in flash", "[nvs][.][long]") +TEST_CASE("nvs api tests, starting with random data in flash", "[nvs][long]") { - for (size_t count = 0; count < 10000; ++count) { - SpiFlashEmulator emu(10); - emu.randomize(static_cast(count)); - + const size_t testIters = 3000; + int lastPercent = -1; + for (size_t count = 0; count < testIters; ++count) { + int percentDone = (int) (count * 100 / testIters); + if (percentDone != lastPercent) { + lastPercent = percentDone; + printf("%d%%\n", percentDone); + } + PartitionEmulationFixture f(0, 10); + f.emu.randomize(static_cast(count)); + const uint32_t NVS_FLASH_SECTOR = 6; const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; - emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); - - TEST_ESP_OK(nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)); - - nvs_handle handle_1; + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + + nvs_handle_t handle_1; TEST_ESP_ERR(nvs_open("namespace1", NVS_READONLY, &handle_1), ESP_ERR_NVS_NOT_FOUND); - + TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle_1)); TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x12345678)); for (size_t i = 0; i < 500; ++i) { - nvs_handle handle_2; + nvs_handle_t handle_2; TEST_ESP_OK(nvs_open("namespace2", NVS_READWRITE, &handle_2)); TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x23456789 % (i + 1))); TEST_ESP_OK(nvs_set_i32(handle_2, "foo", static_cast(i))); @@ -746,38 +1203,42 @@ TEST_CASE("nvs api tests, starting with random data in flash", "[nvs][.][long]") char str_buf[128]; snprintf(str_buf, sizeof(str_buf), str, i + count * 1024); TEST_ESP_OK(nvs_set_str(handle_2, "key", str_buf)); - + int32_t v1; TEST_ESP_OK(nvs_get_i32(handle_1, "foo", &v1)); CHECK(0x23456789 % (i + 1) == v1); - + int32_t v2; TEST_ESP_OK(nvs_get_i32(handle_2, "foo", &v2)); CHECK(static_cast(i) == v2); - + char buf[128]; size_t buf_len = sizeof(buf); - + TEST_ESP_OK(nvs_get_str(handle_2, "key", buf, &buf_len)); - + CHECK(0 == strcmp(buf, str_buf)); nvs_close(handle_2); } nvs_close(handle_1); } -} + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); +} extern "C" void nvs_dump(const char *partName); class RandomTest { - - static const size_t nKeys = 9; + + static const size_t nKeys = 11; int32_t v1 = 0, v2 = 0; uint64_t v3 = 0, v4 = 0; static const size_t strBufLen = 1024; + static const size_t smallBlobLen = Page::CHUNK_MAX_SIZE / 3; + static const size_t largeBlobLen = Page::CHUNK_MAX_SIZE * 3; char v5[strBufLen], v6[strBufLen], v7[strBufLen], v8[strBufLen], v9[strBufLen]; + uint8_t v10[smallBlobLen], v11[largeBlobLen]; bool written[nKeys]; - + public: RandomTest() { @@ -785,17 +1246,17 @@ class RandomTest { } template - esp_err_t doRandomThings(nvs_handle handle, TGen gen, size_t& count) { - - const char* keys[] = {"foo", "bar", "longkey_0123456", "another key", "param1", "param2", "param3", "param4", "param5"}; - const ItemType types[] = {ItemType::I32, ItemType::I32, ItemType::U64, ItemType::U64, ItemType::SZ, ItemType::SZ, ItemType::SZ, ItemType::SZ, ItemType::SZ}; - - void* values[] = {&v1, &v2, &v3, &v4, &v5, &v6, &v7, &v8, &v9}; - + esp_err_t doRandomThings(nvs_handle_t handle, TGen gen, size_t& count) { + + const char* keys[] = {"foo", "bar", "longkey_0123456", "another key", "param1", "param2", "param3", "param4", "param5", "singlepage", "multipage"}; + const ItemType types[] = {ItemType::I32, ItemType::I32, ItemType::U64, ItemType::U64, ItemType::SZ, ItemType::SZ, ItemType::SZ, ItemType::SZ, ItemType::SZ, ItemType::BLOB, ItemType::BLOB}; + + void* values[] = {&v1, &v2, &v3, &v4, &v5, &v6, &v7, &v8, &v9, &v10, &v11}; + const size_t nKeys = sizeof(keys) / sizeof(keys[0]); static_assert(nKeys == sizeof(types) / sizeof(types[0]), ""); static_assert(nKeys == sizeof(values) / sizeof(values[0]), ""); - + auto randomRead = [&](size_t index) -> esp_err_t { switch (types[index]) { case ItemType::I32: @@ -814,7 +1275,7 @@ class RandomTest { } break; } - + case ItemType::U64: { uint64_t val; @@ -831,7 +1292,7 @@ class RandomTest { } break; } - + case ItemType::SZ: { char buf[strBufLen]; @@ -849,19 +1310,47 @@ class RandomTest { } break; } - + + case ItemType::BLOB: + { + uint32_t blobBufLen = 0; + if(strncmp(keys[index],"singlepage", sizeof("singlepage")) == 0) { + blobBufLen = smallBlobLen ; + } else { + blobBufLen = largeBlobLen ; + + } + uint8_t buf[blobBufLen]; + memset(buf, 0, blobBufLen); + + size_t len = blobBufLen; + auto err = nvs_get_blob(handle, keys[index], buf, &len); + if (err == ESP_ERR_FLASH_OP_FAIL) { + return err; + } + if (!written[index]) { + REQUIRE(err == ESP_ERR_NVS_NOT_FOUND); + } + else { + REQUIRE(err == ESP_OK); + REQUIRE(memcmp(buf, reinterpret_cast(values[index]), blobBufLen) == 0); + } + break; + } + + default: assert(0); } return ESP_OK; }; - + auto randomWrite = [&](size_t index) -> esp_err_t { switch (types[index]) { case ItemType::I32: { int32_t val = static_cast(gen()); - + auto err = nvs_set_i32(handle, keys[index], val); if (err == ESP_ERR_FLASH_OP_FAIL) { return err; @@ -876,11 +1365,11 @@ class RandomTest { *reinterpret_cast(values[index]) = val; break; } - + case ItemType::U64: { uint64_t val = static_cast(gen()); - + auto err = nvs_set_u64(handle, keys[index], val); if (err == ESP_ERR_FLASH_OP_FAIL) { return err; @@ -895,19 +1384,19 @@ class RandomTest { *reinterpret_cast(values[index]) = val; break; } - + case ItemType::SZ: { char buf[strBufLen]; size_t len = strBufLen; - + size_t strLen = gen() % (strBufLen - 1); std::generate_n(buf, strLen, [&]() -> char { const char c = static_cast(gen() % 127); return (c < 32) ? 32 : c; }); buf[strLen] = 0; - + auto err = nvs_set_str(handle, keys[index], buf); if (err == ESP_ERR_FLASH_OP_FAIL) { return err; @@ -922,23 +1411,53 @@ class RandomTest { strncpy(reinterpret_cast(values[index]), buf, strBufLen); break; } - + + case ItemType::BLOB: + { + uint32_t blobBufLen = 0; + if(strncmp(keys[index],"singlepage", sizeof("singlepage")) == 0) { + blobBufLen = smallBlobLen ; + } else { + blobBufLen = largeBlobLen ; + } + uint8_t buf[blobBufLen]; + memset(buf, 0, blobBufLen); + size_t blobLen = gen() % blobBufLen; + std::generate_n(buf, blobLen, [&]() -> uint8_t { + return static_cast(gen() % 256); + }); + + auto err = nvs_set_blob(handle, keys[index], buf, blobLen); + if (err == ESP_ERR_FLASH_OP_FAIL) { + return err; + } + if (err == ESP_ERR_NVS_REMOVE_FAILED) { + written[index] = true; + memcpy(reinterpret_cast(values[index]), buf, blobBufLen); + return ESP_ERR_FLASH_OP_FAIL; + } + REQUIRE(err == ESP_OK); + written[index] = true; + memcpy(reinterpret_cast(values[index]), buf, blobBufLen); + break; + } + default: assert(0); } return ESP_OK; }; - - + + for (; count != 0; --count) { - size_t index = gen() % nKeys; + size_t index = gen() % (nKeys); switch (gen() % 3) { case 0: // read, 1/3 if (randomRead(index) == ESP_ERR_FLASH_OP_FAIL) { return ESP_ERR_FLASH_OP_FAIL; } break; - + default: // write, 2/3 if (randomWrite(index) == ESP_ERR_FLASH_OP_FAIL) { return ESP_ERR_FLASH_OP_FAIL; @@ -948,8 +1467,20 @@ class RandomTest { } return ESP_OK; } -}; + esp_err_t handleExternalWriteAtIndex(uint8_t index, const void* value, const size_t len ) { + if(index == 9) { /* This is only done for small-page blobs for now*/ + if(len > smallBlobLen) { + return ESP_FAIL; + } + memcpy(v10, value, len); + written[index] = true; + return ESP_OK; + } else { + return ESP_FAIL; + } + } +}; TEST_CASE("monkey test", "[nvs][monkey]") { @@ -957,49 +1488,54 @@ TEST_CASE("monkey test", "[nvs][monkey]") std::mt19937 gen(rd()); uint32_t seed = 3; gen.seed(seed); - - SpiFlashEmulator emu(10); - emu.randomize(seed); - emu.clearStats(); - - const uint32_t NVS_FLASH_SECTOR = 6; - const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; - emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); - - TEST_ESP_OK(nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)); - - nvs_handle handle; + + PartitionEmulationFixture f(0, 10); + f.emu.randomize(seed); + f.emu.clearStats(); + + const uint32_t NVS_FLASH_SECTOR = 2; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 8; + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + + nvs_handle_t handle; TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle)); RandomTest test; size_t count = 1000; CHECK(test.doRandomThings(handle, gen, count) == ESP_OK); - - s_perf << "Monkey test: nErase=" << emu.getEraseOps() << " nWrite=" << emu.getWriteOps() << std::endl; + + s_perf << "Monkey test: nErase=" << f.emu.getEraseOps() << " nWrite=" << f.emu.getWriteOps() << std::endl; + + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); } -TEST_CASE("test recovery from sudden poweroff", "[.][long][nvs][recovery][monkey]") +TEST_CASE("test recovery from sudden poweroff", "[long][nvs][recovery][monkey]") { std::random_device rd; std::mt19937 gen(rd()); uint32_t seed = 3; gen.seed(seed); const size_t iter_count = 2000; - - SpiFlashEmulator emu(10); - - const uint32_t NVS_FLASH_SECTOR = 6; - const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; - emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); - + + PartitionEmulationFixture f(0, 10); + + const uint32_t NVS_FLASH_SECTOR = 2; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 8; + + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + size_t totalOps = 0; int lastPercent = -1; for (uint32_t errDelay = 0; ; ++errDelay) { INFO(errDelay); - emu.randomize(seed); - emu.clearStats(); - emu.failAfter(errDelay); + f.emu.randomize(seed); + f.emu.clearStats(); + f.emu.failAfter(errDelay); RandomTest test; - + if (totalOps != 0) { int percent = errDelay * 100 / totalOps; if (percent > lastPercent) { @@ -1007,12 +1543,14 @@ TEST_CASE("test recovery from sudden poweroff", "[.][long][nvs][recovery][monkey lastPercent = percent; } } - - nvs_handle handle; + + nvs_handle_t handle; size_t count = iter_count; - if (nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) == ESP_OK) { + if (NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN) == ESP_OK) { if (nvs_open("namespace1", NVS_READWRITE, &handle) == ESP_OK) { if(test.doRandomThings(handle, gen, count) != ESP_ERR_FLASH_OP_FAIL) { nvs_close(handle); @@ -1020,9 +1558,12 @@ TEST_CASE("test recovery from sudden poweroff", "[.][long][nvs][recovery][monkey } nvs_close(handle); } + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); } - - TEST_ESP_OK(nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)); + + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle)); auto res = test.doRandomThings(handle, gen, count); if (res != ESP_OK) { @@ -1030,35 +1571,40 @@ TEST_CASE("test recovery from sudden poweroff", "[.][long][nvs][recovery][monkey CHECK(0); } nvs_close(handle); - totalOps = emu.getEraseOps() + emu.getWriteBytes() / 4; + totalOps = f.emu.getEraseOps() + f.emu.getWriteBytes() / 4; + + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); } } - TEST_CASE("test for memory leaks in open/set", "[leaks]") { - SpiFlashEmulator emu(10); + PartitionEmulationFixture f(0, 10); const uint32_t NVS_FLASH_SECTOR = 6; const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; - emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); - TEST_ESP_OK(nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)); - + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + for (int i = 0; i < 100000; ++i) { - nvs_handle light_handle = 0; + nvs_handle_t light_handle = 0; char lightbulb[1024] = {12, 13, 14, 15, 16}; TEST_ESP_OK(nvs_open("light", NVS_READWRITE, &light_handle)); TEST_ESP_OK(nvs_set_blob(light_handle, "key", lightbulb, sizeof(lightbulb))); TEST_ESP_OK(nvs_commit(light_handle)); nvs_close(light_handle); } + + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); } TEST_CASE("duplicate items are removed", "[nvs][dupes]") { - SpiFlashEmulator emu(3); + PartitionEmulationFixture f(0, 3); { // create one item nvs::Page p; - p.load(0); + p.load(&f.part, 0); p.writeItem(1, "opmode", 3); } { @@ -1066,14 +1612,14 @@ TEST_CASE("duplicate items are removed", "[nvs][dupes]") nvs::Item item(1, ItemType::U8, 1, "opmode"); item.data[0] = 2; item.crc32 = item.calculateCrc32(); - emu.write(3 * 32, reinterpret_cast(&item), sizeof(item)); - emu.write(4 * 32, reinterpret_cast(&item), sizeof(item)); + f.emu.write(3 * 32, reinterpret_cast(&item), sizeof(item)); + f.emu.write(4 * 32, reinterpret_cast(&item), sizeof(item)); uint32_t mask = 0xFFFFFFEA; - emu.write(32, &mask, 4); + f.emu.write(32, &mask, 4); } { // load page and check that second item persists - nvs::Storage s; + nvs::Storage s(&f.part); s.init(0, 3); uint8_t val; ESP_ERROR_CHECK(s.readItem(1, "opmode", val)); @@ -1081,7 +1627,7 @@ TEST_CASE("duplicate items are removed", "[nvs][dupes]") } { Page p; - p.load(0); + p.load(&f.part, 0); CHECK(p.getErasedEntryCount() == 2); CHECK(p.getUsedEntryCount() == 1); } @@ -1089,30 +1635,30 @@ TEST_CASE("duplicate items are removed", "[nvs][dupes]") TEST_CASE("recovery after failure to write data", "[nvs]") { - SpiFlashEmulator emu(3); + PartitionEmulationFixture f(0, 3); const char str[] = "value 0123456789abcdef012345678value 0123456789abcdef012345678"; // make flash write fail exactly in Page::writeEntryData - emu.failAfter(17); + f.emu.failAfter(17); { - Storage storage; + Storage storage(&f.part); TEST_ESP_OK(storage.init(0, 3)); - + TEST_ESP_ERR(storage.writeItem(1, ItemType::SZ, "key", str, strlen(str)), ESP_ERR_FLASH_OP_FAIL); - + // check that repeated operations cause an error TEST_ESP_ERR(storage.writeItem(1, ItemType::SZ, "key", str, strlen(str)), ESP_ERR_NVS_INVALID_STATE); - + uint8_t val; TEST_ESP_ERR(storage.readItem(1, ItemType::U8, "key", &val, sizeof(val)), ESP_ERR_NVS_NOT_FOUND); } { // load page and check that data was erased Page p; - p.load(0); + p.load(&f.part, 0); CHECK(p.getErasedEntryCount() == 3); CHECK(p.getUsedEntryCount() == 0); - + // try to write again TEST_ESP_OK(p.writeItem(1, ItemType::SZ, "key", str, strlen(str))); } @@ -1120,25 +1666,25 @@ TEST_CASE("recovery after failure to write data", "[nvs]") TEST_CASE("crc errors in item header are handled", "[nvs]") { - SpiFlashEmulator emu(3); - Storage storage; + PartitionEmulationFixture f(0, 3); + Storage storage(&f.part); // prepare some data TEST_ESP_OK(storage.init(0, 3)); TEST_ESP_OK(storage.writeItem(0, "ns1", static_cast(1))); TEST_ESP_OK(storage.writeItem(1, "value1", static_cast(1))); TEST_ESP_OK(storage.writeItem(1, "value2", static_cast(2))); - + // corrupt item header uint32_t val = 0; - emu.write(32 * 3, &val, 4); - + f.emu.write(32 * 3, &val, 4); + // check that storage can recover TEST_ESP_OK(storage.init(0, 3)); TEST_ESP_OK(storage.readItem(1, "value2", val)); CHECK(val == 2); // check that the corrupted item is no longer present TEST_ESP_ERR(ESP_ERR_NVS_NOT_FOUND, storage.readItem(1, "value1", val)); - + // add more items to make the page full for (size_t i = 0; i < Page::ENTRY_COUNT; ++i) { char item_name[Item::MAX_KEY_LENGTH + 1]; @@ -1148,8 +1694,8 @@ TEST_CASE("crc errors in item header are handled", "[nvs]") // corrupt another item on the full page val = 0; - emu.write(32 * 4, &val, 4); - + f.emu.write(32 * 4, &val, 4); + // check that storage can recover TEST_ESP_OK(storage.init(0, 3)); // check that the corrupted item is no longer present @@ -1158,13 +1704,13 @@ TEST_CASE("crc errors in item header are handled", "[nvs]") TEST_CASE("crc error in variable length item is handled", "[nvs]") { - SpiFlashEmulator emu(3); + PartitionEmulationFixture f(0, 3); const uint64_t before_val = 0xbef04e; const uint64_t after_val = 0xaf7e4; // write some data { Page p; - p.load(0); + p.load(&f.part, 0); TEST_ESP_OK(p.writeItem(0, "before", before_val)); const char* str = "foobar"; TEST_ESP_OK(p.writeItem(0, ItemType::SZ, "key", str, strlen(str))); @@ -1172,13 +1718,13 @@ TEST_CASE("crc error in variable length item is handled", "[nvs]") } // corrupt some data uint32_t w; - CHECK(emu.read(&w, 32 * 3 + 8, sizeof(w))); + CHECK(f.emu.read(&w, 32 * 3 + 8, sizeof(w))); w &= 0xf000000f; - CHECK(emu.write(32 * 3 + 8, &w, sizeof(w))); + CHECK(f.emu.write(32 * 3 + 8, &w, sizeof(w))); // load and check { Page p; - p.load(0); + p.load(&f.part, 0); CHECK(p.getUsedEntryCount() == 2); CHECK(p.getErasedEntryCount() == 2); @@ -1194,16 +1740,16 @@ TEST_CASE("crc error in variable length item is handled", "[nvs]") TEST_CASE("read/write failure (TW8406)", "[nvs]") { - SpiFlashEmulator emu(3); - nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, 0, 3); + PartitionEmulationFixture f(0, 3); + NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 3); for (int attempts = 0; attempts < 3; ++attempts) { int i = 0; - nvs_handle light_handle = 0; + nvs_handle_t light_handle = 0; char key[15] = {0}; char data[76] = {12, 13, 14, 15, 16}; uint8_t number = 20; size_t data_len = sizeof(data); - + ESP_ERROR_CHECK(nvs_open("LIGHT", NVS_READWRITE, &light_handle)); ESP_ERROR_CHECK(nvs_set_u8(light_handle, "RecordNum", number)); for (i = 0; i < number; ++i) { @@ -1211,7 +1757,7 @@ TEST_CASE("read/write failure (TW8406)", "[nvs]") ESP_ERROR_CHECK(nvs_set_blob(light_handle, key, data, sizeof(data))); } nvs_commit(light_handle); - + uint8_t get_number = 0; ESP_ERROR_CHECK(nvs_get_u8(light_handle, "RecordNum", &get_number)); REQUIRE(number == get_number); @@ -1222,38 +1768,44 @@ TEST_CASE("read/write failure (TW8406)", "[nvs]") } nvs_close(light_handle); } + + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); } TEST_CASE("nvs_flash_init checks for an empty page", "[nvs]") { - const size_t blob_size = Page::BLOB_MAX_SIZE; + const size_t blob_size = Page::CHUNK_MAX_SIZE; uint8_t blob[blob_size] = {0}; - SpiFlashEmulator emu(5); - TEST_ESP_OK( nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, 0, 5) ); - nvs_handle handle; + PartitionEmulationFixture f(0, 8); + TEST_ESP_OK( NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 5) ); + nvs_handle_t handle; TEST_ESP_OK( nvs_open("test", NVS_READWRITE, &handle) ); // Fill first page TEST_ESP_OK( nvs_set_blob(handle, "1a", blob, blob_size) ); - TEST_ESP_OK( nvs_set_blob(handle, "1b", blob, blob_size) ); // Fill second page TEST_ESP_OK( nvs_set_blob(handle, "2a", blob, blob_size) ); - TEST_ESP_OK( nvs_set_blob(handle, "2b", blob, blob_size) ); // Fill third page TEST_ESP_OK( nvs_set_blob(handle, "3a", blob, blob_size) ); - TEST_ESP_OK( nvs_set_blob(handle, "3b", blob, blob_size) ); TEST_ESP_OK( nvs_commit(handle) ); nvs_close(handle); + TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); // first two pages are now full, third one is writable, last two are empty // init should fail - TEST_ESP_ERR( nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, 0, 3), ESP_ERR_NVS_NO_FREE_PAGES ); + TEST_ESP_ERR( NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 3), + ESP_ERR_NVS_NO_FREE_PAGES ); + + // in case this test fails, to not affect other tests + nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME); } TEST_CASE("multiple partitions access check", "[nvs]") { SpiFlashEmulator emu(10); - TEST_ESP_OK( nvs_flash_init_custom("nvs1", 0, 5) ); - TEST_ESP_OK( nvs_flash_init_custom("nvs2", 5, 5) ); - nvs_handle handle1, handle2; + PartitionEmulation p0(&emu, 0 * SPI_FLASH_SEC_SIZE, 5 * SPI_FLASH_SEC_SIZE, "nvs1"); + PartitionEmulation p1(&emu, 5 * SPI_FLASH_SEC_SIZE, 5 * SPI_FLASH_SEC_SIZE, "nvs2"); + TEST_ESP_OK( NVSPartitionManager::get_instance()->init_custom(&p0, 0, 5) ); + TEST_ESP_OK( NVSPartitionManager::get_instance()->init_custom(&p1, 5, 5) ); + nvs_handle_t handle1, handle2; TEST_ESP_OK( nvs_open_from_partition("nvs1", "test", NVS_READWRITE, &handle1) ); TEST_ESP_OK( nvs_open_from_partition("nvs2", "test", NVS_READWRITE, &handle2) ); TEST_ESP_OK( nvs_set_i32(handle1, "foo", 0xdeadbeef)); @@ -1263,15 +1815,18 @@ TEST_CASE("multiple partitions access check", "[nvs]") TEST_ESP_OK( nvs_get_i32(handle2, "foo", &v2)); CHECK(v1 == 0xdeadbeef); CHECK(v2 == 0xcafebabe); + + TEST_ESP_OK(nvs_flash_deinit_partition(p0.get_partition_name())); + TEST_ESP_OK(nvs_flash_deinit_partition(p1.get_partition_name())); } TEST_CASE("nvs page selection takes into account free entries also not just erased entries", "[nvs]") { - const size_t blob_size = Page::BLOB_MAX_SIZE; + const size_t blob_size = Page::CHUNK_MAX_SIZE/2; uint8_t blob[blob_size] = {0}; - SpiFlashEmulator emu(3); - TEST_ESP_OK( nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, 0, 3) ); - nvs_handle handle; + PartitionEmulationFixture f(0, 3); + TEST_ESP_OK( NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 3) ); + nvs_handle_t handle; TEST_ESP_OK( nvs_open("test", NVS_READWRITE, &handle) ); // Fill first page TEST_ESP_OK( nvs_set_blob(handle, "1a", blob, blob_size/3) ); @@ -1284,8 +1839,1689 @@ TEST_CASE("nvs page selection takes into account free entries also not just eras TEST_ESP_OK( nvs_set_blob(handle, "3a", blob, 4) ); TEST_ESP_OK( nvs_commit(handle) ); nvs_close(handle); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); +} + +TEST_CASE("calculate used and free space", "[nvs]") +{ + PartitionEmulationFixture f(0, 6); + nvs_flash_deinit(); + TEST_ESP_ERR(nvs_get_stats(NULL, NULL), ESP_ERR_INVALID_ARG); + nvs_stats_t stat1; + nvs_stats_t stat2; + TEST_ESP_ERR(nvs_get_stats(NULL, &stat1), ESP_ERR_NVS_NOT_INITIALIZED); + CHECK(stat1.free_entries == 0); + CHECK(stat1.namespace_count == 0); + CHECK(stat1.total_entries == 0); + CHECK(stat1.used_entries == 0); + + nvs_handle_t handle = 0; + size_t h_count_entries; + TEST_ESP_ERR(nvs_get_used_entry_count(handle, &h_count_entries), ESP_ERR_NVS_INVALID_HANDLE); + CHECK(h_count_entries == 0); + + // init nvs + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 6)); + + TEST_ESP_ERR(nvs_get_used_entry_count(handle, &h_count_entries), ESP_ERR_NVS_INVALID_HANDLE); + CHECK(h_count_entries == 0); + + Page p; + // after erase. empty partition + TEST_ESP_OK(nvs_get_stats(NULL, &stat1)); + CHECK(stat1.free_entries != 0); + CHECK(stat1.namespace_count == 0); + CHECK(stat1.total_entries == 6 * p.ENTRY_COUNT); + CHECK(stat1.used_entries == 0); + + // create namespace test_k1 + nvs_handle_t handle_1; + TEST_ESP_OK(nvs_open("test_k1", NVS_READWRITE, &handle_1)); + TEST_ESP_OK(nvs_get_stats(NULL, &stat2)); + CHECK(stat2.free_entries + 1 == stat1.free_entries); + CHECK(stat2.namespace_count == 1); + CHECK(stat2.total_entries == stat1.total_entries); + CHECK(stat2.used_entries == 1); + + // create pair key-value com + TEST_ESP_OK(nvs_set_i32(handle_1, "com", 0x12345678)); + TEST_ESP_OK(nvs_get_stats(NULL, &stat1)); + CHECK(stat1.free_entries + 1 == stat2.free_entries); + CHECK(stat1.namespace_count == 1); + CHECK(stat1.total_entries == stat2.total_entries); + CHECK(stat1.used_entries == 2); + + // change value in com + TEST_ESP_OK(nvs_set_i32(handle_1, "com", 0x01234567)); + TEST_ESP_OK(nvs_get_stats(NULL, &stat2)); + CHECK(stat2.free_entries == stat1.free_entries); + CHECK(stat2.namespace_count == 1); + CHECK(stat2.total_entries != 0); + CHECK(stat2.used_entries == 2); + + // create pair key-value ru + TEST_ESP_OK(nvs_set_i32(handle_1, "ru", 0x00FF00FF)); + TEST_ESP_OK(nvs_get_stats(NULL, &stat1)); + CHECK(stat1.free_entries + 1 == stat2.free_entries); + CHECK(stat1.namespace_count == 1); + CHECK(stat1.total_entries != 0); + CHECK(stat1.used_entries == 3); + + // amount valid pair in namespace 1 + size_t h1_count_entries; + TEST_ESP_OK(nvs_get_used_entry_count(handle_1, &h1_count_entries)); + CHECK(h1_count_entries == 2); + + nvs_handle_t handle_2; + // create namespace test_k2 + TEST_ESP_OK(nvs_open("test_k2", NVS_READWRITE, &handle_2)); + TEST_ESP_OK(nvs_get_stats(NULL, &stat2)); + CHECK(stat2.free_entries + 1 == stat1.free_entries); + CHECK(stat2.namespace_count == 2); + CHECK(stat2.total_entries == stat1.total_entries); + CHECK(stat2.used_entries == 4); + + // create pair key-value + TEST_ESP_OK(nvs_set_i32(handle_2, "su1", 0x00000001)); + TEST_ESP_OK(nvs_set_i32(handle_2, "su2", 0x00000002)); + TEST_ESP_OK(nvs_set_i32(handle_2, "sus", 0x00000003)); + TEST_ESP_OK(nvs_get_stats(NULL, &stat1)); + CHECK(stat1.free_entries + 3 == stat2.free_entries); + CHECK(stat1.namespace_count == 2); + CHECK(stat1.total_entries == stat2.total_entries); + CHECK(stat1.used_entries == 7); + + CHECK(stat1.total_entries == (stat1.used_entries + stat1.free_entries)); + + // amount valid pair in namespace 2 + size_t h2_count_entries; + TEST_ESP_OK(nvs_get_used_entry_count(handle_2, &h2_count_entries)); + CHECK(h2_count_entries == 3); + + CHECK(stat1.used_entries == (h1_count_entries + h2_count_entries + stat1.namespace_count)); + + nvs_close(handle_1); + nvs_close(handle_2); + + size_t temp = h2_count_entries; + TEST_ESP_ERR(nvs_get_used_entry_count(handle_1, &h2_count_entries), ESP_ERR_NVS_INVALID_HANDLE); + CHECK(h2_count_entries == 0); + h2_count_entries = temp; + TEST_ESP_ERR(nvs_get_used_entry_count(handle_1, NULL), ESP_ERR_INVALID_ARG); + + nvs_handle_t handle_3; + // create namespace test_k3 + TEST_ESP_OK(nvs_open("test_k3", NVS_READWRITE, &handle_3)); + TEST_ESP_OK(nvs_get_stats(NULL, &stat2)); + CHECK(stat2.free_entries + 1 == stat1.free_entries); + CHECK(stat2.namespace_count == 3); + CHECK(stat2.total_entries == stat1.total_entries); + CHECK(stat2.used_entries == 8); + + // create pair blobs + uint32_t blob[12]; + TEST_ESP_OK(nvs_set_blob(handle_3, "bl1", &blob, sizeof(blob))); + TEST_ESP_OK(nvs_get_stats(NULL, &stat1)); + CHECK(stat1.free_entries + 4 == stat2.free_entries); + CHECK(stat1.namespace_count == 3); + CHECK(stat1.total_entries == stat2.total_entries); + CHECK(stat1.used_entries == 12); + + // amount valid pair in namespace 2 + size_t h3_count_entries; + TEST_ESP_OK(nvs_get_used_entry_count(handle_3, &h3_count_entries)); + CHECK(h3_count_entries == 4); + + CHECK(stat1.used_entries == (h1_count_entries + h2_count_entries + h3_count_entries + stat1.namespace_count)); + + nvs_close(handle_3); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); +} + +// TODO: leaks memory +TEST_CASE("Recovery from power-off when the entry being erased is not on active page", "[nvs]") +{ + const size_t blob_size = Page::CHUNK_MAX_SIZE/2 ; + size_t read_size = blob_size; + uint8_t blob[blob_size] = {0x11}; + PartitionEmulationFixture f(0, 3); + TEST_ESP_OK( NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 3) ); + nvs_handle_t handle; + TEST_ESP_OK( nvs_open("test", NVS_READWRITE, &handle) ); + + f.emu.clearStats(); + f.emu.failAfter(Page::CHUNK_MAX_SIZE/4 + 75); + TEST_ESP_OK( nvs_set_blob(handle, "1a", blob, blob_size) ); + TEST_ESP_OK( nvs_set_blob(handle, "1b", blob, blob_size) ); + + TEST_ESP_ERR( nvs_erase_key(handle, "1a"), ESP_ERR_FLASH_OP_FAIL ); + + TEST_ESP_OK( NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 3) ); + + /* Check 1a is erased fully*/ + TEST_ESP_ERR( nvs_get_blob(handle, "1a", blob, &read_size), ESP_ERR_NVS_NOT_FOUND); + + /* Check 2b is still accessible*/ + TEST_ESP_OK( nvs_get_blob(handle, "1b", blob, &read_size)); + + nvs_close(handle); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); +} + +// TODO: leaks memory +TEST_CASE("Recovery from power-off when page is being freed.", "[nvs]") +{ + const size_t blob_size = (Page::ENTRY_COUNT-3) * Page::ENTRY_SIZE; + size_t read_size = blob_size/2; + uint8_t blob[blob_size] = {0}; + PartitionEmulationFixture f(0, 3); + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 3)); + nvs_handle_t handle; + TEST_ESP_OK(nvs_open("test", NVS_READWRITE, &handle)); + // Fill first page + TEST_ESP_OK(nvs_set_blob(handle, "1a", blob, blob_size/3)); + TEST_ESP_OK(nvs_set_blob(handle, "1b", blob, blob_size/3)); + TEST_ESP_OK(nvs_set_blob(handle, "1c", blob, blob_size/4)); + // Fill second page + TEST_ESP_OK(nvs_set_blob(handle, "2a", blob, blob_size/2)); + TEST_ESP_OK(nvs_set_blob(handle, "2b", blob, blob_size/2)); + + TEST_ESP_OK(nvs_erase_key(handle, "1c")); + + f.emu.clearStats(); + f.emu.failAfter(6 * Page::ENTRY_COUNT); + TEST_ESP_ERR(nvs_set_blob(handle, "1d", blob, blob_size/4), ESP_ERR_FLASH_OP_FAIL); + + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 3)); + + read_size = blob_size/3; + TEST_ESP_OK( nvs_get_blob(handle, "1a", blob, &read_size)); + TEST_ESP_OK( nvs_get_blob(handle, "1b", blob, &read_size)); + + read_size = blob_size /4; + TEST_ESP_ERR( nvs_get_blob(handle, "1c", blob, &read_size), ESP_ERR_NVS_NOT_FOUND); + TEST_ESP_ERR( nvs_get_blob(handle, "1d", blob, &read_size), ESP_ERR_NVS_NOT_FOUND); + + read_size = blob_size /2; + TEST_ESP_OK( nvs_get_blob(handle, "2a", blob, &read_size)); + TEST_ESP_OK( nvs_get_blob(handle, "2b", blob, &read_size)); + + TEST_ESP_OK(nvs_commit(handle)); + nvs_close(handle); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); +} + +TEST_CASE("Multi-page blobs are supported", "[nvs]") +{ + const size_t blob_size = Page::CHUNK_MAX_SIZE *2; + uint8_t blob[blob_size] = {0}; + PartitionEmulationFixture f(0, 5); + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 5)); + nvs_handle_t handle; + TEST_ESP_OK(nvs_open("test", NVS_READWRITE, &handle)); + TEST_ESP_OK(nvs_set_blob(handle, "abc", blob, blob_size)); + TEST_ESP_OK(nvs_commit(handle)); + nvs_close(handle); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); +} + +TEST_CASE("Failures are handled while storing multi-page blobs", "[nvs]") +{ + const size_t blob_size = Page::CHUNK_MAX_SIZE *7; + uint8_t blob[blob_size] = {0}; + PartitionEmulationFixture f(0, 5); + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 5)); + nvs_handle_t handle; + TEST_ESP_OK(nvs_open("test", NVS_READWRITE, &handle)); + TEST_ESP_ERR(nvs_set_blob(handle, "abc", blob, blob_size), ESP_ERR_NVS_VALUE_TOO_LONG); + TEST_ESP_OK(nvs_set_blob(handle, "abc", blob, Page::CHUNK_MAX_SIZE*2)); + TEST_ESP_OK(nvs_commit(handle)); + nvs_close(handle); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); +} + +TEST_CASE("Reading multi-page blobs", "[nvs]") +{ + const size_t blob_size = Page::CHUNK_MAX_SIZE *3; + uint8_t blob[blob_size]; + uint8_t blob_read[blob_size]; + size_t read_size = blob_size; + PartitionEmulationFixture f(0, 5); + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 5)); + nvs_handle_t handle; + memset(blob, 0x11, blob_size); + memset(blob_read, 0xee, blob_size); + TEST_ESP_OK(nvs_open("readTest", NVS_READWRITE, &handle)); + TEST_ESP_OK(nvs_set_blob(handle, "abc", blob, blob_size)); + TEST_ESP_OK(nvs_get_blob(handle, "abc", blob_read, &read_size)); + CHECK(memcmp(blob, blob_read, blob_size) == 0); + TEST_ESP_OK(nvs_commit(handle)); + nvs_close(handle); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); +} + +TEST_CASE("Modification of values for Multi-page blobs are supported", "[nvs]") +{ + const size_t blob_size = Page::CHUNK_MAX_SIZE *2; + uint8_t blob[blob_size] = {0}; + uint8_t blob_read[blob_size] = {0xfe};; + uint8_t blob2[blob_size] = {0x11}; + uint8_t blob3[blob_size] = {0x22}; + uint8_t blob4[blob_size] ={ 0x33}; + size_t read_size = blob_size; + PartitionEmulationFixture f(0, 6); + TEST_ESP_OK( NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 6) ); + nvs_handle_t handle; + memset(blob, 0x11, blob_size); + memset(blob2, 0x22, blob_size); + memset(blob3, 0x33, blob_size); + memset(blob4, 0x44, blob_size); + memset(blob_read, 0xff, blob_size); + TEST_ESP_OK( nvs_open("test", NVS_READWRITE, &handle) ); + TEST_ESP_OK( nvs_set_blob(handle, "abc", blob, blob_size) ); + TEST_ESP_OK( nvs_set_blob(handle, "abc", blob2, blob_size) ); + TEST_ESP_OK( nvs_set_blob(handle, "abc", blob3, blob_size) ); + TEST_ESP_OK( nvs_set_blob(handle, "abc", blob4, blob_size) ); + TEST_ESP_OK( nvs_get_blob(handle, "abc", blob_read, &read_size)); + CHECK(memcmp(blob4, blob_read, blob_size) == 0); + TEST_ESP_OK( nvs_commit(handle) ); + nvs_close(handle); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); +} + +TEST_CASE("Modification from single page blob to multi-page", "[nvs]") +{ + const size_t blob_size = Page::CHUNK_MAX_SIZE *3; + uint8_t blob[blob_size] = {0}; + uint8_t blob_read[blob_size] = {0xff}; + size_t read_size = blob_size; + PartitionEmulationFixture f(0, 5); + TEST_ESP_OK( NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 5) ); + nvs_handle_t handle; + TEST_ESP_OK(nvs_open("Test", NVS_READWRITE, &handle) ); + TEST_ESP_OK(nvs_set_blob(handle, "abc", blob, Page::CHUNK_MAX_SIZE/2)); + TEST_ESP_OK(nvs_set_blob(handle, "abc", blob, blob_size)); + TEST_ESP_OK(nvs_get_blob(handle, "abc", blob_read, &read_size)); + CHECK(memcmp(blob, blob_read, blob_size) == 0); + TEST_ESP_OK(nvs_commit(handle) ); + nvs_close(handle); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); +} + +TEST_CASE("Modification from multi-page to single page", "[nvs]") +{ + const size_t blob_size = Page::CHUNK_MAX_SIZE *3; + uint8_t blob[blob_size] = {0}; + uint8_t blob_read[blob_size] = {0xff}; + size_t read_size = blob_size; + PartitionEmulationFixture f(0, 5); + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 5) ); + nvs_handle_t handle; + TEST_ESP_OK(nvs_open("Test", NVS_READWRITE, &handle) ); + TEST_ESP_OK(nvs_set_blob(handle, "abc", blob, blob_size)); + TEST_ESP_OK(nvs_set_blob(handle, "abc", blob, Page::CHUNK_MAX_SIZE/2)); + TEST_ESP_OK(nvs_set_blob(handle, "abc2", blob, blob_size)); + TEST_ESP_OK(nvs_get_blob(handle, "abc", blob_read, &read_size)); + CHECK(memcmp(blob, blob_read, Page::CHUNK_MAX_SIZE) == 0); + TEST_ESP_OK(nvs_commit(handle) ); + nvs_close(handle); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); +} + +TEST_CASE("Multi-page blob erased using nvs_erase_key should not be found when probed for just length", "[nvs]") +{ + const size_t blob_size = Page::CHUNK_MAX_SIZE *3; + uint8_t blob[blob_size] = {0}; + size_t read_size = blob_size; + PartitionEmulationFixture f(0, 5); + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 5)); + nvs_handle handle; + TEST_ESP_OK(nvs_open("Test", NVS_READWRITE, &handle)); + TEST_ESP_OK(nvs_set_blob(handle, "abc", blob, blob_size)); + TEST_ESP_OK(nvs_erase_key(handle, "abc")); + TEST_ESP_ERR(nvs_get_blob(handle, "abc", NULL, &read_size), ESP_ERR_NVS_NOT_FOUND); + TEST_ESP_OK(nvs_commit(handle)); + nvs_close(handle); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); +} + + +TEST_CASE("Check that orphaned blobs are erased during init", "[nvs]") +{ + const size_t blob_size = Page::CHUNK_MAX_SIZE *3 ; + uint8_t blob[blob_size] = {0x11}; + uint8_t blob2[blob_size] = {0x22}; + uint8_t blob3[blob_size] = {0x33}; + PartitionEmulationFixture f(0, 5); + Storage storage(&f.part); + + TEST_ESP_OK(storage.init(0, 5)); + + TEST_ESP_OK(storage.writeItem(1, ItemType::BLOB, "key", blob, sizeof(blob))); + + + TEST_ESP_OK(storage.init(0, 5)); + /* Check that multi-page item is still available.**/ + TEST_ESP_OK(storage.readItem(1, ItemType::BLOB, "key", blob, sizeof(blob))); + + TEST_ESP_ERR(storage.writeItem(1, ItemType::BLOB, "key2", blob, sizeof(blob)), ESP_ERR_NVS_NOT_ENOUGH_SPACE); + + Page p; + p.load(&f.part, 3); // This is where index will be placed. + p.erase(); + + TEST_ESP_OK(storage.init(0, 5)); + + TEST_ESP_ERR(storage.readItem(1, ItemType::BLOB, "key", blob, sizeof(blob)), ESP_ERR_NVS_NOT_FOUND); + TEST_ESP_OK(storage.writeItem(1, ItemType::BLOB, "key3", blob, sizeof(blob))); +} + +TEST_CASE("nvs blob fragmentation test", "[nvs]") +{ + PartitionEmulationFixture f(0, 4); + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 4) ); + const size_t BLOB_SIZE = 3500; + uint8_t *blob = (uint8_t*) malloc(BLOB_SIZE); + CHECK(blob != NULL); + memset(blob, 0xEE, BLOB_SIZE); + const uint32_t magic = 0xff33eaeb; + nvs_handle_t h; + TEST_ESP_OK( nvs_open("blob_tests", NVS_READWRITE, &h) ); + for (int i = 0; i < 128; i++) { + INFO("Iteration " << i << "...\n"); + TEST_ESP_OK( nvs_set_u32(h, "magic", magic) ); + TEST_ESP_OK( nvs_set_blob(h, "blob", blob, BLOB_SIZE) ); + char seq_buf[16]; + sprintf(seq_buf, "seq%d", i); + TEST_ESP_OK( nvs_set_u32(h, seq_buf, i) ); + } + free(blob); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); +} + +TEST_CASE("nvs code handles errors properly when partition is near to full", "[nvs]") +{ + const size_t blob_size = Page::CHUNK_MAX_SIZE * 0.3 ; + uint8_t blob[blob_size] = {0x11}; + PartitionEmulationFixture f(0, 5); + Storage storage(&f.part); + char nvs_key[16] = ""; + + TEST_ESP_OK(storage.init(0, 5)); + + /* Four pages should fit roughly 12 blobs*/ + for(uint8_t count = 1; count <= 12; count++) { + sprintf(nvs_key, "key:%u", count); + TEST_ESP_OK(storage.writeItem(1, ItemType::BLOB, nvs_key, blob, sizeof(blob))); + } + + for(uint8_t count = 13; count <= 20; count++) { + sprintf(nvs_key, "key:%u", count); + TEST_ESP_ERR(storage.writeItem(1, ItemType::BLOB, nvs_key, blob, sizeof(blob)), ESP_ERR_NVS_NOT_ENOUGH_SPACE); + } +} + +TEST_CASE("Check for nvs version incompatibility", "[nvs]") +{ + PartitionEmulationFixture f(0, 3); + + int32_t val1 = 0x12345678; + Page p; + p.load(&f.part, 0); + TEST_ESP_OK(p.setVersion(Page::NVS_VERSION - 1)); + TEST_ESP_OK(p.writeItem(1, ItemType::I32, "foo", &val1, sizeof(val1))); + + TEST_ESP_ERR(NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 3), + ESP_ERR_NVS_NEW_VERSION_FOUND); + + // if something went wrong, clean up + nvs_flash_deinit_partition(f.part.get_partition_name()); +} + +TEST_CASE("Check that NVS supports old blob format without blob index", "[nvs]") +{ + SpiFlashEmulator emu("../nvs_partition_generator/part_old_blob_format.bin"); + PartitionEmulation part(&emu, 0, 2 * SPI_FLASH_SEC_SIZE, "test"); + nvs_handle_t handle; + + TEST_ESP_OK( NVSPartitionManager::get_instance()->init_custom(&part, 0, 2) ); + TEST_ESP_OK( nvs_open_from_partition("test", "dummyNamespace", NVS_READWRITE, &handle)); + + char buf[64] = {0}; + size_t buflen = 64; + uint8_t hexdata[] = {0x01, 0x02, 0x03, 0xab, 0xcd, 0xef}; + TEST_ESP_OK( nvs_get_blob(handle, "dummyHex2BinKey", buf, &buflen)); + CHECK(memcmp(buf, hexdata, buflen) == 0); + + buflen = 64; + uint8_t base64data[] = {'1', '2', '3', 'a', 'b', 'c'}; + TEST_ESP_OK( nvs_get_blob(handle, "dummyBase64Key", buf, &buflen)); + CHECK(memcmp(buf, base64data, buflen) == 0); + + Page p; + p.load(&part, 0); + + /* Check that item is stored in old format without blob index*/ + TEST_ESP_OK(p.findItem(1, ItemType::BLOB, "dummyHex2BinKey")); + + /* Modify the blob so that it is stored in the new format*/ + hexdata[0] = hexdata[1] = hexdata[2] = 0x99; + TEST_ESP_OK(nvs_set_blob(handle, "dummyHex2BinKey", hexdata, sizeof(hexdata))); + + Page p2; + p2.load(&part, 0); + + /* Check the type of the blob. Expect type mismatch since the blob is stored in new format*/ + TEST_ESP_ERR(p2.findItem(1, ItemType::BLOB, "dummyHex2BinKey"), ESP_ERR_NVS_TYPE_MISMATCH); + + /* Check that index is present for the modified blob according to new format*/ + TEST_ESP_OK(p2.findItem(1, ItemType::BLOB_IDX, "dummyHex2BinKey")); + + /* Read the blob in new format and check the contents*/ + buflen = 64; + TEST_ESP_OK( nvs_get_blob(handle, "dummyBase64Key", buf, &buflen)); + CHECK(memcmp(buf, base64data, buflen) == 0); + + TEST_ESP_OK(nvs_flash_deinit_partition(part.get_partition_name())); +} + +// TODO: leaks memory +TEST_CASE("monkey test with old-format blob present", "[nvs][monkey]") +{ + std::random_device rd; + std::mt19937 gen(rd()); + uint32_t seed = 3; + gen.seed(seed); + + PartitionEmulationFixture f(0, 10); + f.emu.randomize(seed); + f.emu.clearStats(); + + const uint32_t NVS_FLASH_SECTOR = 2; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 8; + static const size_t smallBlobLen = Page::CHUNK_MAX_SIZE / 3; + + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + + nvs_handle_t handle; + TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle)); + RandomTest test; + + for ( uint8_t it = 0; it < 10; it++) { + size_t count = 200; + + /* Erase index and chunks for the blob with "singlepage" key */ + for (uint8_t num = NVS_FLASH_SECTOR; num < NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN; num++) { + Page p; + p.load(&f.part, num); + p.eraseItem(1, ItemType::BLOB, "singlepage", Item::CHUNK_ANY, VerOffset::VER_ANY); + p.eraseItem(1, ItemType::BLOB_IDX, "singlepage", Item::CHUNK_ANY, VerOffset::VER_ANY); + p.eraseItem(1, ItemType::BLOB_DATA, "singlepage", Item::CHUNK_ANY, VerOffset::VER_ANY); + } + + /* Now write "singlepage" blob in old format*/ + for (uint8_t num = NVS_FLASH_SECTOR; num < NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN; num++) { + Page p; + p.load(&f.part, num); + if (p.state() == Page::PageState::ACTIVE) { + uint8_t buf[smallBlobLen]; + size_t blobLen = gen() % smallBlobLen; + + if(blobLen > p.getVarDataTailroom()) { + blobLen = p.getVarDataTailroom(); + } + + std::generate_n(buf, blobLen, [&]() -> uint8_t { + return static_cast(gen() % 256); + }); + + TEST_ESP_OK(p.writeItem(1, ItemType::BLOB, "singlepage", buf, blobLen, Item::CHUNK_ANY)); + TEST_ESP_OK(p.findItem(1, ItemType::BLOB, "singlepage")); + test.handleExternalWriteAtIndex(9, buf, blobLen); // This assumes "singlepage" is always at index 9 + + break; + } + } + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); + /* Initialize again */ + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle)); + + /* Perform random things */ + auto res = test.doRandomThings(handle, gen, count); + if (res != ESP_OK) { + nvs_dump(NVS_DEFAULT_PART_NAME); + CHECK(0); + } + + /* Check that only one version is present for "singlepage". Its possible that last iteration did not write + * anything for "singlepage". So either old version or new version should be present.*/ + bool oldVerPresent = false, newVerPresent = false; + + for (uint8_t num = NVS_FLASH_SECTOR; num < NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN; num++) { + Page p; + p.load(&f.part, num); + if(!oldVerPresent && p.findItem(1, ItemType::BLOB, "singlepage", Item::CHUNK_ANY, VerOffset::VER_ANY) == ESP_OK) { + oldVerPresent = true; + } + + if(!newVerPresent && p.findItem(1, ItemType::BLOB_IDX, "singlepage", Item::CHUNK_ANY, VerOffset::VER_ANY) == ESP_OK) { + newVerPresent = true; + } + } + CHECK(oldVerPresent != newVerPresent); + } + + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); + s_perf << "Monkey test: nErase=" << f.emu.getEraseOps() << " nWrite=" << f.emu.getWriteOps() << std::endl; +} + +TEST_CASE("Recovery from power-off during modification of blob present in old-format (same page)", "[nvs]") +{ + std::random_device rd; + std::mt19937 gen(rd()); + uint32_t seed = 3; + gen.seed(seed); + + PartitionEmulationFixture f(0, 3); + f.emu.clearStats(); + + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 3)); + + nvs_handle_t handle; + TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle)); + + uint8_t hexdata[] = {0x01, 0x02, 0x03, 0xab, 0xcd, 0xef}; + uint8_t hexdata_old[] = {0x11, 0x12, 0x13, 0xbb, 0xcc, 0xee}; + size_t buflen = sizeof(hexdata); + uint8_t buf[Page::CHUNK_MAX_SIZE]; + + /* Power-off when blob was being written on the same page where its old version in old format + * was present*/ + Page p; + p.load(&f.part, 0); + /* Write blob in old-format*/ + TEST_ESP_OK(p.writeItem(1, ItemType::BLOB, "singlepage", hexdata_old, sizeof(hexdata_old))); + + /* Write blob in new format*/ + TEST_ESP_OK(p.writeItem(1, ItemType::BLOB_DATA, "singlepage", hexdata, sizeof(hexdata), 0)); + /* All pages are stored. Now store the index.*/ + Item item; + item.blobIndex.dataSize = sizeof(hexdata); + item.blobIndex.chunkCount = 1; + item.blobIndex.chunkStart = VerOffset::VER_0_OFFSET; + + TEST_ESP_OK(p.writeItem(1, ItemType::BLOB_IDX, "singlepage", item.data, sizeof(item.data))); + + TEST_ESP_OK(p.findItem(1, ItemType::BLOB, "singlepage")); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); + /* Initialize again */ + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 3)); + TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle)); + + TEST_ESP_OK( nvs_get_blob(handle, "singlepage", buf, &buflen)); + CHECK(memcmp(buf, hexdata, buflen) == 0); + + Page p2; + p2.load(&f.part, 0); + TEST_ESP_ERR(p2.findItem(1, ItemType::BLOB, "singlepage"), ESP_ERR_NVS_TYPE_MISMATCH); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); +} + +TEST_CASE("Recovery from power-off during modification of blob present in old-format (different page)", "[nvs]") +{ + std::random_device rd; + std::mt19937 gen(rd()); + uint32_t seed = 3; + gen.seed(seed); + + PartitionEmulationFixture f(0, 3); + f.emu.clearStats(); + + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 3)); + + nvs_handle_t handle; + TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle)); + + uint8_t hexdata[] = {0x01, 0x02, 0x03, 0xab, 0xcd, 0xef}; + uint8_t hexdata_old[] = {0x11, 0x12, 0x13, 0xbb, 0xcc, 0xee}; + size_t buflen = sizeof(hexdata); + uint8_t buf[Page::CHUNK_MAX_SIZE]; + + + /* Power-off when blob was being written on the different page where its old version in old format + * was present*/ + Page p; + p.load(&f.part, 0); + /* Write blob in old-format*/ + TEST_ESP_OK(p.writeItem(1, ItemType::BLOB, "singlepage", hexdata_old, sizeof(hexdata_old))); + + /* Write blob in new format*/ + TEST_ESP_OK(p.writeItem(1, ItemType::BLOB_DATA, "singlepage", hexdata, sizeof(hexdata), 0)); + /* All pages are stored. Now store the index.*/ + Item item; + item.blobIndex.dataSize = sizeof(hexdata); + item.blobIndex.chunkCount = 1; + item.blobIndex.chunkStart = VerOffset::VER_0_OFFSET; + p.markFull(); + Page p2; + p2.load(&f.part, 1); + p2.setSeqNumber(1); + + TEST_ESP_OK(p2.writeItem(1, ItemType::BLOB_IDX, "singlepage", item.data, sizeof(item.data))); + + TEST_ESP_OK(p.findItem(1, ItemType::BLOB, "singlepage")); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); + /* Initialize again */ + TEST_ESP_OK(NVSPartitionManager::get_instance()->init_custom(&f.part, 0, 3)); + TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle)); + + TEST_ESP_OK( nvs_get_blob(handle, "singlepage", buf, &buflen)); + CHECK(memcmp(buf, hexdata, buflen) == 0); + + Page p3; + p3.load(&f.part, 0); + TEST_ESP_ERR(p3.findItem(1, ItemType::BLOB, "singlepage"), ESP_ERR_NVS_NOT_FOUND); + + TEST_ESP_OK(nvs_flash_deinit_partition(f.part.get_partition_name())); +} + +static void check_nvs_part_gen_args(SpiFlashEmulator *spi_flash_emulator, + char const *part_name, + int size, + char const *filename, + bool is_encr, + nvs_sec_cfg_t* xts_cfg) +{ + nvs_handle_t handle; + + esp_partition_t esp_part; + esp_part.encrypted = false; // we're not testing generic flash encryption here, only the legacy NVS encryption + esp_part.address = 0; + esp_part.size = size * SPI_FLASH_SEC_SIZE; + strncpy(esp_part.label, part_name, PART_NAME_MAX_SIZE); + shared_ptr part; + + if (is_encr) { + NVSEncryptedPartition *enc_part = new NVSEncryptedPartition(&esp_part); + TEST_ESP_OK(enc_part->init(xts_cfg)); + part.reset(enc_part); + } else { + part.reset(new PartitionEmulation(spi_flash_emulator, 0, size, part_name)); + } + + TEST_ESP_OK( NVSPartitionManager::get_instance()->init_custom(part.get(), 0, size) ); + + TEST_ESP_OK( nvs_open_from_partition(part_name, "dummyNamespace", NVS_READONLY, &handle)); + uint8_t u8v; + TEST_ESP_OK( nvs_get_u8(handle, "dummyU8Key", &u8v)); + CHECK(u8v == 127); + int8_t i8v; + TEST_ESP_OK( nvs_get_i8(handle, "dummyI8Key", &i8v)); + CHECK(i8v == -128); + uint16_t u16v; + TEST_ESP_OK( nvs_get_u16(handle, "dummyU16Key", &u16v)); + CHECK(u16v == 32768); + uint32_t u32v; + TEST_ESP_OK( nvs_get_u32(handle, "dummyU32Key", &u32v)); + CHECK(u32v == 4294967295); + int32_t i32v; + TEST_ESP_OK( nvs_get_i32(handle, "dummyI32Key", &i32v)); + CHECK(i32v == -2147483648); + + char buf[64] = {0}; + size_t buflen = 64; + TEST_ESP_OK( nvs_get_str(handle, "dummyStringKey", buf, &buflen)); + CHECK(strncmp(buf, "0A:0B:0C:0D:0E:0F", buflen) == 0); + + uint8_t hexdata[] = {0x01, 0x02, 0x03, 0xab, 0xcd, 0xef}; + buflen = 64; + int j; + TEST_ESP_OK( nvs_get_blob(handle, "dummyHex2BinKey", buf, &buflen)); + CHECK(memcmp(buf, hexdata, buflen) == 0); + + uint8_t base64data[] = {'1', '2', '3', 'a', 'b', 'c'}; + TEST_ESP_OK( nvs_get_blob(handle, "dummyBase64Key", buf, &buflen)); + CHECK(memcmp(buf, base64data, buflen) == 0); + + buflen = 64; + uint8_t hexfiledata[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}; + TEST_ESP_OK( nvs_get_blob(handle, "hexFileKey", buf, &buflen)); + CHECK(memcmp(buf, hexfiledata, buflen) == 0); + + buflen = 64; + uint8_t strfiledata[64] = "abcdefghijklmnopqrstuvwxyz\0"; + TEST_ESP_OK( nvs_get_str(handle, "stringFileKey", buf, &buflen)); + CHECK(memcmp(buf, strfiledata, buflen) == 0); + + char bin_data[5200]; + size_t bin_len = sizeof(bin_data); + char binfiledata[5200]; + ifstream file; + file.open(filename); + file.read(binfiledata,5200); + TEST_ESP_OK( nvs_get_blob(handle, "binFileKey", bin_data, &bin_len)); + CHECK(memcmp(bin_data, binfiledata, bin_len) == 0); + + file.close(); + + nvs_close(handle); + + TEST_ESP_OK(nvs_flash_deinit_partition(part_name)); +} + + +TEST_CASE("check and read data from partition generated via partition generation utility with multipage blob support disabled", "[nvs_part_gen]") +{ + int status; + int childpid = fork(); + if (childpid == 0) { + exit(execlp("cp", " cp", + "-rf", + "../nvs_partition_generator/testdata", + ".",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) != -1); + + childpid = fork(); + + if (childpid == 0) { + exit(execlp("python", "python", + "../nvs_partition_generator/nvs_partition_gen.py", + "generate", + "../nvs_partition_generator/sample_singlepage_blob.csv", + "partition_single_page.bin", + "0x3000", + "--version", + "1", + "--outdir", + "../nvs_partition_generator",NULL)); + } else { + CHECK(childpid > 0); + int status; + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + } + } + + SpiFlashEmulator emu("../nvs_partition_generator/partition_single_page.bin"); + + check_nvs_part_gen_args(&emu, "test", 3, "../nvs_partition_generator/testdata/sample_singlepage_blob.bin", false, NULL); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("rm", " rm", + "-rf", + "testdata",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + } +} + +TEST_CASE("check and read data from partition generated via partition generation utility with multipage blob support enabled", "[nvs_part_gen]") +{ + int status; + int childpid = fork(); + if (childpid == 0) { + exit(execlp("cp", " cp", + "-rf", + "../nvs_partition_generator/testdata", + ".",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + childpid = fork(); + + if (childpid == 0) { + exit(execlp("python", "python", + "../nvs_partition_generator/nvs_partition_gen.py", + "generate", + "../nvs_partition_generator/sample_multipage_blob.csv", + "partition_multipage_blob.bin", + "0x4000", + "--version", + "2", + "--outdir", + "../nvs_partition_generator",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + } + } + + SpiFlashEmulator emu("../nvs_partition_generator/partition_multipage_blob.bin"); + + check_nvs_part_gen_args(&emu, "test", 4, "../nvs_partition_generator/testdata/sample_multipage_blob.bin",false,NULL); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("rm", " rm", + "-rf", + "testdata",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + } +} + +TEST_CASE("check and read data from partition generated via manufacturing utility with multipage blob support disabled", "[mfg_gen]") +{ + int childpid = fork(); + int status; + + if (childpid == 0) { + exit(execlp("bash", "bash", + "-c", + "rm -rf ../../../tools/mass_mfg/host_test && \ + cp -rf ../../../tools/mass_mfg/testdata mfg_testdata && \ + cp -rf ../nvs_partition_generator/testdata . && \ + mkdir -p ../../../tools/mass_mfg/host_test", NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("python", "python", + "../../../tools/mass_mfg/mfg_gen.py", + "generate", + "../../../tools/mass_mfg/samples/sample_config.csv", + "../../../tools/mass_mfg/samples/sample_values_singlepage_blob.csv", + "Test", + "0x3000", + "--outdir", + "../../../tools/mass_mfg/host_test", + "--version", + "1",NULL)); + + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("python", "python", + "../nvs_partition_generator/nvs_partition_gen.py", + "generate", + "../../../tools/mass_mfg/host_test/csv/Test-1.csv", + "../nvs_partition_generator/Test-1-partition.bin", + "0x3000", + "--version", + "1",NULL)); + + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + } + + } + + } + + SpiFlashEmulator emu1("../../../tools/mass_mfg/host_test/bin/Test-1.bin"); + check_nvs_part_gen_args(&emu1, "test", 3, "mfg_testdata/sample_singlepage_blob.bin", false, NULL); + + SpiFlashEmulator emu2("../nvs_partition_generator/Test-1-partition.bin"); + check_nvs_part_gen_args(&emu2, "test", 3, "testdata/sample_singlepage_blob.bin", false, NULL); + + + childpid = fork(); + if (childpid == 0) { + exit(execlp("bash", " bash", + "-c", + "rm -rf ../../../tools/mass_mfg/host_test | \ + rm -rf mfg_testdata | \ + rm -rf testdata",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + } + +} + +TEST_CASE("check and read data from partition generated via manufacturing utility with multipage blob support enabled", "[mfg_gen]") +{ + int childpid = fork(); + int status; + + if (childpid == 0) { + exit(execlp("bash", " bash", + "-c", + "rm -rf ../../../tools/mass_mfg/host_test | \ + cp -rf ../../../tools/mass_mfg/testdata mfg_testdata | \ + cp -rf ../nvs_partition_generator/testdata . | \ + mkdir -p ../../../tools/mass_mfg/host_test",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("python", "python", + "../../../tools/mass_mfg/mfg_gen.py", + "generate", + "../../../tools/mass_mfg/samples/sample_config.csv", + "../../../tools/mass_mfg/samples/sample_values_multipage_blob.csv", + "Test", + "0x4000", + "--outdir", + "../../../tools/mass_mfg/host_test", + "--version", + "2",NULL)); + + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("python", "python", + "../nvs_partition_generator/nvs_partition_gen.py", + "generate", + "../../../tools/mass_mfg/host_test/csv/Test-1.csv", + "../nvs_partition_generator/Test-1-partition.bin", + "0x4000", + "--version", + "2",NULL)); + + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + } + + } + + } + + SpiFlashEmulator emu1("../../../tools/mass_mfg/host_test/bin/Test-1.bin"); + check_nvs_part_gen_args(&emu1, "test", 4, "mfg_testdata/sample_multipage_blob.bin", false, NULL); + + SpiFlashEmulator emu2("../nvs_partition_generator/Test-1-partition.bin"); + check_nvs_part_gen_args(&emu2, "test", 4, "testdata/sample_multipage_blob.bin", false, NULL); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("bash", " bash", + "-c", + "rm -rf ../../../tools/mass_mfg/host_test | \ + rm -rf mfg_testdata | \ + rm -rf testdata",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + } + +} + +#if CONFIG_NVS_ENCRYPTION +TEST_CASE("check underlying xts code for 32-byte size sector encryption", "[nvs]") +{ + auto toHex = [](char ch) { + if(ch >= '0' && ch <= '9') + return ch - '0'; + else if(ch >= 'a' && ch <= 'f') + return ch - 'a' + 10; + else if(ch >= 'A' && ch <= 'F') + return ch - 'A' + 10; + else + return 0; + }; + + auto toHexByte = [toHex](char* c) { + return 16 * toHex(c[0]) + toHex(c[1]); + }; + + auto toHexStream = [toHexByte](char* src, uint8_t* dest) { + uint32_t cnt =0; + char* p = src; + while(*p != '\0' && *(p + 1) != '\0') + { + dest[cnt++] = toHexByte(p); p += 2; + } + }; + + uint8_t eky_hex[2 * NVS_KEY_SIZE]; + uint8_t ptxt_hex[Page::ENTRY_SIZE], ctxt_hex[Page::ENTRY_SIZE], ba_hex[16]; + mbedtls_aes_xts_context ectx[1]; + mbedtls_aes_xts_context dctx[1]; + + char eky[][2 * NVS_KEY_SIZE + 1] = { + "0000000000000000000000000000000000000000000000000000000000000000", + "1111111111111111111111111111111111111111111111111111111111111111" + }; + char tky[][2 * NVS_KEY_SIZE + 1] = { + "0000000000000000000000000000000000000000000000000000000000000000", + "2222222222222222222222222222222222222222222222222222222222222222" + }; + char blk_addr[][2*16 + 1] = { + "00000000000000000000000000000000", + "33333333330000000000000000000000" + }; + + char ptxt[][2 * Page::ENTRY_SIZE + 1] = { + "0000000000000000000000000000000000000000000000000000000000000000", + "4444444444444444444444444444444444444444444444444444444444444444" + }; + char ctxt[][2 * Page::ENTRY_SIZE + 1] = { + "d456b4fc2e620bba6ffbed27b956c9543454dd49ebd8d8ee6f94b65cbe158f73", + "e622334f184bbce129a25b2ac76b3d92abf98e22df5bdd15af471f3db8946a85" + }; + + mbedtls_aes_xts_init(ectx); + mbedtls_aes_xts_init(dctx); + + for(uint8_t cnt = 0; cnt < sizeof(eky)/sizeof(eky[0]); cnt++) { + toHexStream(eky[cnt], eky_hex); + toHexStream(tky[cnt], &eky_hex[NVS_KEY_SIZE]); + toHexStream(ptxt[cnt], ptxt_hex); + toHexStream(ctxt[cnt], ctxt_hex); + toHexStream(blk_addr[cnt], ba_hex); + + CHECK(!mbedtls_aes_xts_setkey_enc(ectx, eky_hex, 2 * NVS_KEY_SIZE * 8)); + CHECK(!mbedtls_aes_xts_setkey_enc(dctx, eky_hex, 2 * NVS_KEY_SIZE * 8)); + + CHECK(!mbedtls_aes_crypt_xts(ectx, MBEDTLS_AES_ENCRYPT, Page::ENTRY_SIZE, ba_hex, ptxt_hex, ptxt_hex)); + + CHECK(!memcmp(ptxt_hex, ctxt_hex, Page::ENTRY_SIZE)); + } +} + +TEST_CASE("test nvs apis with encryption enabled", "[nvs]") +{ + nvs_handle_t handle_1; + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + + nvs_sec_cfg_t xts_cfg; + for(int count = 0; count < NVS_KEY_SIZE; count++) { + xts_cfg.eky[count] = 0x11; + xts_cfg.tky[count] = 0x22; + } + EncryptedPartitionFixture fixture(&xts_cfg, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN); + fixture.emu.randomize(100); + fixture.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + for (uint16_t i = NVS_FLASH_SECTOR; i + init_custom(&fixture.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)); + + TEST_ESP_ERR(nvs_open("namespace1", NVS_READONLY, &handle_1), ESP_ERR_NVS_NOT_FOUND); + + TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle_1)); + TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x12345678)); + TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x23456789)); + + nvs_handle_t handle_2; + TEST_ESP_OK(nvs_open("namespace2", NVS_READWRITE, &handle_2)); + TEST_ESP_OK(nvs_set_i32(handle_2, "foo", 0x3456789a)); + const char* str = "value 0123456789abcdef0123456789abcdef"; + TEST_ESP_OK(nvs_set_str(handle_2, "key", str)); + + int32_t v1; + TEST_ESP_OK(nvs_get_i32(handle_1, "foo", &v1)); + CHECK(0x23456789 == v1); + + int32_t v2; + TEST_ESP_OK(nvs_get_i32(handle_2, "foo", &v2)); + CHECK(0x3456789a == v2); + + char buf[strlen(str) + 1]; + size_t buf_len = sizeof(buf); + + size_t buf_len_needed; + TEST_ESP_OK(nvs_get_str(handle_2, "key", NULL, &buf_len_needed)); + CHECK(buf_len_needed == buf_len); + + size_t buf_len_short = buf_len - 1; + TEST_ESP_ERR(ESP_ERR_NVS_INVALID_LENGTH, nvs_get_str(handle_2, "key", buf, &buf_len_short)); + CHECK(buf_len_short == buf_len); + + size_t buf_len_long = buf_len + 1; + TEST_ESP_OK(nvs_get_str(handle_2, "key", buf, &buf_len_long)); + CHECK(buf_len_long == buf_len); + + TEST_ESP_OK(nvs_get_str(handle_2, "key", buf, &buf_len)); + + CHECK(0 == strcmp(buf, str)); + nvs_close(handle_1); + nvs_close(handle_2); + TEST_ESP_OK(nvs_flash_deinit()); + +} + +TEST_CASE("test nvs apis for nvs partition generator utility with encryption enabled", "[nvs_part_gen]") +{ + int status; + int childpid = fork(); + if (childpid == 0) { + exit(execlp("cp", " cp", + "-rf", + "../nvs_partition_generator/testdata", + ".",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + childpid = fork(); + + if (childpid == 0) { + exit(execlp("python", "python", + "../nvs_partition_generator/nvs_partition_gen.py", + "encrypt", + "../nvs_partition_generator/sample_multipage_blob.csv", + "partition_encrypted.bin", + "0x4000", + "--inputkey", + "../nvs_partition_generator/testdata/sample_encryption_keys.bin", + "--outdir", + "../nvs_partition_generator",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + } + } + + SpiFlashEmulator emu("../nvs_partition_generator/partition_encrypted.bin"); + + nvs_sec_cfg_t cfg; + for(int count = 0; count < NVS_KEY_SIZE; count++) { + cfg.eky[count] = 0x11; + cfg.tky[count] = 0x22; + } + + check_nvs_part_gen_args(&emu, NVS_DEFAULT_PART_NAME, 4, "../nvs_partition_generator/testdata/sample_multipage_blob.bin", true, &cfg); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("rm", " rm", + "-rf", + "testdata",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + } + +} + +TEST_CASE("test decrypt functionality for encrypted data", "[nvs_part_gen]") +{ + + //retrieving the temporary test data + int status = system("cp -rf ../nvs_partition_generator/testdata ."); + CHECK(status == 0); + + //encoding data from sample_multipage_blob.csv + status = system("python ../nvs_partition_generator/nvs_partition_gen.py generate ../nvs_partition_generator/sample_multipage_blob.csv partition_encoded.bin 0x5000 --outdir ../nvs_partition_generator"); + CHECK(status == 0); + + //encrypting data from sample_multipage_blob.csv + status = system("python ../nvs_partition_generator/nvs_partition_gen.py encrypt ../nvs_partition_generator/sample_multipage_blob.csv partition_encrypted.bin 0x5000 --inputkey ../nvs_partition_generator/testdata/sample_encryption_keys.bin --outdir ../nvs_partition_generator"); + CHECK(status == 0); + + //decrypting data from partition_encrypted.bin + status = system("python ../nvs_partition_generator/nvs_partition_gen.py decrypt ../nvs_partition_generator/partition_encrypted.bin ../nvs_partition_generator/testdata/sample_encryption_keys.bin ../nvs_partition_generator/partition_decrypted.bin"); + CHECK(status == 0); + + status = system("diff ../nvs_partition_generator/partition_decrypted.bin ../nvs_partition_generator/partition_encoded.bin"); + CHECK(status == 0); + CHECK(WEXITSTATUS(status) == 0); + + + //cleaning up the temporary test data + status = system("rm -rf testdata"); + CHECK(status == 0); + +} + +TEST_CASE("test nvs apis for nvs partition generator utility with encryption enabled using keygen", "[nvs_part_gen]") +{ + int childpid = fork(); + int status; + + if (childpid == 0) { + exit(execlp("cp", " cp", + "-rf", + "../nvs_partition_generator/testdata", + ".",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + childpid = fork(); + + if (childpid == 0) { + exit(execlp("rm", " rm", + "-rf", + "../nvs_partition_generator/keys",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("python", "python", + "../nvs_partition_generator/nvs_partition_gen.py", + "encrypt", + "../nvs_partition_generator/sample_multipage_blob.csv", + "partition_encrypted_using_keygen.bin", + "0x4000", + "--keygen", + "--outdir", + "../nvs_partition_generator",NULL)); + + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + } + } + } + + + DIR *dir; + struct dirent *file; + char *filename; + char *files; + char *file_ext; + + dir = opendir("../nvs_partition_generator/keys"); + while ((file = readdir(dir)) != NULL) + { + filename = file->d_name; + files = strrchr(filename, '.'); + if (files != NULL) + { + file_ext = files+1; + if (strncmp(file_ext,"bin",3) == 0) + { + break; + } + } + } + + std::string encr_file = std::string("../nvs_partition_generator/keys/") + std::string(filename); + SpiFlashEmulator emu("../nvs_partition_generator/partition_encrypted_using_keygen.bin"); + + char buffer[64]; + FILE *fp; + + fp = fopen(encr_file.c_str(),"rb"); + fread(buffer,sizeof(buffer),1,fp); + + fclose(fp); + + nvs_sec_cfg_t cfg; + + for(int count = 0; count < NVS_KEY_SIZE; count++) { + cfg.eky[count] = buffer[count] & 255; + cfg.tky[count] = buffer[count+32] & 255; + } + + check_nvs_part_gen_args(&emu, NVS_DEFAULT_PART_NAME, 4, "../nvs_partition_generator/testdata/sample_multipage_blob.bin", true, &cfg); + } +TEST_CASE("test nvs apis for nvs partition generator utility with encryption enabled using inputkey", "[nvs_part_gen]") +{ + int childpid = fork(); + int status; + + DIR *dir; + struct dirent *file; + char *filename; + char *files; + char *file_ext; + + dir = opendir("../nvs_partition_generator/keys"); + while ((file = readdir(dir)) != NULL) + { + filename = file->d_name; + files = strrchr(filename, '.'); + if (files != NULL) + { + file_ext = files+1; + if (strncmp(file_ext,"bin",3) == 0) + { + break; + } + } + } + + std::string encr_file = std::string("../nvs_partition_generator/keys/") + std::string(filename); + + if (childpid == 0) { + exit(execlp("python", "python", + "../nvs_partition_generator/nvs_partition_gen.py", + "encrypt", + "../nvs_partition_generator/sample_multipage_blob.csv", + "partition_encrypted_using_keyfile.bin", + "0x4000", + "--inputkey", + encr_file.c_str(), + "--outdir", + "../nvs_partition_generator",NULL)); + + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + } + + SpiFlashEmulator emu("../nvs_partition_generator/partition_encrypted_using_keyfile.bin"); + + char buffer[64]; + FILE *fp; + + fp = fopen(encr_file.c_str(),"rb"); + fread(buffer,sizeof(buffer),1,fp); + + fclose(fp); + + nvs_sec_cfg_t cfg; + + for(int count = 0; count < NVS_KEY_SIZE; count++) { + cfg.eky[count] = buffer[count] & 255; + cfg.tky[count] = buffer[count+32] & 255; + } + + check_nvs_part_gen_args(&emu, NVS_DEFAULT_PART_NAME, 4, "../nvs_partition_generator/testdata/sample_multipage_blob.bin", true, &cfg); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("rm", " rm", + "-rf", + "../nvs_partition_generator/keys",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + childpid = fork(); + + if (childpid == 0) { + exit(execlp("rm", " rm", + "-rf", + "testdata",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + } + } + +} + +TEST_CASE("check and read data from partition generated via manufacturing utility with encryption enabled using sample inputkey", "[mfg_gen]") +{ + int childpid = fork(); + int status; + + if (childpid == 0) { + exit(execlp("bash", " bash", + "-c", + "rm -rf ../../../tools/mass_mfg/host_test | \ + cp -rf ../../../tools/mass_mfg/testdata mfg_testdata | \ + cp -rf ../nvs_partition_generator/testdata . | \ + mkdir -p ../../../tools/mass_mfg/host_test",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("python", "python", + "../../../tools/mass_mfg/mfg_gen.py", + "generate", + "../../../tools/mass_mfg/samples/sample_config.csv", + "../../../tools/mass_mfg/samples/sample_values_multipage_blob.csv", + "Test", + "0x4000", + "--outdir", + "../../../tools/mass_mfg/host_test", + "--version", + "2", + "--inputkey", + "mfg_testdata/sample_encryption_keys.bin",NULL)); + + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("python", "python", + "../nvs_partition_generator/nvs_partition_gen.py", + "encrypt", + "../../../tools/mass_mfg/host_test/csv/Test-1.csv", + "../nvs_partition_generator/Test-1-partition-encrypted.bin", + "0x4000", + "--version", + "2", + "--inputkey", + "testdata/sample_encryption_keys.bin",NULL)); + + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + } + + } + + } + + SpiFlashEmulator emu1("../../../tools/mass_mfg/host_test/bin/Test-1.bin"); + + nvs_sec_cfg_t cfg; + for(int count = 0; count < NVS_KEY_SIZE; count++) { + cfg.eky[count] = 0x11; + cfg.tky[count] = 0x22; + } + + check_nvs_part_gen_args(&emu1, NVS_DEFAULT_PART_NAME, 4, "mfg_testdata/sample_multipage_blob.bin", true, &cfg); + + SpiFlashEmulator emu2("../nvs_partition_generator/Test-1-partition-encrypted.bin"); + + check_nvs_part_gen_args(&emu2, NVS_DEFAULT_PART_NAME, 4, "testdata/sample_multipage_blob.bin", true, &cfg); + + + childpid = fork(); + if (childpid == 0) { + exit(execlp("bash", " bash", + "-c", + "rm -rf ../../../tools/mass_mfg/host_test | \ + rm -rf mfg_testdata | \ + rm -rf testdata",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + } + +} + +TEST_CASE("check and read data from partition generated via manufacturing utility with encryption enabled using new generated key", "[mfg_gen]") +{ + int childpid = fork(); + int status; + + if (childpid == 0) { + exit(execlp("bash", " bash", + "-c", + "rm -rf ../../../tools/mass_mfg/host_test | \ + cp -rf ../../../tools/mass_mfg/testdata mfg_testdata | \ + cp -rf ../nvs_partition_generator/testdata . | \ + mkdir -p ../../../tools/mass_mfg/host_test",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("python", "python", + "../../../tools/mass_mfg/mfg_gen.py", + "generate-key", + "--outdir", + "../../../tools/mass_mfg/host_test", + "--keyfile", + "encr_keys_host_test.bin",NULL)); + + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("python", "python", + "../../../tools/mass_mfg/mfg_gen.py", + "generate", + "../../../tools/mass_mfg/samples/sample_config.csv", + "../../../tools/mass_mfg/samples/sample_values_multipage_blob.csv", + "Test", + "0x4000", + "--outdir", + "../../../tools/mass_mfg/host_test", + "--version", + "2", + "--inputkey", + "../../../tools/mass_mfg/host_test/keys/encr_keys_host_test.bin",NULL)); + + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("python", "python", + "../nvs_partition_generator/nvs_partition_gen.py", + "encrypt", + "../../../tools/mass_mfg/host_test/csv/Test-1.csv", + "../nvs_partition_generator/Test-1-partition-encrypted.bin", + "0x4000", + "--version", + "2", + "--inputkey", + "../../../tools/mass_mfg/host_test/keys/encr_keys_host_test.bin",NULL)); + + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + } + + } + + } + + } + + + SpiFlashEmulator emu1("../../../tools/mass_mfg/host_test/bin/Test-1.bin"); + + char buffer[64]; + FILE *fp; + + fp = fopen("../../../tools/mass_mfg/host_test/keys/encr_keys_host_test.bin","rb"); + fread(buffer,sizeof(buffer),1,fp); + + fclose(fp); + + nvs_sec_cfg_t cfg; + + for(int count = 0; count < NVS_KEY_SIZE; count++) { + cfg.eky[count] = buffer[count] & 255; + cfg.tky[count] = buffer[count+32] & 255; + } + + check_nvs_part_gen_args(&emu1, NVS_DEFAULT_PART_NAME, 4, "mfg_testdata/sample_multipage_blob.bin", true, &cfg); + + SpiFlashEmulator emu2("../nvs_partition_generator/Test-1-partition-encrypted.bin"); + + check_nvs_part_gen_args(&emu2, NVS_DEFAULT_PART_NAME, 4, "testdata/sample_multipage_blob.bin", true, &cfg); + + childpid = fork(); + if (childpid == 0) { + exit(execlp("bash", " bash", + "-c", + "rm -rf keys | \ + rm -rf mfg_testdata | \ + rm -rf testdata | \ + rm -rf ../../../tools/mass_mfg/host_test",NULL)); + } else { + CHECK(childpid > 0); + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) == 0); + + } + +} +#endif + +/* Add new tests above */ +/* This test has to be the final one */ + TEST_CASE("dump all performance data", "[nvs]") { std::cout << "====================" << std::endl << "Dumping benchmarks" << std::endl; diff --git a/components/nvs_flash/test_nvs_host/test_nvs_cxx_api.cpp b/components/nvs_flash/test_nvs_host/test_nvs_cxx_api.cpp new file mode 100644 index 000000000..da1d006be --- /dev/null +++ b/components/nvs_flash/test_nvs_host/test_nvs_cxx_api.cpp @@ -0,0 +1,193 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "catch.hpp" +#include +#include +#include "nvs_test_api.h" +#include "nvs_handle_simple.hpp" +#include "nvs_partition_manager.hpp" +#include "spi_flash_emulation.h" + +#include "test_fixtures.hpp" + +#include + +using namespace std; + +TEST_CASE("NVSHandleSimple CXX api open invalid arguments", "[nvs cxx]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + PartitionEmulationFixture f(0, 10, "test"); + esp_err_t result; + shared_ptr handle; + + REQUIRE(nvs::NVSPartitionManager::get_instance()-> + init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) == ESP_OK); + + handle = nvs::open_nvs_handle_from_partition(nullptr, "ns_1", NVS_READWRITE, &result); + CHECK(result == ESP_ERR_INVALID_ARG); + CHECK(!handle); + + handle = nvs::open_nvs_handle_from_partition("test", nullptr, NVS_READWRITE, &result); + CHECK(result == ESP_ERR_INVALID_ARG); + CHECK(!handle); + + nvs::NVSPartitionManager::get_instance()->deinit_partition("test"); +} + +TEST_CASE("NVSHandleSimple CXX api open partition uninitialized", "[nvs cxx]") +{ + SpiFlashEmulator emu(10); + esp_err_t result; + shared_ptr handle; + + handle = nvs::open_nvs_handle_from_partition("test", "ns_1", NVS_READWRITE, &result); + bool result_expected = result == ESP_ERR_NVS_NOT_INITIALIZED || result == ESP_ERR_NVS_PART_NOT_FOUND; + CHECK(result_expected); + CHECK(!handle); +} + +TEST_CASE("NVSHandleSimple CXX api open successful", "[nvs cxx]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + PartitionEmulationFixture f(0, 10, "test"); + esp_err_t result; + shared_ptr handle; + + REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + + CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0); + + handle = nvs::open_nvs_handle_from_partition("test", "ns_1", NVS_READWRITE, &result); + CHECK(result == ESP_OK); + CHECK(handle); + + CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 1); + + handle.reset(); + + CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0); + + nvs::NVSPartitionManager::get_instance()->deinit_partition("test"); +} + +TEST_CASE("NVSHandleSimple CXX api open default part successful", "[nvs cxx]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + PartitionEmulationFixture f(0, 10); + esp_err_t result; + shared_ptr handle; + + REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + + CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0); + + handle = nvs::open_nvs_handle("ns_1", NVS_READWRITE, &result); + CHECK(result == ESP_OK); + CHECK(handle); + + CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 1); + + handle.reset(); + + CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0); + + nvs::NVSPartitionManager::get_instance()->deinit_partition("nvs"); +} + +TEST_CASE("NVSHandleSimple CXX api open default part ns NULL", "[nvs cxx]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + PartitionEmulationFixture f(0, 10); + esp_err_t result; + shared_ptr handle; + + REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + + CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0); + + handle = nvs::open_nvs_handle(nullptr, NVS_READWRITE, &result); + CHECK(result == ESP_ERR_INVALID_ARG); + CHECK(!handle); + + CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0); + + nvs::NVSPartitionManager::get_instance()->deinit_partition("nvs"); +} + +TEST_CASE("NVSHandleSimple CXX api read/write string", "[nvs cxx]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + PartitionEmulationFixture f(0, 10); + char read_buffer [256]; + esp_err_t result; + shared_ptr handle; + + REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + + CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0); + + handle = nvs::open_nvs_handle("test_ns", NVS_READWRITE, &result); + CHECK(result == ESP_OK); + REQUIRE(handle); + + CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 1); + + CHECK(handle->set_string("test", "test string") == ESP_OK); + CHECK(handle->commit() == ESP_OK); + CHECK(handle->get_string("test", read_buffer, sizeof(read_buffer)) == ESP_OK); + + CHECK(string(read_buffer) == "test string"); + + nvs::NVSPartitionManager::get_instance()->deinit_partition("nvs"); +} + +TEST_CASE("NVSHandleSimple CXX api read/write blob", "[nvs cxx]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + PartitionEmulationFixture f(0, 10); + const char blob [6] = {15, 16, 17, 18, 19}; + char read_blob[6] = {0}; + esp_err_t result; + shared_ptr handle; + + REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + + CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0); + + handle = nvs::open_nvs_handle("test_ns", NVS_READWRITE, &result); + CHECK(result == ESP_OK); + REQUIRE(handle); + + CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 1); + + CHECK(handle->set_blob("test", blob, sizeof(blob)) == ESP_OK); + CHECK(handle->commit() == ESP_OK); + CHECK(handle->get_blob("test", read_blob, sizeof(read_blob)) == ESP_OK); + + CHECK(vector(blob, blob + sizeof(blob)) == vector(read_blob, read_blob + sizeof(read_blob))); + + nvs::NVSPartitionManager::get_instance()->deinit_partition("nvs"); +} diff --git a/components/nvs_flash/test_nvs_host/test_nvs_handle.cpp b/components/nvs_flash/test_nvs_host/test_nvs_handle.cpp new file mode 100644 index 000000000..d9f709e7a --- /dev/null +++ b/components/nvs_flash/test_nvs_host/test_nvs_handle.cpp @@ -0,0 +1,281 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "catch.hpp" +#include +#include +#include "nvs_test_api.h" +#include "nvs_handle_simple.hpp" +#include "nvs_partition_manager.hpp" +#include "spi_flash_emulation.h" + +#include "test_fixtures.hpp" + +#include +#include + +using namespace std; +using namespace nvs; + +TEST_CASE("NVSHandleSimple closes its reference in PartitionManager", "[partition_mgr]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + PartitionEmulationFixture f(0, 10, "test"); + + REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + + CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 0); + + NVSHandleSimple *handle; + REQUIRE(NVSPartitionManager::get_instance()->open_handle("test", "ns_1", NVS_READWRITE, &handle) == ESP_OK); + + CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 1); + + delete handle; + + CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 0); + + REQUIRE(NVSPartitionManager::get_instance()->deinit_partition("test") == ESP_OK); + +} + +TEST_CASE("NVSHandleSimple multiple open and closes with PartitionManager", "[partition_mgr]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + PartitionEmulationFixture f(0, 10, "test"); + + REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + + CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 0); + + NVSHandleSimple *handle1; + NVSHandleSimple *handle2; + + REQUIRE(NVSPartitionManager::get_instance()->open_handle("test", "ns_1", NVS_READWRITE, &handle1) == ESP_OK); + + CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 1); + + REQUIRE(NVSPartitionManager::get_instance()->open_handle("test", "ns_1", NVS_READWRITE, &handle2) == ESP_OK); + + CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 2); + + delete handle1; + + CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 1); + + delete handle2; + + CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 0); + + REQUIRE(NVSPartitionManager::get_instance()->deinit_partition("test") == ESP_OK); + +} + +TEST_CASE("NVSHandleSimple readonly fails", "[partition_mgr]") +{ + PartitionEmulationFixture f(0, 10); + + NVSPartitionManager::get_instance()->deinit_partition(NVS_DEFAULT_PART_NAME); + NVSHandleSimple *handle_1; + NVSHandleSimple *handle_2; + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + CHECK(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) == ESP_OK); + CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 0); + + // first, creating namespace... + REQUIRE(NVSPartitionManager::get_instance()->open_handle(NVS_DEFAULT_PART_NAME, "ns_1", NVS_READWRITE, &handle_1) == ESP_OK); + CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 1); + + delete handle_1; + + CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 0); + REQUIRE(NVSPartitionManager::get_instance()->open_handle(NVS_DEFAULT_PART_NAME, "ns_1", NVS_READONLY, &handle_2) == ESP_OK); + CHECK(handle_2->set_item("key", 47) == ESP_ERR_NVS_READ_ONLY); + CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 1); + + delete handle_2; + + CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 0); + // without deinit it affects "nvs api tests" + CHECK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME) == ESP_OK); +} + +TEST_CASE("NVSHandleSimple set/get char", "[partition_mgr]") +{ + enum class TestEnum : char { + FOO = -1, + BEER, + BAR + }; + + PartitionEmulationFixture f(0, 10); + + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + + NVSHandleSimple *handle; + REQUIRE(NVSPartitionManager::get_instance()->open_handle(NVS_DEFAULT_PART_NAME, "ns_1", NVS_READWRITE, &handle) == ESP_OK); + + char test_e = 'a'; + char test_e_read = 'z'; + + CHECK(handle->set_item("key", test_e) == ESP_OK); + + CHECK(handle->get_item("key", test_e_read) == ESP_OK); + CHECK(test_e == test_e_read); + + delete handle; + + REQUIRE(NVSPartitionManager::get_instance()->deinit_partition(NVS_DEFAULT_PART_NAME) == ESP_OK); +} + +TEST_CASE("NVSHandleSimple correctly sets/gets int enum", "[partition_mgr]") +{ + enum class TestEnum : int { + FOO, + BAR + }; + + PartitionEmulationFixture f(0, 10); + + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + + NVSHandleSimple *handle; + REQUIRE(NVSPartitionManager::get_instance()->open_handle(NVS_DEFAULT_PART_NAME, "ns_1", NVS_READWRITE, &handle) == ESP_OK); + + TestEnum test_e = TestEnum::BAR; + TestEnum test_e_read = TestEnum::FOO; + + CHECK(handle->set_item("key", test_e) == ESP_OK); + + CHECK(handle->get_item("key", test_e_read) == ESP_OK); + CHECK(test_e == test_e_read); + + delete handle; + + REQUIRE(NVSPartitionManager::get_instance()->deinit_partition(NVS_DEFAULT_PART_NAME) == ESP_OK); +} + +TEST_CASE("NVSHandleSimple correctly sets/gets int enum with negative values", "[partition_mgr]") +{ + enum class TestEnum : int { + FOO = -1, + BEER, + BAR + }; + + PartitionEmulationFixture f(0, 10); + + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + + NVSHandleSimple *handle; + REQUIRE(NVSPartitionManager::get_instance()->open_handle(NVS_DEFAULT_PART_NAME, "ns_1", NVS_READWRITE, &handle) == ESP_OK); + + TestEnum test_e = TestEnum::FOO; + TestEnum test_e_read = TestEnum::BEER; + + CHECK(handle->set_item("key", test_e) == ESP_OK); + + CHECK(handle->get_item("key", test_e_read) == ESP_OK); + CHECK(test_e == test_e_read); + + delete handle; + + REQUIRE(NVSPartitionManager::get_instance()->deinit_partition(NVS_DEFAULT_PART_NAME) == ESP_OK); +} + +TEST_CASE("NVSHandleSimple correctly sets/gets uint8_t enum", "[partition_mgr]") +{ + enum class TestEnum : uint8_t { + FOO, + BAR + }; + + PartitionEmulationFixture f(0, 10); + + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + + NVSHandleSimple *handle; + REQUIRE(NVSPartitionManager::get_instance()->open_handle(NVS_DEFAULT_PART_NAME, "ns_1", NVS_READWRITE, &handle) == ESP_OK); + + TestEnum test_e = TestEnum::BAR; + TestEnum test_e_read = TestEnum::FOO; + + CHECK(handle->set_item("key", test_e) == ESP_OK); + + CHECK(handle->get_item("key", test_e_read) == ESP_OK); + CHECK(test_e == test_e_read); + + delete handle; + + REQUIRE(NVSPartitionManager::get_instance()->deinit_partition(NVS_DEFAULT_PART_NAME) == ESP_OK); +} + +TEST_CASE("NVSHandleSimple correctly sets/gets char enum", "[partition_mgr]") +{ + enum class TestEnum : char { + FOO = -1, + BEER, + BAR + }; + + PartitionEmulationFixture f(0, 10); + + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN); + + REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + + NVSHandleSimple *handle; + REQUIRE(NVSPartitionManager::get_instance()->open_handle(NVS_DEFAULT_PART_NAME, "ns_1", NVS_READWRITE, &handle) == ESP_OK); + + TestEnum test_e = TestEnum::BAR; + TestEnum test_e_read = TestEnum::FOO; + + CHECK(handle->set_item("key", test_e) == ESP_OK); + + CHECK(handle->get_item("key", test_e_read) == ESP_OK); + CHECK(test_e == test_e_read); + + delete handle; + + REQUIRE(NVSPartitionManager::get_instance()->deinit_partition(NVS_DEFAULT_PART_NAME) == ESP_OK); +} diff --git a/components/nvs_flash/test_nvs_host/test_nvs_initialization.cpp b/components/nvs_flash/test_nvs_host/test_nvs_initialization.cpp new file mode 100644 index 000000000..7731d1da5 --- /dev/null +++ b/components/nvs_flash/test_nvs_host/test_nvs_initialization.cpp @@ -0,0 +1,46 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "catch.hpp" +#include "nvs_partition_manager.hpp" +#include "spi_flash_emulation.h" +#include "esp_partition.h" +#include "nvs.h" +#include + +using namespace nvs; + +TEST_CASE("nvs_flash_init_partition_ptr fails due to nullptr arg", "[nvs_custom_part]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + SpiFlashEmulator emu(10); + + CHECK(nvs_flash_init_partition_ptr(nullptr) == ESP_ERR_INVALID_ARG); +} + +TEST_CASE("nvs_flash_init_partition_ptr inits one partition", "[nvs_custom_part]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + SpiFlashEmulator emu(10); + + esp_partition_t partition = {}; + strcpy(partition.label, "test"); + partition.address = NVS_FLASH_SECTOR * SPI_FLASH_SEC_SIZE; + partition.size = NVS_FLASH_SECTOR_COUNT_MIN * SPI_FLASH_SEC_SIZE; + + CHECK(nvs_flash_init_partition_ptr(&partition) == ESP_OK); + CHECK(NVSPartitionManager::get_instance()->lookup_storage_from_name("test") != nullptr); + CHECK(NVSPartitionManager::get_instance()->deinit_partition("test") == ESP_OK); +} diff --git a/components/nvs_flash/test_nvs_host/test_nvs_partition.cpp b/components/nvs_flash/test_nvs_host/test_nvs_partition.cpp new file mode 100644 index 000000000..4385b9a6d --- /dev/null +++ b/components/nvs_flash/test_nvs_host/test_nvs_partition.cpp @@ -0,0 +1,55 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "catch.hpp" +#include +#include +#include "nvs_test_api.h" +#include "nvs_handle_simple.hpp" +#include "nvs_partition.hpp" +#include "spi_flash_emulation.h" + +#include "test_fixtures.hpp" + +#include + +using namespace std; +using namespace nvs; + +TEST_CASE("encrypted partition read size must be item size", "[nvs]") +{ + char foo [32] = { }; + nvs_sec_cfg_t xts_cfg; + for(int count = 0; count < NVS_KEY_SIZE; count++) { + xts_cfg.eky[count] = 0x11; + xts_cfg.tky[count] = 0x22; + } + EncryptedPartitionFixture fix(&xts_cfg); + + CHECK(fix.part.read(0, foo, sizeof (foo) -1) == ESP_ERR_INVALID_SIZE); +} + +TEST_CASE("encrypted partition write size must be mod item size", "[nvs]") +{ + char foo [64] = { }; + nvs_sec_cfg_t xts_cfg; + for(int count = 0; count < NVS_KEY_SIZE; count++) { + xts_cfg.eky[count] = 0x11; + xts_cfg.tky[count] = 0x22; + } + EncryptedPartitionFixture fix(&xts_cfg); + + CHECK(fix.part.write(0, foo, sizeof (foo) -1) == ESP_ERR_INVALID_SIZE); + CHECK(fix.part.write(0, foo, sizeof (foo)) == ESP_OK); + CHECK(fix.part.write(0, foo, sizeof (foo) * 2) == ESP_OK); +} diff --git a/components/nvs_flash/test_nvs_host/test_nvs_storage.cpp b/components/nvs_flash/test_nvs_host/test_nvs_storage.cpp new file mode 100644 index 000000000..a0ace089c --- /dev/null +++ b/components/nvs_flash/test_nvs_host/test_nvs_storage.cpp @@ -0,0 +1,60 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "catch.hpp" +#include +#include "nvs_test_api.h" +#include "nvs_storage.hpp" +#include "nvs_partition_manager.hpp" +#include "spi_flash_emulation.h" + +#include "test_fixtures.hpp" + +#include + +using namespace std; +using namespace nvs; + +TEST_CASE("Storage iterator recognizes blob with VerOffset::VER_1_OFFSET", "[nvs_storage]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + PartitionEmulationFixture f(0, 10, "test"); + + REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + + uint8_t blob [] = {0x0, 0x1, 0x2, 0x3}; + uint8_t blob_new [] = {0x3, 0x2, 0x1, 0x0}; + Storage *storage = NVSPartitionManager::get_instance()->lookup_storage_from_name("test"); + uint8_t ns_index; + storage->createOrOpenNamespace("test_ns", true, ns_index); + + CHECK(storage->writeItem(ns_index, ItemType::BLOB, "test_blob", blob, sizeof(blob)) == ESP_OK); + + // changing provokes a blob with version offset 1 (VerOffset::VER_1_OFFSET) + CHECK(storage->writeItem(ns_index, ItemType::BLOB, "test_blob", blob_new, sizeof(blob_new)) == ESP_OK); + + nvs_opaque_iterator_t it; + it.storage = storage; + it.type = NVS_TYPE_ANY; + + // Central check: does the iterator recognize the blob with version 1? + REQUIRE(storage->findEntry(&it, "test_ns")); + + CHECK(string(it.entry_info.namespace_name) == string("test_ns")); + CHECK(string(it.entry_info.key) == string("test_blob")); + CHECK(it.entry_info.type == NVS_TYPE_BLOB); + + REQUIRE(NVSPartitionManager::get_instance()->deinit_partition("test") == ESP_OK); +} diff --git a/components/nvs_flash/test_nvs_host/test_partition_manager.cpp b/components/nvs_flash/test_nvs_host/test_partition_manager.cpp new file mode 100644 index 000000000..b2db3a9cf --- /dev/null +++ b/components/nvs_flash/test_nvs_host/test_partition_manager.cpp @@ -0,0 +1,91 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "catch.hpp" +#include +#include +#include "nvs_test_api.h" +#include "nvs_handle_simple.hpp" +#include "nvs_partition_manager.hpp" +#include "spi_flash_emulation.h" +#include "nvs_test_api.h" + +#include "test_fixtures.hpp" + +using namespace nvs; + +TEST_CASE("Partition manager initializes storage", "[partition_mgr]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + PartitionEmulationFixture f(0, 10, "test"); + + REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) == ESP_OK); + CHECK(NVSPartitionManager::get_instance()->lookup_storage_from_name("test") != nullptr); + REQUIRE(NVSPartitionManager::get_instance()->deinit_partition(f.part.get_partition_name()) == ESP_OK); +} + +TEST_CASE("Partition manager de-initializes storage", "[partition_mgr]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + PartitionEmulationFixture f(0, 10, "test"); + + REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) == ESP_OK); + CHECK(NVSPartitionManager::get_instance()->lookup_storage_from_name("test") != nullptr); + CHECK(NVSPartitionManager::get_instance()->deinit_partition("test") == ESP_OK); + CHECK(NVSPartitionManager::get_instance()->lookup_storage_from_name("test") == nullptr); +} + +TEST_CASE("Partition manager initializes multiple partitions", "[partition_mgr]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + SpiFlashEmulator emu(10); + PartitionEmulation part_0(&emu, NVS_FLASH_SECTOR * SPI_FLASH_SEC_SIZE, NVS_FLASH_SECTOR_COUNT_MIN * SPI_FLASH_SEC_SIZE, "test1"); + PartitionEmulation part_1(&emu, NVS_FLASH_SECTOR * SPI_FLASH_SEC_SIZE, NVS_FLASH_SECTOR_COUNT_MIN * SPI_FLASH_SEC_SIZE, "test2"); + + REQUIRE(NVSPartitionManager::get_instance()->init_custom(&part_0, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + // TODO: why does this work, actually? same sectors used as above + REQUIRE(NVSPartitionManager::get_instance()->init_custom(&part_1, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + Storage *storage1 = NVSPartitionManager::get_instance()->lookup_storage_from_name("test1"); + REQUIRE(storage1 != nullptr); + Storage *storage2 = NVSPartitionManager::get_instance()->lookup_storage_from_name("test2"); + REQUIRE(storage2 != nullptr); + + CHECK(storage1 != storage2); + REQUIRE(NVSPartitionManager::get_instance()->deinit_partition(part_0.get_partition_name()) == ESP_OK); + REQUIRE(NVSPartitionManager::get_instance()->deinit_partition(part_1.get_partition_name()) == ESP_OK); +} + +TEST_CASE("Partition manager invalidates handle on partition de-init", "[partition_mgr]") +{ + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3; + PartitionEmulationFixture f(0, 10, "test"); + + REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) + == ESP_OK); + + NVSHandleSimple *handle; + REQUIRE(NVSPartitionManager::get_instance()->open_handle("test", "ns_1", NVS_READWRITE, &handle) == ESP_OK); + CHECK(handle->erase_all() == ESP_OK); + + REQUIRE(NVSPartitionManager::get_instance()->deinit_partition("test") == ESP_OK); + + CHECK(handle->erase_all() == ESP_ERR_NVS_INVALID_HANDLE); + + delete handle; +} diff --git a/components/nvs_flash/test_nvs_host/test_spi_flash_emulation.cpp b/components/nvs_flash/test_nvs_host/test_spi_flash_emulation.cpp index 0c77aa966..353e1212a 100644 --- a/components/nvs_flash/test_nvs_host/test_spi_flash_emulation.cpp +++ b/components/nvs_flash/test_nvs_host/test_spi_flash_emulation.cpp @@ -13,7 +13,9 @@ // limitations under the License. #include "catch.hpp" #include "esp_spi_flash.h" +#include "esp_partition.h" #include "spi_flash_emulation.h" +#include using namespace std; @@ -23,14 +25,21 @@ bool range_empty_n(Tit it_begin, size_t n) return all_of(it_begin, it_begin + n, bind(equal_to(), placeholders::_1, 0xffffffff)); } +struct FlashEmuFixture { + FlashEmuFixture(size_t sectors) : esp_part(), emu(sectors) { } + + esp_partition_t esp_part; + SpiFlashEmulator emu; +}; + TEST_CASE("flash starts with all bytes == 0xff", "[spi_flash_emu]") { - SpiFlashEmulator emu(4); + FlashEmuFixture f(4); uint8_t sector[SPI_FLASH_SEC_SIZE]; for (int i = 0; i < 4; ++i) { - CHECK(spi_flash_read(0, sector, sizeof(sector)) == ESP_OK); + CHECK(esp_partition_read(&f.esp_part, 0, sector, sizeof(sector)) == ESP_OK); for (auto v: sector) { CHECK(v == 0xff); } @@ -39,116 +48,138 @@ TEST_CASE("flash starts with all bytes == 0xff", "[spi_flash_emu]") TEST_CASE("invalid writes are checked", "[spi_flash_emu]") { - SpiFlashEmulator emu(1); + FlashEmuFixture f(1); uint32_t val = 0; - CHECK(spi_flash_write(0, &val, 4) == ESP_OK); + CHECK(esp_partition_write(&f.esp_part, 0, &val, 4) == ESP_OK); val = 1; - CHECK(spi_flash_write(0, &val, 4) == ESP_ERR_FLASH_OP_FAIL); + CHECK(esp_partition_write(&f.esp_part, 0, &val, 4) == ESP_ERR_FLASH_OP_FAIL); } TEST_CASE("out of bounds writes fail", "[spi_flash_emu]") { - SpiFlashEmulator emu(4); + FlashEmuFixture f(4); uint32_t vals[8]; std::fill_n(vals, 8, 0); - CHECK(spi_flash_write(0, vals, sizeof(vals)) == ESP_OK); + CHECK(esp_partition_write(&f.esp_part, 0, &vals, sizeof(vals)) == ESP_OK); - CHECK(spi_flash_write(4*4096 - sizeof(vals), vals, sizeof(vals)) == ESP_OK); + CHECK(esp_partition_write(&f.esp_part, 4*4096 - sizeof(vals), &vals, sizeof(vals)) == ESP_OK); - CHECK(spi_flash_write(4*4096 - sizeof(vals) + 4, vals, sizeof(vals)) == ESP_ERR_FLASH_OP_FAIL); + CHECK(esp_partition_write(&f.esp_part, 4*4096 - sizeof(vals) + 4, &vals, sizeof(vals)) == ESP_ERR_FLASH_OP_FAIL); } - TEST_CASE("after erase the sector is set to 0xff", "[spi_flash_emu]") { - SpiFlashEmulator emu(4); + FlashEmuFixture f(4); uint32_t val1 = 0xab00cd12; - CHECK(spi_flash_write(0, &val1, sizeof(val1)) == ESP_OK); + CHECK(esp_partition_write(&f.esp_part, 0, &val1, sizeof(val1)) == ESP_OK); uint32_t val2 = 0x5678efab; - CHECK(spi_flash_write(4096 - 4, &val2, sizeof(val2)) == ESP_OK); + CHECK(esp_partition_write(&f.esp_part, 4096 - 4, &val2, sizeof(val2)) == ESP_OK); + + CHECK(f.emu.words()[0] == val1); + CHECK(range_empty_n(f.emu.words() + 1, 4096 / 4 - 2)); + CHECK(f.emu.words()[4096 / 4 - 1] == val2); + + CHECK(esp_partition_erase_range(&f.esp_part, 0, SPI_FLASH_SEC_SIZE) == ESP_OK); + + CHECK(f.emu.words()[0] == 0xffffffff); + CHECK(range_empty_n(f.emu.words() + 1, 4096 / 4 - 2)); + CHECK(f.emu.words()[4096 / 4 - 1] == 0xffffffff); +} + +TEST_CASE("EMU raw read function works", "[spi_flash_emu]") +{ + FlashEmuFixture f(4); + uint32_t value = 0xdeadbeef; + uint32_t read_value = 0; + CHECK(esp_partition_write(&f.esp_part, 0, &value, sizeof(value)) == ESP_OK); + + CHECK(esp_partition_read(&f.esp_part, 0, &read_value, sizeof(&read_value)) == ESP_OK); + + CHECK(read_value == 0xdeadbeef); +} - CHECK(emu.words()[0] == val1); - CHECK(range_empty_n(emu.words() + 1, 4096 / 4 - 2)); - CHECK(emu.words()[4096 / 4 - 1] == val2); +TEST_CASE("EMU raw write function works", "[spi_flash_emu]") +{ + FlashEmuFixture f(4); + uint32_t value = 0xdeadbeef; + uint32_t read_value = 0; + CHECK(esp_partition_write(&f.esp_part, 0, &value, sizeof(value)) == ESP_OK); - CHECK(spi_flash_erase_sector(0) == ESP_OK); + CHECK(esp_partition_read(&f.esp_part, 0, &read_value, sizeof(&read_value)) == ESP_OK); - CHECK(emu.words()[0] == 0xffffffff); - CHECK(range_empty_n(emu.words() + 1, 4096 / 4 - 2)); - CHECK(emu.words()[4096 / 4 - 1] == 0xffffffff); + CHECK(read_value == 0xdeadbeef); } TEST_CASE("read/write/erase operation times are calculated correctly", "[spi_flash_emu]") { - SpiFlashEmulator emu(1); + FlashEmuFixture f(1); uint8_t data[512]; - spi_flash_read(0, data, 4); - CHECK(emu.getTotalTime() == 7); - CHECK(emu.getReadOps() == 1); - CHECK(emu.getReadBytes() == 4); - emu.clearStats(); - spi_flash_read(0, data, 8); - CHECK(emu.getTotalTime() == 5); - CHECK(emu.getReadOps() == 1); - CHECK(emu.getReadBytes() == 8); - emu.clearStats(); - spi_flash_read(0, data, 16); - CHECK(emu.getTotalTime() == 6); - CHECK(emu.getReadOps() == 1); - CHECK(emu.getReadBytes() == 16); - emu.clearStats(); - spi_flash_read(0, data, 128); - CHECK(emu.getTotalTime() == 18); - CHECK(emu.getReadOps() == 1); - CHECK(emu.getReadBytes() == 128); - emu.clearStats(); - spi_flash_read(0, data, 256); - CHECK(emu.getTotalTime() == 32); - emu.clearStats(); - spi_flash_read(0, data, (128+256)/2); - CHECK(emu.getTotalTime() == (18+32)/2); - emu.clearStats(); - - spi_flash_write(0, data, 4); - CHECK(emu.getTotalTime() == 19); - CHECK(emu.getWriteOps() == 1); - CHECK(emu.getWriteBytes() == 4); - emu.clearStats(); - CHECK(emu.getWriteOps() == 0); - CHECK(emu.getWriteBytes() == 0); - spi_flash_write(0, data, 8); - CHECK(emu.getTotalTime() == 23); - emu.clearStats(); - spi_flash_write(0, data, 16); - CHECK(emu.getTotalTime() == 35); - CHECK(emu.getWriteOps() == 1); - CHECK(emu.getWriteBytes() == 16); - emu.clearStats(); - spi_flash_write(0, data, 128); - CHECK(emu.getTotalTime() == 205); - emu.clearStats(); - spi_flash_write(0, data, 256); - CHECK(emu.getTotalTime() == 417); - emu.clearStats(); - spi_flash_write(0, data, (128+256)/2); - CHECK(emu.getTotalTime() == (205+417)/2); - emu.clearStats(); - - spi_flash_erase_sector(0); - CHECK(emu.getEraseOps() == 1); - CHECK(emu.getTotalTime() == 37142); + esp_partition_read(&f.esp_part, 0, data, 4); + CHECK(f.emu.getTotalTime() == 7); + CHECK(f.emu.getReadOps() == 1); + CHECK(f.emu.getReadBytes() == 4); + f.emu.clearStats(); + esp_partition_read(&f.esp_part, 0, data, 8); + CHECK(f.emu.getTotalTime() == 5); + CHECK(f.emu.getReadOps() == 1); + CHECK(f.emu.getReadBytes() == 8); + f.emu.clearStats(); + esp_partition_read(&f.esp_part, 0, data, 16); + CHECK(f.emu.getTotalTime() == 6); + CHECK(f.emu.getReadOps() == 1); + CHECK(f.emu.getReadBytes() == 16); + f.emu.clearStats(); + esp_partition_read(&f.esp_part, 0, data, 128); + CHECK(f.emu.getTotalTime() == 18); + CHECK(f.emu.getReadOps() == 1); + CHECK(f.emu.getReadBytes() == 128); + f.emu.clearStats(); + esp_partition_read(&f.esp_part, 0, data, 256); + CHECK(f.emu.getTotalTime() == 32); + f.emu.clearStats(); + esp_partition_read(&f.esp_part, 0, data, (128+256)/2); + CHECK(f.emu.getTotalTime() == (18+32)/2); + f.emu.clearStats(); + + esp_partition_write(&f.esp_part, 0, data, 4); + CHECK(f.emu.getTotalTime() == 19); + CHECK(f.emu.getWriteOps() == 1); + CHECK(f.emu.getWriteBytes() == 4); + f.emu.clearStats(); + CHECK(f.emu.getWriteOps() == 0); + CHECK(f.emu.getWriteBytes() == 0); + esp_partition_write(&f.esp_part, 0, data, 8); + CHECK(f.emu.getTotalTime() == 23); + f.emu.clearStats(); + esp_partition_write(&f.esp_part, 0, data, 16); + CHECK(f.emu.getTotalTime() == 35); + CHECK(f.emu.getWriteOps() == 1); + CHECK(f.emu.getWriteBytes() == 16); + f.emu.clearStats(); + esp_partition_write(&f.esp_part, 0, data, 128); + CHECK(f.emu.getTotalTime() == 205); + f.emu.clearStats(); + esp_partition_write(&f.esp_part, 0, data, 256); + CHECK(f.emu.getTotalTime() == 417); + f.emu.clearStats(); + esp_partition_write(&f.esp_part, 0, data, (128+256)/2); + CHECK(f.emu.getTotalTime() == (205+417)/2); + f.emu.clearStats(); + + esp_partition_erase_range(&f.esp_part, 0, SPI_FLASH_SEC_SIZE); + CHECK(f.emu.getEraseOps() == 1); + CHECK(f.emu.getTotalTime() == 37142); } TEST_CASE("data is randomized predictably", "[spi_flash_emu]") { SpiFlashEmulator emu1(3); emu1.randomize(0x12345678); - + SpiFlashEmulator emu2(3); emu2.randomize(0x12345678); - + CHECK(std::equal(emu1.bytes(), emu1.bytes() + emu1.size(), emu2.bytes())); } - diff --git a/components/openssl/Kconfig b/components/openssl/Kconfig index 0df49080c..4b6de5d5c 100644 --- a/components/openssl/Kconfig +++ b/components/openssl/Kconfig @@ -1,5 +1,5 @@ -menu "OpenSSL" - +menu "OpenSSL (Not Support mbedtls V3.x)" + depends on !MBEDTLS_V3 config OPENSSL_DEBUG bool "Enable OpenSSL debugging" default n diff --git a/components/openssl/platform/ssl_pm.c b/components/openssl/platform/ssl_pm.c index 1448faa4e..90df8a225 100644 --- a/components/openssl/platform/ssl_pm.c +++ b/components/openssl/platform/ssl_pm.c @@ -26,6 +26,12 @@ #include "mbedtls/certs.h" #define X509_INFO_STRING_LENGTH 8192 +#if defined(CONFIG_MBEDTLS_V3) +// Only for compliation, not work +#define MBEDTLS_SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ +#endif struct ssl_pm { @@ -261,7 +267,7 @@ static int mbedtls_handshake( mbedtls_ssl_context *ssl ) { int ret = 0; - while (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { + while (ssl->MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) { ret = mbedtls_ssl_handshake_step(ssl); SSL_DEBUG(SSL_PLATFORM_DEBUG_LEVEL, "ssl ret %d state %d", ret, ssl->state); @@ -391,7 +397,7 @@ OSSL_HANDSHAKE_STATE ssl_pm_get_state(const SSL *ssl) struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm; - switch (ssl_pm->ssl.state) + switch (ssl_pm->ssl.MBEDTLS_PRIVATE(state)) { case MBEDTLS_SSL_CLIENT_HELLO: state = TLS_ST_CW_CLNT_HELLO; @@ -426,9 +432,11 @@ OSSL_HANDSHAKE_STATE ssl_pm_get_state(const SSL *ssl) case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: state = TLS_ST_SR_KEY_EXCH; break; +#if !defined(CONFIG_MBEDTLS_V3) case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET: state = TLS_ST_SW_SESSION_TICKET; break; +#endif case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: state = TLS_ST_SW_CERT_REQ; break; @@ -605,6 +613,14 @@ void pkey_pm_free(EVP_PKEY *pk) pk->pkey_pm = NULL; } +#if defined(CONFIG_MBEDTLS_V3) +static int mbedtls_ctr_drbg_random_fake(void *p_rng, unsigned char *output, + size_t output_len) +{ + return 0; +} +#endif + int pkey_pm_load(EVP_PKEY *pk, const unsigned char *buffer, int len) { int ret; @@ -632,8 +648,12 @@ int pkey_pm_load(EVP_PKEY *pk, const unsigned char *buffer, int len) load_buf[len] = '\0'; mbedtls_pk_init(pkey_pm->pkey); - +#if defined(CONFIG_MBEDTLS_V3) + ret = mbedtls_pk_parse_key(pkey_pm->pkey, load_buf, len + 1, NULL, 0, + mbedtls_ctr_drbg_random_fake, NULL); +#else ret = mbedtls_pk_parse_key(pkey_pm->pkey, load_buf, len + 1, NULL, 0); +#endif ssl_mem_free(load_buf); if (ret) { diff --git a/components/spi_flash/CMakeLists.txt b/components/spi_flash/CMakeLists.txt index b2a0f715c..7b6adf802 100644 --- a/components/spi_flash/CMakeLists.txt +++ b/components/spi_flash/CMakeLists.txt @@ -5,6 +5,18 @@ if(BOOTLOADER_BUILD) set(srcs "${srcs}" "port/port.c") set(priv_requires "bootloader_support") else() + + if (CONFIG_ENABLE_SPI_FLASH_PATCH) + list(APPEND srcs "src/patch/common.c") + if(CONFIG_ENABLE_TH25Q16HB_PATCH_0) + list(APPEND srcs "src/patch/th25q16hb.c") + endif() + + if(CONFIG_ENABLE_FM25Q16A_PATCH_0) + list(APPEND srcs "src/patch/fm25q16a.c") + endif() + endif() + set(priv_requires "esp8266" "freertos" "bootloader_support") endif() diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig new file mode 100644 index 000000000..1ab135ce2 --- /dev/null +++ b/components/spi_flash/Kconfig @@ -0,0 +1,31 @@ +menu "SPI Flash" + + menu "Patch" + config ENABLE_SPI_FLASH_PATCH + bool "Enable SPI Flash Patch" + default n + + config ENABLE_TH25Q16HB_PATCH_0 + bool "Enable TH25Q16HB Patch 0" + depends on ENABLE_SPI_FLASH_PATCH + default n + help + WARNING: If you don't use TH25Q16HB, you must not enable this option. + Although you use TH25Q16HB, you should ask your flash manufacturer + if your flash need use this patch. + + config ENABLE_FM25Q16A_PATCH_0 + bool "Enable FM25Q16A Patch 0" + depends on ENABLE_SPI_FLASH_PATCH + default n + help + WARNING: If you don't use FM25Q16A, you must not enable this option. + Although you use FM25Q16A, you should ask your flash manufacturer + if your flash need use this patch. + + config ENABLE_SPI_FLASH_PATCH_DEBUG + bool "Enable SPI flash patch debug" + depends on ENABLE_SPI_FLASH_PATCH + default n + endmenu +endmenu diff --git a/components/spi_flash/component.mk b/components/spi_flash/component.mk index f5eb97ca6..6e574d959 100644 --- a/components/spi_flash/component.mk +++ b/components/spi_flash/component.mk @@ -15,4 +15,15 @@ CFLAGS += -DPARTITION_QUEUE_HEADER=\"sys/queue.h\" ifdef IS_BOOTLOADER_BUILD COMPONENT_SRCDIRS += port COMPONENT_OBJS += port/port.o +else +ifdef CONFIG_ENABLE_SPI_FLASH_PATCH +COMPONENT_SRCDIRS += src/patch +ifdef CONFIG_ENABLE_TH25Q16HB_PATCH_0 +COMPONENT_SRCDIRS += src/patch/th25q16hb.c +endif + +ifdef CONFIG_ENABLE_FM25Q16A_PATCH_0 +COMPONENT_SRCDIRS += src/patch/fm25q16a.c" +endif +endif endif diff --git a/components/spi_flash/include/spi_flash.h b/components/spi_flash/include/spi_flash.h index d51756d72..13e10f09a 100644 --- a/components/spi_flash/include/spi_flash.h +++ b/components/spi_flash/include/spi_flash.h @@ -204,6 +204,19 @@ int esp_patition_table_init_data(void *partition_info); int esp_patition_copy_ota1_to_ota0(const void *partition_info); #endif +#ifdef CONFIG_ENABLE_TH25Q16HB_PATCH_0 +/** + * @brief Apply TH25Q16HB patch 0 to avoid some hardware issues. + * + * @return 0 if success or others if failed + */ +int th25q16hb_apply_patch_0(void); +#endif + +#ifdef CONFIG_ENABLE_FM25Q16A_PATCH_0 +int fm25q16a_apply_patch_0(); +#endif + #ifdef __cplusplus } #endif diff --git a/components/spi_flash/linker.lf b/components/spi_flash/linker.lf index 9ac365ea5..27695eb70 100644 --- a/components/spi_flash/linker.lf +++ b/components/spi_flash/linker.lf @@ -2,3 +2,4 @@ archive: libspi_flash.a entries: spi_flash_raw (noflash) + th25q16hb (noflash) diff --git a/components/spi_flash/src/patch/common.c b/components/spi_flash/src/patch/common.c new file mode 100644 index 000000000..cc00d9428 --- /dev/null +++ b/components/spi_flash/src/patch/common.c @@ -0,0 +1,219 @@ +// Copyright 2023 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include "esp_log.h" +#include "esp_attr.h" +#include "spi_flash.h" +#include "priv/esp_spi_flash_raw.h" +#include "FreeRTOS.h" + +#include "esp8266/eagle_soc.h" +#include "esp8266/pin_mux_register.h" +#include "esp8266/spi_register.h" +#include "esp8266/spi_struct.h" + +#include "driver/gpio.h" +#include "esp_attr.h" + +#include "spi_flash_patch.h" + +#define SPI_FLASH SPI0 +#define SPI_BLOCK_SIZE 32 +#define ADDR_SHIFT_BITS 8 + +extern void Cache_Read_Disable_2(void); +extern void Cache_Read_Enable_2(); +extern void vPortEnterCritical(void); +extern void vPortExitCritical(void); + +void FLASH_PATCH_TEXT_ATTR patch_delay(int ms) +{ + for (volatile int i = 0; i < ms; i++) { + for (volatile int j = 0; j < 7800; j++) { + } + } +} + +void FLASH_PATCH_TEXT_ATTR spi_enter(spi_state_t *state) +{ + vPortEnterCritical(); + Cache_Read_Disable_2(); + + Wait_SPI_Idle(&g_rom_flashchip); + + state->io_mux_reg = READ_PERI_REG(PERIPHS_IO_MUX_CONF_U); + state->spi_clk_reg = SPI_FLASH.clock.val; + state->spi_ctrl_reg = SPI_FLASH.ctrl.val; + state->spi_user_reg = SPI_FLASH.user.val; + + SPI_FLASH.user.usr_command = 1; + SPI_FLASH.user.flash_mode = 0; + SPI_FLASH.user.usr_miso_highpart = 0; + + CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYS_CLK); + + SPI_FLASH.user.cs_setup = 1; + SPI_FLASH.user.cs_hold = 1; + SPI_FLASH.user.usr_mosi = 1; + + SPI_FLASH.user.usr_command = 1; + SPI_FLASH.user.flash_mode = 0; + + SPI_FLASH.ctrl.fread_qio = 0; + SPI_FLASH.ctrl.fread_dio = 0; + SPI_FLASH.ctrl.fread_quad = 0; + SPI_FLASH.ctrl.fread_dual = 0; + + SPI_FLASH.clock.val = 0; + SPI_FLASH.clock.clkcnt_l = 3; + SPI_FLASH.clock.clkcnt_h = 1; + SPI_FLASH.clock.clkcnt_n = 3; + + SPI_FLASH.ctrl.fastrd_mode = 1; + + while (SPI_FLASH.cmd.usr) { + ; + } +} + +void FLASH_PATCH_TEXT_ATTR spi_exit(spi_state_t *state) +{ + while (SPI_FLASH.cmd.usr) { + ; + } + + WRITE_PERI_REG(PERIPHS_IO_MUX_CONF_U, state->io_mux_reg); + + SPI_FLASH.ctrl.val = state->spi_ctrl_reg; + SPI_FLASH.clock.val = state->spi_clk_reg; + SPI_FLASH.user.val = state->spi_user_reg; + + Cache_Read_Enable_2(); + vPortExitCritical(); + patch_delay(1); +} + +static void FLASH_PATCH_TEXT_ATTR spi_trans_block(bool write_mode, + uint32_t cmd, + uint32_t cmd_bits, + uint32_t addr, + uint32_t addr_bits, + uint8_t *data, + uint32_t data_bytes, + uint32_t dummy_bits) +{ + if ((uint32_t)data & 0x3) { + ROM_PRINTF(FLASH_PATCH_STR("ERROR: data=%p\n"), data); + return; + } + + if (cmd_bits) { + SPI_FLASH.user.usr_command = 1; + SPI_FLASH.user2.usr_command_value = cmd; + SPI_FLASH.user2.usr_command_bitlen = cmd_bits - 1; + } else { + SPI_FLASH.user.usr_command = 0; + SPI_FLASH.user2.usr_command_bitlen = 0; + } + + if (addr_bits) { + SPI_FLASH.user.usr_addr = 1; + SPI_FLASH.addr = addr << ADDR_SHIFT_BITS; + SPI_FLASH.user1.usr_addr_bitlen = addr_bits - 1; + } else { + SPI_FLASH.user.usr_addr = 0; + SPI_FLASH.user1.usr_addr_bitlen = 0; + } + + if (dummy_bits) { + SPI_FLASH.user.usr_dummy = 1; + SPI_FLASH.user1.usr_dummy_cyclelen = dummy_bits - 1; + } else { + SPI_FLASH.user.usr_dummy = 0; + SPI_FLASH.user1.usr_dummy_cyclelen = 0; + } + + if (data_bytes) { + if (write_mode) { + int words = (data_bytes + 3) / 4; + uint32_t *p = (uint32_t *)data; + + SPI_FLASH.user.usr_mosi = 1; + SPI_FLASH.user.usr_miso = 0; + SPI_FLASH.user1.usr_mosi_bitlen = data_bytes * 8 - 1; + SPI_FLASH.user1.usr_miso_bitlen = 0; + for (int i = 0; i < words; i++) { + SPI_FLASH.data_buf[i] = p[i]; + } + } else { + int words = (data_bytes + 3) / 4; + + SPI_FLASH.user.usr_mosi = 0; + SPI_FLASH.user.usr_miso = 1; + SPI_FLASH.user1.usr_miso_bitlen = data_bytes * 8 - 1; + SPI_FLASH.user1.usr_mosi_bitlen = 0; + + for (int i = 0; i < words; i++) { + SPI_FLASH.data_buf[i] = 0; + } + } + } else { + SPI_FLASH.user.usr_mosi = 0; + SPI_FLASH.user1.usr_mosi_bitlen = 0; + SPI_FLASH.user.usr_miso = 0; + SPI_FLASH.user1.usr_miso_bitlen = 0; + } + + SPI_FLASH.cmd.usr = 1; + while (SPI_FLASH.cmd.usr) { + ; + } + + if (!write_mode && data_bytes) { + int words = (data_bytes + 3) / 4; + uint32_t *p = (uint32_t *)data; + + for (int i = 0; i < words; i++) { + p[i] = SPI_FLASH.data_buf[i]; + } + } +} + +void FLASH_PATCH_TEXT_ATTR spi_trans(bool write_mode, + uint32_t cmd, + uint32_t cmd_bits, + uint32_t addr, + uint32_t addr_bits, + uint8_t *data, + uint32_t data_bytes, + uint32_t dummy_bits) + +{ + if (!data_bytes || data_bytes <= SPI_BLOCK_SIZE) { + return spi_trans_block(write_mode, cmd, cmd_bits, addr, + addr_bits, data, data_bytes, dummy_bits); + } + + for (int i = 0; i < data_bytes; i += SPI_BLOCK_SIZE) { + uint32_t n = MIN(SPI_BLOCK_SIZE, data_bytes - i); + + spi_trans_block(write_mode, cmd, cmd_bits, addr + i, + addr_bits, data + i, n, dummy_bits); + } +} diff --git a/components/spi_flash/src/patch/fm25q16a.c b/components/spi_flash/src/patch/fm25q16a.c new file mode 100644 index 000000000..81406d86d --- /dev/null +++ b/components/spi_flash/src/patch/fm25q16a.c @@ -0,0 +1,659 @@ +// Copyright 2023 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include "esp_log.h" +#include "esp_attr.h" +#include "spi_flash.h" +#include "priv/esp_spi_flash_raw.h" +#include "FreeRTOS.h" + +#include "esp8266/eagle_soc.h" +#include "esp8266/pin_mux_register.h" +#include "esp8266/spi_register.h" +#include "esp8266/spi_struct.h" +#include "driver/gpio.h" +#include "spi_flash_patch.h" + +#define DEBUG(fmt,...) fm_printf(fmt, ##__VA_ARGS__) +#define INFO(fmt,...) fm_printf(fmt, ##__VA_ARGS__) +#define ERROR(fmt,...) fm_printf(fmt, ##__VA_ARGS__) + +#ifndef IRAM_FUNC_ATTR +#define IRAM_FUNC_ATTR +#endif + +#define fm_printf ROM_PRINTF + +extern bool IRAM_FUNC_ATTR spi_user_cmd(spi_cmd_dir_t mode, spi_cmd_t *p_cmd); +extern uint32_t IRAM_FUNC_ATTR spi_flash_get_id(void); + +static bool FLASH_PATCH_TEXT_ATTR double_check_fm25q16a(void); + +static void FLASH_PATCH_TEXT_ATTR fm_send_spi_cmd(uint8_t cmd, uint8_t cmd_len, uint32_t addr, uint8_t addr_len, const void* mosi_data, int mosi_len, void* miso_data, int miso_len, uint8_t dummy_bits) +{ + bool write_mode = false; + uint32_t data_bytes = 0; + + if (mosi_len > 0) { + write_mode = true; + data_bytes = mosi_len / 8; + } else if (miso_len > 0) { + write_mode = false; + data_bytes = miso_len / 8; + } + uint32_t data[(data_bytes+3)/4]; + if (write_mode && mosi_data) { + memcpy(data, mosi_data, data_bytes); + } + + spi_trans(write_mode, cmd, cmd_len, addr, addr_len, (uint8_t *)data, data_bytes, dummy_bits); + + if (!write_mode && miso_data) { + memcpy(miso_data, data, data_bytes); + } +} + +static void FLASH_PATCH_TEXT_ATTR fm_cam_cmd_start() +{ + fm_send_spi_cmd(0x66, 1*8, 0, 0, NULL, 0, NULL, 0, 0); + fm_send_spi_cmd(0x3C, 1*8, 0, 0, NULL, 0, NULL, 0, 0); + fm_send_spi_cmd(0xC3, 1*8, 0, 0, NULL, 0, NULL, 0, 0); +} + +static void FLASH_PATCH_TEXT_ATTR fm_cam_cmd_end() +{ + fm_send_spi_cmd(0xff, 1*8, 0, 0, NULL, 0, NULL, 0, 0); +} + +static void FLASH_PATCH_TEXT_ATTR fm_cam_pre_cmd_generic(uint8_t (*send_list)[5], int lines) +{ + int i; + fm_cam_cmd_start(); + for(i = 0; i < lines; i++) { + fm_send_spi_cmd(0x0, 0, 0, 0, &send_list[i][0], 5*8, NULL, 0, 0); + } + + fm_cam_cmd_end(); +} + +static const uint8_t FLASH_PATCH_RODATA_ATTR read_after_erase_pre_send_list[7][5] = { + {0x32,0x00,0x03,0xc0,0x88}, + {0x32,0x00,0x00,0x80,0x01}, + {0x32,0x00,0x00,0x84,0x47}, + {0x32,0x00,0x00,0x88,0x47}, + {0x32,0x00,0x00,0x8c,0x04}, + {0x32,0x00,0x00,0x90,0x19}, + {0x32,0x00,0x00,0x94,0x03}, +}; + +static void FLASH_PATCH_TEXT_ATTR fm_cam_read_after_erase_pre(void) +{ + // cmd NO.7 in the doc + uint8_t send_list[7][5]; + + memcpy(send_list, read_after_erase_pre_send_list, 7 * 5); + + fm_cam_pre_cmd_generic(send_list, sizeof(send_list) / sizeof(send_list[0])); +} + +static const uint8_t FLASH_PATCH_RODATA_ATTR step_prog_pre_send_list[8][5] = { + {0x32,0x00,0x03,0xc0,0x88}, + {0x32,0x00,0x00,0x64,0xb7}, + {0x32,0x00,0x00,0x80,0x13}, + {0x32,0x00,0x00,0x84,0x4f}, + {0x32,0x00,0x00,0x88,0x78}, + {0x32,0x00,0x00,0x8c,0x10}, + {0x32,0x00,0x00,0x90,0x40}, + {0x32,0x00,0x00,0x94,0xff}, +}; + +static void FLASH_PATCH_TEXT_ATTR fm_cam_step_prog_pre(void) +{ + // cmd NO.6 in the doc + uint8_t send_list[8][5]; + + memcpy(send_list, step_prog_pre_send_list, 8 * 5); + + fm_cam_pre_cmd_generic(send_list, sizeof(send_list) / sizeof(send_list[0])); +} + +static const uint8_t FLASH_PATCH_RODATA_ATTR step_erase_pre_send_list[8][5] = { + {0x32,0x00,0x00,0x64,0x77}, + {0x32,0x00,0x03,0xc0,0x88}, + {0x32,0x00,0x00,0x80,0x01}, + {0x32,0x00,0x00,0x84,0x46}, + {0x32,0x00,0x00,0x88,0x7e}, + {0x32,0x00,0x00,0x8c,0x06}, + {0x32,0x00,0x00,0x90,0x31}, + {0x32,0x00,0x00,0x94,0x01}, +}; + +static void FLASH_PATCH_TEXT_ATTR fm_cam_step_erase_pre(void) +{ + // cmd NO.5 in the doc + uint8_t send_list[8][5]; + + memcpy(send_list, step_erase_pre_send_list, 8 * 5); + + fm_cam_pre_cmd_generic(send_list, sizeof(send_list) / sizeof(send_list[0])); +} + +static const uint8_t FLASH_PATCH_RODATA_ATTR preprog_pre_send_list[8][5] = { + {0x32,0x00,0x03,0xc0,0x88}, + {0x32,0x00,0x00,0x64,0xf1}, + {0x32,0x00,0x00,0x80,0x53}, + {0x32,0x00,0x00,0x84,0x5c}, + {0x32,0x00,0x00,0x88,0x7c}, + {0x32,0x00,0x00,0x8c,0x04}, + {0x32,0x00,0x00,0x90,0x1f}, + {0x32,0x00,0x00,0x94,0xff}, +}; + +static void FLASH_PATCH_TEXT_ATTR fm_cam_preprog_pre(void) +{ + // cmd NO.4 in the doc + uint8_t send_list[8][5]; + + memcpy(send_list, preprog_pre_send_list, 8 * 5); + + fm_cam_pre_cmd_generic(send_list, sizeof(send_list) / sizeof(send_list[0])); +} + +static const uint8_t FLASH_PATCH_RODATA_ATTR prog_pre_send_list[7][5] = { + {0x32,0x00,0x03,0xc0,0x88}, + {0x32,0x00,0x00,0x80,0x53}, + {0x32,0x00,0x00,0x84,0x7c}, + {0x32,0x00,0x00,0x88,0x7f}, + {0x32,0x00,0x00,0x8c,0x10}, + {0x32,0x00,0x00,0x90,0xff}, + {0x32,0x00,0x00,0x94,0xff}, +}; + +static void FLASH_PATCH_TEXT_ATTR fm_cam_prog_pre(void) +{ + // cmd NO.3 in the doc + uint8_t send_list[7][5]; + + memcpy(send_list, prog_pre_send_list, 7 * 5); + + fm_cam_pre_cmd_generic(send_list, sizeof(send_list) / sizeof(send_list[0])); +} + +static const uint8_t FLASH_PATCH_RODATA_ATTR uid_pre_send_list[7][5] = { + {0x32,0x00,0x03,0xc0,0x48}, + {0x32,0x00,0x00,0x80,0x00}, + {0x32,0x00,0x00,0x84,0x47}, + {0x32,0x00,0x00,0x88,0x47}, + {0x32,0x00,0x00,0x8c,0x04}, + {0x32,0x00,0x00,0x90,0x19}, + {0x32,0x00,0x00,0x94,0x03}, +}; + +static void FLASH_PATCH_TEXT_ATTR fm_cam_uid_pre(void) +{ + // cmd NO.2 in the doc + uint8_t send_list[7][5]; + + memcpy(send_list, uid_pre_send_list, 7 * 5); + + fm_cam_pre_cmd_generic(send_list, sizeof(send_list) / sizeof(send_list[0])); +} + +static const uint8_t FLASH_PATCH_RODATA_ATTR read_pre_send_list[7][5] = { + {0x32,0x00,0x03,0xc0,0x88}, + {0x32,0x00,0x00,0x80,0x00}, + {0x32,0x00,0x00,0x84,0x47}, + {0x32,0x00,0x00,0x88,0x47}, + {0x32,0x00,0x00,0x8c,0x04}, + {0x32,0x00,0x00,0x90,0x19}, + {0x32,0x00,0x00,0x94,0x03}, +}; + +static void FLASH_PATCH_TEXT_ATTR fm_cam_read_pre(void) +{ + // cmd NO.1 in the doc + uint8_t send_list[7][5]; + + memcpy(send_list, read_pre_send_list, 7 * 5); + + // fm_cam_pre_cmd_generic(send_list, sizeof(send_list) / sizeof(send_list[0])); + fm_cam_pre_cmd_generic(send_list, 7); +} + +static bool FLASH_PATCH_TEXT_ATTR fm_flash_wait_idle() +{ + uint8_t status = 0x1; + while ((status&0x1) == 0x1) { + fm_send_spi_cmd(0x05, 1*8, 0, 0, NULL, 0, &status, 1*8, 0); + } + return true; +} + +static void FLASH_PATCH_TEXT_ATTR fm_soft_reset() +{ + fm_send_spi_cmd(0x66, 1*8, 0, 0, NULL, 0, NULL, 0, 0); + // patch_delay(1); + fm_send_spi_cmd(0x99, 1*8, 0, 0, NULL, 0, NULL, 0, 0); + fm_flash_wait_idle(); +} + +static const uint8_t FLASH_PATCH_RODATA_ATTR uid_cmd[4] = {0x00, 0x03, 0xc0, 0x40}; +static const uint8_t FLASH_PATCH_RODATA_ATTR uid_data[4] = {0x00, 0x01, 0x00, 0x8F}; + +static bool FLASH_PATCH_TEXT_ATTR fm_set_uid_flag(void) +{ + fm_soft_reset(); + fm_cam_cmd_start(); + fm_send_spi_cmd(0x32, 8, 0, 0, uid_cmd, 4 * 8, NULL, 0, 0); + fm_cam_cmd_end(); + fm_send_spi_cmd(0x06, 1*8, 0, 0, NULL, 0, NULL, 0, 0); + fm_send_spi_cmd(0x02, 8, 0, 0, uid_data, 4 * 8, 0, 0, 0); + fm_flash_wait_idle(); + + return true; +} + +static bool FLASH_PATCH_TEXT_ATTR fm_erase_sector(uint32_t addr) +{ + // write en + fm_send_spi_cmd(0x06, 1*8, 0, 0, NULL, 0, NULL, 0, 0); + fm_send_spi_cmd(0x20, 1*8, addr, 24, 0, 0, 0, 0, 0); + return fm_flash_wait_idle(); +} + +static bool FLASH_PATCH_TEXT_ATTR fm_cam_erase_and_fix(uint8_t (*buf)[32]) +{ + INFO(FLASH_PATCH_STR("Start erase and program cam buf\n")); + // cmd 4. + fm_cam_preprog_pre(); + if (!fm_erase_sector(0x0)) { + ERROR(FLASH_PATCH_STR("ERR in ERASE %d\n"), __LINE__); + return false; + } + int retry = 40; + while (retry > 0) { + WDT_FEED(); + // cmd 5. + fm_cam_step_erase_pre(); + if (!fm_erase_sector(0x0)) { + ERROR(FLASH_PATCH_STR("ERR in ERASE %d\n"), __LINE__); + return false; + } + // cmd 6. + fm_cam_step_prog_pre(); + if (!fm_erase_sector(0x0)) { + ERROR(FLASH_PATCH_STR("ERR in ERASE %d\n"), __LINE__); + return false; + } + + // + INFO(FLASH_PATCH_STR("Start programming 5 page\n")); + fm_cam_prog_pre(); + int line = 0; + for (line = 0; line < 5; line++) { + // write en + fm_send_spi_cmd(0x06, 1*8, 0, 0, NULL, 0, NULL, 0, 0); + // prog + fm_send_spi_cmd(0x02, 8, 0x20*line, 24, &buf[line][0], 32*8, 0, 0, 0); + fm_flash_wait_idle(); + WDT_FEED(); + // for (uint32_t loop = 0; loop < 32; loop++) { + // DEBUG(FLASH_PATCH_STR("%02x "), buf[line][loop]); + // } + // INFO(FLASH_PATCH_STR("\n")); + } + INFO(FLASH_PATCH_STR("Programming Done\n")); + + // cmd 7. + fm_cam_read_after_erase_pre(); + int found_error = false; + for (line = 0; line < 5; line++) { + uint32_t cam_rd[8]; + fm_send_spi_cmd(0x03, 8, 0x20 * line, 24, 0, 0, cam_rd, 32*8, 0); + int idx = 0; + for (idx = 0;idx < 8; idx++) { + uint32_t* p = (uint32_t*)buf[line]; + if (cam_rd[idx] != p[idx]) { + found_error = true; + ERROR(FLASH_PATCH_STR("erase check error, retry...%d, %d, 0x%08x\n"), retry, idx, cam_rd[idx]); + break; + } + } + retry -= 1; + } + + if (!found_error) { + for (line = 5; line < 20; line++) { + uint32_t cam_rd[8]; + fm_send_spi_cmd(0x03, 8, 0x20 * line, 24, 0, 0, cam_rd, 32*8, 0); + int idx = 0; + for (idx = 0;idx < 8; idx++) { + if (cam_rd[idx] != 0x000000ff) { + found_error = true; + ERROR(FLASH_PATCH_STR("erase check error, retry...%d, %d, 0x%08x\n"), retry, idx, cam_rd[idx]); + break; + } + } + retry -= 1; + } + } + + if (! found_error) { + INFO(FLASH_PATCH_STR("Erase Pass !!!\n")); + break; + } + } + if (retry <= 0) { + ERROR(FLASH_PATCH_STR("Erase fail !!!\n")); + return false; + } + + // cmd 3. + INFO(FLASH_PATCH_STR("Start programming\n")); + fm_cam_prog_pre(); + int line = 0; + for (line = 5; line < 20; line++) { + // write en + fm_send_spi_cmd(0x06, 1*8, 0, 0, NULL, 0, NULL, 0, 0); + // prog + fm_send_spi_cmd(0x02, 8, 0x20*line, 24, &buf[line][0], 32*8, 0, 0, 0); + fm_flash_wait_idle(); + WDT_FEED(); + for (uint32_t loop = 0; loop < 32; loop++) { + DEBUG(FLASH_PATCH_STR("%02x "), buf[line][loop]); + } + INFO(FLASH_PATCH_STR("\n")); + } + + // read buffer + INFO(FLASH_PATCH_STR("Prog done, read and check")); + fm_cam_read_pre(); + for (line = 0;line < 20; line++) { + WDT_FEED(); + uint8_t cam_check[32]; + fm_send_spi_cmd(0x03, 8, 0x20*line, 24, 0, 0, cam_check, 32*8, 0); + int j = 0; + for (j = 0; j < 32; j++) { + DEBUG(FLASH_PATCH_STR("%02x "), cam_check[j]); + if ((j + 1) % 16 == 0) { + DEBUG(FLASH_PATCH_STR("\n")); + } + } + if (memcmp(cam_check, buf[line], 32) != 0) { + ERROR(FLASH_PATCH_STR("CAM BUF[%d] check error\n"), line); + patch_delay(50); + return false; + } + } + + fm_set_uid_flag(); + INFO(FLASH_PATCH_STR("CAM prog done !!!\n")); + return true; +} + +static const uint8_t FLASH_PATCH_RODATA_ATTR cam_buf_default_rodata[20][32] = { + {0x55, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x53, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x53, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x23, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xe3, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x23, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, +}; + +static bool FLASH_PATCH_TEXT_ATTR esp_fm_check_uid() +{ + uint8_t cam_buf_default[20][32]; + + memcpy(cam_buf_default, cam_buf_default_rodata, 20*32); + + // cmd 2. + fm_cam_uid_pre(); + uint8_t uid[6]; + fm_send_spi_cmd(0x03, 1*8, 0x25, 3*8, NULL, 0, uid, 6*8, 0); + if(uid[0] == ~uid[1] && uid[2] == ~uid[3] && uid[4] == ~uid[5]) { + INFO(FLASH_PATCH_STR("UID check correct, update buf\n")); + cam_buf_default[3][12] = uid[0] & 0xff; + cam_buf_default[5][0] = uid[2] & 0xff; + cam_buf_default[6][0] = uid[2] & 0xff; + cam_buf_default[7][0] = uid[4] & 0xff; + cam_buf_default[9][0] = uid[4] & 0xff; + } else { + INFO(FLASH_PATCH_STR("UID check error, use default buf\n")); + } + WDT_FEED(); + bool res = fm_cam_erase_and_fix(cam_buf_default); + WDT_FEED(); + fm_soft_reset(); + return res; +} + +static bool FLASH_PATCH_TEXT_ATTR fm_cam_check_buf_valid(uint8_t (*buf)[32]) +{ + bool res = false; + uint8_t count = 3; + + while (!res && count--) { + // cmd 1. + fm_cam_read_pre(); + + int i = 0, j = 0; + for (i = 0; i < 20; i++) { + // read buf + fm_send_spi_cmd(0x03, 8, 0x20 * i, 24, 0, 0, &buf[i][0], 32*8, 0); + for (j = 0; j < 32; j++) { + DEBUG(FLASH_PATCH_STR("%02x "), buf[i][j]); + if ((j + 1) % 16 == 0) { + DEBUG(FLASH_PATCH_STR("\n")); + INFO(FLASH_PATCH_STR("\r")); + } + } + } + + if (buf[0][0] == 0x55 && buf[0][4] == 0xaa \ + && buf[4][0] == 0x00 \ + && buf[10][0] == 0x1 && buf[10][20] == 0xff\ + && buf[11][0] == 0x1 && buf[11][20] == 0xff\ + && buf[12][0] == 0x1 && buf[12][20] == 0xff\ + && buf[13][0] == 0x1 && buf[13][20] == 0xff\ + && buf[14][0] == 0x1 && buf[14][20] == 0xff\ + && buf[15][0] == 0x1 && buf[15][20] == 0xff\ + && buf[16][0] == 0x1 && buf[16][20] == 0xff\ + && buf[17][0] == 0x1 && buf[17][20] == 0xff + ) { + INFO(FLASH_PATCH_STR("CAM buffer check valid !!!\n")); + res = true; + } else { + INFO(FLASH_PATCH_STR("CAM buffer check IN-Valid !!!\n")); + res = false; + } + } + // while(1); + return res; +} + +static bool FLASH_PATCH_TEXT_ATTR fm_cam_check_uid(void) +{ + bool res = false; + uint8_t count = 3; + uint8_t uid[8]; + + while (!res && count--) { + fm_send_spi_cmd(0x4B, 8, 0, 0, 0, 0, &uid[0], 8*8, 4*8); + DEBUG(FLASH_PATCH_STR("uid 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"), uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]); + if ((((uid[1]&0xf0) == 0x0) && ((uid[0]&0x70) == 0)) + || (((uid[1]&0xf0) != 0x0))) { + res = true; + } + } + + return res; +} + +static bool FLASH_PATCH_TEXT_ATTR fm_fix_cam() +{ + uint8_t check_buf[20][32]; + + if (fm_cam_check_uid()) { + return true; + } + + if (!double_check_fm25q16a()) { + return true; + } + + if (fm_cam_check_buf_valid(check_buf) == false) { + ERROR(FLASH_PATCH_STR("Cam buf not valid\n")); + return esp_fm_check_uid(); + } else { + INFO(FLASH_PATCH_STR("Cam buf valid\n")); + + if ((check_buf[3][0] & 0x08) == 0x08) { + INFO(FLASH_PATCH_STR("Bit3 == 1, already fixed....\n")); + fm_set_uid_flag(); + fm_soft_reset(); + } else { + check_buf[3][0] |= 0x08; + bool res = fm_cam_erase_and_fix(check_buf); + fm_soft_reset(); + return res; + } + } + + return true; +} + +static uint32_t FLASH_PATCH_TEXT_ATTR fm_flash_id(void) +{ + uint32_t data[6]; + uint8_t* id = (uint8_t*)data; +#if 1 + fm_send_spi_cmd(0x9f, 8, 0, 0, 0, 0, id, 24*8, 0); + return (id[0]<<16 | id[1]<<8 | id[2]); +#else + uint32_t flash_id = spi_flash_get_id(); + memcpy(id, &flash_id, 3); + return (id[0]<<16 | id[1]<<8 | id[2]); +#endif +} + +static bool FLASH_PATCH_TEXT_ATTR double_check_fm25q16a(void) +{ + uint32_t addr = 0x10; + uint8_t value[6]; + fm_send_spi_cmd(0x9f, 8, 0, 0, 0, 0, NULL, 0, 0); + + fm_cam_cmd_start(); + fm_send_spi_cmd(0x90, 8, addr, 3 * 8, 0, 0, value, sizeof(value) * 8, 0); + fm_cam_cmd_end(); + DEBUG(FLASH_PATCH_STR("fm25q16a confirm: ")); + for (uint loop = 0; loop < sizeof(value); loop++) { + DEBUG(FLASH_PATCH_STR(" 0x%02x"), value[loop]); + if (value[loop] != 0xA1) { + DEBUG(FLASH_PATCH_STR("\r\n")); + return false; + } + } + DEBUG(FLASH_PATCH_STR("\r\n")); + + return true; +} + +static bool FLASH_PATCH_TEXT_ATTR is_fm25q16a(void) +{ + uint8_t status = 0x0; + uint8_t count = 3; + uint8_t value = 0; + + while (((status&0x20) == 0x0) && count--) { + fm_send_spi_cmd(0x50, 1*8, 0, 0, NULL, 0, NULL, 0, 0); + value = 0x80; + fm_send_spi_cmd(0x01, 1*8, 0, 0, &value, 1*8, NULL, 0, 0); + fm_send_spi_cmd(0x50, 1*8, 0, 0, NULL, 0, NULL, 0, 0); + value = 0x03; + fm_send_spi_cmd(0x31, 1*8, 0, 0, &value, 1*8, NULL, 0, 0); + fm_send_spi_cmd(0x06, 1*8, 0, 0, NULL, 0, NULL, 0, 0); + value = 0x02; + fm_send_spi_cmd(0x31, 1*8, 0, 0, &value, 1*8, NULL, 0, 0); + + fm_flash_wait_idle(); + fm_send_spi_cmd(0x35, 1*8, 0x0, 0, NULL, 0, &status, 1*8, 0); + + fm_soft_reset(); + } + + if ((status&0x20) == 0) { + DEBUG(FLASH_PATCH_STR("It's FM25Q16A\n")); + return true; + } + + DEBUG(FLASH_PATCH_STR("It's FM25Q16B\n")); + return false; +} + +int FLASH_PATCH_TEXT_ATTR fm25q16a_apply_patch_0() +{ + bool res = true; + + spi_state_t state; + spi_enter(&state); + + uint32_t flash_id = fm_flash_id(); + DEBUG(FLASH_PATCH_STR("Flash id: 0x%x\n"), flash_id); + + WDT_FEED(); + if (flash_id == 0xa14015) { + fm_soft_reset(); + INFO(DRAM_STR("Found FM25Q16A or FM25Q16B\n")); + if(is_fm25q16a()) { + INFO(DRAM_STR("Found FM25Q16A, check CAM buf\n")); + res = fm_fix_cam(); + } + } else if ((flash_id&0xffffff) == 0x0 || (flash_id&0xffffff) == 0xffffff) { + INFO(FLASH_PATCH_STR("Found ID error, recover default CAM buf\n")); + res = esp_fm_check_uid(); + } else { + INFO(FLASH_PATCH_STR("Normal flash, continue...\n")); + } + WDT_FEED(); + + spi_exit(&state); + + if (res != true) { + fm_printf(FLASH_PATCH_STR("fix fail\n")); + // we should keep running + return 0; + } + + fm_printf(FLASH_PATCH_STR("fix done\n")); + return 0; +} diff --git a/components/spi_flash/src/patch/spi_flash_patch.h b/components/spi_flash/src/patch/spi_flash_patch.h new file mode 100644 index 000000000..24243184e --- /dev/null +++ b/components/spi_flash/src/patch/spi_flash_patch.h @@ -0,0 +1,58 @@ +// Copyright 2024-2026 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _SPI_FLASH_PATCH_H +#define _SPI_FLASH_PATCH_H + +#include +#include + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define FLASH_PATCH_TEXT_ATTR __attribute__((section(".flash.patch.text"))) +#define FLASH_PATCH_RODATA_ATTR __attribute__((section(".flash.patch.rodata"))) +#define FLASH_PATCH_BSS_ATTR __attribute__((section(".flash.patch.bss"))) + +#define FLASH_PATCH_STR(str) (__extension__({static const FLASH_PATCH_RODATA_ATTR char __c[] = (str); (const char *)&__c;})) + +#if CONFIG_ENABLE_SPI_FLASH_PATCH_DEBUG +typedef int (*__ets_printf_t)(const char *fmt, ...); +#define ROM_PRINTF(_fmt, ...) ((__ets_printf_t)(0x400024cc))(_fmt, ##__VA_ARGS__) +#else +#define ROM_PRINTF(_fmt, ...) +#endif + +typedef struct spi_state { + uint32_t io_mux_reg; + uint32_t spi_clk_reg; + uint32_t spi_ctrl_reg; + uint32_t spi_user_reg; +} spi_state_t; + +void spi_enter(spi_state_t *state); +void spi_exit(spi_state_t *state); + +void spi_trans(bool write_mode, uint32_t cmd, uint32_t cmd_bits, uint32_t addr, uint32_t addr_bits, uint8_t *data, + uint32_t data_bytes, uint32_t dummy_bits); +void patch_delay(int ms); + +#ifdef __cplusplus +} +#endif + +#endif /* _SPI_FLASH_H */ diff --git a/components/spi_flash/src/patch/th25q16hb.c b/components/spi_flash/src/patch/th25q16hb.c new file mode 100644 index 000000000..d3f255a67 --- /dev/null +++ b/components/spi_flash/src/patch/th25q16hb.c @@ -0,0 +1,494 @@ +// Copyright 2023 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include "esp_log.h" +#include "esp_attr.h" +#include "spi_flash.h" +#include "priv/esp_spi_flash_raw.h" +#include "FreeRTOS.h" + +#include "esp8266/eagle_soc.h" +#include "esp8266/pin_mux_register.h" +#include "esp8266/spi_register.h" +#include "esp8266/spi_struct.h" + +#include "spi_flash_patch.h" + +#define SPI_BLOCK_SIZE 32 + +void spi_trans(bool write_mode, uint32_t cmd, uint32_t cmd_bits, uint32_t addr, uint32_t addr_bits, uint8_t *data, + uint32_t data_bytes, uint32_t dummy_bits); +void patch_delay(int ms); + +#define TOCHAR(_v) #_v +#define PRINT_STEP(_s) ROM_PRINTF(FLASH_PATCH_STR("Step %d\n"), (_s)); +#define JUMP_TO_STEP(_s) { ROM_PRINTF(FLASH_PATCH_STR("%d line Jump to " TOCHAR(_s) "\n"), __LINE__); goto _s; } +#define GOTO_FAILED(_s) { ROM_PRINTF(FLASH_PATCH_STR("ERROR: " TOCHAR(_s) " failed\n")); ret = -EIO; JUMP_TO_STEP(step17); } + +#define write_u8_dummy(_c, _a, _d8,_d) {uint32_t __data = _d8; spi_trans(1, (_c), 8, (_a), 24, (uint8_t *)&__data, 1, (_d));} +#define write_u8(_c, _a, _d8) write_u8_dummy((_c), (_a), (_d8), 0) + +extern uint32_t spi_flash_get_id(void); + +static uint8_t FLASH_PATCH_BSS_ATTR buffer1024[1024]; + +static void FLASH_PATCH_TEXT_ATTR write_cmd(uint32_t cmd) +{ + spi_trans(1, cmd, 8, 0, 0, NULL, 0, 0); +} + +static void FLASH_PATCH_TEXT_ATTR write_buffer(uint32_t addr, uint8_t *buffer, int size) +{ + for (int i = 0; i < size; i += SPI_BLOCK_SIZE) { + int n = MIN(size - i, SPI_BLOCK_SIZE); + + write_cmd(0x6); + spi_trans(1, 0x42, 8, addr + i, 24, buffer + i, n, 0); + patch_delay(3); + } +} + +static void FLASH_PATCH_TEXT_ATTR read_buffer(uint32_t addr, uint8_t *buffer, int n) +{ + spi_trans(0, 0x48, 8, addr, 24, buffer, n, 8); +} + +static void FLASH_PATCH_TEXT_ATTR erase_sector(uint32_t addr) +{ + write_cmd(0x6); + spi_trans(1, 0x44, 8, addr, 24, NULL, 0, 0); + patch_delay(8); +} + +int FLASH_PATCH_TEXT_ATTR th25q16hb_apply_patch_0(void) +{ + int ret = 0; + uint32_t flash_id; + int count; + spi_state_t state; + uint8_t *buffer256_0; + uint8_t *buffer256_1; + uint8_t *buffer256_2; + + flash_id = spi_flash_get_id(); + if (flash_id != 0x1560eb) { + uint32_t data = 0; + bool is_th25q16hb = false; + if (flash_id == 0x0) { + spi_trans(0, 0x5A, 8, 0x10, 24, &data, 1, 0); + if (data == 0xEB) { + spi_trans(0, 0x5A, 8, 0x14, 24, &data, 1, 0); + if (data == 0x60) { + spi_trans(0, 0x5A, 8, 0x34, 24, &data, 4, 0); + if (data == 0xFFFFFF00) { + is_th25q16hb = true; + } + } + } + } + + if (!is_th25q16hb) { + ROM_PRINTF(FLASH_PATCH_STR("WARN: id=0x%x, is not TH25Q16HB\n"), flash_id); + return 0; + } + } + + buffer256_0 = buffer1024; + buffer256_1 = buffer1024 + 256; + buffer256_2 = buffer1024 + 512; + + spi_enter(&state); + + // Step 1 + PRINT_STEP(1); + write_cmd(0x33); + + // Step 2 + PRINT_STEP(2); + write_cmd(0xcc); + + // Step 3 + PRINT_STEP(3); + write_cmd(0xaa); + + // Step 4 + PRINT_STEP(4); + write_u8(0xfa, 0x1200d, 0x3); + write_u8_dummy(0xfa, 0x2200d, 0x3, 1); + + // Step 5-1 + PRINT_STEP(5); + read_buffer(0xbed, buffer256_0, 3); + if (buffer256_0[0] == 0xff && + buffer256_0[1] == 0xff && + buffer256_0[2] == 0xff) { + ROM_PRINTF(FLASH_PATCH_STR("INFO: check done 0\n")); + } else if (buffer256_0[0] == 0x55 && + buffer256_0[1] == 0xff && + buffer256_0[2] == 0xff) { + JUMP_TO_STEP(step10); + } else if (buffer256_0[0] == 0x55 && + buffer256_0[1] == 0x55 && + buffer256_0[2] == 0xff) { + JUMP_TO_STEP(step14); + } else if (buffer256_0[0] == 0x55 && + buffer256_0[1] == 0x55 && + buffer256_0[2] == 0x55) { + JUMP_TO_STEP(step17); + } else { + ROM_PRINTF(FLASH_PATCH_STR("ERROR: 0xbed=0x%x 0xbee=0x%x 0xbef=0x%x\n"), + buffer256_0[0], buffer256_0[1], buffer256_0[2]); + GOTO_FAILED(5-1); + } +JUMP_TO_STEP(step17); + // Step 5-2 + read_buffer(0x50d, buffer256_0, 1); + buffer256_0[0] &= 0x7f; + if (buffer256_0[0] == 0x7c) { + JUMP_TO_STEP(step17); + } else if (buffer256_0[0] == 0x3c) { + ROM_PRINTF(FLASH_PATCH_STR("INFO: check done 1\n")); + } else { + ROM_PRINTF(FLASH_PATCH_STR("ERROR: 0x50d=0x%x\n"), buffer256_0[0]); + GOTO_FAILED(5-2); + } + + // Step 6 + PRINT_STEP(6); + for (count = 0; count < 3; count++) { + erase_sector(0); + + bool check_done = true; + read_buffer(0x0, buffer1024, 1024); + for (int i = 0; i < 1024; i++) { + if (buffer1024[i] != 0xff) { + check_done = false; + ROM_PRINTF(FLASH_PATCH_STR("ERROR: buffer1024[%d]=0x%x\n"), i, buffer1024[i]); + break; + } + } + + if (check_done) { + break; + } + } + if (count >= 3) { + GOTO_FAILED(6) + } + + // Step 7-1.1 + PRINT_STEP(7); + read_buffer(0x400, buffer256_0, 256); + read_buffer(0x400, buffer256_1, 256); + read_buffer(0x400, buffer256_2, 256); + if (memcmp(buffer256_0, buffer256_1, 256) || + memcmp(buffer256_0, buffer256_2, 256)) { + GOTO_FAILED(7-1.1); + } + + write_buffer(0, buffer256_0, 256); + write_buffer(0x200, buffer256_0, 256); + + // Step 7-1.2 + for (count = 0; count < 3; count++) { + read_buffer(0, buffer256_1, 256); + if (memcmp(buffer256_0, buffer256_1, 256)) { + break; + } + + read_buffer(0x200, buffer256_1, 256); + if (memcmp(buffer256_0, buffer256_1, 256)) { + break; + } + } + if (count < 3) { + GOTO_FAILED(7-1.2); + } + + // Step 7-2.1 + read_buffer(0x500, buffer256_0, 256); + read_buffer(0x500, buffer256_1, 256); + read_buffer(0x500, buffer256_2, 256); + if (memcmp(buffer256_0, buffer256_1, 256) || + memcmp(buffer256_0, buffer256_2, 256)) { + GOTO_FAILED(7-2.1); + } + write_buffer(0x100, buffer256_0, 256); + write_buffer(0x300, buffer256_0, 256); + + // Step 7-2.2 + for (count = 0; count < 3; count++) { + read_buffer(0x100, buffer256_1, 256); + if (memcmp(buffer256_0, buffer256_1, 256)) { + break; + } + read_buffer(0x300, buffer256_1, 256); + if (memcmp(buffer256_0, buffer256_1, 256)) { + break; + } + } + if (count < 3) { + GOTO_FAILED(7-2.2); + } + + // Step 8 + PRINT_STEP(8); + read_buffer(0x0, buffer256_0, 1); + read_buffer(0x23, buffer256_1, 1); + if (buffer256_0[0] != 0x13 || buffer256_1[0] != 0x14) { + ROM_PRINTF(FLASH_PATCH_STR("ERROR: 0x0=0x%x 0x23=0x%x\n"), buffer256_0[0], buffer256_1[0]); + GOTO_FAILED(8); + } + + // Step 9-1 + PRINT_STEP(9); + read_buffer(0x140, buffer256_0, 2); + if (buffer256_0[0] != 0 || buffer256_0[1] != 0xff) { + ROM_PRINTF(FLASH_PATCH_STR("ERROR: 0x140=0x%x 0x141=0x%x\n"), buffer256_0[0], buffer256_0[1]); + GOTO_FAILED(9-1); + } + + // Step 9-2 + buffer256_0[0] = 0x55; + write_buffer(0xaed, buffer256_0, 1); + write_buffer(0xbed, buffer256_0, 1); + for (count = 0; count < 3; count++) { + read_buffer(0xaed, buffer256_0, 1); + if (buffer256_0[0] != 0x55) { + break; + } + + read_buffer(0xbed, buffer256_0, 1); + if (buffer256_0[0] != 0x55) { + break; + } + } + if (count < 3) { + GOTO_FAILED(9-2); + } + +step10: + // Step 10-1 + PRINT_STEP(10); + for (count = 0; count < 3; count++) { + erase_sector(0x400); + + bool check_done = true; + read_buffer(0x400, buffer1024, 1024); + for (int i = 0; i < 1024; i++) { + if (buffer1024[i] != 0xff) { + check_done = false; + ROM_PRINTF(FLASH_PATCH_STR("ERROR: buffer1024[%d]=0x%x\n"), i, buffer1024[i]); + break; + } + } + + if (check_done) { + break; + } + } + if (count >= 3) { + GOTO_FAILED(10-1); + } + + // Step 10-3.1 + read_buffer(0, buffer256_0, 256); + read_buffer(0, buffer256_1, 256); + read_buffer(0, buffer256_2, 256); + if (memcmp(buffer256_0, buffer256_1, 256) || + memcmp(buffer256_0, buffer256_2, 256)) { + GOTO_FAILED(10-3.1); + } + write_buffer(0x400, buffer256_0, 256); + write_buffer(0x600, buffer256_0, 256); + + // Step 10-3.2 + for (count = 0; count < 3; count++) { + read_buffer(0x400, buffer256_1, 256); + if (memcmp(buffer256_0, buffer256_1, 256)) { + break; + } + + read_buffer(0x600, buffer256_1, 256); + if (memcmp(buffer256_0, buffer256_1, 256)) { + break; + } + } + if (count < 3) { + GOTO_FAILED(10-3.2); + } + + // Step 10-3.3 + read_buffer(0x100, buffer256_0, 256); + read_buffer(0x100, buffer256_1, 256); + read_buffer(0x100, buffer256_2, 256); + if (memcmp(buffer256_0, buffer256_1, 256) || + memcmp(buffer256_0, buffer256_2, 256)) { + GOTO_FAILED(10-3.3); + } + buffer256_0[9] = 0x79; + buffer256_0[13] = (buffer256_0[13] & 0x3f) | + ((~buffer256_0[13]) & 0x80) | + 0x40; + write_buffer(0x500, buffer256_0, 256); + write_buffer(0x700, buffer256_0, 256); + + // Step 10-3.4 + for (count = 0; count < 3; count++) { + read_buffer(0x500, buffer256_1, 256); + if (memcmp(buffer256_0, buffer256_1, 256)) { + break; + } + + read_buffer(0x700, buffer256_1, 256); + if (memcmp(buffer256_0, buffer256_1, 256)) { + break; + } + } + if (count < 3) { + GOTO_FAILED(10-3.4); + } + + // Step11-1 + PRINT_STEP(11); + + for (count = 0; count < 3; count++) { + read_buffer(0x400, buffer256_0, 1); + read_buffer(0x423, buffer256_1, 1); + if (buffer256_0[0] != 0x13 || buffer256_1[0] != 0x14) { + ROM_PRINTF(FLASH_PATCH_STR("ERROR: 0x400=0x%x 0x423=0x%x\n"), buffer256_0[0], buffer256_1[0]); + break; + } + } + if (count < 3) { + GOTO_FAILED(11-1); + } + + // Step11-2.1 + for (count = 0; count < 3; count++) { + read_buffer(0x540, buffer256_0, 2); + if (buffer256_0[0] != 0 || buffer256_0[1] != 0xff) { + ROM_PRINTF(FLASH_PATCH_STR("ERROR: 0x540=0x%x 0x541=0x%x\n"), buffer256_0[0], buffer256_0[1]); + break; + } + } + if (count < 3) { + GOTO_FAILED(11-2); + } + + // Step11-2.2 + for (count = 0; count < 3; count++) { + read_buffer(0x50d, buffer256_0, 1); + buffer256_0[0] &= 0x7f; + if (buffer256_0[0] != 0x7c) { + ROM_PRINTF(FLASH_PATCH_STR("ERROR: 0x50d=0x%x\n"), buffer256_0[0]); + break; + } + } + if (count < 3) { + GOTO_FAILED(11-2); + } + + // Step 12 + PRINT_STEP(12); + buffer256_0[0] = 0x55; + write_buffer(0xaee, buffer256_0, 1); + write_buffer(0xbee, buffer256_0, 1); + + // Step 13 + PRINT_STEP(13); + for (count = 0; count < 3; count++) { + read_buffer(0xaee, buffer256_0, 1); + if (buffer256_0[0] != 0x55) { + break; + } + + read_buffer(0xbee, buffer256_0, 1); + if (buffer256_0[0] != 0x55) { + break; + } + } + if (count < 3) { + GOTO_FAILED(13); + } + +step14: + // Step 14 + PRINT_STEP(14); + for (count = 0; count < 3; count++) { + erase_sector(0); + + bool check_done = true; + read_buffer(0x0, buffer1024, 1024); + for (int i = 0; i < 1024; i++) { + if (buffer1024[i] != 0xff) { + check_done = false; + ROM_PRINTF(FLASH_PATCH_STR("ERROR: buffer1024[%d]=0x%x\n"), i, buffer1024[i]); + break; + } + } + + if (check_done) { + break; + } + } + if (count >= 3) { + GOTO_FAILED(14); + } + + // Step 15 + PRINT_STEP(15); + buffer256_0[0] = 0x55; + write_buffer(0xaef, buffer256_0, 1); + write_buffer(0xbef, buffer256_0, 1); + + // Step 16 + PRINT_STEP(16); + for (count = 0; count < 3; count++) { + read_buffer(0xaef, buffer256_0, 1); + if (buffer256_0[0] != 0x55) { + break; + } + + read_buffer(0xbef, buffer256_0, 1); + if (buffer256_0[0] != 0x55) { + break; + } + } + if (count < 3) { + GOTO_FAILED(16); + } + +step17: + // Step 17 + PRINT_STEP(17); + write_cmd(0x55); + + // Step 18 + PRINT_STEP(18); + write_cmd(0x88); + + spi_exit(&state); + + if (!ret) { + ROM_PRINTF(FLASH_PATCH_STR("INFO: Patch for TH25Q16HB is done\n")); + } + + return ret; +} diff --git a/components/spi_flash/src/spi_flash.c b/components/spi_flash/src/spi_flash.c index 93240e9d2..221b25951 100644 --- a/components/spi_flash/src/spi_flash.c +++ b/components/spi_flash/src/spi_flash.c @@ -259,6 +259,12 @@ bool spi_flash_check_wr_protect(void) special_flash_write_status(0x01, status&(~(SPI_GD25Q32_FLASH_WRITE_PROTECT_STATUS)), 1, true); } } + } else if (flash_id == 0x164068) { + if(spi_flash_read_status(&status)==0) { //Read status Ok + if(status&SPI_GD25Q32_FLASH_WRITE_PROTECT_STATUS) { + special_flash_write_status(0x01, status&(~(SPI_GD25Q32_FLASH_WRITE_PROTECT_STATUS)), 1, true); + } + } } //Others else { @@ -435,6 +441,10 @@ void user_spi_flash_dio_to_qio_pre_init(void) to_qio = true; } //ENBALE FLASH QIO 0X01H+0X00+0X02 + } else if (flash_id == 0x164068) { + if (flash_gd25q32c_enable_QIO_mode() == true) { + to_qio = true; + } } else { if (spi_flash_enable_qmode_raw(&g_rom_flashchip) == ESP_OK) { to_qio = true; diff --git a/components/spi_flash/src/spi_flash_raw.c b/components/spi_flash/src/spi_flash_raw.c index dee89962b..10abf29e0 100644 --- a/components/spi_flash/src/spi_flash_raw.c +++ b/components/spi_flash/src/spi_flash_raw.c @@ -39,7 +39,9 @@ uint32_t spi_flash_get_id_raw(esp_rom_spiflash_chip_t *chip) { uint32_t rdid = 0; +#ifndef BOOTLOADER_BUILD Cache_Read_Disable(); +#endif Wait_SPI_Idle(chip); @@ -49,7 +51,9 @@ uint32_t spi_flash_get_id_raw(esp_rom_spiflash_chip_t *chip) rdid = READ_PERI_REG(PERIPHS_SPI_FLASH_C0)&0xffffff; +#ifndef BOOTLOADER_BUILD Cache_Read_Enable_New(); +#endif return rdid; } @@ -150,8 +154,11 @@ bool spi_user_cmd_raw(esp_rom_spiflash_chip_t *chip, spi_cmd_dir_t mode, spi_cmd { int idx = 0; +#ifndef BOOTLOADER_BUILD // Cache Disable Cache_Read_Disable_2(); +#endif + //wait spi idle if((mode & SPI_RAW) == 0) { Wait_SPI_Idle(chip); @@ -272,8 +279,11 @@ bool spi_user_cmd_raw(esp_rom_spiflash_chip_t *chip, spi_cmd_dir_t mode, spi_cmd if((mode & SPI_RAW) == 0) { Wait_SPI_Idle(chip); } + +#ifndef BOOTLOADER_BUILD //enable icache Cache_Read_Enable_2(); +#endif return true; } diff --git a/components/tcpip_adapter/tcpip_adapter_lwip.c b/components/tcpip_adapter/tcpip_adapter_lwip.c index d3a31d635..3faabd07e 100644 --- a/components/tcpip_adapter/tcpip_adapter_lwip.c +++ b/components/tcpip_adapter/tcpip_adapter_lwip.c @@ -74,7 +74,6 @@ static esp_err_t tcpip_adapter_reset_ip_info(tcpip_adapter_if_t tcpip_if); static esp_err_t tcpip_adapter_start_ip_lost_timer(tcpip_adapter_if_t tcpip_if); static void tcpip_adapter_dhcpc_cb(struct netif *netif); static void tcpip_adapter_ip_lost_timer(void *arg); -static void tcpip_adapter_dhcpc_done(TimerHandle_t arg); static bool tcpip_inited = false; static const char* TAG = "tcpip_adapter"; @@ -85,9 +84,25 @@ ESP_EVENT_DEFINE_BASE(IP_EVENT); err_t ethernetif_init(struct netif* netif); void system_station_got_ip_set(); -static int dhcp_fail_time = 0; static tcpip_adapter_ip_info_t esp_ip[TCPIP_ADAPTER_IF_MAX]; -static TimerHandle_t *dhcp_check_timer; + +static void tcpip_adapter_set_wifi_ps(bool flag) +{ + static bool is_ps_set = false; + if (flag) { + if (!is_ps_set) { + ESP_LOGD(TAG, "enable wifi ps"); + esp_wifi_ps_lock(); + is_ps_set = true; + } + } else { + if (is_ps_set) { + ESP_LOGD(TAG, "disable wifi ps"); + esp_wifi_ps_unlock(); + is_ps_set = false; + } + } +} static void tcpip_adapter_dhcps_cb(u8_t client_ip[4]) { @@ -192,11 +207,6 @@ void tcpip_adapter_init(void) IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].ip, 192, 168 , 4, 1); IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].gw, 192, 168 , 4, 1); IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].netmask, 255, 255 , 255, 0); - - dhcp_check_timer = xTimerCreate("check_dhcp", 500 / portTICK_RATE_MS, true, NULL, tcpip_adapter_dhcpc_done); - if (!dhcp_check_timer) { - ESP_LOGI(TAG, "TCPIP adapter timer create error"); - } } } @@ -287,56 +297,6 @@ static int tcpip_adapter_sta_recv_cb(void *buffer, uint16_t len, void *eb) return tcpip_adapter_recv_cb(esp_netif[ESP_IF_WIFI_STA], buffer, len, eb); } -static void tcpip_adapter_dhcpc_done(TimerHandle_t xTimer) -{ - bool unlock_ps = true; - struct dhcp *clientdhcp = netif_dhcp_data(esp_netif[TCPIP_ADAPTER_IF_STA]) ; - struct netif *netif = esp_netif[TCPIP_ADAPTER_IF_STA]; - - if (!netif) { - ESP_LOGD(TAG, "null netif=%p", netif); - return; - } - -#if LWIP_IPV4 && LWIP_AUTOIP - struct autoip *autoip = netif_autoip_data(netif); -#endif - - xTimerStop(dhcp_check_timer, 0); - if (netif_is_up(esp_netif[TCPIP_ADAPTER_IF_STA])) { - if ((clientdhcp && clientdhcp->state == DHCP_STATE_BOUND) -#if LWIP_IPV4 && LWIP_AUTOIP - || (autoip && autoip->state == AUTOIP_STATE_ANNOUNCING) -#endif - ) { - /*send event here*/ - tcpip_adapter_dhcpc_cb(esp_netif[TCPIP_ADAPTER_IF_STA]); - ESP_LOGD(TAG,"ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR "\n", IP2STR(ip_2_ip4(&(esp_netif[0]->ip_addr))), - IP2STR(ip_2_ip4(&(esp_netif[0]->netmask))), IP2STR(ip_2_ip4(&(esp_netif[0]->gw)))); - dhcp_fail_time = 0; - } else if (dhcp_fail_time < (CONFIG_IP_LOST_TIMER_INTERVAL * 1000 / 500)) { - ESP_LOGD(TAG,"dhcpc time(ms): %d\n", dhcp_fail_time * 500); - dhcp_fail_time ++; - xTimerReset(dhcp_check_timer, 0); - unlock_ps = false; - } else { - dhcp_fail_time = 0; - ESP_LOGD(TAG,"ERROR dhcp get ip error\n"); - } - } else { - dhcp_fail_time = 0; - tcpip_adapter_release_dhcp(esp_netif[TCPIP_ADAPTER_IF_STA]); - - dhcpc_status[TCPIP_ADAPTER_IF_STA] = TCPIP_ADAPTER_DHCP_INIT; - - tcpip_adapter_reset_ip_info(TCPIP_ADAPTER_IF_STA); - } - - if (unlock_ps) { - esp_wifi_ps_unlock(); - } -} - static esp_err_t tcpip_adapter_update_default_netif(void) { if ((esp_netif[TCPIP_ADAPTER_IF_STA] != NULL) && netif_is_up(esp_netif[TCPIP_ADAPTER_IF_STA])) { @@ -865,8 +825,14 @@ esp_err_t tcpip_adapter_set_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; } +#if CONFIG_LWIP_IPV6 + if (!IP_IS_V4(&dns->ip) && !IP_IS_V6(&dns->ip)) { + IP_SET_TYPE_VAL(dns->ip, IPADDR_TYPE_V4); + } +#else ESP_LOGD(TAG, "set dns if=%d type=%d dns=%x", tcpip_if, type, ip_2_ip4(&(dns->ip))->addr); IP_SET_TYPE_VAL(dns->ip, IPADDR_TYPE_V4); +#endif if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH) { dns_setserver(type, &(dns->ip)); @@ -1073,6 +1039,7 @@ static void tcpip_adapter_dhcpc_cb(struct netif *netif) } } + tcpip_adapter_set_wifi_ps(false); return; } @@ -1171,16 +1138,13 @@ esp_err_t tcpip_adapter_dhcpc_start(tcpip_adapter_if_t tcpip_if) return ESP_OK; } - esp_wifi_ps_lock(); + tcpip_adapter_set_wifi_ps(true); if (tcpip_adapter_start_dhcp(p_netif) != ERR_OK) { - esp_wifi_ps_unlock(); + tcpip_adapter_set_wifi_ps(false); ESP_LOGD(TAG, "dhcp client start failed"); return ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED; } - - dhcp_fail_time = 0; - xTimerReset(dhcp_check_timer, portMAX_DELAY); ESP_LOGD(TAG, "dhcp client start successfully"); dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_STARTED; return ESP_OK; diff --git a/components/wpa_supplicant/src/ap/ap_config.c b/components/wpa_supplicant/src/ap/ap_config.c index 14f73547e..5fc87cd5d 100644 --- a/components/wpa_supplicant/src/ap/ap_config.c +++ b/components/wpa_supplicant/src/ap/ap_config.c @@ -130,14 +130,12 @@ static int hostapd_derive_psk(struct hostapd_ssid *ssid) wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)", (u8 *) ssid->wpa_passphrase, strlen(ssid->wpa_passphrase)); -#ifdef ESP_SUPPLICANT - memcpy(ssid->wpa_psk->psk, esp_wifi_ap_get_prof_pmk_internal(), PMK_LEN); -#else + /* It's too SLOW */ pbkdf2_sha1(ssid->wpa_passphrase, - ssid->ssid, ssid->ssid_len, + (const char *)ssid->ssid, ssid->ssid_len, 4096, ssid->wpa_psk->psk, PMK_LEN); -#endif + wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)", ssid->wpa_psk->psk, PMK_LEN); return 0; diff --git a/components/wpa_supplicant/src/common/wpa_common.h b/components/wpa_supplicant/src/common/wpa_common.h index f88e8a6fa..fd1d9995a 100644 --- a/components/wpa_supplicant/src/common/wpa_common.h +++ b/components/wpa_supplicant/src/common/wpa_common.h @@ -110,6 +110,8 @@ #define WPA_CAPABILITY_MFPR BIT(6) #define WPA_CAPABILITY_MFPC BIT(7) #define WPA_CAPABILITY_PEERKEY_ENABLED BIT(9) +#define WPA_CAPABILITY_SPP_CAPABLE BIT(10) +#define WPA_CAPABILITY_SPP_REQUIRED BIT(11) /* IEEE 802.11r */ diff --git a/components/wpa_supplicant/src/crypto/crypto_mbedtls-ec.c b/components/wpa_supplicant/src/crypto/crypto_mbedtls-ec.c index 42290b038..8edb90b0b 100644 --- a/components/wpa_supplicant/src/crypto/crypto_mbedtls-ec.c +++ b/components/wpa_supplicant/src/crypto/crypto_mbedtls-ec.c @@ -164,7 +164,7 @@ int crypto_ec_point_to_bin(struct crypto_ec *e, int len = mbedtls_mpi_size(&e->group.P); if (x) { - if(crypto_bignum_to_bin((struct crypto_bignum *) & ((mbedtls_ecp_point *) point)->X, + if(crypto_bignum_to_bin((struct crypto_bignum *) & ((mbedtls_ecp_point *) point)->MBEDTLS_PRIVATE(X), x, len, len) < 0) { return -1; } @@ -172,7 +172,7 @@ int crypto_ec_point_to_bin(struct crypto_ec *e, } if (y) { - if(crypto_bignum_to_bin((struct crypto_bignum *) & ((mbedtls_ecp_point *) point)->Y, + if(crypto_bignum_to_bin((struct crypto_bignum *) & ((mbedtls_ecp_point *) point)->MBEDTLS_PRIVATE(Y), y, len, len) < 0) { return -1; } @@ -187,17 +187,17 @@ int crypto_ec_get_affine_coordinates(struct crypto_ec *e, struct crypto_ec_point int ret = -1; mbedtls_ecp_point *point = (mbedtls_ecp_point *)pt; - if (!mbedtls_ecp_is_zero(point) && (mbedtls_mpi_cmp_int( &point->Z, 1 ) == 0 )) { + if (!mbedtls_ecp_is_zero(point) && (mbedtls_mpi_cmp_int( &point->MBEDTLS_PRIVATE(Z), 1 ) == 0 )) { // Affine coordinates mean that z should be 1, wpa_printf(MSG_ERROR, "Z coordinate is neither 0 or 1"); return -1; } if (x) { - MBEDTLS_MPI_CHK(mbedtls_mpi_copy((mbedtls_mpi*) x, &((mbedtls_ecp_point* )point)->X)); + MBEDTLS_MPI_CHK(mbedtls_mpi_copy((mbedtls_mpi*) x, &((mbedtls_ecp_point* )point)->MBEDTLS_PRIVATE(X))); } if (y) { - MBEDTLS_MPI_CHK(mbedtls_mpi_copy((mbedtls_mpi*) y, &((mbedtls_ecp_point* )point)->Y)); + MBEDTLS_MPI_CHK(mbedtls_mpi_copy((mbedtls_mpi*) y, &((mbedtls_ecp_point* )point)->MBEDTLS_PRIVATE(Y))); } return 0; cleanup: @@ -217,11 +217,14 @@ struct crypto_ec_point *crypto_ec_point_from_bin(struct crypto_ec *e, len = mbedtls_mpi_size(&e->group.P); pt = os_zalloc(sizeof(mbedtls_ecp_point)); + if (!pt) { + return NULL; + } mbedtls_ecp_point_init(pt); - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->X, val, len)); - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->Y, val + len, len)); - MBEDTLS_MPI_CHK(mbedtls_mpi_lset((&pt->Z), 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->MBEDTLS_PRIVATE(X), val, len)); + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->MBEDTLS_PRIVATE(Y), val + len, len)); + MBEDTLS_MPI_CHK(mbedtls_mpi_lset((&pt->MBEDTLS_PRIVATE(Z)), 1)); return (struct crypto_ec_point *) pt; @@ -291,8 +294,8 @@ static int ecp_opp(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbe } /* In-place opposite */ - if (mbedtls_mpi_cmp_int(&R->Y, 0) != 0) { - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&R->Y, &grp->P, &R->Y)); + if (mbedtls_mpi_cmp_int(&R->MBEDTLS_PRIVATE(Y), 0) != 0) { + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&R->MBEDTLS_PRIVATE(Y), &grp->P, &R->MBEDTLS_PRIVATE(Y))); } cleanup: @@ -313,7 +316,7 @@ int crypto_ec_point_solve_y_coord(struct crypto_ec *e, mbedtls_mpi_init(&temp); int ret = 0; - y = &((mbedtls_ecp_point *)p)->Y; + y = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y); /* Faster way to find sqrt * Works only with curves having prime p @@ -337,8 +340,8 @@ int crypto_ec_point_solve_y_coord(struct crypto_ec *e, if (y_bit != mbedtls_mpi_get_bit(y, 0)) MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(y, &e->group.P, y)); - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&((mbedtls_ecp_point* )p)->X, (const mbedtls_mpi*) x)); - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&((mbedtls_ecp_point *)p)->Z, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&((mbedtls_ecp_point* )p)->MBEDTLS_PRIVATE(X), (const mbedtls_mpi*) x)); + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Z), 1)); } else { ret = 1; } @@ -422,9 +425,9 @@ int crypto_ec_point_is_on_curve(struct crypto_ec *e, /* Calculate y^2 mod P*/ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&two, 2)); - MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&y_sqr_lhs, &((const mbedtls_ecp_point *)p)->Y , &two, &e->group.P, NULL)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&y_sqr_lhs, &((const mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y) , &two, &e->group.P, NULL)); - y_sqr_rhs = (mbedtls_mpi *) crypto_ec_point_compute_y_sqr(e, (const struct crypto_bignum *) & ((const mbedtls_ecp_point *)p)->X); + y_sqr_rhs = (mbedtls_mpi *) crypto_ec_point_compute_y_sqr(e, (const struct crypto_bignum *) & ((const mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X)); if (y_sqr_rhs && (mbedtls_mpi_cmp_mpi(y_sqr_rhs, &y_sqr_lhs) == 0)) { on_curve = 1; @@ -447,10 +450,30 @@ int crypto_ec_point_cmp(const struct crypto_ec *e, } int crypto_key_compare(struct crypto_key *key1, struct crypto_key *key2) { +#ifdef CONFIG_MBEDTLS_V3 + int ret = 0; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + + mbedtls_entropy_init(&entropy); + mbedtls_ctr_drbg_init(&ctr_drbg); + + MBEDTLS_MPI_CHK(mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0)); + if (mbedtls_pk_check_pair((mbedtls_pk_context *)key1, (mbedtls_pk_context *)key2, mbedtls_ctr_drbg_random, &ctr_drbg) < 0) { + goto cleanup; + } + + ret = 1; +cleanup: + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + return ret; +#else if (mbedtls_pk_check_pair((mbedtls_pk_context *)key1, (mbedtls_pk_context *)key2) < 0) return 0; return 1; +#endif } void crypto_debug_print_point(const char *title, struct crypto_ec *e, @@ -490,11 +513,15 @@ struct crypto_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *gro mbedtls_pk_context *key = (mbedtls_pk_context *)crypto_alloc_key(); if (!key) { - wpa_printf(MSG_ERROR, "%s: memory allocation failed\n", __func__); + wpa_printf(MSG_ERROR, "%s: memory allocation failed", __func__); return NULL; } point = (mbedtls_ecp_point *)crypto_ec_point_from_bin((struct crypto_ec *)group, buf); + if (!point) { + wpa_printf(MSG_ERROR, "%s: Point initialization failed", __func__); + goto fail; + } if (crypto_ec_point_is_at_infinity((struct crypto_ec *)group, (struct crypto_ec_point *)point)) { wpa_printf(MSG_ERROR, "Point is at infinity"); goto fail; @@ -503,7 +530,22 @@ struct crypto_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *gro wpa_printf(MSG_ERROR, "Point not on curve"); goto fail; } +#ifdef CONFIG_MBEDTLS_V3 + mbedtls_ecp_group *ecp_grp = (mbedtls_ecp_group *)group; + if (mbedtls_ecp_check_pubkey(ecp_grp, point) < 0) { + // ideally should have failed in upper condition, duplicate code?? + wpa_printf(MSG_ERROR, "Invalid key"); + goto fail; + } + /* Assign values */ + if( ( ret = mbedtls_pk_setup( key, + mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY) ) ) != 0 ) + goto fail; + mbedtls_ecp_copy(&mbedtls_pk_ec(*key)->MBEDTLS_PRIVATE(Q), point); + mbedtls_ecp_group_load(&mbedtls_pk_ec(*key)->MBEDTLS_PRIVATE(grp), ecp_grp->id); + pkey = (struct crypto_key *)key; +#else if (mbedtls_ecp_check_pubkey((mbedtls_ecp_group *)group, point) < 0) { //typecast // ideally should have failed in upper condition, duplicate code?? wpa_printf(MSG_ERROR, "Invalid key"); @@ -533,6 +575,7 @@ struct crypto_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *gro pkey = (struct crypto_key *)key; cleanup: +#endif crypto_ec_point_deinit((struct crypto_ec_point *)point, 0); return pkey; fail: @@ -556,7 +599,7 @@ struct crypto_ec_point *crypto_ec_get_public_key(struct crypto_key *key) { mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; - return (struct crypto_ec_point *)&mbedtls_pk_ec(*pkey)->Q; + return (struct crypto_ec_point *)&mbedtls_pk_ec(*pkey)->MBEDTLS_PRIVATE(Q); } @@ -584,14 +627,14 @@ struct crypto_ec_group *crypto_ec_get_group_from_key(struct crypto_key *key) { mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; - return (struct crypto_ec_group *)&(mbedtls_pk_ec(*pkey)->grp); + return (struct crypto_ec_group *)&(mbedtls_pk_ec(*pkey)->MBEDTLS_PRIVATE(grp)); } struct crypto_bignum *crypto_ec_get_private_key(struct crypto_key *key) { mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; - return ((struct crypto_bignum *)&(mbedtls_pk_ec(*pkey)->d)); + return ((struct crypto_bignum *)&(mbedtls_pk_ec(*pkey)->MBEDTLS_PRIVATE(d))); } int crypto_ec_get_publickey_buf(struct crypto_key *key, u8 *key_buf, int len) @@ -599,12 +642,12 @@ int crypto_ec_get_publickey_buf(struct crypto_key *key, u8 *key_buf, int len) mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; unsigned char buf[MBEDTLS_MPI_MAX_SIZE + 10]; /* tag, length + MPI */ unsigned char *c = buf + sizeof(buf ); - size_t pk_len = 0; + int pk_len = 0; memset(buf, 0, sizeof(buf) ); pk_len = mbedtls_pk_write_pubkey( &c, buf, pkey); - if (!pk_len) + if (pk_len < 0) return -1; if (len == 0) @@ -637,11 +680,14 @@ struct crypto_key *crypto_ec_get_key(const u8 *privkey, size_t privkey_len) mbedtls_pk_context *kctx = (mbedtls_pk_context *)crypto_alloc_key(); if (!kctx) { - wpa_printf(MSG_ERROR, "memory allocation failed\n"); + wpa_printf(MSG_ERROR, "memory allocation failed"); return NULL; } +#ifdef CONFIG_MBEDTLS_V3 + ret = mbedtls_pk_parse_key(kctx, privkey, privkey_len, NULL, 0, crypto_rng_wrapper, NULL); +#else ret = mbedtls_pk_parse_key(kctx, privkey, privkey_len, NULL, 0); - +#endif if (ret < 0) { //crypto_print_error_string(ret); goto fail; @@ -752,7 +798,7 @@ int crypto_ecdsa_get_sign(unsigned char *hash, mbedtls_ecdsa_context *ctx = os_malloc(sizeof(*ctx)); if (!ctx) { - wpa_printf(MSG_ERROR,"failed to allcate memory\n"); + wpa_printf(MSG_ERROR,"failed to allcate memory"); return -1; } mbedtls_ecdsa_init(ctx); @@ -760,8 +806,8 @@ int crypto_ecdsa_get_sign(unsigned char *hash, if (mbedtls_ecdsa_from_keypair(ctx, mbedtls_pk_ec(*pkey)) < 0) { goto fail; } - ret = mbedtls_ecdsa_sign(&ctx->grp, (mbedtls_mpi *)r, (mbedtls_mpi *)s, - &ctx->d, hash, SHA256_MAC_LEN, crypto_rng_wrapper, NULL); + ret = mbedtls_ecdsa_sign(&ctx->MBEDTLS_PRIVATE(grp), (mbedtls_mpi *)r, (mbedtls_mpi *)s, + &ctx->MBEDTLS_PRIVATE(d), hash, SHA256_MAC_LEN, crypto_rng_wrapper, NULL); fail: mbedtls_ecdsa_free(ctx); @@ -773,6 +819,22 @@ int crypto_ecdsa_get_sign(unsigned char *hash, int crypto_edcsa_sign_verify(const unsigned char *hash, const struct crypto_bignum *r, const struct crypto_bignum *s, struct crypto_key *csign, int hlen) { +#ifdef CONFIG_MBEDTLS_V3 + /* (mbedtls_ecdsa_context *) */ + mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)csign); + if (!ecp_kp) { + return -1; + } + + mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp); + mbedtls_ecp_point *ecp_kp_q = &ecp_kp->MBEDTLS_PRIVATE(Q); + int ret = mbedtls_ecdsa_verify(ecp_kp_grp, hash, hlen, + ecp_kp_q, (mbedtls_mpi *)r, (mbedtls_mpi *)s); + if (ret != 0) { + wpa_printf(MSG_ERROR, "ecdsa verification failed"); + return ret; + } +#else mbedtls_pk_context *pkey = (mbedtls_pk_context *)csign; int ret = 0; @@ -794,7 +856,7 @@ int crypto_edcsa_sign_verify(const unsigned char *hash, mbedtls_ecdsa_free(ctx); os_free(ctx); - +#endif return ret; } @@ -805,7 +867,7 @@ void crypto_debug_print_ec_key(const char *title, struct crypto_key *key) mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( *pkey ); u8 x[32], y[32], d[32]; wpa_printf(MSG_ERROR, "curve: %s\n", - mbedtls_ecp_curve_info_from_grp_id( ecp->grp.id )->name ); + mbedtls_ecp_curve_info_from_grp_id( ecp->MBEDTLS_PRIVATE(grp).id )->name ); int len = mbedtls_mpi_size((mbedtls_mpi *)crypto_ec_get_prime((struct crypto_ec *)crypto_ec_get_group_from_key(key))); wpa_printf(MSG_ERROR, "prime len is %d\n", len); @@ -874,7 +936,7 @@ static int pk_write_ec_param( unsigned char **p, unsigned char *start, const char *oid; size_t oid_len; - if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) + if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->MBEDTLS_PRIVATE(grp).id, &oid, &oid_len ) ) != 0 ) return( ret ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); @@ -889,7 +951,7 @@ static int pk_write_ec_pubkey_formatted( unsigned char **p, unsigned char *start size_t len = 0; unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; - if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q, + if( ( ret = mbedtls_ecp_point_write_binary( &ec->MBEDTLS_PRIVATE(grp), &ec->MBEDTLS_PRIVATE(Q), format, &len, buf, sizeof( buf ) ) ) != 0 ) { diff --git a/components/wpa_supplicant/src/crypto/crypto_mbedtls-rsa.c b/components/wpa_supplicant/src/crypto/crypto_mbedtls-rsa.c index 2f50f64ea..06f22385a 100644 --- a/components/wpa_supplicant/src/crypto/crypto_mbedtls-rsa.c +++ b/components/wpa_supplicant/src/crypto/crypto_mbedtls-rsa.c @@ -110,6 +110,13 @@ struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) return (struct crypto_public_key *)pkey; } +#ifdef CONFIG_MBEDTLS_V3 +static int crypto_rng_wrapper(void *ctx, unsigned char *buf, size_t len) +{ + return os_get_random(buf, len); +} +#endif + struct crypto_private_key * crypto_private_key_import(const u8 *key, size_t len, const char *passwd) @@ -120,8 +127,12 @@ struct crypto_private_key * crypto_private_key_import(const u8 *key, return NULL; mbedtls_pk_init(pkey); - +#ifdef CONFIG_MBEDTLS_V3 + ret = mbedtls_pk_parse_key(pkey, key, len, (const unsigned char *)passwd, + passwd ? os_strlen(passwd) : 0, crypto_rng_wrapper, NULL); +#else ret = mbedtls_pk_parse_key(pkey, key, len, (const unsigned char *)passwd, passwd ? os_strlen(passwd) : 0); +#endif if (ret < 0) { wpa_printf(MSG_ERROR, "failed to parse private key"); @@ -210,7 +221,16 @@ int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, ret ); goto cleanup; } +#ifdef CONFIG_MBEDTLS_V3 + ret = mbedtls_rsa_pkcs1_encrypt(mbedtls_pk_rsa(*pkey), mbedtls_ctr_drbg_random, + ctr_drbg, inlen, in, out); + if(ret != 0) { + wpa_printf(MSG_ERROR, " failed ! mbedtls_rsa_pkcs1_encrypt returned -0x%04x", -ret); + goto cleanup; + } + *outlen = mbedtls_rsa_get_len(mbedtls_pk_rsa(*pkey)); +#else ret = mbedtls_rsa_pkcs1_encrypt(mbedtls_pk_rsa(*pkey), mbedtls_ctr_drbg_random, ctr_drbg, MBEDTLS_RSA_PUBLIC, inlen, in, out); @@ -219,6 +239,7 @@ int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, goto cleanup; } *outlen = mbedtls_pk_rsa(*pkey)->len; +#endif cleanup: mbedtls_ctr_drbg_free( ctr_drbg ); @@ -256,11 +277,15 @@ int crypto_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key, if (ret < 0) goto cleanup; - +#ifdef CONFIG_MBEDTLS_V3 + i = mbedtls_rsa_get_len(mbedtls_pk_rsa(*pkey)); + ret = mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_pk_rsa(*pkey), mbedtls_ctr_drbg_random, + ctr_drbg, &i, in, out, *outlen); +#else i = mbedtls_pk_rsa(*pkey)->len; ret = mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_pk_rsa(*pkey), mbedtls_ctr_drbg_random, ctr_drbg, MBEDTLS_RSA_PRIVATE, &i, in, out, *outlen); - +#endif *outlen = i; cleanup: @@ -277,6 +302,41 @@ int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { +#ifdef CONFIG_MBEDTLS_V3 + int ret; + const char *pers = "rsa_encrypt"; + mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; + mbedtls_entropy_context *entropy = os_malloc(sizeof(*entropy)); + mbedtls_ctr_drbg_context *ctr_drbg = os_malloc(sizeof(*ctr_drbg)); + + if (!pkey || !entropy || !ctr_drbg) { + if (entropy) + os_free(entropy); + if (ctr_drbg) + os_free(ctr_drbg); + return -1; + } + mbedtls_ctr_drbg_init( ctr_drbg ); + mbedtls_entropy_init( entropy ); + ret = mbedtls_ctr_drbg_seed(ctr_drbg, mbedtls_entropy_func, + entropy, (const unsigned char *) pers, + strlen(pers)); + + if((ret = mbedtls_rsa_pkcs1_sign(mbedtls_pk_rsa(*pkey), mbedtls_ctr_drbg_random, ctr_drbg, + (mbedtls_pk_rsa(*pkey))->MBEDTLS_PRIVATE(hash_id), + inlen, in, out)) != 0 ) { + wpa_printf(MSG_ERROR, " failed ! mbedtls_rsa_pkcs1_sign returned %d", ret ); + goto cleanup; + } + *outlen = mbedtls_rsa_get_len(mbedtls_pk_rsa(*pkey)); + + cleanup: + mbedtls_ctr_drbg_free( ctr_drbg ); + mbedtls_entropy_free( entropy ); + os_free(entropy); + os_free(ctr_drbg); + return ret; +#else int ret; mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; @@ -289,6 +349,7 @@ int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, *outlen = mbedtls_pk_rsa(*pkey)->len; return 0; +#endif } @@ -336,10 +397,16 @@ int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, goto cleanup; } - i = mbedtls_pk_rsa(*pkey)->len; + i = mbedtls_pk_rsa(*pkey)->MBEDTLS_PRIVATE(len); +#ifdef CONFIG_MBEDTLS_V3 + ret = mbedtls_rsa_pkcs1_decrypt(mbedtls_pk_rsa(*pkey), mbedtls_ctr_drbg_random, + &ctr_drbg, &i, + crypt, plain, *plain_len); +#else ret = mbedtls_rsa_pkcs1_decrypt(mbedtls_pk_rsa(*pkey), mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PUBLIC, &i, crypt, plain, *plain_len); +#endif if( ret != 0 ) { wpa_printf(MSG_ERROR, " failed ! mbedtls_rsa_pkcs1_decrypt returned %d", ret ); diff --git a/components/wpa_supplicant/src/crypto/tls_mbedtls.c b/components/wpa_supplicant/src/crypto/tls_mbedtls.c index 409281ff9..9e0684902 100644 --- a/components/wpa_supplicant/src/crypto/tls_mbedtls.c +++ b/components/wpa_supplicant/src/crypto/tls_mbedtls.c @@ -17,6 +17,10 @@ #include "utils/includes.h" #include "utils/common.h" +#ifdef CONFIG_MBEDTLS_V3 +#include "ssl_misc.h" +#endif + #include "tls/tls.h" #include "crypto/sha1.h" #include "crypto/md5.h" @@ -159,10 +163,15 @@ static int set_pki_context(tls_context_t *tls, const struct tls_connection_param wpa_printf(MSG_ERROR, "mbedtls_x509_crt_parse returned -0x%x", -ret); return ret; } - +#ifdef CONFIG_MBEDTLS_V3 + ret = mbedtls_pk_parse_key(&tls->clientkey, cfg->private_key_blob, cfg->private_key_blob_len, + (const unsigned char *)cfg->private_key_passwd, + cfg->private_key_passwd ? os_strlen(cfg->private_key_passwd) : 0, mbedtls_ctr_drbg_random, &tls->ctr_drbg); +#else ret = mbedtls_pk_parse_key(&tls->clientkey, cfg->private_key_blob, cfg->private_key_blob_len, (const unsigned char *)cfg->private_key_passwd, cfg->private_key_passwd ? os_strlen(cfg->private_key_passwd) : 0); +#endif if (ret < 0) { wpa_printf(MSG_ERROR, "mbedtls_pk_parse_keyfile returned -0x%x", -ret); return ret; @@ -519,7 +528,7 @@ int tls_connection_established(void *tls_ctx, struct tls_connection *conn) { mbedtls_ssl_context *ssl = &conn->tls->ssl; - if (ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER) { + if (ssl->MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_HANDSHAKE_OVER) { return 1; } @@ -566,7 +575,7 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx, } /* State machine just started, get client hello */ - if (tls->ssl.state == MBEDTLS_SSL_CLIENT_HELLO) { + if (tls->ssl.MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_CLIENT_HELLO) { ret = mbedtls_ssl_handshake_step(&tls->ssl); } @@ -576,15 +585,15 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx, } /* Already read sever data till hello done */ - if (tls->ssl.state == MBEDTLS_SSL_CLIENT_CERTIFICATE) { + if (tls->ssl.MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_CLIENT_CERTIFICATE) { /* Read random data before session completes, not present after handshake */ - if (tls->ssl.handshake) { - os_memcpy(conn->randbytes, tls->ssl.handshake->randbytes, + if (tls->ssl.MBEDTLS_PRIVATE(handshake)) { + os_memcpy(conn->randbytes, tls->ssl.MBEDTLS_PRIVATE(handshake)->randbytes, TLS_RANDOM_LEN * 2); } /* trigger state machine multiple times to reach till finish */ - while (tls->ssl.state <= MBEDTLS_SSL_CLIENT_FINISHED) { + while (tls->ssl.MBEDTLS_PRIVATE(state) <= MBEDTLS_SSL_CLIENT_FINISHED) { ret = mbedtls_ssl_handshake_step(&tls->ssl); if (ret < 0) { break; @@ -593,8 +602,8 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx, } /* Trigger state machine till handshake is complete or error occures */ - if (tls->ssl.state == MBEDTLS_SSL_FLUSH_BUFFERS) { - while (tls->ssl.state <= MBEDTLS_SSL_HANDSHAKE_OVER) { + if (tls->ssl.MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_FLUSH_BUFFERS) { + while (tls->ssl.MBEDTLS_PRIVATE(state) <= MBEDTLS_SSL_HANDSHAKE_OVER) { ret = mbedtls_ssl_handshake_step(&tls->ssl); if (ret < 0) { break; @@ -663,8 +672,8 @@ struct wpabuf * tls_connection_decrypt(void *tls_ctx, int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) { - if (conn && conn->tls && conn->tls->ssl.handshake) { - return conn->tls->ssl.handshake->resume; + if (conn && conn->tls && conn->tls->ssl.MBEDTLS_PRIVATE(handshake)) { + return conn->tls->ssl.MBEDTLS_PRIVATE(handshake)->resume; } return 0; @@ -799,14 +808,14 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, int ret; u8 seed[2 * TLS_RANDOM_LEN]; mbedtls_ssl_context *ssl = &conn->tls->ssl; - mbedtls_ssl_transform *transform = ssl->transform; + mbedtls_ssl_transform *transform = ssl->MBEDTLS_PRIVATE(transform); if (!ssl || !transform) { wpa_printf(MSG_ERROR, "TLS: %s, session ingo is null", __func__); return -1; } - if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { - wpa_printf(MSG_ERROR, "TLS: %s, incorrect tls state=%d", __func__, ssl->state); + if (ssl->MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) { + wpa_printf(MSG_ERROR, "TLS: %s, incorrect tls state=%d", __func__, ssl->MBEDTLS_PRIVATE(state)); return -1; } @@ -818,16 +827,22 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, } wpa_hexdump_key(MSG_MSGDUMP, "random", seed, 2 * TLS_RANDOM_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "master", ssl->session->master, TLS_MASTER_SECRET_LEN); + wpa_hexdump_key(MSG_MSGDUMP, "master", ssl->MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(master), TLS_MASTER_SECRET_LEN); + +#ifdef CONFIG_MBEDTLS_V3 + mbedtls_md_type_t type = ssl->MBEDTLS_PRIVATE(handshake)->ciphersuite_info->mac; +#else + mbedtls_md_type_t type = transform->ciphersuite_info->mac; +#endif - if (transform->ciphersuite_info->mac == MBEDTLS_MD_SHA384) { - ret = tls_prf_sha384(ssl->session->master, TLS_MASTER_SECRET_LEN, + if (type == MBEDTLS_MD_SHA384) { + ret = tls_prf_sha384(ssl->MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(master), TLS_MASTER_SECRET_LEN, label, seed, 2 * TLS_RANDOM_LEN, out, out_len); - } else if (transform->ciphersuite_info->mac == MBEDTLS_MD_SHA256) { - ret = tls_prf_sha256(ssl->session->master, TLS_MASTER_SECRET_LEN, + } else if (type == MBEDTLS_MD_SHA256) { + ret = tls_prf_sha256(ssl->MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(master), TLS_MASTER_SECRET_LEN, label, seed, 2 * TLS_RANDOM_LEN, out, out_len); } else { - ret = tls_prf_sha1_md5(ssl->session->master, TLS_MASTER_SECRET_LEN, + ret = tls_prf_sha1_md5(ssl->MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(master), TLS_MASTER_SECRET_LEN, label, seed, 2 * TLS_RANDOM_LEN, out, out_len); } @@ -864,14 +879,14 @@ int tls_connection_get_random(void *tls_ctx, struct tls_connection *conn, mbedtls_ssl_context *ssl = &conn->tls->ssl; os_memset(data, 0, sizeof(*data)); - if (ssl->state == MBEDTLS_SSL_CLIENT_HELLO) { + if (ssl->MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_CLIENT_HELLO) { return -1; } data->client_random = conn->randbytes; data->client_random_len = TLS_RANDOM_LEN; - if (ssl->state != MBEDTLS_SSL_SERVER_HELLO) { + if (ssl->MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_SERVER_HELLO) { data->server_random = conn->randbytes + TLS_RANDOM_LEN; data->server_random_len = TLS_RANDOM_LEN; } diff --git a/components/wpa_supplicant/src/eap_peer/eap_peap.c b/components/wpa_supplicant/src/eap_peer/eap_peap.c index 54e0ac0c6..38890f4bb 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_peap.c +++ b/components/wpa_supplicant/src/eap_peer/eap_peap.c @@ -66,6 +66,7 @@ struct eap_peap_data { u8 cmk[20]; int soh; /* Whether IF-TNCCS-SOH (Statement of Health; Microsoft NAP) * is enabled. */ + enum { NO_AUTH, FOR_INITIAL, ALWAYS } phase2_auth; }; @@ -114,6 +115,19 @@ eap_peap_parse_phase1(struct eap_peap_data *data, wpa_printf(MSG_DEBUG, "EAP-PEAP: Require cryptobinding"); } + if (os_strstr(phase1, "phase2_auth=0")) { + data->phase2_auth = NO_AUTH; + wpa_printf(MSG_DEBUG, + "EAP-PEAP: Do not require Phase 2 authentication"); + } else if (os_strstr(phase1, "phase2_auth=1")) { + data->phase2_auth = FOR_INITIAL; + wpa_printf(MSG_DEBUG, + "EAP-PEAP: Require Phase 2 authentication for initial connection"); + } else if (os_strstr(phase1, "phase2_auth=2")) { + data->phase2_auth = ALWAYS; + wpa_printf(MSG_DEBUG, + "EAP-PEAP: Require Phase 2 authentication for all cases"); + } #ifdef EAP_TNC if (os_strstr(phase1, "tnc=soh2")) { data->soh = 2; @@ -145,6 +159,7 @@ eap_peap_init(struct eap_sm *sm) data->force_peap_version = -1; data->peap_outer_success = 2; data->crypto_binding = OPTIONAL_BINDING; + data->phase2_auth = FOR_INITIAL; if (config && config->phase1 && eap_peap_parse_phase1(data, config->phase1) < 0) { @@ -449,6 +464,18 @@ eap_tlv_validate_cryptobinding(struct eap_sm *sm, return 0; } +static bool peap_phase2_sufficient(struct eap_sm *sm, + struct eap_peap_data *data) +{ + if ((data->phase2_auth == ALWAYS || + (data->phase2_auth == FOR_INITIAL && + !tls_connection_resumed(sm->ssl_ctx, data->ssl.conn) && + !data->ssl.client_cert_conf) || + data->phase2_eap_started) && + !data->phase2_eap_success) + return false; + return true; +} /** * eap_tlv_process - Process a received EAP-TLV message and generate a response @@ -565,6 +592,11 @@ eap_tlv_process(struct eap_sm *sm, struct eap_peap_data *data, " - force failed Phase 2"); resp_status = EAP_TLV_RESULT_FAILURE; ret->decision = DECISION_FAIL; + } else if (!peap_phase2_sufficient(sm, data)) { + wpa_printf(MSG_INFO, + "EAP-PEAP: Server indicated Phase 2 success, but sufficient Phase 2 authentication has not been completed"); + resp_status = EAP_TLV_RESULT_FAILURE; + ret->decision = DECISION_FAIL; } else { resp_status = EAP_TLV_RESULT_SUCCESS; ret->decision = DECISION_UNCOND_SUCC; @@ -939,8 +971,7 @@ eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data, /* EAP-Success within TLS tunnel is used to indicate * shutdown of the TLS channel. The authentication has * been completed. */ - if (data->phase2_eap_started && - !data->phase2_eap_success) { + if (!peap_phase2_sufficient(sm, data)) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 " "Success used to indicate success, " "but Phase 2 EAP was not yet " @@ -1194,7 +1225,7 @@ eap_peap_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_peap_data *data = priv; return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - data->phase2_success; + data->phase2_success && data->phase2_auth != ALWAYS; } diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls_common.c b/components/wpa_supplicant/src/eap_peer/eap_tls_common.c index 9c93f6d0c..31299b7f6 100755 --- a/components/wpa_supplicant/src/eap_peer/eap_tls_common.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls_common.c @@ -84,7 +84,7 @@ static void eap_tls_params_from_conf1(struct tls_connection_params *params, static int eap_tls_params_from_conf(struct eap_sm *sm, struct eap_ssl_data *data, struct tls_connection_params *params, - struct eap_peer_config *config) + struct eap_peer_config *config, int phase2) { os_memset(params, 0, sizeof(*params)); if (sm->workaround && data->eap_type != EAP_TYPE_FAST) { @@ -119,6 +119,12 @@ static int eap_tls_params_from_conf(struct eap_sm *sm, return -1; } + if (!phase2) + data->client_cert_conf = params->client_cert || + params->client_cert_blob || + params->private_key || + params->private_key_blob; + return 0; } @@ -196,7 +202,7 @@ int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, data->eap = sm; data->eap_type = eap_type; data->ssl_ctx = sm->ssl_ctx; - if (eap_tls_params_from_conf(sm, data, ¶ms, config) < 0) /* no phase2 */ + if (eap_tls_params_from_conf(sm, data, ¶ms, config, data->phase2) < 0) /* no phase2 */ return -1; if (eap_tls_init_connection(sm, data, config, ¶ms) < 0) diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls_common.h b/components/wpa_supplicant/src/eap_peer/eap_tls_common.h index 1a5e0f89e..50390c4ce 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls_common.h +++ b/components/wpa_supplicant/src/eap_peer/eap_tls_common.h @@ -73,6 +73,11 @@ struct eap_ssl_data { * eap_type - EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST) */ u8 eap_type; + + /** + * client_cert_conf: Whether client certificate has been configured + */ + bool client_cert_conf; }; diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c index d648a4542..5ad24bb99 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c @@ -225,6 +225,9 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, } } #endif /* CONFIG_IEEE80211W */ + + capab |= WPA_CAPABILITY_SPP_CAPABLE; + WPA_PUT_LE16(pos, capab); pos += 2; diff --git a/components/wpa_supplicant/src/utils/common.h b/components/wpa_supplicant/src/utils/common.h index 9d9cef3fd..a65e0edf0 100644 --- a/components/wpa_supplicant/src/utils/common.h +++ b/components/wpa_supplicant/src/utils/common.h @@ -443,6 +443,9 @@ struct wpa_freq_range_list { }; #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#ifndef TEST_FAIL +#define TEST_FAIL() 0 +#endif void wpa_bin_clear_free(void *bin, size_t len); int int_array_len(const int *a); diff --git a/docs/en/api-reference/wifi/esp_wifi.rst b/docs/en/api-reference/wifi/esp_wifi.rst index d7c24b176..2368cbd26 100644 --- a/docs/en/api-reference/wifi/esp_wifi.rst +++ b/docs/en/api-reference/wifi/esp_wifi.rst @@ -10,7 +10,7 @@ The WiFi libraries provide support for configuring and monitoring the ESP8266 Wi - AP mode (aka Soft-AP mode or Access Point mode). Stations connect to the ESP8266. - Combined AP-STA mode (ESP8266 is concurrently an access point and a station connected to another access point). -- Various security modes for the above (WPA, WPA2, WEP, etc.) +- Various security modes for the above (WPA, WPA2, WPA3, WEP, etc.) - Scanning for access points (active & passive scanning). - Promiscuous mode monitoring of IEEE802.11 WiFi packets. diff --git a/examples/get-started/hello_world/sdkconfig.ci.2MB b/examples/get-started/hello_world/sdkconfig.ci.2MB new file mode 100644 index 000000000..b6c645057 --- /dev/null +++ b/examples/get-started/hello_world/sdkconfig.ci.2MB @@ -0,0 +1 @@ +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y diff --git a/examples/get-started/hello_world/sdkconfig.ci.4MB b/examples/get-started/hello_world/sdkconfig.ci.4MB new file mode 100644 index 000000000..df4c6ef13 --- /dev/null +++ b/examples/get-started/hello_world/sdkconfig.ci.4MB @@ -0,0 +1 @@ +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y diff --git a/examples/protocols/https_mbedtls/sdkconfig.ci.mbedtlsv2 b/examples/protocols/https_mbedtls/sdkconfig.ci.mbedtlsv2 new file mode 100644 index 000000000..dac573bd2 --- /dev/null +++ b/examples/protocols/https_mbedtls/sdkconfig.ci.mbedtlsv2 @@ -0,0 +1 @@ +CONFIG_MBEDTLS_V2=y \ No newline at end of file diff --git a/examples/protocols/https_mbedtls/sdkconfig.ci.mbedtlsv3 b/examples/protocols/https_mbedtls/sdkconfig.ci.mbedtlsv3 new file mode 100644 index 000000000..8526fb91b --- /dev/null +++ b/examples/protocols/https_mbedtls/sdkconfig.ci.mbedtlsv3 @@ -0,0 +1 @@ +CONFIG_MBEDTLS_V3=y \ No newline at end of file diff --git a/examples/wifi/smart_config/main/Kconfig.projbuild b/examples/wifi/smart_config/main/Kconfig.projbuild index 533a7140c..8d27ee8e0 100644 --- a/examples/wifi/smart_config/main/Kconfig.projbuild +++ b/examples/wifi/smart_config/main/Kconfig.projbuild @@ -12,7 +12,7 @@ config ESP_TOUCH bool "ESPTouch" config AIRKISS bool "AirKiss" -config ESP_TOUCH-AIRKISS +config ESP_TOUCH_AIRKISS bool "ESPTouch and AirKiss" config ESP_TOUCH_V2 bool "ESPTouch-V2" @@ -22,7 +22,7 @@ config ESP_SMARTCONFIG_TYPE int default 0 if ESP_TOUCH default 1 if AIRKISS - default 2 if ESP_TOUCH-AIRKISS + default 2 if ESP_TOUCH_AIRKISS default 3 if ESP_TOUCH_V2 endmenu diff --git a/requirements.txt b/requirements.txt index a43c6d4ae..6a9793304 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,6 +8,6 @@ setuptools click>=5.0 pyserial>=3.0 future>=0.15.2 -cryptography>=2.1.4 +cryptography>=2.1.4,<35 pyparsing>=2.0.3,<2.4.0 pyelftools>=0.22 diff --git a/tools/ci/build_examples.sh b/tools/ci/build_examples.sh index b30f5c51f..fbeaf65ae 100755 --- a/tools/ci/build_examples.sh +++ b/tools/ci/build_examples.sh @@ -118,53 +118,75 @@ build_example () { local EXAMPLE_DIR=$(dirname "${MAKE_FILE}") local EXAMPLE_NAME=$(basename "${EXAMPLE_DIR}") - local EXAMPLE_BUILD_DIR="${ID}_${EXAMPLE_NAME}" + local EXAMPLE_BUILD_DIRS=() - if [[ -f "example_builds/${EXAMPLE_BUILD_DIR}/build/ci_build_success" ]]; then - echo "Project ${EXAMPLE_BUILD_DIR} has been built and skip building ..." + # count number of CI sdkconfig files + SDKCONFIG_CI_FILES=$( find ${EXAMPLE_DIR}/ -type f -name sdkconfig.ci.* | sort ) + if [[ -z ${SDKCONFIG_CI_FILES} ]]; then + EXAMPLE_BUILD_DIRS[0]="${ID}_${EXAMPLE_NAME}" else - echo "Building ${EXAMPLE_BUILD_DIR}..." - mkdir -p "example_builds/${EXAMPLE_BUILD_DIR}" - cp -r "${EXAMPLE_DIR}/"* "example_builds/${EXAMPLE_BUILD_DIR}/" - pushd "example_builds/${EXAMPLE_BUILD_DIR}" - # be stricter in the CI build than the default IDF settings - export EXTRA_CFLAGS="-Werror -Werror=deprecated-declarations" - export EXTRA_CXXFLAGS=${EXTRA_CFLAGS} - - # sdkconfig files are normally not checked into git, but may be present when - # a developer runs this script locally - rm -f sdkconfig - - # If sdkconfig.ci file is present, append it to sdkconfig.defaults, - # replacing environment variables - if [[ -f "$SDKCONFIG_DEFAULTS_CI" ]]; then - cat $SDKCONFIG_DEFAULTS_CI | $IDF_PATH/tools/ci/envsubst.py >> sdkconfig.defaults - fi - - # build non-verbose first - local BUILDLOG=${LOG_PATH}/ex_${EXAMPLE_BUILD_DIR}_log.txt - touch ${BUILDLOG} - - local FLASH_ARGS=build/download.config - - make clean >>${BUILDLOG} 2>&1 && - make defconfig >>${BUILDLOG} 2>&1 && - make all -j4 >>${BUILDLOG} 2>&1 && - make ota >>${BUILDLOG} 2>&1 && - make print_flash_cmd >${FLASH_ARGS}.full 2>>${BUILDLOG} && - touch build/ci_build_success || - { - RESULT=$?; FAILED_EXAMPLES+=" ${EXAMPLE_NAME}" ; - } - - tail -n 1 ${FLASH_ARGS}.full > ${FLASH_ARGS} || : - test -s ${FLASH_ARGS} || die "Error: ${FLASH_ARGS} file is empty" - - cat ${BUILDLOG} - popd - - grep -i "error\|warning" "${BUILDLOG}" 2>&1 >> "${LOG_SUSPECTED}" || : + COUNT=0 + for CI_FILE in ${SDKCONFIG_CI_FILES} + do + EXAMPLE_BUILD_DIRS[COUNT]="${ID}_${EXAMPLE_NAME}_${CI_FILE##*.}" + COUNT=$(( $COUNT + 1 )) + done fi + + for EXAMPLE_BUILD_DIR in ${EXAMPLE_BUILD_DIRS[*]} + do + if [[ -f "example_builds/${EXAMPLE_BUILD_DIR}/build/ci_build_success" ]]; then + echo "Project ${EXAMPLE_BUILD_DIR} has been built and skip building ..." + else + echo "Building ${EXAMPLE_BUILD_DIR}..." + mkdir -p "example_builds/${EXAMPLE_BUILD_DIR}" + cp -r "${EXAMPLE_DIR}/"* "example_builds/${EXAMPLE_BUILD_DIR}/" + + if [[ -n ${SDKCONFIG_CI_FILES} ]]; then + cp "example_builds/${EXAMPLE_BUILD_DIR}/sdkconfig.ci.${EXAMPLE_BUILD_DIR##*_}" "example_builds/${EXAMPLE_BUILD_DIR}/sdkconfig.ci" + rm example_builds/${EXAMPLE_BUILD_DIR}/sdkconfig.ci.* + fi + + pushd "example_builds/${EXAMPLE_BUILD_DIR}" + # be stricter in the CI build than the default IDF settings + export EXTRA_CFLAGS="-Werror -Werror=deprecated-declarations" + export EXTRA_CXXFLAGS=${EXTRA_CFLAGS} + + # sdkconfig files are normally not checked into git, but may be present when + # a developer runs this script locally + rm -f sdkconfig + + # If sdkconfig.ci file is present, append it to sdkconfig.defaults, + # replacing environment variables + if [[ -f "$SDKCONFIG_DEFAULTS_CI" ]]; then + cat $SDKCONFIG_DEFAULTS_CI | $IDF_PATH/tools/ci/envsubst.py >> sdkconfig.defaults + fi + + # build non-verbose first + local BUILDLOG=${LOG_PATH}/ex_${EXAMPLE_BUILD_DIR}_log.txt + touch ${BUILDLOG} + + local FLASH_ARGS=build/download.config + + make clean >>${BUILDLOG} 2>&1 && + make defconfig >>${BUILDLOG} 2>&1 && + make all -j4 >>${BUILDLOG} 2>&1 && + make ota >>${BUILDLOG} 2>&1 && + make print_flash_cmd >${FLASH_ARGS}.full 2>>${BUILDLOG} && + touch build/ci_build_success || + { + RESULT=$?; FAILED_EXAMPLES+=" ${EXAMPLE_NAME}" ; + } + + tail -n 1 ${FLASH_ARGS}.full > ${FLASH_ARGS} || : + test -s ${FLASH_ARGS} || die "Error: ${FLASH_ARGS} file is empty" + + cat ${BUILDLOG} + popd + + grep -i "error\|warning" "${BUILDLOG}" 2>&1 >> "${LOG_SUSPECTED}" || : + fi + done } EXAMPLE_NUM=0 diff --git a/tools/ci/build_examples_cmake.sh b/tools/ci/build_examples_cmake.sh index 914dbcc2e..24063bad9 100755 --- a/tools/ci/build_examples_cmake.sh +++ b/tools/ci/build_examples_cmake.sh @@ -132,47 +132,70 @@ build_example () { local EXAMPLE_DIR=$(dirname "${CMAKELISTS}") local EXAMPLE_NAME=$(basename "${EXAMPLE_DIR}") - local EXAMPLE_BUILD_DIR="${ID}_${EXAMPLE_NAME}" + local EXAMPLE_BUILD_DIRS=() - if [[ -f "example_builds/${EXAMPLE_BUILD_DIR}/build/ci_build_success" ]]; then - echo "Project ${EXAMPLE_NAME} has been built and skip building ..." + # count number of CI sdkconfig files + SDKCONFIG_CI_FILES=$( find ${EXAMPLE_DIR}/ -type f -name sdkconfig.ci.* | sort ) + if [[ -z ${SDKCONFIG_CI_FILES} ]]; then + EXAMPLE_BUILD_DIRS[0]="${ID}_${EXAMPLE_NAME}" else - echo "Building ${EXAMPLE_BUILD_DIR}..." - mkdir -p "example_builds/${EXAMPLE_BUILD_DIR}" - cp -r "${EXAMPLE_DIR}/"* "example_builds/${EXAMPLE_BUILD_DIR}" - pushd "example_builds/${EXAMPLE_BUILD_DIR}" - # be stricter in the CI build than the default IDF settings - export EXTRA_CFLAGS="-Werror -Werror=deprecated-declarations" - export EXTRA_CXXFLAGS=${EXTRA_CFLAGS} - - prepare_build ${EXAMPLE_NAME} - - # sdkconfig files are normally not checked into git, but may be present when - # a developer runs this script locally - rm -f sdkconfig - - # If sdkconfig.ci file is present, append it to sdkconfig.defaults, - # replacing environment variables - if [[ -f "$SDKCONFIG_DEFAULTS_CI" ]]; then - cat $SDKCONFIG_DEFAULTS_CI | $IDF_PATH/tools/ci/envsubst.py >> sdkconfig.defaults - fi - - # build non-verbose first - local BUILDLOG=${LOG_PATH}/ex_${EXAMPLE_BUILD_DIR}_log.txt - touch ${BUILDLOG} - - idf.py build >>${BUILDLOG} 2>&1 && - cp build/flash_project_args build/download.config && # backwards compatible download.config filename - touch build/ci_build_success || - { - RESULT=$?; FAILED_EXAMPLES+=" ${EXAMPLE_NAME}" ; - } - - cat ${BUILDLOG} - popd - - grep -i "error\|warning" "${BUILDLOG}" 2>&1 | grep -v "error.c.obj" >> "${LOG_SUSPECTED}" || : + COUNT=0 + for CI_FILE in ${SDKCONFIG_CI_FILES} + do + echo "${COUNT} ${CI_FILE}" + EXAMPLE_BUILD_DIRS[COUNT]="${ID}_${EXAMPLE_NAME}_${CI_FILE##*.}" + COUNT=$(( $COUNT + 1 )) + done fi + + for EXAMPLE_BUILD_DIR in ${EXAMPLE_BUILD_DIRS[*]} + do + if [[ -f "example_builds/${EXAMPLE_BUILD_DIR}/build/ci_build_success" ]]; then + echo "Project ${EXAMPLE_BUILD_DIR} has been built and skip building ..." + else + echo "Building ${EXAMPLE_BUILD_DIR}..." + mkdir -p "example_builds/${EXAMPLE_BUILD_DIR}" + cp -r "${EXAMPLE_DIR}/"* "example_builds/${EXAMPLE_BUILD_DIR}/" + + if [[ -n ${SDKCONFIG_CI_FILES} ]]; then + cp "example_builds/${EXAMPLE_BUILD_DIR}/sdkconfig.ci.${EXAMPLE_BUILD_DIR##*_}" "example_builds/${EXAMPLE_BUILD_DIR}/sdkconfig.ci" + rm example_builds/${EXAMPLE_BUILD_DIR}/sdkconfig.ci.* + fi + + pushd "example_builds/${EXAMPLE_BUILD_DIR}" + # be stricter in the CI build than the default IDF settings + export EXTRA_CFLAGS="-Werror -Werror=deprecated-declarations" + export EXTRA_CXXFLAGS=${EXTRA_CFLAGS} + + prepare_build ${EXAMPLE_NAME} + + # sdkconfig files are normally not checked into git, but may be present when + # a developer runs this script locally + rm -f sdkconfig + + # If sdkconfig.ci file is present, append it to sdkconfig.defaults, + # replacing environment variables + if [[ -f "$SDKCONFIG_DEFAULTS_CI" ]]; then + cat $SDKCONFIG_DEFAULTS_CI | $IDF_PATH/tools/ci/envsubst.py >> sdkconfig.defaults + fi + + # build non-verbose first + local BUILDLOG=${LOG_PATH}/ex_${EXAMPLE_BUILD_DIR}_log.txt + touch ${BUILDLOG} + + idf.py build >>${BUILDLOG} 2>&1 && + cp build/flash_project_args build/download.config && # backwards compatible download.config filename + touch build/ci_build_success || + { + RESULT=$?; FAILED_EXAMPLES+=" ${EXAMPLE_NAME}" ; + } + + cat ${BUILDLOG} + popd + + grep -i "error\|warning" "${BUILDLOG}" 2>&1 | grep -v "error.c.obj" >> "${LOG_SUSPECTED}" || : + fi + done } EXAMPLE_NUM=0 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy