mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-01 19:54:32 +02:00
coredump: Core dump is encrypted if the partition itself is encrypted
Core dump can now be written in plain text if the partition itself is encrypted. So it is important to modify the partition table if the user wants an encrypted core dump partition as by default, it is not. Added some functions in core_dump_port.c to abstract the checksum implementation from core_dump_flash.c file. Closes IDF-458
This commit is contained in:
@@ -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
|
||||
*/
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
#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);
|
||||
/* Update the checksum according to what was just read. */
|
||||
esp_core_dump_checksum_update(&wr_data, wr_data.cached_data, toread);
|
||||
|
||||
/* 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);
|
||||
/* Move the offset forward and decrease the remaining size. */
|
||||
offset += toread;
|
||||
size -= toread;
|
||||
}
|
||||
|
||||
/* The coredump has been totally read, finish the checksum calculation. */
|
||||
esp_core_dump_checksum_finish(&wr_data, &checksum_calc);
|
||||
|
||||
/* 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;
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user