diff --git a/components/espcoredump/include/esp_core_dump.h b/components/espcoredump/include/esp_core_dump.h index 24a13e5d86..022bde9513 100644 --- a/components/espcoredump/include/esp_core_dump.h +++ b/components/espcoredump/include/esp_core_dump.h @@ -79,7 +79,7 @@ void esp_core_dump_to_uart(panic_info_t *info); * This function is always available, even when core dump is disabled in menuconfig. * * @param out_addr pointer to store image address in flash. - * @param out_size pointer to store image size in flash (including CRC). In bytes. + * @param out_size pointer to store image size in flash (including checksum). In bytes. * * @return ESP_OK on success, otherwise \see esp_err_t */ diff --git a/components/espcoredump/include_core_dump/esp_core_dump_port.h b/components/espcoredump/include_core_dump/esp_core_dump_port.h index 95226cea93..46df6f7edd 100644 --- a/components/espcoredump/include_core_dump/esp_core_dump_port.h +++ b/components/espcoredump/include_core_dump/esp_core_dump_port.h @@ -73,12 +73,14 @@ int esp_core_dump_get_user_ram_info(coredump_region_t region, uint32_t *start); void esp_core_dump_checksum_init(core_dump_write_data_t* wr_data); void esp_core_dump_checksum_update(core_dump_write_data_t* wr_data, void* data, size_t data_len); size_t esp_core_dump_checksum_finish(core_dump_write_data_t* wr_data, void** chs_ptr); +uint32_t esp_core_dump_checksum_size(void); #if CONFIG_ESP_COREDUMP_CHECKSUM_SHA256 void esp_core_dump_print_sha256(const char* msg, const uint8_t* sha_output); int esp_core_dump_sha(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen, unsigned char output[32]); #endif +void esp_core_dump_print_checksum(const char* msg, const void* checksum); #define esp_core_dump_in_isr_context() xPortInterruptedFromISRContext() uint32_t esp_core_dump_get_isr_stack_end(void); diff --git a/components/espcoredump/include_core_dump/esp_core_dump_priv.h b/components/espcoredump/include_core_dump/esp_core_dump_priv.h index a7df11b147..14149daaa2 100644 --- a/components/espcoredump/include_core_dump/esp_core_dump_priv.h +++ b/components/espcoredump/include_core_dump/esp_core_dump_priv.h @@ -66,6 +66,8 @@ extern "C" { #define COREDUMP_VERSION COREDUMP_VERSION_BIN_CURRENT #endif +#define COREDUMP_CHECKSUM_MAX_LEN 32 + typedef esp_err_t (*esp_core_dump_write_prepare_t)(void *priv, uint32_t *data_len); typedef esp_err_t (*esp_core_dump_write_start_t)(void *priv); typedef esp_err_t (*esp_core_dump_write_end_t)(void *priv); diff --git a/components/espcoredump/src/core_dump_flash.c b/components/espcoredump/src/core_dump_flash.c index dd3cfbeadb..1103f4bc78 100644 --- a/components/espcoredump/src/core_dump_flash.c +++ b/components/espcoredump/src/core_dump_flash.c @@ -29,6 +29,8 @@ typedef struct _core_dump_partition_t uint32_t start; /* Core dump partition size. */ uint32_t size; + /* Flag set to true if the partition is encrypted. */ + bool encrypted; } core_dump_partition_t; typedef struct _core_dump_flash_config_t @@ -56,7 +58,7 @@ static esp_err_t esp_core_dump_flash_custom_write(uint32_t address, const void * { esp_err_t err = ESP_OK; - if (esp_flash_encryption_enabled()) { + if (esp_flash_encryption_enabled() && s_core_flash_config.partition.encrypted) { err = ESP_COREDUMP_FLASH_WRITE_ENCRYPTED(address, buffer, length); } else { err = ESP_COREDUMP_FLASH_WRITE(address, buffer, length); @@ -86,6 +88,7 @@ void esp_core_dump_flash_init(void) ESP_COREDUMP_LOGI("Found partition '%s' @ %x %d bytes", core_part->label, core_part->address, core_part->size); s_core_flash_config.partition.start = core_part->address; s_core_flash_config.partition.size = core_part->size; + s_core_flash_config.partition.encrypted = core_part->encrypted; s_core_flash_config.partition_config_crc = esp_core_dump_calc_flash_config_crc(); } @@ -346,10 +349,20 @@ void esp_core_dump_init(void) esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size) { - spi_flash_mmap_handle_t core_data_handle = { 0 }; esp_err_t err = ESP_OK; - const void *core_data = NULL; + core_dump_write_data_t wr_data = { 0 }; + uint32_t size = 0; + uint32_t offset = 0; + const uint32_t checksum_size = esp_core_dump_checksum_size(); + void* checksum_calc = NULL; + /* Initialize the checksum we have to read from the flash to the biggest + * size we can have for a checksum. */ + uint8_t checksum_read[COREDUMP_CHECKSUM_MAX_LEN] = { 0 }; + /* Assert that we won't have any problems with our checksum size. */ + assert(checksum_size <= COREDUMP_CHECKSUM_MAX_LEN); + + /* Check the validity of the parameters. */ if (out_addr == NULL || out_size == NULL) { return ESP_ERR_INVALID_ARG; } @@ -367,78 +380,77 @@ esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size) return ESP_ERR_INVALID_SIZE; } - /* The partition has been found, map its first uint32_t value, which + /* The partition has been found, get its first uint32_t value, which * describes the core dump file size. */ - err = esp_partition_mmap(core_part, 0, sizeof(uint32_t), - SPI_FLASH_MMAP_DATA, &core_data, &core_data_handle); + err = esp_partition_read(core_part, 0, &size, sizeof(uint32_t)); if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to mmap core dump data (%d)!", err); + ESP_LOGE(TAG, "Failed to read core dump data size (%d)!", err); return err; } - /* Extract the size and unmap the partition. */ - uint32_t *dw = (uint32_t *)core_data; - *out_size = *dw; - spi_flash_munmap(core_data_handle); - if (*out_size == 0xFFFFFFFF) { + /* Verify that the size read from the flash is not corrupted. */ + if (size == 0xFFFFFFFF) { ESP_LOGD(TAG, "Blank core dump partition!"); - return ESP_ERR_INVALID_SIZE; - } else if ((*out_size < sizeof(uint32_t)) || (*out_size > core_part->size)) { - ESP_LOGE(TAG, "Incorrect size of core dump image: %d", *out_size); - return ESP_ERR_INVALID_SIZE; + err = ESP_ERR_INVALID_SIZE; + } else if ((size < sizeof(uint32_t)) || (size > core_part->size)) { + ESP_LOGE(TAG, "Incorrect size of core dump image: %d", size); + err = ESP_ERR_INVALID_SIZE; } - /* Remap the full core dump parition, including the final checksum. */ - err = esp_partition_mmap(core_part, 0, *out_size, - SPI_FLASH_MMAP_DATA, &core_data, &core_data_handle); if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to mmap core dump data (%d)!", err); return err; } - // TODO: check CRC or SHA basing on the version of core dump image stored in flash -#if CONFIG_ESP_COREDUMP_CHECKSUM_CRC32 - uint32_t *crc = (uint32_t *)(((uint8_t *)core_data) + *out_size); - /* Decrement crc to make it point onto our CRC checksum. */ - crc--; + /* Save the size read. */ + *out_size = size; - /* Calculate CRC checksum again over core dump data read from the flash, - * excluding CRC field. */ - core_dump_crc_t cur_crc = esp_rom_crc32_le(0, (uint8_t const *)core_data, *out_size - sizeof(core_dump_crc_t)); - if (*crc != cur_crc) { - ESP_LOGD(TAG, "Core dump CRC offset 0x%x, data size: %u", - (uint32_t)((uint32_t)crc - (uint32_t)core_data), *out_size); - ESP_LOGE(TAG, "Core dump data CRC check failed: 0x%x -> 0x%x!", *crc, cur_crc); - spi_flash_munmap(core_data_handle); - return ESP_ERR_INVALID_CRC; + /* The final checksum, from the image, doesn't take part into the checksum + * calculation, so subtract it from the bytes we are going to read. */ + size -= checksum_size ; + + /* Initiate the checksum calculation for the coredump in the flash. */ + esp_core_dump_checksum_init(&wr_data); + + while (size > 0) { + /* Use the cache in core_dump_write_data_t structure to read the + * partition. */ + const uint32_t toread = (size < COREDUMP_CACHE_SIZE) ? size : COREDUMP_CACHE_SIZE; + + /* Read the content of the flash. */ + err = esp_partition_read(core_part, offset, wr_data.cached_data, toread); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to read data from core dump (%d)!", err); + return err; + } + + /* Update the checksum according to what was just read. */ + esp_core_dump_checksum_update(&wr_data, wr_data.cached_data, toread); + + /* Move the offset forward and decrease the remaining size. */ + offset += toread; + size -= toread; } -#elif CONFIG_ESP_COREDUMP_CHECKSUM_SHA256 - /* sha256_ptr will point to our checksum. */ - uint8_t* sha256_ptr = (uint8_t*)(((uint8_t *)core_data) + *out_size); - sha256_ptr -= COREDUMP_SHA256_LEN; - ESP_LOGD(TAG, "Core dump data offset, size: %d, %u!", - (uint32_t)((uint32_t)sha256_ptr - (uint32_t)core_data), *out_size); - /* The following array will contain the SHA256 value of the core dump data - * read from the flash. */ - unsigned char sha_output[COREDUMP_SHA256_LEN]; - mbedtls_sha256_context ctx; - ESP_LOGI(TAG, "Calculate SHA256 for coredump:"); - (void)esp_core_dump_sha(&ctx, core_data, *out_size - COREDUMP_SHA256_LEN, sha_output); + /* The coredump has been totally read, finish the checksum calculation. */ + esp_core_dump_checksum_finish(&wr_data, &checksum_calc); - /* Compare the two checksums, if they are different, the file on the flash - * may be corrupted. */ - if (memcmp((uint8_t*)sha256_ptr, (uint8_t*)sha_output, COREDUMP_SHA256_LEN) != 0) { - ESP_LOGE(TAG, "Core dump data SHA256 check failed:"); - esp_core_dump_print_sha256("Calculated SHA256", (uint8_t*)sha_output); - esp_core_dump_print_sha256("Image SHA256",(uint8_t*)sha256_ptr); - spi_flash_munmap(core_data_handle); + /* Read the checksum from the flash and compare to the one just + * calculated. */ + err = esp_partition_read(core_part, *out_size - checksum_size, checksum_read, checksum_size); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to read checksum from core dump (%d)!", err); + return err; + } + + /* Compare the checksum read from the flash and the one just calculated. */ + if (memcmp(checksum_calc, checksum_read, checksum_size) != 0) { + ESP_LOGE(TAG, "Core dump data check failed:"); + esp_core_dump_print_checksum("Calculated checksum", checksum_calc); + esp_core_dump_print_checksum("Image checksum", checksum_read); return ESP_ERR_INVALID_CRC; } else { - ESP_LOGI(TAG, "Core dump data SHA256 is correct"); + ESP_LOGI(TAG, "Core dump data checksum is correct"); } -#endif - spi_flash_munmap(core_data_handle); *out_addr = core_part->address; return ESP_OK; diff --git a/components/espcoredump/src/core_dump_port.c b/components/espcoredump/src/core_dump_port.c index 7be3f5beec..ff316c29a8 100644 --- a/components/espcoredump/src/core_dump_port.c +++ b/components/espcoredump/src/core_dump_port.c @@ -207,6 +207,22 @@ void esp_core_dump_print_sha256(const char* msg, const uint8_t* sha_output) } #endif +/** + * Prints a message and a checksum given as parameters. + * This function is useful when the caller isn't explicitly aware of which + * checksum type (CRC32, SHA256, etc) is being used. + */ +void esp_core_dump_print_checksum(const char* msg, const void* checksum) +{ +#if CONFIG_ESP_COREDUMP_CHECKSUM_CRC32 + esp_rom_printf(DRAM_STR("%s='"), msg); + esp_rom_printf(DRAM_STR("%08x"), *((const uint32_t*) checksum)); + esp_rom_printf(DRAM_STR("'\r\n")); +#elif CONFIG_ESP_COREDUMP_CHECKSUM_SHA256 + esp_core_dump_print_sha256(msg, (const uint8_t*) checksum); +#endif +} + void esp_core_dump_checksum_init(core_dump_write_data_t* wr_data) { if (wr_data) { @@ -238,6 +254,18 @@ void esp_core_dump_checksum_update(core_dump_write_data_t* wr_data, void* data, } } +/** + * Returns the size, in bytes, of the checksums. + * Currently, this function is just an alias to esp_core_dump_checksum_finish + * function, which can return the size of the checksum if given parameters + * are NULL. However, the implementation can evolve in the future independently + * from esp_core_dump_checksum_finish function. + */ +uint32_t esp_core_dump_checksum_size(void) +{ + return esp_core_dump_checksum_finish(NULL, NULL); +} + uint32_t esp_core_dump_checksum_finish(core_dump_write_data_t* wr_data, void** chs_ptr) { // get core dump checksum