CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
Ardupilot

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AP_CheckFirmware/AP_CheckFirmware.cpp
Views: 1798
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
void check_firmware_print(void)
227
{
228
hal.console->printf("Booting %u/%u\n",
229
app_descriptor.version_major,
230
app_descriptor.version_minor);
231
}
232
#endif
233
234
235
#endif // AP_CHECK_FIRMWARE_ENABLED
236
237