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
pull/6365/head
Ivan Grokhotkov 2020-12-14 15:40:05 +08:00
commit e0e6194c95
5 zmienionych plików z 101 dodań i 57 usunięć

Wyświetl plik

@ -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
*/

Wyświetl plik

@ -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);

Wyświetl plik

@ -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);

Wyświetl plik

@ -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;

Wyświetl plik

@ -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