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