/src/wolfBoot/include/image.h
Line | Count | Source |
1 | | /* image.h |
2 | | * |
3 | | * Functions to help with wolfBoot image header |
4 | | * |
5 | | * |
6 | | * Copyright (C) 2026 wolfSSL Inc. |
7 | | * |
8 | | * This file is part of wolfBoot. |
9 | | * |
10 | | * wolfBoot is free software; you can redistribute it and/or modify |
11 | | * it under the terms of the GNU General Public License as published by |
12 | | * the Free Software Foundation; either version 3 of the License, or |
13 | | * (at your option) any later version. |
14 | | * |
15 | | * wolfBoot is distributed in the hope that it will be useful, |
16 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | | * GNU General Public License for more details. |
19 | | * |
20 | | * You should have received a copy of the GNU General Public License |
21 | | * along with this program; if not, write to the Free Software |
22 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA |
23 | | */ |
24 | | |
25 | | #ifndef IMAGE_H |
26 | | #define IMAGE_H |
27 | | |
28 | | #ifdef __cplusplus |
29 | | extern "C" { |
30 | | #endif |
31 | | |
32 | | #include <stdint.h> |
33 | | |
34 | | #include "target.h" |
35 | | #include "wolfboot/wolfboot.h" |
36 | | |
37 | | #ifdef EXT_FLASH |
38 | | #include "hal.h" |
39 | | #endif |
40 | | |
41 | | #if defined(EXT_ENCRYPTED) && (defined(__WOLFBOOT) || defined(UNIT_TEST)) |
42 | | #include "encrypt.h" |
43 | | #endif |
44 | | |
45 | | #ifndef WOLFBOOT_FLAGS_INVERT |
46 | | #define SECT_FLAG_NEW 0x0F |
47 | | #define SECT_FLAG_SWAPPING 0x07 |
48 | | #define SECT_FLAG_BACKUP 0x03 |
49 | | #define SECT_FLAG_UPDATED 0x00 |
50 | | #else |
51 | | #define SECT_FLAG_NEW 0x00 |
52 | | #define SECT_FLAG_SWAPPING 0x08 |
53 | | #define SECT_FLAG_BACKUP 0x0c |
54 | | #define SECT_FLAG_UPDATED 0x0f |
55 | | #endif |
56 | | |
57 | | #ifdef WOLFBOOT_SIGN_ED25519 |
58 | | #define wolfBoot_verify_signature_primary wolfBoot_verify_signature_ed25519 |
59 | | #endif |
60 | | #ifdef WOLFBOOT_SIGN_ED448 |
61 | | #define wolfBoot_verify_signature_primary wolfBoot_verify_signature_ed448 |
62 | | #endif |
63 | | #if defined (WOLFBOOT_SIGN_RSA2048) || \ |
64 | | defined (WOLFBOOT_SIGN_RSA3072) || \ |
65 | | defined (WOLFBOOT_SIGN_RSA4096) || \ |
66 | | defined (WOLFBOOT_SIGN_RSA2048ENC) || \ |
67 | | defined (WOLFBOOT_SIGN_RSA3072ENC) || \ |
68 | | defined (WOLFBOOT_SIGN_RSA4096ENC) |
69 | | #define wolfBoot_verify_signature_primary wolfBoot_verify_signature_rsa |
70 | | #endif |
71 | | #if defined (WOLFBOOT_SIGN_RSAPSS2048) || \ |
72 | | defined (WOLFBOOT_SIGN_RSAPSS3072) || \ |
73 | | defined (WOLFBOOT_SIGN_RSAPSS4096) |
74 | | #define wolfBoot_verify_signature_primary wolfBoot_verify_signature_rsa_pss |
75 | | #endif |
76 | | #if defined (WOLFBOOT_SIGN_ECC256) || \ |
77 | | defined (WOLFBOOT_SIGN_ECC384) || \ |
78 | | defined (WOLFBOOT_SIGN_ECC521) |
79 | | #define wolfBoot_verify_signature_primary wolfBoot_verify_signature_ecc |
80 | | #endif |
81 | | #if defined(WOLFBOOT_SIGN_LMS) |
82 | | #define wolfBoot_verify_signature_primary wolfBoot_verify_signature_lms |
83 | | #endif |
84 | | #if defined(WOLFBOOT_SIGN_XMSS ) |
85 | | #define wolfBoot_verify_signature_primary wolfBoot_verify_signature_xmss |
86 | | #endif |
87 | | #ifdef WOLFBOOT_SIGN_ML_DSA |
88 | | #define wolfBoot_verify_signature_primary wolfBoot_verify_signature_ml_dsa |
89 | | #endif |
90 | | |
91 | | #ifdef WOLFBOOT_SIGN_SECONDARY_ED25519 |
92 | | #define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_ed25519 |
93 | | #endif |
94 | | #ifdef WOLFBOOT_SIGN_SECONDARY_ED448 |
95 | | #define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_ed448 |
96 | | #endif |
97 | | #if defined (WOLFBOOT_SIGN_SECONDARY_RSA2048) || \ |
98 | | defined (WOLFBOOT_SIGN_SECONDARY_RSA3072) || \ |
99 | | defined (WOLFBOOT_SIGN_SECONDARY_RSA4096) || \ |
100 | | defined (WOLFBOOT_SIGN_SECONDARY_RSA2048ENC) || \ |
101 | | defined (WOLFBOOT_SIGN_SECONDARY_RSA3072ENC) || \ |
102 | | defined (WOLFBOOT_SIGN_SECONDARY_RSA4096ENC) |
103 | | #define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_rsa |
104 | | #endif |
105 | | #if defined (WOLFBOOT_SIGN_SECONDARY_RSAPSS2048) || \ |
106 | | defined (WOLFBOOT_SIGN_SECONDARY_RSAPSS3072) || \ |
107 | | defined (WOLFBOOT_SIGN_SECONDARY_RSAPSS4096) |
108 | | #define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_rsa_pss |
109 | | #endif |
110 | | #if defined (WOLFBOOT_SIGN_SECONDARY_ECC256) || \ |
111 | | defined (WOLFBOOT_SIGN_SECONDARY_ECC384) || \ |
112 | | defined (WOLFBOOT_SIGN_SECONDARY_ECC521) |
113 | | #define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_ecc |
114 | | #endif |
115 | | #ifdef WOLFBOOT_SIGN_SECONDARY_LMS |
116 | | #define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_lms |
117 | | #endif |
118 | | #ifdef WOLFBOOT_SIGN_SECONDARY_XMSS |
119 | | #define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_xmss |
120 | | #endif |
121 | | #ifdef WOLFBOOT_SIGN_SECONDARY_ML_DSA |
122 | | #define wolfBoot_verify_signature_secondary wolfBoot_verify_signature_ml_dsa |
123 | | #endif |
124 | | |
125 | | /* Thin wrappers: dispatch RSA / RSA-PSS to the unified verify function */ |
126 | | #define wolfBoot_verify_signature_rsa(ks, img, sig) \ |
127 | | wolfBoot_verify_signature_rsa_common(ks, img, sig, 0) |
128 | | #define wolfBoot_verify_signature_rsa_pss(ks, img, sig) \ |
129 | | wolfBoot_verify_signature_rsa_common(ks, img, sig, 1) |
130 | | |
131 | | #if defined(WOLFBOOT_TPM) && defined (WOLFBOOT_TPM_VERIFY) |
132 | | #undef wolfBoot_verify_signature_primary |
133 | | #define wolfBoot_verify_signature_primary wolfBoot_verify_signature_tpm |
134 | | #endif |
135 | | |
136 | | /* Validate sector size is larger than image header size */ |
137 | | #if defined(WOLFBOOT_SECTOR_SIZE) && defined(IMAGE_HEADER_SIZE) && \ |
138 | | (WOLFBOOT_SECTOR_SIZE < IMAGE_HEADER_SIZE) |
139 | | #error WOLFBOOT_SECTOR_SIZE must be larger than IMAGE_HEADER_SIZE |
140 | | #endif |
141 | | |
142 | | |
143 | | #if (defined(WOLFBOOT_ARMORED) && defined(__WOLFBOOT)) |
144 | | #if !defined(ARCH_ARM) || (!defined(__GNUC__) && \ |
145 | | !(defined(__ICCARM__) && defined(__IAR_SYSTEMS_ICC__))) |
146 | | # error WOLFBOOT_ARMORED only available for ARM with IAR or gcc compilers |
147 | | #endif |
148 | | |
149 | | #if defined(__GNUC__) |
150 | | #define likely(x) __builtin_expect((x),1) |
151 | | #define unlikely(x) __builtin_expect((x),0) |
152 | | #else |
153 | | #define likely(x) (x) |
154 | | #define unlikely(x) (x) |
155 | | #endif |
156 | | |
157 | | struct wolfBoot_image { |
158 | | uint8_t *hdr; |
159 | | #ifdef EXT_FLASH |
160 | | uint8_t *hdr_cache; |
161 | | #endif |
162 | | uint8_t *trailer; |
163 | | uint8_t *sha_hash; |
164 | | uint8_t *fw_base; |
165 | | uint32_t fw_size; |
166 | | uint32_t part; |
167 | | uint32_t hdr_ok; |
168 | | uint32_t canary_FEED4567; |
169 | | uint32_t signature_ok; |
170 | | uint32_t canary_FEED6789; |
171 | | uint32_t not_signature_ok; |
172 | | uint32_t canary_FEED89AB; |
173 | | uint32_t sha_ok; |
174 | | uint32_t canary_FEEDCAFE; |
175 | | uint32_t not_sha_ok; |
176 | | uintptr_t not_fw_base; /* complement of fw_base, for FI hardening */ |
177 | | uint32_t not_ext; /* image is no longer external */ |
178 | | }; |
179 | | |
180 | | |
181 | | /** |
182 | | * This function sets the flag that indicates the signature is valid for the |
183 | | * wolfBoot_image. |
184 | | * |
185 | | * With ARMORED setup, the flag is redundant, and the information is wrapped in |
186 | | * between canary variables, to mitigate attacks based on memory corruptions. |
187 | | */ |
188 | | static void NOINLINEFUNCTION wolfBoot_image_confirm_signature_ok( |
189 | | struct wolfBoot_image *img) |
190 | | { |
191 | | img->canary_FEED4567 = 0xFEED4567UL; |
192 | | img->signature_ok = 1UL; |
193 | | img->canary_FEED6789 = 0xFEED6789UL; |
194 | | img->not_signature_ok = ~(1UL); |
195 | | img->canary_FEED89AB = 0xFEED89ABUL; |
196 | | } |
197 | | |
198 | | static void NOINLINEFUNCTION wolfBoot_image_clear_signature_ok( |
199 | | struct wolfBoot_image *img) |
200 | | { |
201 | | img->canary_FEED4567 = 0xFEED4567UL; |
202 | | img->signature_ok = 0UL; |
203 | | img->canary_FEED6789 = 0xFEED6789UL; |
204 | | img->not_signature_ok = 1UL; |
205 | | img->canary_FEED89AB = 0xFEED89ABUL; |
206 | | } |
207 | | |
208 | | /** |
209 | | * This function sets the flag that indicates the digest (integrity) check |
210 | | * succeeded for the wolfBoot_image. |
211 | | * |
212 | | * As with the signature flag, the value is redundant and wrapped between |
213 | | * canary variables, so that a single fault cannot forge a valid state. |
214 | | */ |
215 | | static void NOINLINEFUNCTION wolfBoot_image_confirm_sha_ok( |
216 | | struct wolfBoot_image *img) |
217 | | { |
218 | | img->canary_FEED89AB = 0xFEED89ABUL; |
219 | | img->sha_ok = 1UL; |
220 | | img->canary_FEEDCAFE = 0xFEEDCAFEUL; |
221 | | img->not_sha_ok = ~(1UL); |
222 | | } |
223 | | |
224 | | static void NOINLINEFUNCTION wolfBoot_image_clear_sha_ok( |
225 | | struct wolfBoot_image *img) |
226 | | { |
227 | | img->canary_FEED89AB = 0xFEED89ABUL; |
228 | | img->sha_ok = 0UL; |
229 | | img->canary_FEEDCAFE = 0xFEEDCAFEUL; |
230 | | img->not_sha_ok = 1UL; |
231 | | } |
232 | | |
233 | | /** |
234 | | * Records the image entry base together with its complement, so that a single |
235 | | * fault on the pointer that do_boot() jumps through can be detected by |
236 | | * FW_BASE_SANITY_CHECK() before the branch is taken. |
237 | | */ |
238 | | static void NOINLINEFUNCTION wolfBoot_image_set_fw_base( |
239 | | struct wolfBoot_image *img, void *base) |
240 | | { |
241 | | img->fw_base = (uint8_t *)base; |
242 | | img->not_fw_base = ~(uintptr_t)base; |
243 | | } |
244 | | |
245 | | /** |
246 | | * Final sanity check, performed just before do_boot, or before starting an |
247 | | * update that has been verified. |
248 | | * |
249 | | * This procedure detects if any of the previous checks has been skipped. |
250 | | * If any of the required flags does not match the expected value, wolfBoot |
251 | | * panics. |
252 | | */ |
253 | | #define PART_SANITY_CHECK(p) \ |
254 | | /* Redundant set of r2=0 */ \ |
255 | | asm volatile("mov r2, #0":::"r2"); \ |
256 | | asm volatile("mov r2, #0":::"r2"); \ |
257 | | asm volatile("mov r2, #0":::"r2"); \ |
258 | | asm volatile("mov r2, #0":::"r2"); \ |
259 | | asm volatile("mov r2, #0":::"r2"); \ |
260 | | /* Loading hdr_ok flag, verifying */ \ |
261 | | asm volatile("mov r2, %0" ::"r"((p)->hdr_ok):"r2"); \ |
262 | | asm volatile("cmp r2, #1":::"cc"); \ |
263 | | asm volatile("cmp r2, #1":::"cc"); \ |
264 | | asm volatile("cmp r2, #1":::"cc"); \ |
265 | | asm volatile("bne ."); \ |
266 | | asm volatile("cmp r2, #1":::"cc"); \ |
267 | | asm volatile("cmp r2, #1":::"cc"); \ |
268 | | asm volatile("cmp r2, #1":::"cc"); \ |
269 | | asm volatile("bne .-4"); \ |
270 | | asm volatile("cmp r2, #1":::"cc"); \ |
271 | | asm volatile("cmp r2, #1":::"cc"); \ |
272 | | asm volatile("cmp r2, #1":::"cc"); \ |
273 | | asm volatile("bne .-8"); \ |
274 | | asm volatile("cmp r2, #1":::"cc"); \ |
275 | | asm volatile("cmp r2, #1":::"cc"); \ |
276 | | asm volatile("cmp r2, #1":::"cc"); \ |
277 | | asm volatile("bne .-12"); \ |
278 | | /* Redundant set of r2=0 */ \ |
279 | | asm volatile("mov r2, #0":::"r2"); \ |
280 | | asm volatile("mov r2, #0":::"r2"); \ |
281 | | asm volatile("mov r2, #0":::"r2"); \ |
282 | | asm volatile("mov r2, #0":::"r2"); \ |
283 | | asm volatile("mov r2, #0":::"r2"); \ |
284 | | /* Loading hdr_ok flag, verifying */ \ |
285 | | asm volatile("mov r2, %0" ::"r"((p)->sha_ok):"r2"); \ |
286 | | asm volatile("cmp r2, #1":::"cc"); \ |
287 | | asm volatile("cmp r2, #1":::"cc"); \ |
288 | | asm volatile("cmp r2, #1":::"cc"); \ |
289 | | asm volatile("bne ."); \ |
290 | | asm volatile("cmp r2, #1":::"cc"); \ |
291 | | asm volatile("cmp r2, #1":::"cc"); \ |
292 | | asm volatile("cmp r2, #1":::"cc"); \ |
293 | | asm volatile("bne .-4"); \ |
294 | | asm volatile("cmp r2, #1":::"cc"); \ |
295 | | asm volatile("cmp r2, #1":::"cc"); \ |
296 | | asm volatile("cmp r2, #1":::"cc"); \ |
297 | | asm volatile("bne .-8"); \ |
298 | | asm volatile("cmp r2, #1":::"cc"); \ |
299 | | asm volatile("cmp r2, #1":::"cc"); \ |
300 | | asm volatile("cmp r2, #1":::"cc"); \ |
301 | | asm volatile("bne .-12"); \ |
302 | | /* Redundant set of r2=0 */ \ |
303 | | asm volatile("mov r2, #0":::"r2"); \ |
304 | | asm volatile("mov r2, #0":::"r2"); \ |
305 | | asm volatile("mov r2, #0":::"r2"); \ |
306 | | asm volatile("mov r2, #0":::"r2"); \ |
307 | | asm volatile("mov r2, #0":::"r2"); \ |
308 | | /* Loading ~(sha_ok) flag, verifying */ \ |
309 | | asm volatile("mov r2, %0" ::"r"((p)->not_sha_ok):"r2"); \ |
310 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
311 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
312 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
313 | | asm volatile("bne ."); \ |
314 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
315 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
316 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
317 | | asm volatile("bne .-4"); \ |
318 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
319 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
320 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
321 | | asm volatile("bne .-8"); \ |
322 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
323 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
324 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
325 | | asm volatile("bne .-12"); \ |
326 | | /* Redundant set of r2=0 */ \ |
327 | | asm volatile("mov r2, #0":::"r2"); \ |
328 | | asm volatile("mov r2, #0":::"r2"); \ |
329 | | asm volatile("mov r2, #0":::"r2"); \ |
330 | | asm volatile("mov r2, #0":::"r2"); \ |
331 | | asm volatile("mov r2, #0":::"r2"); \ |
332 | | /* Loading canary value, verifying */ \ |
333 | | asm volatile("mov r2, %0" ::"r"((p)->canary_FEEDCAFE):"r2"); \ |
334 | | asm volatile("mov r0, %0" ::"r"(0xFEEDCAFE):"r0"); \ |
335 | | asm volatile("cmp r2, r0":::"cc"); \ |
336 | | asm volatile("cmp r2, r0":::"cc"); \ |
337 | | asm volatile("cmp r2, r0":::"cc"); \ |
338 | | asm volatile("bne ."); \ |
339 | | asm volatile("cmp r2, r0":::"cc"); \ |
340 | | asm volatile("cmp r2, r0":::"cc"); \ |
341 | | asm volatile("cmp r2, r0":::"cc"); \ |
342 | | asm volatile("bne .-4"); \ |
343 | | asm volatile("cmp r2, r0":::"cc"); \ |
344 | | asm volatile("cmp r2, r0":::"cc"); \ |
345 | | asm volatile("cmp r2, r0":::"cc"); \ |
346 | | asm volatile("bne .-8"); \ |
347 | | asm volatile("cmp r2, r0":::"cc"); \ |
348 | | asm volatile("cmp r2, r0":::"cc"); \ |
349 | | asm volatile("cmp r2, r0":::"cc"); \ |
350 | | asm volatile("bne .-12"); \ |
351 | | /* Redundant set of r2=0 */ \ |
352 | | asm volatile("mov r2, #0":::"r2"); \ |
353 | | asm volatile("mov r2, #0":::"r2"); \ |
354 | | asm volatile("mov r2, #0":::"r2"); \ |
355 | | asm volatile("mov r2, #0":::"r2"); \ |
356 | | asm volatile("mov r2, #0":::"r2"); \ |
357 | | /* Loading signature_ok flag, verifying */ \ |
358 | | asm volatile("mov r2, %0" ::"r"((p)->signature_ok):"r2"); \ |
359 | | asm volatile("cmp r2, #1":::"cc"); \ |
360 | | asm volatile("cmp r2, #1":::"cc"); \ |
361 | | asm volatile("cmp r2, #1":::"cc"); \ |
362 | | asm volatile("bne ."); \ |
363 | | asm volatile("cmp r2, #1":::"cc"); \ |
364 | | asm volatile("cmp r2, #1":::"cc"); \ |
365 | | asm volatile("cmp r2, #1":::"cc"); \ |
366 | | asm volatile("bne .-4"); \ |
367 | | asm volatile("cmp r2, #1":::"cc"); \ |
368 | | asm volatile("cmp r2, #1":::"cc"); \ |
369 | | asm volatile("cmp r2, #1":::"cc"); \ |
370 | | asm volatile("bne .-8"); \ |
371 | | asm volatile("cmp r2, #1":::"cc"); \ |
372 | | asm volatile("cmp r2, #1":::"cc"); \ |
373 | | asm volatile("cmp r2, #1":::"cc"); \ |
374 | | asm volatile("bne .-12"); \ |
375 | | /* Redundant set of r2=0 */ \ |
376 | | asm volatile("mov r2, #0"); \ |
377 | | asm volatile("mov r2, #0"); \ |
378 | | asm volatile("mov r2, #0"); \ |
379 | | asm volatile("mov r2, #0"); \ |
380 | | asm volatile("mov r2, #0"); \ |
381 | | /* Loading ~(signature_ok) flag, verifying */ \ |
382 | | asm volatile("mov r2, %0" ::"r"((p)->not_signature_ok):"r2"); \ |
383 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
384 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
385 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
386 | | asm volatile("bne ."); \ |
387 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
388 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
389 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
390 | | asm volatile("bne .-4"); \ |
391 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
392 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
393 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
394 | | asm volatile("bne .-8"); \ |
395 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
396 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
397 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
398 | | asm volatile("bne .-12"); \ |
399 | | /* Redundant set of r2=0 */ \ |
400 | | asm volatile("mov r2, #0":::"r2"); \ |
401 | | asm volatile("mov r2, #0":::"r2"); \ |
402 | | asm volatile("mov r2, #0":::"r2"); \ |
403 | | asm volatile("mov r2, #0":::"r2"); \ |
404 | | asm volatile("mov r2, #0":::"r2"); \ |
405 | | /* Loading canary value, verifying */ \ |
406 | | asm volatile("mov r2, %0" ::"r"((p)->canary_FEED6789):"r2"); \ |
407 | | asm volatile("mov r0, %0" ::"r"(0xFEED6789):"r0"); \ |
408 | | asm volatile("cmp r2, r0":::"cc"); \ |
409 | | asm volatile("cmp r2, r0":::"cc"); \ |
410 | | asm volatile("cmp r2, r0":::"cc"); \ |
411 | | asm volatile("bne ."); \ |
412 | | asm volatile("cmp r2, r0":::"cc"); \ |
413 | | asm volatile("cmp r2, r0":::"cc"); \ |
414 | | asm volatile("cmp r2, r0":::"cc"); \ |
415 | | asm volatile("bne .-4"); \ |
416 | | asm volatile("cmp r2, r0":::"cc"); \ |
417 | | asm volatile("cmp r2, r0":::"cc"); \ |
418 | | asm volatile("cmp r2, r0":::"cc"); \ |
419 | | asm volatile("bne .-8"); \ |
420 | | asm volatile("cmp r2, r0":::"cc"); \ |
421 | | asm volatile("cmp r2, r0":::"cc"); \ |
422 | | asm volatile("cmp r2, r0":::"cc"); \ |
423 | | asm volatile("bne .-12"); \ |
424 | | /* Redundant set of r2=0 */ \ |
425 | | asm volatile("mov r2, #0":::"r2"); \ |
426 | | asm volatile("mov r2, #0":::"r2"); \ |
427 | | asm volatile("mov r2, #0":::"r2"); \ |
428 | | asm volatile("mov r2, #0":::"r2"); \ |
429 | | asm volatile("mov r2, #0":::"r2"); \ |
430 | | /* Loading canary value, verifying */ \ |
431 | | asm volatile("mov r2, %0" ::"r"((p)->canary_FEED4567):"r2"); \ |
432 | | asm volatile("mov r0, %0" ::"r"(0xFEED4567):"r0"); \ |
433 | | asm volatile("cmp r2, r0":::"cc"); \ |
434 | | asm volatile("cmp r2, r0":::"cc"); \ |
435 | | asm volatile("cmp r2, r0":::"cc"); \ |
436 | | asm volatile("bne ."); \ |
437 | | asm volatile("cmp r2, r0":::"cc"); \ |
438 | | asm volatile("cmp r2, r0":::"cc"); \ |
439 | | asm volatile("cmp r2, r0":::"cc"); \ |
440 | | asm volatile("bne .-4"); \ |
441 | | asm volatile("cmp r2, r0":::"cc"); \ |
442 | | asm volatile("cmp r2, r0":::"cc"); \ |
443 | | asm volatile("cmp r2, r0":::"cc"); \ |
444 | | asm volatile("bne .-8"); \ |
445 | | asm volatile("cmp r2, r0":::"cc"); \ |
446 | | asm volatile("cmp r2, r0":::"cc"); \ |
447 | | asm volatile("cmp r2, r0":::"cc"); \ |
448 | | asm volatile("bne .-12"); \ |
449 | | /* Redundant set of r2=0 */ \ |
450 | | asm volatile("mov r2, #0":::"r2"); \ |
451 | | asm volatile("mov r2, #0":::"r2"); \ |
452 | | asm volatile("mov r2, #0":::"r2"); \ |
453 | | asm volatile("mov r2, #0":::"r2"); \ |
454 | | asm volatile("mov r2, #0":::"r2"); \ |
455 | | /* Loading canary value, verifying */ \ |
456 | | asm volatile("mov r2, %0" ::"r"((p)->canary_FEED89AB):"r2"); \ |
457 | | asm volatile("mov r0, %0" ::"r"(0xFEED89AB):"r0"); \ |
458 | | asm volatile("cmp r2, r0":::"cc"); \ |
459 | | asm volatile("cmp r2, r0":::"cc"); \ |
460 | | asm volatile("cmp r2, r0":::"cc"); \ |
461 | | asm volatile("bne ."); \ |
462 | | asm volatile("cmp r2, r0":::"cc"); \ |
463 | | asm volatile("cmp r2, r0":::"cc"); \ |
464 | | asm volatile("cmp r2, r0":::"cc"); \ |
465 | | asm volatile("bne .-4"); \ |
466 | | asm volatile("cmp r2, r0":::"cc"); \ |
467 | | asm volatile("cmp r2, r0":::"cc"); \ |
468 | | asm volatile("cmp r2, r0":::"cc"); \ |
469 | | asm volatile("bne .-8"); \ |
470 | | asm volatile("cmp r2, r0":::"cc"); \ |
471 | | asm volatile("cmp r2, r0":::"cc"); \ |
472 | | asm volatile("cmp r2, r0":::"cc"); \ |
473 | | asm volatile("bne .-12") \ |
474 | | |
475 | | /** |
476 | | * First part of RSA verification. Ensure that the function is called by |
477 | | * double checking its return value contains a valid |
478 | | * len (>= WOLFBOOT_SHA_DIGEST_SIZE). |
479 | | * |
480 | | * Uses GAS local numeric labels (1f/1:) so the macro can be safely expanded |
481 | | * multiple times in the same function (e.g. RSA PKCS#1.5 + RSA-PSS paths). |
482 | | */ |
483 | | #define RSA_VERIFY_FN(ret,fn,...) \ |
484 | | { \ |
485 | | /* Redundant set of r0=0 */ \ |
486 | | asm volatile("mov r0, #0":::"r0"); \ |
487 | | asm volatile("mov r0, #0":::"r0"); \ |
488 | | asm volatile("mov r0, #0":::"r0"); \ |
489 | | /* Call the function */ \ |
490 | | int tmp_ret = fn(__VA_ARGS__); \ |
491 | | ret = -1; \ |
492 | | /* Redundant set of r2=SHA_DIGEST_SIZE */ \ |
493 | | asm volatile("mov r2, %0" ::"r"(WOLFBOOT_SHA_DIGEST_SIZE):"r2"); \ |
494 | | asm volatile("mov r2, %0" ::"r"(WOLFBOOT_SHA_DIGEST_SIZE):"r2"); \ |
495 | | asm volatile("mov r2, %0" ::"r"(WOLFBOOT_SHA_DIGEST_SIZE):"r2"); \ |
496 | | /* Redundant check for fn() return value >= r2 */ \ |
497 | | asm volatile("cmp r0, r2":::"cc"); \ |
498 | | asm volatile("cmp r0, r2":::"cc"); \ |
499 | | asm volatile("cmp r0, r2":::"cc"); \ |
500 | | asm volatile("blt 1f"); \ |
501 | | asm volatile("cmp r0, r2":::"cc"); \ |
502 | | asm volatile("cmp r0, r2":::"cc"); \ |
503 | | asm volatile("cmp r0, r2":::"cc"); \ |
504 | | asm volatile("blt 1f"); \ |
505 | | asm volatile("cmp r0, r2":::"cc"); \ |
506 | | asm volatile("cmp r0, r2":::"cc"); \ |
507 | | asm volatile("cmp r0, r2":::"cc"); \ |
508 | | asm volatile("blt 1f"); \ |
509 | | asm volatile("cmp r0, r2":::"cc"); \ |
510 | | asm volatile("cmp r0, r2":::"cc"); \ |
511 | | asm volatile("cmp r0, r2":::"cc"); \ |
512 | | asm volatile("blt 1f"); \ |
513 | | /* Return value is set here in case of success */ \ |
514 | | ret = tmp_ret; \ |
515 | | asm volatile("1:"); \ |
516 | | asm volatile("nop"); \ |
517 | | } |
518 | | |
519 | | /** |
520 | | * Second part of RSA verification. |
521 | | * |
522 | | * Compare the digest twice, then confirm via |
523 | | * wolfBoot_image_confirm_signature_ok(); |
524 | | * |
525 | | * Uses GAS local numeric labels (2f/2:) for safe multi-expansion. |
526 | | */ |
527 | | #define RSA_VERIFY_HASH(img,digest) \ |
528 | | { \ |
529 | | volatile int compare_res; \ |
530 | | if (!img || !digest) \ |
531 | | asm volatile("b 2f"); \ |
532 | | /* Redundant set of r0=50*/ \ |
533 | | asm volatile("mov r0, #50":::"r0"); \ |
534 | | asm volatile("mov r0, #50":::"r0"); \ |
535 | | asm volatile("mov r0, #50":::"r0"); \ |
536 | | compare_res = image_CT_compare(digest, img->sha_hash, \ |
537 | | WOLFBOOT_SHA_DIGEST_SIZE); \ |
538 | | /* Redundant checks that ensure the function actually returned 0 */ \ |
539 | | asm volatile("cmp r0, #0":::"cc"); \ |
540 | | asm volatile("cmp r0, #0":::"cc"); \ |
541 | | asm volatile("cmp r0, #0":::"cc"); \ |
542 | | asm volatile("bne 2f":::"cc"); \ |
543 | | asm volatile("cmp r0, #0"); \ |
544 | | asm volatile("cmp r0, #0"); \ |
545 | | asm volatile("cmp r0, #0"); \ |
546 | | asm volatile("bne 2f":::"cc"); \ |
547 | | asm volatile("cmp r0, #0":::"cc"); \ |
548 | | asm volatile("cmp r0, #0":::"cc"); \ |
549 | | asm volatile("cmp r0, #0":::"cc"); \ |
550 | | asm volatile("bne 2f"); \ |
551 | | asm volatile("cmp r0, #0":::"cc"); \ |
552 | | asm volatile("cmp r0, #0":::"cc"); \ |
553 | | asm volatile("cmp r0, #0":::"cc"); \ |
554 | | asm volatile("bne 2f"); \ |
555 | | /* Repeat comparison call */ \ |
556 | | compare_res = image_CT_compare(digest, img->sha_hash, \ |
557 | | WOLFBOOT_SHA_DIGEST_SIZE); \ |
558 | | compare_res; \ |
559 | | /* Redundant checks that ensure the function actually returned 0 */ \ |
560 | | asm volatile("cmp r0, #0":::"cc"); \ |
561 | | asm volatile("cmp r0, #0":::"cc"); \ |
562 | | asm volatile("cmp r0, #0":::"cc"); \ |
563 | | asm volatile("bne 2f"); \ |
564 | | asm volatile("cmp r0, #0":::"cc"); \ |
565 | | asm volatile("cmp r0, #0":::"cc"); \ |
566 | | asm volatile("cmp r0, #0":::"cc"); \ |
567 | | asm volatile("bne 2f"); \ |
568 | | asm volatile("cmp r0, #0":::"cc"); \ |
569 | | asm volatile("cmp r0, #0":::"cc"); \ |
570 | | asm volatile("cmp r0, #0":::"cc"); \ |
571 | | asm volatile("bne 2f"); \ |
572 | | asm volatile("cmp r0, #0":::"cc"); \ |
573 | | asm volatile("cmp r0, #0":::"cc"); \ |
574 | | asm volatile("cmp r0, #0":::"cc"); \ |
575 | | asm volatile("bne 2f"); \ |
576 | | /* Confirm that the signature is OK */ \ |
577 | | wolfBoot_image_confirm_signature_ok(img); \ |
578 | | asm volatile("2:"); \ |
579 | | asm volatile("nop"); \ |
580 | | } |
581 | | |
582 | | /** |
583 | | * Second part of RSA-PSS verification. |
584 | | * |
585 | | * Call wc_RsaPSS_CheckPadding twice, then confirm via |
586 | | * wolfBoot_image_confirm_signature_ok(); |
587 | | * |
588 | | * Uses GAS local numeric labels (3f/3:) for safe multi-expansion. |
589 | | */ |
590 | | #define RSA_PSS_VERIFY_HASH(img, pss_data, pss_data_sz, hash_type) \ |
591 | | { \ |
592 | | volatile int pss_res; \ |
593 | | if (!img || !pss_data) \ |
594 | | asm volatile("b 3f"); \ |
595 | | /* Redundant set of r0=50*/ \ |
596 | | asm volatile("mov r0, #50":::"r0"); \ |
597 | | asm volatile("mov r0, #50":::"r0"); \ |
598 | | asm volatile("mov r0, #50":::"r0"); \ |
599 | | pss_res = wc_RsaPSS_CheckPadding(img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, \ |
600 | | pss_data, pss_data_sz, hash_type); \ |
601 | | /* Redundant checks that ensure the function actually returned 0 */ \ |
602 | | asm volatile("cmp r0, #0":::"cc"); \ |
603 | | asm volatile("cmp r0, #0":::"cc"); \ |
604 | | asm volatile("cmp r0, #0":::"cc"); \ |
605 | | asm volatile("bne 3f":::"cc"); \ |
606 | | asm volatile("cmp r0, #0"); \ |
607 | | asm volatile("cmp r0, #0"); \ |
608 | | asm volatile("cmp r0, #0"); \ |
609 | | asm volatile("bne 3f":::"cc"); \ |
610 | | asm volatile("cmp r0, #0":::"cc"); \ |
611 | | asm volatile("cmp r0, #0":::"cc"); \ |
612 | | asm volatile("cmp r0, #0":::"cc"); \ |
613 | | asm volatile("bne 3f"); \ |
614 | | asm volatile("cmp r0, #0":::"cc"); \ |
615 | | asm volatile("cmp r0, #0":::"cc"); \ |
616 | | asm volatile("cmp r0, #0":::"cc"); \ |
617 | | asm volatile("bne 3f"); \ |
618 | | /* Repeat wc_RsaPSS_CheckPadding call */ \ |
619 | | pss_res = wc_RsaPSS_CheckPadding(img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, \ |
620 | | pss_data, pss_data_sz, hash_type); \ |
621 | | pss_res; \ |
622 | | /* Redundant checks that ensure the function actually returned 0 */ \ |
623 | | asm volatile("cmp r0, #0":::"cc"); \ |
624 | | asm volatile("cmp r0, #0":::"cc"); \ |
625 | | asm volatile("cmp r0, #0":::"cc"); \ |
626 | | asm volatile("bne 3f"); \ |
627 | | asm volatile("cmp r0, #0":::"cc"); \ |
628 | | asm volatile("cmp r0, #0":::"cc"); \ |
629 | | asm volatile("cmp r0, #0":::"cc"); \ |
630 | | asm volatile("bne 3f"); \ |
631 | | asm volatile("cmp r0, #0":::"cc"); \ |
632 | | asm volatile("cmp r0, #0":::"cc"); \ |
633 | | asm volatile("cmp r0, #0":::"cc"); \ |
634 | | asm volatile("bne 3f"); \ |
635 | | asm volatile("cmp r0, #0":::"cc"); \ |
636 | | asm volatile("cmp r0, #0":::"cc"); \ |
637 | | asm volatile("cmp r0, #0":::"cc"); \ |
638 | | asm volatile("bne 3f"); \ |
639 | | /* Confirm that the signature is OK */ \ |
640 | | wolfBoot_image_confirm_signature_ok(img); \ |
641 | | asm volatile("3:"); \ |
642 | | asm volatile("nop"); \ |
643 | | } |
644 | | |
645 | | /* Redundant, canary-wrapped test for a confirmed integrity (digest) check. */ |
646 | | #define SHA_OK(imgp) (((imgp)->sha_ok == 1) && \ |
647 | | ((imgp)->not_sha_ok == ~(uint32_t)1)) |
648 | | |
649 | | /** |
650 | | * Digest (integrity) verification. |
651 | | * |
652 | | * Compare the freshly computed digest against the stored one twice, and after |
653 | | * each call ensure via redundant checks that image_CT_compare() actually |
654 | | * returned 0. Only then record the verified digest and confirm sha_ok through |
655 | | * the unskippable callback. A single instruction skip can neither coerce |
656 | | * image_CT_compare() into a false match nor set the sha_ok flag on its own. |
657 | | * |
658 | | * Uses GAS local numeric labels (5f/5:) for safe multi-expansion. |
659 | | */ |
660 | | #define VERIFY_INTEGRITY_FN(img, computed_digest, stored) \ |
661 | | { \ |
662 | | volatile int compare_res; \ |
663 | | if (!(img) || !(stored)) \ |
664 | | asm volatile("b 5f"); \ |
665 | | /* Redundant set of r0=50 */ \ |
666 | | asm volatile("mov r0, #50":::"r0"); \ |
667 | | asm volatile("mov r0, #50":::"r0"); \ |
668 | | asm volatile("mov r0, #50":::"r0"); \ |
669 | | compare_res = image_CT_compare((computed_digest), (stored), \ |
670 | | WOLFBOOT_SHA_DIGEST_SIZE); \ |
671 | | /* Redundant checks that ensure the function actually returned 0 */ \ |
672 | | asm volatile("cmp r0, #0":::"cc"); \ |
673 | | asm volatile("cmp r0, #0":::"cc"); \ |
674 | | asm volatile("cmp r0, #0":::"cc"); \ |
675 | | asm volatile("bne 5f"); \ |
676 | | asm volatile("cmp r0, #0":::"cc"); \ |
677 | | asm volatile("cmp r0, #0":::"cc"); \ |
678 | | asm volatile("cmp r0, #0":::"cc"); \ |
679 | | asm volatile("bne 5f"); \ |
680 | | asm volatile("cmp r0, #0":::"cc"); \ |
681 | | asm volatile("cmp r0, #0":::"cc"); \ |
682 | | asm volatile("cmp r0, #0":::"cc"); \ |
683 | | asm volatile("bne 5f"); \ |
684 | | asm volatile("cmp r0, #0":::"cc"); \ |
685 | | asm volatile("cmp r0, #0":::"cc"); \ |
686 | | asm volatile("cmp r0, #0":::"cc"); \ |
687 | | asm volatile("bne 5f"); \ |
688 | | /* Repeat comparison call */ \ |
689 | | compare_res = image_CT_compare((computed_digest), (stored), \ |
690 | | WOLFBOOT_SHA_DIGEST_SIZE); \ |
691 | | compare_res; \ |
692 | | /* Redundant checks that ensure the function actually returned 0 */ \ |
693 | | asm volatile("cmp r0, #0":::"cc"); \ |
694 | | asm volatile("cmp r0, #0":::"cc"); \ |
695 | | asm volatile("cmp r0, #0":::"cc"); \ |
696 | | asm volatile("bne 5f"); \ |
697 | | asm volatile("cmp r0, #0":::"cc"); \ |
698 | | asm volatile("cmp r0, #0":::"cc"); \ |
699 | | asm volatile("cmp r0, #0":::"cc"); \ |
700 | | asm volatile("bne 5f"); \ |
701 | | asm volatile("cmp r0, #0":::"cc"); \ |
702 | | asm volatile("cmp r0, #0":::"cc"); \ |
703 | | asm volatile("cmp r0, #0":::"cc"); \ |
704 | | asm volatile("bne 5f"); \ |
705 | | asm volatile("cmp r0, #0":::"cc"); \ |
706 | | asm volatile("cmp r0, #0":::"cc"); \ |
707 | | asm volatile("cmp r0, #0":::"cc"); \ |
708 | | asm volatile("bne 5f"); \ |
709 | | /* Integrity confirmed: record verified digest and set sha_ok */ \ |
710 | | (img)->sha_hash = (stored); \ |
711 | | wolfBoot_image_confirm_sha_ok(img); \ |
712 | | asm volatile("5:"); \ |
713 | | asm volatile("nop"); \ |
714 | | } |
715 | | |
716 | | /** |
717 | | * Hardened assertion that the integrity (digest) check has actually been |
718 | | * performed and passed. Mirrors the sha portion of PART_SANITY_CHECK and is |
719 | | * used right after the integrity re-check in wolfBoot_verify_authenticity(), |
720 | | * so that skipping the re-check (or its result) cannot let an unverified |
721 | | * image proceed to signature verification. |
722 | | */ |
723 | | #define SHA_SANITY_CHECK(p) \ |
724 | | /* Redundant set of r2=0 */ \ |
725 | | asm volatile("mov r2, #0":::"r2"); \ |
726 | | asm volatile("mov r2, #0":::"r2"); \ |
727 | | asm volatile("mov r2, #0":::"r2"); \ |
728 | | asm volatile("mov r2, #0":::"r2"); \ |
729 | | asm volatile("mov r2, #0":::"r2"); \ |
730 | | /* Loading sha_ok flag, verifying */ \ |
731 | | asm volatile("mov r2, %0" ::"r"((p)->sha_ok):"r2"); \ |
732 | | asm volatile("cmp r2, #1":::"cc"); \ |
733 | | asm volatile("cmp r2, #1":::"cc"); \ |
734 | | asm volatile("cmp r2, #1":::"cc"); \ |
735 | | asm volatile("bne ."); \ |
736 | | asm volatile("cmp r2, #1":::"cc"); \ |
737 | | asm volatile("cmp r2, #1":::"cc"); \ |
738 | | asm volatile("cmp r2, #1":::"cc"); \ |
739 | | asm volatile("bne .-4"); \ |
740 | | asm volatile("cmp r2, #1":::"cc"); \ |
741 | | asm volatile("cmp r2, #1":::"cc"); \ |
742 | | asm volatile("cmp r2, #1":::"cc"); \ |
743 | | asm volatile("bne .-8"); \ |
744 | | asm volatile("cmp r2, #1":::"cc"); \ |
745 | | asm volatile("cmp r2, #1":::"cc"); \ |
746 | | asm volatile("cmp r2, #1":::"cc"); \ |
747 | | asm volatile("bne .-12"); \ |
748 | | /* Redundant set of r2=0 */ \ |
749 | | asm volatile("mov r2, #0":::"r2"); \ |
750 | | asm volatile("mov r2, #0":::"r2"); \ |
751 | | asm volatile("mov r2, #0":::"r2"); \ |
752 | | asm volatile("mov r2, #0":::"r2"); \ |
753 | | asm volatile("mov r2, #0":::"r2"); \ |
754 | | /* Loading ~(sha_ok) flag, verifying */ \ |
755 | | asm volatile("mov r2, %0" ::"r"((p)->not_sha_ok):"r2"); \ |
756 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
757 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
758 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
759 | | asm volatile("bne ."); \ |
760 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
761 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
762 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
763 | | asm volatile("bne .-4"); \ |
764 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
765 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
766 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
767 | | asm volatile("bne .-8"); \ |
768 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
769 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
770 | | asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \ |
771 | | asm volatile("bne .-12") |
772 | | |
773 | | /** |
774 | | * Hardened assertion that the image entry base is consistent with its stored |
775 | | * complement (fw_base == ~not_fw_base), performed immediately before do_boot() |
776 | | * dereferences fw_base. A single fault on either the pointer or the loads |
777 | | * fails the check safely (spins) instead of redirecting the boot jump. |
778 | | */ |
779 | | #define FW_BASE_SANITY_CHECK(p) \ |
780 | | do { \ |
781 | | /* Single asm block so the compiler cannot allocate over r0/r2 between \ |
782 | | * steps: r2 = fw_base, r0 = ~not_fw_base (== expected fw_base), then \ |
783 | | * a redundant self-trapping comparison that spins on any mismatch. */ \ |
784 | | asm volatile( \ |
785 | | "mov r2, %[fwb]\n\t" \ |
786 | | "mov r0, %[nfwb]\n\t" \ |
787 | | "mvn r0, r0\n\t" \ |
788 | | "cmp r2, r0\n\t" \ |
789 | | "cmp r2, r0\n\t" \ |
790 | | "cmp r2, r0\n\t" \ |
791 | | "bne .\n\t" \ |
792 | | "cmp r2, r0\n\t" \ |
793 | | "cmp r2, r0\n\t" \ |
794 | | "cmp r2, r0\n\t" \ |
795 | | "bne .-4\n\t" \ |
796 | | "cmp r2, r0\n\t" \ |
797 | | "cmp r2, r0\n\t" \ |
798 | | "cmp r2, r0\n\t" \ |
799 | | "bne .-8\n\t" \ |
800 | | "cmp r2, r0\n\t" \ |
801 | | "cmp r2, r0\n\t" \ |
802 | | "cmp r2, r0\n\t" \ |
803 | | "bne .-12\n\t" \ |
804 | | : \ |
805 | | : [fwb] "r" ((uintptr_t)(p)->fw_base), \ |
806 | | [nfwb] "r" ((uintptr_t)(p)->not_fw_base) \ |
807 | | : "r0", "r2", "cc"); \ |
808 | | } while (0) |
809 | | |
810 | | /** |
811 | | * ECC / Ed / PQ signature verification. |
812 | | * Those verify functions set an additional value 'p_res' |
813 | | * which is passed as a pointer. |
814 | | * |
815 | | * Ensure that the verification function has been called, and then |
816 | | * set the return value accordingly. |
817 | | * |
818 | | * Double check by reading the value in p_res from memory a few times. |
819 | | * |
820 | | * Uses GAS local numeric labels (4f/4:) for safe multi-expansion. |
821 | | */ |
822 | | #if defined(__GNUC__) |
823 | | |
824 | | #define VERIFY_FN(img,p_res,fn,...) \ |
825 | | /* Redundant set of r0=50*/ \ |
826 | | asm volatile("mov r0, #50":::"r0"); \ |
827 | | asm volatile("mov r0, #50":::"r0"); \ |
828 | | asm volatile("mov r0, #50":::"r0"); \ |
829 | | /* Call the verify function */ \ |
830 | | fn(__VA_ARGS__); \ |
831 | | /* Redundant checks that ensure the function actually returned 0 */ \ |
832 | | asm volatile("cmp r0, #0":::"cc"); \ |
833 | | asm volatile("cmp r0, #0":::"cc"); \ |
834 | | asm volatile("cmp r0, #0":::"cc"); \ |
835 | | asm volatile("bne 4f"); \ |
836 | | asm volatile("cmp r0, #0":::"cc"); \ |
837 | | asm volatile("cmp r0, #0":::"cc"); \ |
838 | | asm volatile("cmp r0, #0":::"cc"); \ |
839 | | asm volatile("bne 4f"); \ |
840 | | asm volatile("cmp r0, #0":::"cc"); \ |
841 | | asm volatile("cmp r0, #0":::"cc"); \ |
842 | | asm volatile("cmp r0, #0":::"cc"); \ |
843 | | asm volatile("bne 4f"); \ |
844 | | asm volatile("cmp r0, #0":::"cc"); \ |
845 | | asm volatile("cmp r0, #0":::"cc"); \ |
846 | | asm volatile("cmp r0, #0":::"cc"); \ |
847 | | asm volatile("bne 4f"); \ |
848 | | /* Check that res = 1, a few times, reading the value from memory */ \ |
849 | | asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ |
850 | | asm volatile("cmp r2, #1":::"cc"); \ |
851 | | asm volatile("cmp r2, #1":::"cc"); \ |
852 | | asm volatile("cmp r2, #1":::"cc"); \ |
853 | | asm volatile("bne 4f"); \ |
854 | | asm volatile("mvn r3, r2":::"r3"); \ |
855 | | asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ |
856 | | asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ |
857 | | asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ |
858 | | asm volatile("bne 4f"); \ |
859 | | asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ |
860 | | asm volatile("cmp r2, #1":::"cc"); \ |
861 | | asm volatile("cmp r2, #1":::"cc"); \ |
862 | | asm volatile("cmp r2, #1":::"cc"); \ |
863 | | asm volatile("bne 4f"); \ |
864 | | asm volatile("mvn r3, r2":::"r3"); \ |
865 | | asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ |
866 | | asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ |
867 | | asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ |
868 | | asm volatile("bne 4f"); \ |
869 | | asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ |
870 | | asm volatile("cmp r2, #1":::"cc"); \ |
871 | | asm volatile("cmp r2, #1":::"cc"); \ |
872 | | asm volatile("cmp r2, #1":::"cc"); \ |
873 | | asm volatile("bne 4f"); \ |
874 | | asm volatile("mvn r3, r2":::"r3"); \ |
875 | | asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ |
876 | | asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ |
877 | | asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ |
878 | | asm volatile("bne 4f"); \ |
879 | | asm volatile("ldr r2, [%0]" ::"r"(p_res)); \ |
880 | | asm volatile("cmp r2, #1":::"cc"); \ |
881 | | asm volatile("cmp r2, #1":::"cc"); \ |
882 | | asm volatile("cmp r2, #1":::"cc"); \ |
883 | | asm volatile("bne 4f"); \ |
884 | | asm volatile("mvn r3, r2":::"r3"); \ |
885 | | asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ |
886 | | asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ |
887 | | asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \ |
888 | | asm volatile("bne 4f"); \ |
889 | | /* Confirm that the signature is OK */ \ |
890 | | wolfBoot_image_confirm_signature_ok(img); \ |
891 | | asm volatile("4:"); \ |
892 | | asm volatile("nop") \ |
893 | | |
894 | | #elif defined(__ICCARM__) && defined(__IAR_SYSTEMS_ICC__) |
895 | | |
896 | | #define VERIFY_FN(img, p_res, fn, ...) \ |
897 | | do { \ |
898 | | __asm volatile( \ |
899 | | "mov r0, #50\n" \ |
900 | | "mov r0, #50\n" \ |
901 | | "mov r0, #50\n" \ |
902 | | : /* No output operands */ \ |
903 | | : /* No input operands */ \ |
904 | | : "r0" /* Clobbered registers */ \ |
905 | | ); \ |
906 | | void (*confirm_func)(struct wolfBoot_image *) = \ |
907 | | wolfBoot_image_confirm_signature_ok; \ |
908 | | fn(__VA_ARGS__); \ |
909 | | __asm volatile( \ |
910 | | "cmp r0, #0\n" \ |
911 | | "cmp r0, #0\n" \ |
912 | | "cmp r0, #0\n" \ |
913 | | "beq 30f\n" \ |
914 | | "bne 1f\n" \ |
915 | | "bne 1f\n" \ |
916 | | "bne 1f\n" \ |
917 | | "bne 1f\n" \ |
918 | | "b .\n" \ |
919 | | "b .\n" \ |
920 | | "b .\n" \ |
921 | | "30:\n" \ |
922 | | "ldr r2, [%0]\n" \ |
923 | | "cmp r2, #1\n" \ |
924 | | "cmp r2, #1\n" \ |
925 | | "cmp r2, #1\n" \ |
926 | | "beq 31f\n" \ |
927 | | "bne 1f\n" \ |
928 | | "bne 1f\n" \ |
929 | | "bne 1f\n" \ |
930 | | "bne 1f\n" \ |
931 | | "b .\n" \ |
932 | | "b .\n" \ |
933 | | "b .\n" \ |
934 | | "31:\n" \ |
935 | | "mvn r3, r2\n" \ |
936 | | "cmp r3, #0xFFFFFFFE\n" \ |
937 | | "cmp r3, #0xFFFFFFFE\n" \ |
938 | | "cmp r3, #0xFFFFFFFE\n" \ |
939 | | "beq 32f\n" \ |
940 | | "bne 1f\n" \ |
941 | | "bne 1f\n" \ |
942 | | "bne 1f\n" \ |
943 | | "bne 1f\n" \ |
944 | | "b .\n" \ |
945 | | "b .\n" \ |
946 | | "b .\n" \ |
947 | | "32:\n" \ |
948 | | "ldr r2, [%0]\n" \ |
949 | | "cmp r2, #1\n" \ |
950 | | "cmp r2, #1\n" \ |
951 | | "cmp r2, #1\n" \ |
952 | | "beq 33f\n" \ |
953 | | "bne 1f\n" \ |
954 | | "bne 1f\n" \ |
955 | | "bne 1f\n" \ |
956 | | "bne 1f\n" \ |
957 | | "b .\n" \ |
958 | | "b .\n" \ |
959 | | "b .\n" \ |
960 | | "33:\n" \ |
961 | | "mvn r3, r2\n" \ |
962 | | "cmp r3, #0xFFFFFFFE\n" \ |
963 | | "cmp r3, #0xFFFFFFFE\n" \ |
964 | | "cmp r3, #0xFFFFFFFE\n" \ |
965 | | "beq 34f\n" \ |
966 | | "bne 1f\n" \ |
967 | | "bne 1f\n" \ |
968 | | "bne 1f\n" \ |
969 | | "bne 1f\n" \ |
970 | | "b .\n" \ |
971 | | "b .\n" \ |
972 | | "b .\n" \ |
973 | | "34:\n" \ |
974 | | "ldr r2, [%0]\n" \ |
975 | | "cmp r2, #1\n" \ |
976 | | "cmp r2, #1\n" \ |
977 | | "cmp r2, #1\n" \ |
978 | | "beq 35f\n" \ |
979 | | "bne 1f\n" \ |
980 | | "bne 1f\n" \ |
981 | | "bne 1f\n" \ |
982 | | "bne 1f\n" \ |
983 | | "b .\n" \ |
984 | | "b .\n" \ |
985 | | "b .\n" \ |
986 | | "35:\n" \ |
987 | | "mvn r3, r2\n" \ |
988 | | "cmp r3, #0xFFFFFFFE\n" \ |
989 | | "cmp r3, #0xFFFFFFFE\n" \ |
990 | | "cmp r3, #0xFFFFFFFE\n" \ |
991 | | "beq 36f\n" \ |
992 | | "bne 1f\n" \ |
993 | | "bne 1f\n" \ |
994 | | "bne 1f\n" \ |
995 | | "bne 1f\n" \ |
996 | | "b .\n" \ |
997 | | "b .\n" \ |
998 | | "b .\n" \ |
999 | | "36:\n" \ |
1000 | | "ldr r2, [%0]\n" \ |
1001 | | "cmp r2, #1\n" \ |
1002 | | "cmp r2, #1\n" \ |
1003 | | "cmp r2, #1\n" \ |
1004 | | "beq 37f\n" \ |
1005 | | "bne 1f\n" \ |
1006 | | "bne 1f\n" \ |
1007 | | "bne 1f\n" \ |
1008 | | "bne 1f\n" \ |
1009 | | "b .\n" \ |
1010 | | "b .\n" \ |
1011 | | "b .\n" \ |
1012 | | "37:\n" \ |
1013 | | "mvn r3, r2\n" \ |
1014 | | "cmp r3, #0xFFFFFFFE\n" \ |
1015 | | "cmp r3, #0xFFFFFFFE\n" \ |
1016 | | "cmp r3, #0xFFFFFFFE\n" \ |
1017 | | "beq 38f\n" \ |
1018 | | "bne 1f\n" \ |
1019 | | "bne 1f\n" \ |
1020 | | "bne 1f\n" \ |
1021 | | "bne 1f\n" \ |
1022 | | "b .\n" \ |
1023 | | "b .\n" \ |
1024 | | "b .\n" \ |
1025 | | "38:\n" \ |
1026 | | /* Load 'img' into r0 (first argument to the function) */ \ |
1027 | | "mov r0, %1\n" \ |
1028 | | /* Load the function pointer into r3 */ \ |
1029 | | "mov r3, %2\n" \ |
1030 | | "blx r3\n"\ |
1031 | | "b 2f\n" \ |
1032 | | "b .\n" \ |
1033 | | "b .\n" \ |
1034 | | "b .\n" \ |
1035 | | "1:\n" \ |
1036 | | "nop\n" \ |
1037 | | "2:\n" \ |
1038 | | : /* No output operands */ \ |
1039 | | : "r"(p_res), "r"(img), "r"(confirm_func) /* Input operands */ \ |
1040 | | : "r0", "r2", "r3", "lr" /* Clobbered registers */ \ |
1041 | | ); \ |
1042 | | } while (0) |
1043 | | #endif |
1044 | | |
1045 | | |
1046 | | /** |
1047 | | * This macro is only invoked after a successful update version check, prior to |
1048 | | * initiating the update installation. |
1049 | | * |
1050 | | * At this point, wolfBoot thinks that the version check has been successful. |
1051 | | * |
1052 | | * |
1053 | | * The fallback flag (checked with redundancy) causes wolfBoot to skip the |
1054 | | * redundant version checks. |
1055 | | * |
1056 | | * The redundant checks here ensure that the image version is read twice per |
1057 | | * each partition, and the two return values are the same. |
1058 | | * |
1059 | | * |
1060 | | * The comparison is also redundant, causing wolfBoot to panic if the update |
1061 | | * version is not strictly greater than the current one. |
1062 | | * |
1063 | | */ |
1064 | | #if defined(__GNUC__) |
1065 | | |
1066 | | #define VERIFY_VERSION_ALLOWED(fb_ok) \ |
1067 | | asm volatile( \ |
1068 | | "push {r4, r5, r6, r7}\n" \ |
1069 | | "mov r0, #0\n" \ |
1070 | | "mov r4, #1\n" \ |
1071 | | "mov r5, #0\n" \ |
1072 | | "mov r6, #2\n" \ |
1073 | | "mov r7, #0\n" \ |
1074 | | "mov r0, #0\n" \ |
1075 | | "mov r4, #1\n" \ |
1076 | | "mov r5, #0\n" \ |
1077 | | "mov r6, #2\n" \ |
1078 | | "mov r7, #0\n" \ |
1079 | | "mov r0, %0\n" \ |
1080 | | "mov r4, %0\n" \ |
1081 | | "cmp r0, #1\n" \ |
1082 | | "cmp r0, #1\n" \ |
1083 | | "cmp r0, #1\n" \ |
1084 | | "beq 20f\n" \ |
1085 | | "bne do_check\n" \ |
1086 | | "bne do_check\n" \ |
1087 | | "bne do_check\n" \ |
1088 | | "bne do_check\n" \ |
1089 | | "b .\n" \ |
1090 | | "b .\n" \ |
1091 | | "b .\n" \ |
1092 | | "20:\n" \ |
1093 | | "cmp r4, #1\n" \ |
1094 | | "cmp r4, #1\n" \ |
1095 | | "cmp r4, #1\n" \ |
1096 | | "beq 21f\n" \ |
1097 | | "bne do_check\n" \ |
1098 | | "bne do_check\n" \ |
1099 | | "bne do_check\n" \ |
1100 | | "bne do_check\n" \ |
1101 | | "b .\n" \ |
1102 | | "b .\n" \ |
1103 | | "b .\n" \ |
1104 | | "21:\n" \ |
1105 | | "cmp r0, r4\n" \ |
1106 | | "cmp r0, r4\n" \ |
1107 | | "cmp r0, r4\n" \ |
1108 | | "beq 22f\n" \ |
1109 | | "bne do_check\n" \ |
1110 | | "bne do_check\n" \ |
1111 | | "bne do_check\n" \ |
1112 | | "bne do_check\n" \ |
1113 | | "b .\n" \ |
1114 | | "b .\n" \ |
1115 | | "b .\n" \ |
1116 | | "22:\n" \ |
1117 | | "cmp r0, #1\n" \ |
1118 | | "cmp r0, #1\n" \ |
1119 | | "cmp r0, #1\n" \ |
1120 | | "beq 23f\n" \ |
1121 | | "bne do_check\n" \ |
1122 | | "bne do_check\n" \ |
1123 | | "bne do_check\n" \ |
1124 | | "bne do_check\n" \ |
1125 | | "b .\n" \ |
1126 | | "b .\n" \ |
1127 | | "b .\n" \ |
1128 | | "23:\n" \ |
1129 | | "b end_check\n" \ |
1130 | | "do_check:\n" \ |
1131 | | "mov r0, #1\n" \ |
1132 | | "mov r0, #1\n" \ |
1133 | | "mov r0, #1\n" \ |
1134 | | "bl wolfBoot_get_image_version\n" \ |
1135 | | "mov r5, r0\n" \ |
1136 | | "mov r5, r0\n" \ |
1137 | | "mov r5, r0\n" \ |
1138 | | "mov r0, #1\n" \ |
1139 | | "mov r0, #1\n" \ |
1140 | | "mov r0, #1\n" \ |
1141 | | "bl wolfBoot_get_image_version\n" \ |
1142 | | "mov r7, r0\n" \ |
1143 | | "mov r7, r0\n" \ |
1144 | | "mov r7, r0\n" \ |
1145 | | "cmp r5, r7\n" \ |
1146 | | "cmp r5, r7\n" \ |
1147 | | "cmp r5, r7\n" \ |
1148 | | "beq 24f\n" \ |
1149 | | "bne ver_panic\n" \ |
1150 | | "bne ver_panic\n" \ |
1151 | | "bne ver_panic\n" \ |
1152 | | "bne ver_panic\n" \ |
1153 | | "b .\n" \ |
1154 | | "b .\n" \ |
1155 | | "b .\n" \ |
1156 | | "24:\n" \ |
1157 | | "mov r0, #0\n" \ |
1158 | | "mov r0, #0\n" \ |
1159 | | "mov r0, #0\n" \ |
1160 | | "bl wolfBoot_get_image_version\n" \ |
1161 | | "mov r4, r0\n" \ |
1162 | | "mov r4, r0\n" \ |
1163 | | "mov r4, r0\n" \ |
1164 | | "mov r0, #0\n" \ |
1165 | | "mov r0, #0\n" \ |
1166 | | "mov r0, #0\n" \ |
1167 | | "bl wolfBoot_get_image_version\n" \ |
1168 | | "mov r6, r0\n" \ |
1169 | | "mov r6, r0\n" \ |
1170 | | "mov r6, r0\n" \ |
1171 | | "cmp r4, r6\n" \ |
1172 | | "cmp r4, r6\n" \ |
1173 | | "cmp r4, r6\n" \ |
1174 | | "beq 25f\n" \ |
1175 | | "bne ver_panic\n" \ |
1176 | | "bne ver_panic\n" \ |
1177 | | "bne ver_panic\n" \ |
1178 | | "bne ver_panic\n" \ |
1179 | | "b .\n" \ |
1180 | | "b .\n" \ |
1181 | | "b .\n" \ |
1182 | | "25:\n" \ |
1183 | | "mov r0, #0\n" \ |
1184 | | "mov r0, #0\n" \ |
1185 | | "mov r0, #0\n" \ |
1186 | | "cmp r4, r5\n" \ |
1187 | | "cmp r4, r5\n" \ |
1188 | | "cmp r4, r5\n" \ |
1189 | | "blo 26f\n" \ |
1190 | | "bhs ver_panic\n" \ |
1191 | | "bhs ver_panic\n" \ |
1192 | | "bhs ver_panic\n" \ |
1193 | | "bhs ver_panic\n" \ |
1194 | | "b .\n" \ |
1195 | | "b .\n" \ |
1196 | | "b .\n" \ |
1197 | | "26:\n" \ |
1198 | | "cmp r6, r7\n" \ |
1199 | | "cmp r6, r7\n" \ |
1200 | | "cmp r6, r7\n" \ |
1201 | | "blo 27f\n" \ |
1202 | | "bhs ver_panic\n" \ |
1203 | | "bhs ver_panic\n" \ |
1204 | | "bhs ver_panic\n" \ |
1205 | | "bhs ver_panic\n" \ |
1206 | | "b .\n" \ |
1207 | | "b .\n" \ |
1208 | | "b .\n" \ |
1209 | | "27:\n" \ |
1210 | | "cmp r4, r5\n" \ |
1211 | | "cmp r4, r5\n" \ |
1212 | | "cmp r4, r5\n" \ |
1213 | | "blo 28f\n" \ |
1214 | | "bhs ver_panic\n" \ |
1215 | | "bhs ver_panic\n" \ |
1216 | | "bhs ver_panic\n" \ |
1217 | | "bhs ver_panic\n" \ |
1218 | | "b .\n" \ |
1219 | | "b .\n" \ |
1220 | | "b .\n" \ |
1221 | | "28:\n" \ |
1222 | | "cmp r6, r7\n" \ |
1223 | | "cmp r6, r7\n" \ |
1224 | | "cmp r6, r7\n" \ |
1225 | | "blo 29f\n" \ |
1226 | | "bhs ver_panic\n" \ |
1227 | | "bhs ver_panic\n" \ |
1228 | | "bhs ver_panic\n" \ |
1229 | | "bhs ver_panic\n" \ |
1230 | | "b .\n" \ |
1231 | | "b .\n" \ |
1232 | | "b .\n" \ |
1233 | | "29:\n" \ |
1234 | | "b end_check\n" \ |
1235 | | "ver_panic:\n" \ |
1236 | | "b .\n" \ |
1237 | | "b .\n" \ |
1238 | | "b .\n" \ |
1239 | | "b .\n" \ |
1240 | | "b .\n" \ |
1241 | | "b .\n" \ |
1242 | | "b .\n" \ |
1243 | | "b .\n" \ |
1244 | | "b .\n" \ |
1245 | | "b .\n" \ |
1246 | | "b .\n" \ |
1247 | | "end_check:\n" \ |
1248 | | "pop {r4, r5, r6, r7}\n" \ |
1249 | | : \ |
1250 | | : "r"(fb_ok) \ |
1251 | | : "r0", "r4", "r5", "r6", "r7", "lr", "cc", "memory" \ |
1252 | | ) |
1253 | | |
1254 | | #elif defined(__ICCARM__) && defined(__IAR_SYSTEMS_ICC__) |
1255 | | |
1256 | | #define VERIFY_VERSION_ALLOWED(fb_ok) \ |
1257 | | do { \ |
1258 | | __asm volatile( \ |
1259 | | "push {r4, r5, r6, r7}\n" \ |
1260 | | "mov r0, #0\n" \ |
1261 | | "mov r4, #1\n" \ |
1262 | | "mov r5, #0\n" \ |
1263 | | "mov r6, #2\n" \ |
1264 | | "mov r7, #0\n" \ |
1265 | | "mov r0, #0\n" \ |
1266 | | "mov r4, #1\n" \ |
1267 | | "mov r5, #0\n" \ |
1268 | | "mov r6, #2\n" \ |
1269 | | "mov r7, #0\n" \ |
1270 | | "mov r0, %0\n" \ |
1271 | | "mov r4, %0\n" \ |
1272 | | "cmp r0, #0\n" \ |
1273 | | "cmp r0, #0\n" \ |
1274 | | "cmp r0, #0\n" \ |
1275 | | "beq 4f\n" \ |
1276 | | "bne 6f\n" \ |
1277 | | "bne 6f\n" \ |
1278 | | "bne 6f\n" \ |
1279 | | "bne 6f\n" \ |
1280 | | "b .\n" \ |
1281 | | "b .\n" \ |
1282 | | "b .\n" \ |
1283 | | "6:\n" \ |
1284 | | "cmp r0, #1\n" \ |
1285 | | "cmp r0, #1\n" \ |
1286 | | "cmp r0, #1\n" \ |
1287 | | "beq 4f\n" \ |
1288 | | "bne 1f\n" \ |
1289 | | "bne 1f\n" \ |
1290 | | "bne 1f\n" \ |
1291 | | "bne 1f\n" \ |
1292 | | "b .\n" \ |
1293 | | "b .\n" \ |
1294 | | "b .\n" \ |
1295 | | "4:\n" \ |
1296 | | "cmp r4, #0\n" \ |
1297 | | "cmp r4, #0\n" \ |
1298 | | "cmp r4, #0\n" \ |
1299 | | "beq 5f\n" \ |
1300 | | "bne 7f\n" \ |
1301 | | "bne 7f\n" \ |
1302 | | "bne 7f\n" \ |
1303 | | "bne 7f\n" \ |
1304 | | "b .\n" \ |
1305 | | "b .\n" \ |
1306 | | "b .\n" \ |
1307 | | "7:\n" \ |
1308 | | "cmp r4, #1\n" \ |
1309 | | "cmp r4, #1\n" \ |
1310 | | "cmp r4, #1\n" \ |
1311 | | "beq 5f\n" \ |
1312 | | "bne 1f\n" \ |
1313 | | "bne 1f\n" \ |
1314 | | "bne 1f\n" \ |
1315 | | "bne 1f\n" \ |
1316 | | "b .\n" \ |
1317 | | "b .\n" \ |
1318 | | "b .\n" \ |
1319 | | "5:\n" \ |
1320 | | "cmp r0, #1\n" \ |
1321 | | "cmp r0, #1\n" \ |
1322 | | "cmp r0, #1\n" \ |
1323 | | "beq 8f\n" \ |
1324 | | "bne 1f\n" \ |
1325 | | "bne 1f\n" \ |
1326 | | "bne 1f\n" \ |
1327 | | "bne 1f\n" \ |
1328 | | "b .\n" \ |
1329 | | "b .\n" \ |
1330 | | "b .\n" \ |
1331 | | "8:\n" \ |
1332 | | "cmp r4, #1\n" \ |
1333 | | "cmp r4, #1\n" \ |
1334 | | "cmp r4, #1\n" \ |
1335 | | "beq 9f\n" \ |
1336 | | "bne 1f\n" \ |
1337 | | "bne 1f\n" \ |
1338 | | "bne 1f\n" \ |
1339 | | "bne 1f\n" \ |
1340 | | "b .\n" \ |
1341 | | "b .\n" \ |
1342 | | "b .\n" \ |
1343 | | "9:\n" \ |
1344 | | "cmp r0, r4\n" \ |
1345 | | "cmp r0, r4\n" \ |
1346 | | "cmp r0, r4\n" \ |
1347 | | "beq 10f\n" \ |
1348 | | "bne 1f\n" \ |
1349 | | "bne 1f\n" \ |
1350 | | "bne 1f\n" \ |
1351 | | "bne 1f\n" \ |
1352 | | "b .\n" \ |
1353 | | "b .\n" \ |
1354 | | "b .\n" \ |
1355 | | "10:\n" \ |
1356 | | "cmp r0, #1\n" \ |
1357 | | "cmp r0, #1\n" \ |
1358 | | "cmp r0, #1\n" \ |
1359 | | "beq 11f\n" \ |
1360 | | "bne 1f\n" \ |
1361 | | "bne 1f\n" \ |
1362 | | "bne 1f\n" \ |
1363 | | "bne 1f\n" \ |
1364 | | "b .\n" \ |
1365 | | "b .\n" \ |
1366 | | "b .\n" \ |
1367 | | "11:\n" \ |
1368 | | "b 2f\n" \ |
1369 | | "b .\n" \ |
1370 | | "b .\n" \ |
1371 | | "b .\n" \ |
1372 | | "1:\n" \ |
1373 | | "mov r0, #1\n" \ |
1374 | | "mov r0, #1\n" \ |
1375 | | "mov r0, #1\n" \ |
1376 | | "bl wolfBoot_get_image_version\n" \ |
1377 | | "mov r5, r0\n" \ |
1378 | | "mov r5, r0\n" \ |
1379 | | "mov r5, r0\n" \ |
1380 | | "mov r0, #1\n" \ |
1381 | | "mov r0, #1\n" \ |
1382 | | "mov r0, #1\n" \ |
1383 | | "bl wolfBoot_get_image_version\n" \ |
1384 | | "mov r7, r0\n" \ |
1385 | | "mov r7, r0\n" \ |
1386 | | "mov r7, r0\n" \ |
1387 | | "cmp r5, r7\n" \ |
1388 | | "cmp r5, r7\n" \ |
1389 | | "cmp r5, r7\n" \ |
1390 | | "beq 12f\n" \ |
1391 | | "bne 3f\n" \ |
1392 | | "bne 3f\n" \ |
1393 | | "bne 3f\n" \ |
1394 | | "bne 3f\n" \ |
1395 | | "b .\n" \ |
1396 | | "b .\n" \ |
1397 | | "b .\n" \ |
1398 | | "12:\n" \ |
1399 | | "mov r0, #0\n" \ |
1400 | | "mov r0, #0\n" \ |
1401 | | "mov r0, #0\n" \ |
1402 | | "bl wolfBoot_get_image_version\n" \ |
1403 | | "mov r4, r0\n" \ |
1404 | | "mov r4, r0\n" \ |
1405 | | "mov r4, r0\n" \ |
1406 | | "mov r0, #0\n" \ |
1407 | | "mov r0, #0\n" \ |
1408 | | "mov r0, #0\n" \ |
1409 | | "bl wolfBoot_get_image_version\n" \ |
1410 | | "mov r6, r0\n" \ |
1411 | | "mov r6, r0\n" \ |
1412 | | "mov r6, r0\n" \ |
1413 | | "cmp r4, r6\n" \ |
1414 | | "cmp r4, r6\n" \ |
1415 | | "cmp r4, r6\n" \ |
1416 | | "beq 13f\n" \ |
1417 | | "bne 3f\n" \ |
1418 | | "bne 3f\n" \ |
1419 | | "bne 3f\n" \ |
1420 | | "bne 3f\n" \ |
1421 | | "b .\n" \ |
1422 | | "b .\n" \ |
1423 | | "b .\n" \ |
1424 | | "13:\n" \ |
1425 | | "mov r0, #0\n" \ |
1426 | | "mov r0, #0\n" \ |
1427 | | "mov r0, #0\n" \ |
1428 | | "cmp r4, r5\n" \ |
1429 | | "cmp r4, r5\n" \ |
1430 | | "cmp r4, r5\n" \ |
1431 | | "blo 14f\n" \ |
1432 | | "bhs 3f\n" \ |
1433 | | "bhs 3f\n" \ |
1434 | | "bhs 3f\n" \ |
1435 | | "bhs 3f\n" \ |
1436 | | "b .\n" \ |
1437 | | "b .\n" \ |
1438 | | "b .\n" \ |
1439 | | "14:\n" \ |
1440 | | "cmp r6, r7\n" \ |
1441 | | "cmp r6, r7\n" \ |
1442 | | "cmp r6, r7\n" \ |
1443 | | "blo 15f\n" \ |
1444 | | "bhs 3f\n" \ |
1445 | | "bhs 3f\n" \ |
1446 | | "bhs 3f\n" \ |
1447 | | "bhs 3f\n" \ |
1448 | | "b .\n" \ |
1449 | | "b .\n" \ |
1450 | | "b .\n" \ |
1451 | | "15:\n" \ |
1452 | | "cmp r4, r5\n" \ |
1453 | | "cmp r4, r5\n" \ |
1454 | | "cmp r4, r5\n" \ |
1455 | | "blo 16f\n" \ |
1456 | | "bhs 3f\n" \ |
1457 | | "bhs 3f\n" \ |
1458 | | "bhs 3f\n" \ |
1459 | | "bhs 3f\n" \ |
1460 | | "b .\n" \ |
1461 | | "b .\n" \ |
1462 | | "b .\n" \ |
1463 | | "16:\n" \ |
1464 | | "cmp r6, r7\n" \ |
1465 | | "cmp r6, r7\n" \ |
1466 | | "cmp r6, r7\n" \ |
1467 | | "blo 17f\n" \ |
1468 | | "bhs 3f\n" \ |
1469 | | "bhs 3f\n" \ |
1470 | | "bhs 3f\n" \ |
1471 | | "bhs 3f\n" \ |
1472 | | "b .\n" \ |
1473 | | "b .\n" \ |
1474 | | "b .\n" \ |
1475 | | "17:\n" \ |
1476 | | "b 2f\n" \ |
1477 | | "b .\n" \ |
1478 | | "b .\n" \ |
1479 | | "b .\n" \ |
1480 | | "3:\n" \ |
1481 | | "b .\n" \ |
1482 | | "b .\n" \ |
1483 | | "b .\n" \ |
1484 | | "b .\n" \ |
1485 | | "b .\n" \ |
1486 | | "b .\n" \ |
1487 | | "b .\n" \ |
1488 | | "b .\n" \ |
1489 | | "2:\n" \ |
1490 | | "pop {r4, r5, r6, r7}\n" \ |
1491 | | : /* No output operands */ \ |
1492 | | : "r"(fb_ok) /* Input operands */ \ |
1493 | | : "r0", "r4", "r5", "r6", "r7" /* Clobbered registers */ \ |
1494 | | ); \ |
1495 | | } while (0) |
1496 | | #endif |
1497 | | |
1498 | | |
1499 | | #define CONFIRM_MASK_VALID(id, mask) \ |
1500 | | asm volatile("mov r1, %0" :: "r"(id):"r1"); \ |
1501 | | /* id &= 0x0F */ \ |
1502 | | asm volatile("and.w r1, r1, #15":::"r1"); \ |
1503 | | asm volatile("mov r0, %0" :: "r"(mask):"r0"); \ |
1504 | | asm volatile("movs r2, #1":::"r2"); \ |
1505 | | asm volatile("lsls r2, r1":::"r2","cc"); \ |
1506 | | asm volatile("ands r2, r0":::"r2","cc"); \ |
1507 | | asm volatile("movs r0, #1":::"cc"); \ |
1508 | | asm volatile("lsls r0, r1":::"r0","cc"); \ |
1509 | | asm volatile("cmp r0, r2"); \ |
1510 | | asm volatile("cmp r0, r2"); \ |
1511 | | asm volatile("cmp r0, r2"); \ |
1512 | | asm volatile("bne ."); \ |
1513 | | asm volatile("mov r0, %0" :: "r"(mask)); \ |
1514 | | asm volatile("movs r2, #1":::"r2"); \ |
1515 | | asm volatile("lsls r2, r1":::"r2", "cc"); \ |
1516 | | asm volatile("ands r2, r0":::"r2", "cc"); \ |
1517 | | asm volatile("movs r0, #1":::"r0"); \ |
1518 | | asm volatile("lsls r0, r1":::"r0", "cc"); \ |
1519 | | asm volatile("cmp r0, r2":::"cc"); \ |
1520 | | asm volatile("cmp r0, r2":::"cc"); \ |
1521 | | asm volatile("cmp r0, r2":::"cc"); \ |
1522 | | asm volatile("bne ."); \ |
1523 | | asm volatile("mov r0, %0" :: "r"(mask):"r0"); \ |
1524 | | asm volatile("movs r2, #1":::"r2"); \ |
1525 | | asm volatile("lsls r2, r1":::"r2", "cc"); \ |
1526 | | asm volatile("ands r2, r0":::"r2", "cc"); \ |
1527 | | asm volatile("movs r0, #1":::"r0"); \ |
1528 | | asm volatile("lsls r0, r1":::"r0", "cc"); \ |
1529 | | asm volatile("cmp r0, r2":::"cc"); \ |
1530 | | asm volatile("cmp r0, r2":::"cc"); \ |
1531 | | asm volatile("cmp r0, r2":::"cc"); \ |
1532 | | asm volatile("bne ."); \ |
1533 | | |
1534 | | #else |
1535 | | |
1536 | | struct wolfBoot_image { |
1537 | | uint8_t *hdr; |
1538 | | #ifdef EXT_FLASH |
1539 | | uint8_t *hdr_cache; |
1540 | | #endif |
1541 | | uint8_t *trailer; |
1542 | | uint8_t *sha_hash; |
1543 | | uint8_t *fw_base; |
1544 | | uint32_t fw_size; |
1545 | | uint8_t part; |
1546 | | uint8_t hdr_ok : 1; |
1547 | | uint8_t signature_ok : 1; |
1548 | | uint8_t sha_ok : 1; |
1549 | | uint8_t not_ext : 1; /* image is no longer external */ |
1550 | | }; |
1551 | | |
1552 | | |
1553 | | /* do not warn if this is not used */ |
1554 | | static void UNUSEDFUNCTION wolfBoot_image_confirm_signature_ok( |
1555 | | struct wolfBoot_image *img) |
1556 | 0 | { |
1557 | 0 | img->signature_ok = 1; |
1558 | 0 | } |
1559 | | static void UNUSEDFUNCTION wolfBoot_image_clear_signature_ok( |
1560 | | struct wolfBoot_image *img) |
1561 | 0 | { |
1562 | 0 | img->signature_ok = 0; |
1563 | 0 | } |
1564 | | static void UNUSEDFUNCTION wolfBoot_image_confirm_sha_ok( |
1565 | | struct wolfBoot_image *img) |
1566 | 0 | { |
1567 | 0 | img->sha_ok = 1; |
1568 | 0 | } |
1569 | | static void UNUSEDFUNCTION wolfBoot_image_clear_sha_ok( |
1570 | | struct wolfBoot_image *img) |
1571 | 0 | { |
1572 | 0 | img->sha_ok = 0; |
1573 | 0 | } |
1574 | | static void UNUSEDFUNCTION wolfBoot_image_set_fw_base( |
1575 | | struct wolfBoot_image *img, void *base) |
1576 | 0 | { |
1577 | 0 | img->fw_base = (uint8_t *)base; |
1578 | 0 | } |
1579 | | |
1580 | | #define likely(x) (x) |
1581 | | #define unlikely(x) (x) |
1582 | | |
1583 | | #define VERIFY_FN(img,p_res,fn,...) {\ |
1584 | | int ret = fn(__VA_ARGS__); \ |
1585 | | if ((ret == 0) && (*p_res == 1)) \ |
1586 | | wolfBoot_image_confirm_signature_ok(img); \ |
1587 | | } |
1588 | | |
1589 | | #define RSA_VERIFY_FN(ret,fn,...) \ |
1590 | | ret = fn(__VA_ARGS__); |
1591 | | |
1592 | | #define RSA_VERIFY_HASH(img,digest) \ |
1593 | | if (image_CT_compare(img->sha_hash, digest, WOLFBOOT_SHA_DIGEST_SIZE) == 0) \ |
1594 | | wolfBoot_image_confirm_signature_ok(img); |
1595 | | |
1596 | | #define RSA_PSS_VERIFY_HASH(img, pss_data, pss_data_sz, hash_type) \ |
1597 | | if (wc_RsaPSS_CheckPadding(img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, \ |
1598 | | pss_data, pss_data_sz, hash_type) == 0) \ |
1599 | | wolfBoot_image_confirm_signature_ok(img); |
1600 | | |
1601 | | #define SHA_OK(imgp) ((imgp)->sha_ok == 1) |
1602 | | |
1603 | | #define VERIFY_INTEGRITY_FN(img, computed_digest, stored) \ |
1604 | | if (image_CT_compare((computed_digest), (stored), \ |
1605 | | WOLFBOOT_SHA_DIGEST_SIZE) == 0) { \ |
1606 | | (img)->sha_hash = (stored); \ |
1607 | | wolfBoot_image_confirm_sha_ok(img); \ |
1608 | | } |
1609 | | |
1610 | | #define PART_SANITY_CHECK(p) \ |
1611 | | if (((p)->hdr_ok != 1) || ((p)->sha_ok != 1) || ((p)->signature_ok != 1)) \ |
1612 | | wolfBoot_panic() |
1613 | | |
1614 | | #define SHA_SANITY_CHECK(p) \ |
1615 | | if ((p)->sha_ok != 1) \ |
1616 | | wolfBoot_panic() |
1617 | | |
1618 | | #define FW_BASE_SANITY_CHECK(p) do{} while(0) |
1619 | | |
1620 | | #define CONFIRM_MASK_VALID(id, mask) \ |
1621 | | if ((mask & (1UL << id)) != (1UL << id)) \ |
1622 | | wolfBoot_panic() |
1623 | | |
1624 | | #define VERIFY_VERSION_ALLOWED(fb_ok) do{} while(0) /* okay */ |
1625 | | |
1626 | | #endif |
1627 | | |
1628 | | /* Defined in image.c */ |
1629 | | int image_CT_compare(const uint8_t *expected, const uint8_t *actual, |
1630 | | uint32_t len); |
1631 | | int wolfBoot_hardened_CT_compare(const uint8_t *expected, const uint8_t *actual, |
1632 | | uint32_t len); |
1633 | | int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part); |
1634 | | #ifdef EXT_FLASH |
1635 | | int wolfBoot_open_image_external(struct wolfBoot_image* img, uint8_t part, uint8_t* addr); |
1636 | | #endif |
1637 | | int wolfBoot_open_image_address(struct wolfBoot_image* img, uint8_t* image); |
1638 | | #ifdef WOLFBOOT_SELF_HEADER |
1639 | | int wolfBoot_open_self(struct wolfBoot_image *img); |
1640 | | int wolfBoot_open_self_address(struct wolfBoot_image *img, uint8_t *hdr, |
1641 | | uint8_t *image); |
1642 | | #endif |
1643 | | int wolfBoot_verify_integrity(struct wolfBoot_image *img); |
1644 | | int wolfBoot_verify_authenticity(struct wolfBoot_image *img); |
1645 | | int wolfBoot_set_partition_state(uint8_t part, uint8_t newst); |
1646 | | int wolfBoot_get_update_sector_flag(uint16_t sector, uint8_t *flag); |
1647 | | int wolfBoot_set_update_sector_flag(uint16_t sector, uint8_t newflag); |
1648 | | |
1649 | | #ifdef WOLFBOOT_ELF_FLASH_SCATTER |
1650 | | /* Support for ELF scatter/gather format */ |
1651 | | int wolfBoot_load_flash_image_elf(int part, unsigned long* entry_out, |
1652 | | int ext_flash); |
1653 | | int wolfBoot_check_flash_image_elf(uint8_t part, unsigned long* entry_out); |
1654 | | #endif |
1655 | | |
1656 | | uint8_t* wolfBoot_peek_image(struct wolfBoot_image *img, uint32_t offset, |
1657 | | uint32_t* sz); |
1658 | | |
1659 | | /* get header type for image */ |
1660 | | uint16_t wolfBoot_get_header(struct wolfBoot_image *img, uint16_t type, uint8_t **ptr); |
1661 | | |
1662 | | /* Find the key slot ID based on the SHA hash of the key. */ |
1663 | | int keyslot_id_by_sha(const uint8_t *hint); |
1664 | | |
1665 | | #ifdef EXT_FLASH |
1666 | | # ifdef PART_BOOT_EXT |
1667 | | # define BOOT_EXT 1 |
1668 | | # else |
1669 | | # define BOOT_EXT 0 |
1670 | | # endif |
1671 | | # ifdef PART_UPDATE_EXT |
1672 | | # define UPDATE_EXT 1 |
1673 | | # else |
1674 | | # define UPDATE_EXT 0 |
1675 | | # endif |
1676 | | # ifdef PART_SWAP_EXT |
1677 | | # define SWAP_EXT 1 |
1678 | | # else |
1679 | | # define SWAP_EXT 0 |
1680 | | # endif |
1681 | | # if defined(WOLFBOOT_SELF_HEADER_EXT) |
1682 | | # define SELF_HEADER_EXT 1 |
1683 | | # else |
1684 | | # define SELF_HEADER_EXT 0 |
1685 | | # endif |
1686 | | # define PARTN_IS_EXT(pn) \ |
1687 | | ((pn == PART_BOOT || pn == PART_DTS_BOOT) ? BOOT_EXT: \ |
1688 | | ((pn == PART_UPDATE || pn == PART_DTS_UPDATE) ? UPDATE_EXT : \ |
1689 | | ((pn == PART_SWAP) ? SWAP_EXT : \ |
1690 | | ((pn == PART_SELF) ? SELF_HEADER_EXT : 0)))) |
1691 | | # define PART_IS_EXT(x) (!(x)->not_ext) && PARTN_IS_EXT(((x)->part)) |
1692 | | |
1693 | | |
1694 | | #if defined(EXT_ENCRYPTED) && (defined(__WOLFBOOT) || defined(UNIT_TEST)) |
1695 | | #define ext_flash_check_write ext_flash_encrypt_write |
1696 | | #define ext_flash_check_read ext_flash_decrypt_read |
1697 | | #else |
1698 | | #define ext_flash_check_write ext_flash_write |
1699 | | #define ext_flash_check_read ext_flash_read |
1700 | | #endif |
1701 | | |
1702 | | static inline int wb_flash_erase(struct wolfBoot_image *img, uint32_t off, |
1703 | | uint32_t size) |
1704 | | { |
1705 | | if (PART_IS_EXT(img)) |
1706 | | return ext_flash_erase((uintptr_t)(img->hdr) + off, size); |
1707 | | else |
1708 | | return hal_flash_erase((uintptr_t)(img->hdr) + off, size); |
1709 | | } |
1710 | | |
1711 | | static inline int wb_flash_write(struct wolfBoot_image *img, uint32_t off, |
1712 | | const void *data, uint32_t size) |
1713 | | { |
1714 | | if (PART_IS_EXT(img)) |
1715 | | return ext_flash_check_write((uintptr_t)(img->hdr) + off, data, size); |
1716 | | else |
1717 | | return hal_flash_write((uintptr_t)(img->hdr) + off, data, size); |
1718 | | } |
1719 | | |
1720 | | static inline int wb_flash_write_verify_word(struct wolfBoot_image *img, |
1721 | | uint32_t off, uint32_t word) |
1722 | | { |
1723 | | int ret; |
1724 | | volatile uint32_t copy; |
1725 | | if (PART_IS_EXT(img)) |
1726 | | { |
1727 | | ext_flash_check_read((uintptr_t)(img->hdr) + off, (void *)©, |
1728 | | sizeof(uint32_t)); |
1729 | | while (copy != word) { |
1730 | | ret = ext_flash_check_write((uintptr_t)(img->hdr) + off, |
1731 | | (void *)&word, sizeof(uint32_t)); |
1732 | | if (ret < 0) |
1733 | | return ret; |
1734 | | ext_flash_check_read((uintptr_t)(img->hdr) + off, (void *)©, |
1735 | | sizeof(uint32_t)); |
1736 | | } |
1737 | | } else { |
1738 | | volatile uint32_t *pcopy = (volatile uint32_t*)(img->hdr + off); |
1739 | | while(*pcopy != word) { |
1740 | | hal_flash_write((uintptr_t)pcopy, (void *)&word, sizeof(uint32_t)); |
1741 | | } |
1742 | | } |
1743 | | return 0; |
1744 | | } |
1745 | | |
1746 | | |
1747 | | #else |
1748 | | |
1749 | | # define SWAP_EXT (0) |
1750 | | # define BOOT_EXT (0) |
1751 | | # define UPDATE_EXT (0) |
1752 | | # define PART_IS_EXT(x) (0) |
1753 | | # define PARTN_IS_EXT(x) (0) |
1754 | | # define wb_flash_erase(im, of, siz) \ |
1755 | | hal_flash_erase(((uintptr_t)(((im)->hdr)) + of), siz) |
1756 | | # define wb_flash_write(im, of, dat, siz) \ |
1757 | | hal_flash_write(((uintptr_t)((im)->hdr)) + of, dat, siz) |
1758 | | |
1759 | | #endif /* EXT_FLASH */ |
1760 | | |
1761 | | /* -- Image Formats -- */ |
1762 | | /* Legacy U-Boot Image */ |
1763 | | #ifdef BIG_ENDIAN_ORDER |
1764 | | #define UBOOT_IMG_HDR_MAGIC 0x27051956UL |
1765 | | #else |
1766 | | #define UBOOT_IMG_HDR_MAGIC 0x56190527UL |
1767 | | #endif |
1768 | | #define UBOOT_IMG_HDR_SZ 64 |
1769 | | |
1770 | | /* --- Flattened Device Tree Blob */ |
1771 | | #ifdef MMU |
1772 | | #include "fdt.h" |
1773 | | #endif |
1774 | | |
1775 | | #ifndef EXT_ENCRYPTED |
1776 | | #define WOLFBOOT_MAX_SPACE (WOLFBOOT_PARTITION_SIZE - \ |
1777 | | (TRAILER_SKIP + sizeof(uint32_t) + \ |
1778 | | ((WOLFBOOT_PARTITION_SIZE + 1) / (WOLFBOOT_SECTOR_SIZE * 8)))) |
1779 | | #else |
1780 | | #define WOLFBOOT_MAX_SPACE (WOLFBOOT_PARTITION_SIZE - ENCRYPT_TMP_SECRET_OFFSET) |
1781 | | #endif |
1782 | | |
1783 | | #ifdef __cplusplus |
1784 | | } |
1785 | | #endif |
1786 | | |
1787 | | #endif /* !IMAGE_H */ |