Line data Source code
1 : /*
2 : support checking board ID and firmware CRC in the bootloader
3 : */
4 : #include "AP_CheckFirmware.h"
5 : #include <AP_HAL/HAL.h>
6 : #include <AP_Math/crc.h>
7 :
8 : #if AP_CHECK_FIRMWARE_ENABLED
9 :
10 : #if defined(HAL_BOOTLOADER_BUILD)
11 :
12 : #if AP_SIGNED_FIRMWARE
13 : #include "../../Tools/AP_Bootloader/support.h"
14 : #include <string.h>
15 : #include "monocypher.h"
16 :
17 : const struct ap_secure_data public_keys __attribute__((section(".apsec_data")));
18 :
19 : /*
20 : return true if all public keys are zero. We allow boot of an
21 : unsigned firmware in that case
22 : */
23 : static bool all_zero_public_keys(void)
24 : {
25 : /*
26 : look over all public keys, if one matches then we are OK
27 : */
28 : const uint8_t zero_key[AP_PUBLIC_KEY_LEN] {};
29 : for (const auto &public_key : public_keys.public_key) {
30 : if (memcmp(public_key.key, zero_key, AP_PUBLIC_KEY_LEN) != 0) {
31 : return false;
32 : }
33 : }
34 : return true;
35 : }
36 :
37 : /*
38 : check a signature against bootloader keys
39 : */
40 : static check_fw_result_t check_firmware_signature(const app_descriptor_signed *ad,
41 : const uint8_t *flash1, uint32_t len1,
42 : const uint8_t *flash2, uint32_t len2)
43 : {
44 : if (all_zero_public_keys()) {
45 : return check_fw_result_t::CHECK_FW_OK;
46 : }
47 :
48 : // 8 byte signature version
49 : static const uint64_t sig_version = 30437LLU;
50 : if (ad->signature_length != 72) {
51 : return check_fw_result_t::FAIL_REASON_BAD_FIRMWARE_SIGNATURE;
52 : }
53 : if (memcmp((const uint8_t*)&sig_version, ad->signature, sizeof(sig_version)) != 0) {
54 : return check_fw_result_t::FAIL_REASON_BAD_FIRMWARE_SIGNATURE;
55 : }
56 :
57 : /*
58 : look over all public keys, if one matches then we are OK
59 : */
60 : for (const auto &public_key : public_keys.public_key) {
61 : crypto_check_ctx ctx {};
62 : crypto_check_ctx_abstract *actx = (crypto_check_ctx_abstract*)&ctx;
63 : crypto_check_init(actx, &ad->signature[sizeof(sig_version)], public_key.key);
64 :
65 : crypto_check_update(actx, flash1, len1);
66 : crypto_check_update(actx, flash2, len2);
67 : if (crypto_check_final(actx) == 0) {
68 : // good signature
69 : return check_fw_result_t::CHECK_FW_OK;
70 : }
71 : }
72 :
73 : // none of the public keys matched
74 : return check_fw_result_t::FAIL_REASON_VERIFICATION;
75 : }
76 : #endif // AP_SIGNED_FIRMWARE
77 :
78 : /*
79 : check firmware CRC and board ID to see if it matches
80 : */
81 : static check_fw_result_t check_good_firmware_signed(void)
82 : {
83 : const uint8_t sig[8] = AP_APP_DESCRIPTOR_SIGNATURE_SIGNED;
84 : const uint8_t *flash1 = (const uint8_t *)(FLASH_LOAD_ADDRESS + (FLASH_BOOTLOADER_LOAD_KB + APP_START_OFFSET_KB)*1024);
85 : const uint32_t flash_size = (BOARD_FLASH_SIZE - (FLASH_BOOTLOADER_LOAD_KB + APP_START_OFFSET_KB))*1024;
86 : const app_descriptor_signed *ad = (const app_descriptor_signed *)memmem(flash1, flash_size-sizeof(app_descriptor_signed), sig, sizeof(sig));
87 : if (ad == nullptr) {
88 : // no application signature
89 : return check_fw_result_t::FAIL_REASON_NO_APP_SIG;
90 : }
91 : // check length
92 : if (ad->image_size > flash_size) {
93 : return check_fw_result_t::FAIL_REASON_BAD_LENGTH_APP;
94 : }
95 :
96 : bool id_ok = (ad->board_id == APJ_BOARD_ID);
97 : #ifdef ALT_BOARD_ID
98 : id_ok |= (ad->board_id == ALT_BOARD_ID);
99 : #endif
100 :
101 : if (!id_ok) {
102 : return check_fw_result_t::FAIL_REASON_BAD_BOARD_ID;
103 : }
104 :
105 : const uint8_t *flash2 = (const uint8_t *)&ad->version_major;
106 : const uint8_t desc_len = offsetof(app_descriptor_signed, version_major) - offsetof(app_descriptor_signed, image_crc1);
107 : const uint32_t len1 = ((const uint8_t *)&ad->image_crc1) - flash1;
108 :
109 : if ((len1 + desc_len) > ad->image_size) {
110 : return check_fw_result_t::FAIL_REASON_BAD_LENGTH_DESCRIPTOR;
111 : }
112 :
113 : const uint32_t len2 = ad->image_size - (len1 + desc_len);
114 : uint32_t crc1 = crc32_small(0, flash1, len1);
115 : uint32_t crc2 = crc32_small(0, flash2, len2);
116 : if (crc1 != ad->image_crc1 || crc2 != ad->image_crc2) {
117 : return check_fw_result_t::FAIL_REASON_BAD_CRC;
118 : }
119 :
120 : check_fw_result_t ret = check_fw_result_t::CHECK_FW_OK;
121 :
122 : #if AP_SIGNED_FIRMWARE
123 : ret = check_firmware_signature(ad, flash1, len1, flash2, len2);
124 : #endif
125 :
126 : return ret;
127 : }
128 :
129 : /*
130 : check firmware CRC and board ID to see if it matches, using unsigned
131 : signature
132 : */
133 : static check_fw_result_t check_good_firmware_unsigned(void)
134 : {
135 : const uint8_t sig[8] = AP_APP_DESCRIPTOR_SIGNATURE_UNSIGNED;
136 : const uint8_t *flash1 = (const uint8_t *)(FLASH_LOAD_ADDRESS + (FLASH_BOOTLOADER_LOAD_KB + APP_START_OFFSET_KB)*1024);
137 : const uint32_t flash_size = (BOARD_FLASH_SIZE - (FLASH_BOOTLOADER_LOAD_KB + APP_START_OFFSET_KB))*1024;
138 : const app_descriptor_unsigned *ad = (const app_descriptor_unsigned *)memmem(flash1, flash_size-sizeof(app_descriptor_unsigned), sig, sizeof(sig));
139 : if (ad == nullptr) {
140 : // no application signature
141 : return check_fw_result_t::FAIL_REASON_NO_APP_SIG;
142 : }
143 : // check length
144 : if (ad->image_size > flash_size) {
145 : return check_fw_result_t::FAIL_REASON_BAD_LENGTH_APP;
146 : }
147 :
148 : bool id_ok = (ad->board_id == APJ_BOARD_ID);
149 : #ifdef ALT_BOARD_ID
150 : id_ok |= (ad->board_id == ALT_BOARD_ID);
151 : #endif
152 :
153 : if (!id_ok) {
154 : return check_fw_result_t::FAIL_REASON_BAD_BOARD_ID;
155 : }
156 :
157 : const uint8_t *flash2 = (const uint8_t *)&ad->version_major;
158 : const uint8_t desc_len = offsetof(app_descriptor_unsigned, version_major) - offsetof(app_descriptor_unsigned, image_crc1);
159 : const uint32_t len1 = ((const uint8_t *)&ad->image_crc1) - flash1;
160 :
161 : if ((len1 + desc_len) > ad->image_size) {
162 : return check_fw_result_t::FAIL_REASON_BAD_LENGTH_DESCRIPTOR;
163 : }
164 :
165 : const uint32_t len2 = ad->image_size - (len1 + desc_len);
166 : uint32_t crc1 = crc32_small(0, flash1, len1);
167 : uint32_t crc2 = crc32_small(0, flash2, len2);
168 : if (crc1 != ad->image_crc1 || crc2 != ad->image_crc2) {
169 : return check_fw_result_t::FAIL_REASON_BAD_CRC;
170 : }
171 :
172 : return check_fw_result_t::CHECK_FW_OK;
173 : }
174 :
175 : check_fw_result_t check_good_firmware(void)
176 : {
177 : #if AP_SIGNED_FIRMWARE
178 : // allow unsigned format if we have no public keys. This allows
179 : // for use of SECURE_COMMAND to remove all public keys and then
180 : // load of unsigned firmware
181 : const auto ret = check_good_firmware_signed();
182 : if (ret != check_fw_result_t::CHECK_FW_OK &&
183 : all_zero_public_keys() &&
184 : check_good_firmware_unsigned() == check_fw_result_t::CHECK_FW_OK) {
185 : return check_fw_result_t::CHECK_FW_OK;
186 : }
187 : return ret;
188 : #else
189 : const auto ret = check_good_firmware_unsigned();
190 : if (ret != check_fw_result_t::CHECK_FW_OK) {
191 : // allow for signed format, not checking public keys. This
192 : // allows for booting of a signed firmware with an unsigned
193 : // bootloader, which allows for bootstrapping a system up from
194 : // unsigned to signed
195 : const auto ret2 = check_good_firmware_signed();
196 : if (ret2 == check_fw_result_t::CHECK_FW_OK) {
197 : return check_fw_result_t::CHECK_FW_OK;
198 : }
199 : }
200 : return ret;
201 : #endif
202 : }
203 :
204 : const app_descriptor_t *get_app_descriptor(void)
205 : {
206 : #if AP_SIGNED_FIRMWARE
207 : const uint8_t sig[8] = AP_APP_DESCRIPTOR_SIGNATURE_SIGNED;
208 : #else
209 : const uint8_t sig[8] = AP_APP_DESCRIPTOR_SIGNATURE_UNSIGNED;
210 : #endif
211 : const uint8_t *flash1 = (const uint8_t *)(FLASH_LOAD_ADDRESS + (FLASH_BOOTLOADER_LOAD_KB + APP_START_OFFSET_KB)*1024);
212 : const uint32_t flash_size = (BOARD_FLASH_SIZE - (FLASH_BOOTLOADER_LOAD_KB + APP_START_OFFSET_KB))*1024;
213 : const app_descriptor_t *ad = (const app_descriptor_t *)memmem(flash1, flash_size-sizeof(app_descriptor_t), sig, sizeof(sig));
214 : return ad;
215 : }
216 :
217 : #endif // HAL_BOOTLOADER_BUILD
218 :
219 : #if !defined(HAL_BOOTLOADER_BUILD)
220 : extern const AP_HAL::HAL &hal;
221 : extern const app_descriptor_t app_descriptor;
222 :
223 : /*
224 : this is needed to ensure we don't elide the app_descriptor
225 : */
226 2094 : void check_firmware_print(void)
227 : {
228 2094 : hal.console->printf("Booting %u/%u\n",
229 2094 : app_descriptor.version_major,
230 2094 : app_descriptor.version_minor);
231 2094 : }
232 : #endif
233 :
234 :
235 : #endif // AP_CHECK_FIRMWARE_ENABLED
|