mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-02 12:14:32 +02:00
Merge branch 'bugfix/coredump_plain_partition_on_encrypted_flash' into 'master'
coredump: Core dump is encrypted if the partition itself is encrypted Closes IDF-458 See merge request espressif/esp-idf!11424
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.
|
* 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_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
|
* @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_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);
|
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);
|
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
|
#if CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
|
||||||
void esp_core_dump_print_sha256(const char* msg, const uint8_t* sha_output);
|
void esp_core_dump_print_sha256(const char* msg, const uint8_t* sha_output);
|
||||||
int esp_core_dump_sha(mbedtls_sha256_context *ctx,
|
int esp_core_dump_sha(mbedtls_sha256_context *ctx,
|
||||||
const unsigned char *input, size_t ilen, unsigned char output[32]);
|
const unsigned char *input, size_t ilen, unsigned char output[32]);
|
||||||
#endif
|
#endif
|
||||||
|
void esp_core_dump_print_checksum(const char* msg, const void* checksum);
|
||||||
|
|
||||||
#define esp_core_dump_in_isr_context() xPortInterruptedFromISRContext()
|
#define esp_core_dump_in_isr_context() xPortInterruptedFromISRContext()
|
||||||
uint32_t esp_core_dump_get_isr_stack_end(void);
|
uint32_t esp_core_dump_get_isr_stack_end(void);
|
||||||
|
@@ -66,6 +66,8 @@ extern "C" {
|
|||||||
#define COREDUMP_VERSION COREDUMP_VERSION_BIN_CURRENT
|
#define COREDUMP_VERSION COREDUMP_VERSION_BIN_CURRENT
|
||||||
#endif
|
#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_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_start_t)(void *priv);
|
||||||
typedef esp_err_t (*esp_core_dump_write_end_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;
|
uint32_t start;
|
||||||
/* Core dump partition size. */
|
/* Core dump partition size. */
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
/* Flag set to true if the partition is encrypted. */
|
||||||
|
bool encrypted;
|
||||||
} core_dump_partition_t;
|
} core_dump_partition_t;
|
||||||
|
|
||||||
typedef struct _core_dump_flash_config_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;
|
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);
|
err = ESP_COREDUMP_FLASH_WRITE_ENCRYPTED(address, buffer, length);
|
||||||
} else {
|
} else {
|
||||||
err = ESP_COREDUMP_FLASH_WRITE(address, buffer, length);
|
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);
|
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.start = core_part->address;
|
||||||
s_core_flash_config.partition.size = core_part->size;
|
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();
|
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)
|
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;
|
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) {
|
if (out_addr == NULL || out_size == NULL) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
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;
|
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. */
|
* describes the core dump file size. */
|
||||||
err = esp_partition_mmap(core_part, 0, sizeof(uint32_t),
|
err = esp_partition_read(core_part, 0, &size, sizeof(uint32_t));
|
||||||
SPI_FLASH_MMAP_DATA, &core_data, &core_data_handle);
|
|
||||||
if (err != ESP_OK) {
|
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;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extract the size and unmap the partition. */
|
/* Verify that the size read from the flash is not corrupted. */
|
||||||
uint32_t *dw = (uint32_t *)core_data;
|
if (size == 0xFFFFFFFF) {
|
||||||
*out_size = *dw;
|
|
||||||
spi_flash_munmap(core_data_handle);
|
|
||||||
if (*out_size == 0xFFFFFFFF) {
|
|
||||||
ESP_LOGD(TAG, "Blank core dump partition!");
|
ESP_LOGD(TAG, "Blank core dump partition!");
|
||||||
return ESP_ERR_INVALID_SIZE;
|
err = ESP_ERR_INVALID_SIZE;
|
||||||
} else if ((*out_size < sizeof(uint32_t)) || (*out_size > core_part->size)) {
|
} else if ((size < sizeof(uint32_t)) || (size > core_part->size)) {
|
||||||
ESP_LOGE(TAG, "Incorrect size of core dump image: %d", *out_size);
|
ESP_LOGE(TAG, "Incorrect size of core dump image: %d", size);
|
||||||
return ESP_ERR_INVALID_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) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to mmap core dump data (%d)!", err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check CRC or SHA basing on the version of core dump image stored in flash
|
/* Save the size read. */
|
||||||
#if CONFIG_ESP_COREDUMP_CHECKSUM_CRC32
|
*out_size = size;
|
||||||
uint32_t *crc = (uint32_t *)(((uint8_t *)core_data) + *out_size);
|
|
||||||
/* Decrement crc to make it point onto our CRC checksum. */
|
|
||||||
crc--;
|
|
||||||
|
|
||||||
/* Calculate CRC checksum again over core dump data read from the flash,
|
/* The final checksum, from the image, doesn't take part into the checksum
|
||||||
* excluding CRC field. */
|
* calculation, so subtract it from the bytes we are going to read. */
|
||||||
core_dump_crc_t cur_crc = esp_rom_crc32_le(0, (uint8_t const *)core_data, *out_size - sizeof(core_dump_crc_t));
|
size -= checksum_size ;
|
||||||
if (*crc != cur_crc) {
|
|
||||||
ESP_LOGD(TAG, "Core dump CRC offset 0x%x, data size: %u",
|
/* Initiate the checksum calculation for the coredump in the flash. */
|
||||||
(uint32_t)((uint32_t)crc - (uint32_t)core_data), *out_size);
|
esp_core_dump_checksum_init(&wr_data);
|
||||||
ESP_LOGE(TAG, "Core dump data CRC check failed: 0x%x -> 0x%x!", *crc, cur_crc);
|
|
||||||
spi_flash_munmap(core_data_handle);
|
while (size > 0) {
|
||||||
return ESP_ERR_INVALID_CRC;
|
/* 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
|
/* Update the checksum according to what was just read. */
|
||||||
* read from the flash. */
|
esp_core_dump_checksum_update(&wr_data, wr_data.cached_data, toread);
|
||||||
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);
|
|
||||||
|
|
||||||
/* Compare the two checksums, if they are different, the file on the flash
|
/* Move the offset forward and decrease the remaining size. */
|
||||||
* may be corrupted. */
|
offset += toread;
|
||||||
if (memcmp((uint8_t*)sha256_ptr, (uint8_t*)sha_output, COREDUMP_SHA256_LEN) != 0) {
|
size -= toread;
|
||||||
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);
|
/* The coredump has been totally read, finish the checksum calculation. */
|
||||||
spi_flash_munmap(core_data_handle);
|
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;
|
return ESP_ERR_INVALID_CRC;
|
||||||
} else {
|
} 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;
|
*out_addr = core_part->address;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
|
@@ -207,6 +207,22 @@ void esp_core_dump_print_sha256(const char* msg, const uint8_t* sha_output)
|
|||||||
}
|
}
|
||||||
#endif
|
#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)
|
void esp_core_dump_checksum_init(core_dump_write_data_t* wr_data)
|
||||||
{
|
{
|
||||||
if (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)
|
uint32_t esp_core_dump_checksum_finish(core_dump_write_data_t* wr_data, void** chs_ptr)
|
||||||
{
|
{
|
||||||
// get core dump checksum
|
// get core dump checksum
|
||||||
|
Reference in New Issue
Block a user