sha: Add fault injection checks reading hash digest state

Vulnerability reported by LimitedResults under Espressif Bug Bounty Program.
This commit is contained in:
Angus Gratton
2019-05-22 10:18:55 +10:00
committed by Angus Gratton
parent ae8b2684d7
commit 0ce94950b7

View File

@@ -228,6 +228,7 @@ void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state)
{ {
uint32_t *digest_state_words = NULL; uint32_t *digest_state_words = NULL;
uint32_t *reg_addr_buf = NULL; uint32_t *reg_addr_buf = NULL;
uint32_t word_len = sha_length(sha_type)/4;
#ifndef NDEBUG #ifndef NDEBUG
{ {
SemaphoreHandle_t *engine_state = sha_get_engine_state(sha_type); SemaphoreHandle_t *engine_state = sha_get_engine_state(sha_type);
@@ -250,15 +251,25 @@ void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state)
if(sha_type == SHA2_384 || sha_type == SHA2_512) { if(sha_type == SHA2_384 || sha_type == SHA2_512) {
/* for these ciphers using 64-bit states, swap each pair of words */ /* for these ciphers using 64-bit states, swap each pair of words */
DPORT_INTERRUPT_DISABLE(); // Disable interrupt only on current CPU. DPORT_INTERRUPT_DISABLE(); // Disable interrupt only on current CPU.
for(int i = 0; i < sha_length(sha_type)/4; i += 2) { for(int i = 0; i < word_len; i += 2) {
digest_state_words[i+1] = DPORT_SEQUENCE_REG_READ((uint32_t)&reg_addr_buf[i]); digest_state_words[i+1] = DPORT_SEQUENCE_REG_READ((uint32_t)&reg_addr_buf[i]);
digest_state_words[i] = DPORT_SEQUENCE_REG_READ((uint32_t)&reg_addr_buf[i+1]); digest_state_words[i] = DPORT_SEQUENCE_REG_READ((uint32_t)&reg_addr_buf[i+1]);
} }
DPORT_INTERRUPT_RESTORE(); // restore the previous interrupt level DPORT_INTERRUPT_RESTORE(); // restore the previous interrupt level
} else { } else {
esp_dport_access_read_buffer(digest_state_words, (uint32_t)&reg_addr_buf[0], sha_length(sha_type)/4); esp_dport_access_read_buffer(digest_state_words, (uint32_t)&reg_addr_buf[0], word_len);
} }
esp_sha_unlock_memory_block(); esp_sha_unlock_memory_block();
/* Fault injection check: verify SHA engine actually ran,
state is not all zeroes.
*/
for (int i = 0; i < word_len; i++) {
if (digest_state_words[i] != 0) {
return;
}
}
abort(); // SHA peripheral returned all zero state, probably due to fault injection
} }
void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block) void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block)