1 // Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 /**
16 * @file
17 * @brief Checksum interface implemetation
18 *
19 * This file is an implementation for the coredump checksum interface defined
20 * in "core_dump_checksum.h".
21 * Please refer to this file for more information about the functions.
22 */
23
24 #include <stddef.h>
25 #include "esp_core_dump_port_impl.h"
26 #include "esp_core_dump_types.h"
27 #include "core_dump_checksum.h"
28 #include "esp_attr.h"
29
30 #if CONFIG_ESP_COREDUMP_CHECKSUM_CRC32
31 #include "esp_rom_crc.h"
32 #elif CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
33 #include "mbedtls/sha256.h"
34 #endif
35
36 #if CONFIG_ESP_COREDUMP_ENABLE
37
38 const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_checksum";
39
40 #define COREDUMP_SHA256_LEN 32
41
42 typedef uint32_t core_dump_crc_t;
43
44 struct core_dump_checksum_ctx {
45 #if CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
46 mbedtls_sha256_context ctx;
47 uint8_t sha_output[COREDUMP_SHA256_LEN];
48 #elif CONFIG_ESP_COREDUMP_CHECKSUM_CRC32
49 core_dump_crc_t crc;
50 #endif
51 /* Number of bytes used to calculate the checksum */
52 uint32_t total_bytes_checksum;
53 };
54
55 static core_dump_checksum_ctx s_checksum_context = { 0 };
56
57 /**
58 * Get ELF core dump version.
59 * Please check esp checksum interface for more details.
60 */
esp_core_dump_elf_version(void)61 uint32_t esp_core_dump_elf_version(void)
62 {
63 #if CONFIG_ESP_COREDUMP_CHECKSUM_CRC32
64 return COREDUMP_VERSION_ELF_CRC32;
65 #elif CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
66 return COREDUMP_VERSION_ELF_SHA256;
67 #endif
68 }
69
esp_core_dump_checksum_init(core_dump_checksum_ctx ** out_ctx)70 void esp_core_dump_checksum_init(core_dump_checksum_ctx** out_ctx)
71 {
72 if (out_ctx) {
73 #if CONFIG_ESP_COREDUMP_CHECKSUM_CRC32
74 s_checksum_context.crc = 0;
75 #elif CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
76 mbedtls_sha256_init(&s_checksum_context.ctx);
77 (void)mbedtls_sha256_starts_ret(&s_checksum_context.ctx, 0);
78 #endif
79 s_checksum_context.total_bytes_checksum = 0;
80
81 *out_ctx = &s_checksum_context;
82 }
83 }
84
85
esp_core_dump_checksum_update(core_dump_checksum_ctx * cks_ctx,void * data,size_t data_len)86 void esp_core_dump_checksum_update(core_dump_checksum_ctx* cks_ctx, void* data, size_t data_len)
87 {
88 ESP_COREDUMP_DEBUG_ASSERT(cks_ctx);
89
90 if (data) {
91 #if CONFIG_ESP_COREDUMP_CHECKSUM_CRC32
92 cks_ctx->crc = esp_rom_crc32_le(cks_ctx->crc, data, data_len);
93 #elif CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
94 #if CONFIG_MBEDTLS_HARDWARE_SHA
95 // set software mode of SHA calculation
96 cks_ctx->ctx.mode = ESP_MBEDTLS_SHA256_SOFTWARE;
97 #endif
98 (void)mbedtls_sha256_update_ret(&cks_ctx->ctx, data, data_len);
99 #endif
100 // keep counter of cashed bytes
101 cks_ctx->total_bytes_checksum += data_len;
102 } else {
103 ESP_COREDUMP_LOGE("Empty data to add to checksum calculation!");
104 }
105 }
106
107
esp_core_dump_checksum_finish(core_dump_checksum_ctx * cks_ctx,core_dump_checksum_bytes * chs_ptr)108 uint32_t esp_core_dump_checksum_finish(core_dump_checksum_ctx* cks_ctx, core_dump_checksum_bytes* chs_ptr)
109 {
110 uint32_t chs_len = 0;
111
112 /* cks_ctx pointer can be NULL only if chs_ptr is also NULL. */
113 ESP_COREDUMP_DEBUG_ASSERT(cks_ctx != NULL || chs_ptr == NULL);
114
115 #if CONFIG_ESP_COREDUMP_CHECKSUM_CRC32
116 if (chs_ptr != NULL) {
117 *chs_ptr = (core_dump_checksum_bytes) &cks_ctx->crc;
118 }
119 chs_len = sizeof(cks_ctx->crc);
120
121 #elif CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
122 if (chs_ptr != NULL) {
123 (void)mbedtls_sha256_finish_ret(&cks_ctx->ctx, (uint8_t*)&cks_ctx->sha_output);
124 *chs_ptr = &cks_ctx->sha_output[0];
125 mbedtls_sha256_free(&cks_ctx->ctx);
126 }
127 chs_len = sizeof(cks_ctx->sha_output);
128
129 #endif
130
131 if (cks_ctx) {
132 ESP_COREDUMP_LOG_PROCESS("Total length of hashed data: %d", cks_ctx->total_bytes_checksum);
133 }
134
135 return chs_len;
136 }
137
138
139 /**
140 * Returns the size, in bytes, of the checksums.
141 * Currently, this function is just an alias to esp_core_dump_checksum_finish
142 * function, which can return the size of the checksum if given parameters
143 * are NULL. However, the implementation can evolve in the future independently
144 * from esp_core_dump_checksum_finish function.
145 */
esp_core_dump_checksum_size(void)146 uint32_t esp_core_dump_checksum_size(void)
147 {
148 return esp_core_dump_checksum_finish(NULL, NULL);
149 }
150
151
152 #if CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
153
esp_core_dump_print_sha256(const char * msg,const uint8_t * sha_output)154 static void esp_core_dump_print_sha256(const char* msg, const uint8_t* sha_output)
155 {
156 /* As this function is only called by `esp_core_dump_print_checksum`, we
157 * have the guarantee that sha_output is not NULL. */
158 if (msg != NULL) {
159 esp_rom_printf(DRAM_STR("%s='"), msg);
160 }
161
162 for (int i = 0; i < COREDUMP_SHA256_LEN; i++) {
163 esp_rom_printf(DRAM_STR("%02x"), sha_output[i]);
164 }
165 esp_rom_printf(DRAM_STR("'\r\n"));
166 }
167
168 #endif
169
170
171 /**
172 * Prints a message and a checksum given as parameters.
173 * This function is useful when the caller isn't explicitly aware of which
174 * checksum type (CRC32, SHA256, etc) is being used.
175 */
esp_core_dump_print_checksum(const char * msg,core_dump_checksum_bytes checksum)176 void esp_core_dump_print_checksum(const char* msg, core_dump_checksum_bytes checksum)
177 {
178 ESP_COREDUMP_DEBUG_ASSERT(checksum != NULL);
179
180 #if CONFIG_ESP_COREDUMP_CHECKSUM_CRC32
181 if (msg != NULL) {
182 esp_rom_printf(DRAM_STR("%s='"), msg);
183 }
184 esp_rom_printf(DRAM_STR("%08x"), *((const uint32_t*) checksum));
185 esp_rom_printf(DRAM_STR("'\r\n"));
186 #elif CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
187 esp_core_dump_print_sha256(msg, (const uint8_t*) checksum);
188 #endif
189 }
190
191
192 #endif
193