blob: 5c6a47553fe3e3e328ae1f4b6f0c1b6348c42e6d [file] [log] [blame]
Gustavo Henrique Nihei523ef3f2021-11-12 17:53:18 -03001/*
2 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#include <string.h>
8#include "sdkconfig.h"
9#include "esp_log.h"
10#include "esp_secure_boot.h"
11#include "bootloader_flash_priv.h"
12#include "bootloader_sha.h"
13#include "bootloader_utility.h"
14#include "esp_image_format.h"
15#include "esp_efuse.h"
16#include "esp_efuse_table.h"
17
Almir Okato54ef4842023-03-07 17:56:53 -030018#if CONFIG_IDF_TARGET_ESP32
19#include "esp32/rom/secure_boot.h"
20#elif CONFIG_IDF_TARGET_ESP32S2
21#include "esp32s2/rom/secure_boot.h"
22#elif CONFIG_IDF_TARGET_ESP32C3
23#include "esp32c3/rom/secure_boot.h"
24#elif CONFIG_IDF_TARGET_ESP32S3
25#include "esp32s3/rom/secure_boot.h"
26#elif CONFIG_IDF_TARGET_ESP32H4
27#include "esp32h4/rom/secure_boot.h"
28#elif CONFIG_IDF_TARGET_ESP32C2
29#include "esp32c2/rom/secure_boot.h"
30#elif CONFIG_IDF_TARGET_ESP32C6
31#include "esp32c6/rom/secure_boot.h"
32#endif
33
Gustavo Henrique Nihei523ef3f2021-11-12 17:53:18 -030034/* The following API implementations are used only when called
35 * from the bootloader code.
36 */
37
38#ifdef CONFIG_SECURE_BOOT_V2_ENABLED
39
40#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
41static const char *TAG = "secure_boot_v2";
42
43/* A signature block is valid when it has correct magic byte, crc and image digest. */
44static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block, int block_num, const uint8_t *image_digest)
45{
46 if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC) {
47 // All signature blocks have been parsed, no new signature block present.
48 ESP_LOGD(TAG, "Signature block(%d) invalid/absent.", block_num);
49 return ESP_FAIL;
50 }
51 if (block->block_crc != esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN)) {
52 ESP_LOGE(TAG, "Magic byte correct but incorrect crc.");
53 return ESP_FAIL;
54 }
55 if (memcmp(image_digest, block->image_digest, ESP_SECURE_BOOT_DIGEST_LEN)) {
56 ESP_LOGE(TAG, "Magic byte & CRC correct but incorrect image digest.");
57 return ESP_FAIL;
58 } else {
59 ESP_LOGD(TAG, "valid signature block(%d) found", block_num);
60 return ESP_OK;
61 }
62 return ESP_FAIL;
63}
64
65/* Generates the public key digests of the valid public keys in an image's
66 signature block, verifies each signature, and stores the key digests in the
67 public_key_digests structure.
68
69 @param flash_offset Image offset in flash
70 @param flash_size Image size in flash (not including signature block)
71 @param[out] public_key_digests Pointer to structure to hold the key digests for valid sig blocks
72
73
74 Note that this function doesn't read any eFuses, so it doesn't know if the
75 keys are ultimately trusted by the hardware or not
76
77 @return - ESP_OK if no signatures failed to verify, or if no valid signature blocks are found at all.
78 - ESP_FAIL if there's a valid signature block that doesn't verify using the included public key (unexpected!)
79*/
80static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, esp_image_sig_public_key_digests_t *public_key_digests)
81{
82 esp_err_t ret;
83 uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
84 uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
85 size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
86
87 ESP_LOGD(TAG, "calculating public key digests for sig blocks of image offset 0x%x (sig block offset 0x%x)", flash_offset, sig_block_addr);
88
89 bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t));
90
91 ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
92 if (ret != ESP_OK) {
93 ESP_LOGE(TAG, "error generating image digest, %d", ret);
94 return ret;
95 }
96
97 ESP_LOGD(TAG, "reading signature(s)");
98 const ets_secure_boot_signature_t *signatures = bootloader_mmap(sig_block_addr, sizeof(ets_secure_boot_signature_t));
99 if (signatures == NULL) {
100 ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", sig_block_addr, sizeof(ets_secure_boot_signature_t));
101 return ESP_FAIL;
102 }
103
104 /* Validating Signature block */
105 for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
106 const ets_secure_boot_sig_block_t *block = &signatures->block[i];
107
108 ret = validate_signature_block(block, i, image_digest);
109 if (ret != ESP_OK) {
110 ret = ESP_OK; // past the last valid signature block
111 break;
112 }
113
114 /* Generating the SHA of the public key components in the signature block */
115 bootloader_sha256_handle_t sig_block_sha;
116 sig_block_sha = bootloader_sha256_start();
117 bootloader_sha256_data(sig_block_sha, &block->key, sizeof(block->key));
118 bootloader_sha256_finish(sig_block_sha, key_digest);
119
120 // Check we can verify the image using this signature and this key
121 uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN];
122 bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest);
123
124 if (!verified) {
125 /* We don't expect this: the signature blocks before we enable secure boot should all be verifiable or invalid,
126 so this is a fatal error
127 */
128 ret = ESP_FAIL;
129 ESP_LOGE(TAG, "Secure boot key (%d) verification failed.", i);
130 break;
131 }
132 ESP_LOGD(TAG, "Signature block (%d) is verified", i);
133 /* Copy the key digest to the buffer provided by the caller */
134 memcpy((void *)public_key_digests->key_digests[i], key_digest, ESP_SECURE_BOOT_DIGEST_LEN);
135 public_key_digests->num_digests++;
136 }
137
138 if (ret == ESP_OK && public_key_digests->num_digests > 0) {
139 ESP_LOGI(TAG, "Digests successfully calculated, %d valid signatures (image offset 0x%x)",
140 public_key_digests->num_digests, flash_offset);
141 }
142
143 bootloader_munmap(signatures);
144 return ret;
145}
146
147esp_err_t check_and_generate_secure_boot_keys(void)
148{
149 esp_err_t ret;
150#ifdef CONFIG_IDF_TARGET_ESP32
151 esp_efuse_purpose_t secure_boot_key_purpose[SECURE_BOOT_NUM_BLOCKS] = {
152 ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_V2,
153 };
154 esp_efuse_coding_scheme_t coding_scheme = esp_efuse_get_coding_scheme(EFUSE_BLK_SECURE_BOOT);
155 if (coding_scheme != EFUSE_CODING_SCHEME_NONE) {
156 ESP_LOGE(TAG, "No coding schemes are supported in secure boot v2.(Detected scheme: 0x%x)", coding_scheme);
157 return ESP_ERR_NOT_SUPPORTED;
158 }
159#else
160 esp_efuse_purpose_t secure_boot_key_purpose[SECURE_BOOT_NUM_BLOCKS] = {
161 ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0,
162 ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1,
163 ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2,
164 };
165#endif // CONFIG_IDF_TARGET_ESP32
166
167 /* Verify the bootloader */
168 esp_image_metadata_t bootloader_data = { 0 };
169 ret = esp_image_verify_bootloader_data(&bootloader_data);
170 if (ret != ESP_OK) {
171 ESP_LOGE(TAG, "bootloader image appears invalid! error %d", ret);
172 return ret;
173 }
174
175 /* Initialize all efuse block entries to invalid (max) value */
176 esp_efuse_block_t blocks[SECURE_BOOT_NUM_BLOCKS] = {[0 ... SECURE_BOOT_NUM_BLOCKS-1] = EFUSE_BLK_KEY_MAX};
177 /* Check if secure boot digests are present */
178 bool has_secure_boot_digest = false;
179 for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
180 bool tmp_has_key = esp_efuse_find_purpose(secure_boot_key_purpose[i], &blocks[i]);
181 if (tmp_has_key) { // For ESP32: esp_efuse_find_purpose() always returns True, need to check whether the key block is used or not.
182 tmp_has_key &= !esp_efuse_key_block_unused(blocks[i]);
183 }
184 has_secure_boot_digest |= tmp_has_key;
185 }
186
187 esp_image_sig_public_key_digests_t boot_key_digests = {0};
188 ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating..");
189
190 if (!has_secure_boot_digest) {
191 /* Generate the bootloader public key digests */
192 ret = s_calculate_image_public_key_digests(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, &boot_key_digests);
193 if (ret != ESP_OK) {
194 ESP_LOGE(TAG, "Bootloader signature block is invalid");
195 return ret;
196 }
197
198 if (boot_key_digests.num_digests == 0) {
199 ESP_LOGE(TAG, "No valid bootloader signature blocks found.");
200 return ESP_FAIL;
201 }
202 ESP_LOGI(TAG, "%d signature block(s) found appended to the bootloader.", boot_key_digests.num_digests);
203
204 ESP_LOGI(TAG, "Burning public key hash to eFuse");
205 ret = esp_efuse_write_keys(secure_boot_key_purpose, boot_key_digests.key_digests, boot_key_digests.num_digests);
206 if (ret != ESP_OK) {
207 if (ret == ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS) {
208 ESP_LOGE(TAG, "Bootloader signatures(%d) more than available key slots.", boot_key_digests.num_digests);
209 } else {
210 ESP_LOGE(TAG, "Failed to write efuse block with purpose (err=0x%x). Can't continue.", ret);
211 }
212 return ret;
213 }
214 } else {
215 for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
216 /* Check if corresponding digest slot is used or not */
217 if (blocks[i] == EFUSE_BLK_KEY_MAX) {
218 ESP_LOGD(TAG, "SECURE_BOOT_DIGEST%d slot is not used", i);
219 continue;
220 }
221
222#if SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS
223 if (esp_efuse_get_digest_revoke(i)) {
224 continue;
225 }
226#endif
227 if (esp_efuse_get_key_dis_read(blocks[i])) {
228 ESP_LOGE(TAG, "Key digest (BLK%d) read protected, aborting...", blocks[i]);
229 return ESP_FAIL;
230 }
231 if (esp_efuse_block_is_empty(blocks[i])) {
232 ESP_LOGE(TAG, "%d eFuse block is empty, aborting...", blocks[i]);
233 return ESP_FAIL;
234 }
235 esp_efuse_set_key_dis_write(blocks[i]);
236 ret = esp_efuse_read_block(blocks[i], boot_key_digests.key_digests[boot_key_digests.num_digests], 0,
237 sizeof(boot_key_digests.key_digests[0]) * 8);
238 if (ret) {
239 ESP_LOGE(TAG, "Error during reading %d eFuse block (err=0x%x)", blocks[i], ret);
240 return ret;
241 }
242 boot_key_digests.num_digests++;
243 }
244 if (boot_key_digests.num_digests == 0) {
245 ESP_LOGE(TAG, "No valid pre-loaded public key digest in eFuse");
246 return ESP_FAIL;
247 }
248 ESP_LOGW(TAG, "Using pre-loaded public key digest in eFuse");
249 }
250
251#if SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS
252 /* Revoke the empty signature blocks */
253 if (boot_key_digests.num_digests < SECURE_BOOT_NUM_BLOCKS) {
254 /* The revocation index can be 0, 1, 2. Bootloader count can be 1,2,3. */
255 for (unsigned i = boot_key_digests.num_digests; i < SECURE_BOOT_NUM_BLOCKS; i++) {
256 ESP_LOGI(TAG, "Revoking empty key digest slot (%d)...", i);
257 esp_efuse_set_digest_revoke(i);
258 }
259 }
260#endif // SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS
261 return ESP_OK;
262}
263
264#endif // CONFIG_SECURE_BOOT_V2_ENABLED