Coverage Report

Created: 2026-08-14 06:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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 UNUSEDFUNCTION 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
 * Sets sha_ok from the value the digest comparison produced rather than from
235
 * the control flow that reached here. Sole setter of sha_ok in the ARMORED
236
 * integrity path, so skipping the call leaves the flag clear.
237
 */
238
static void NOINLINEFUNCTION wolfBoot_image_seal_sha_ok(
239
    struct wolfBoot_image *img, uint32_t witness)
240
{
241
    volatile uint32_t z1 = 0U, z2 = 0U, z3 = 0U, ok = 0U;
242
243
    z1 = (witness - 1U) >> 31;                       /* 1 iff witness == 0 */
244
    z2 = 1U ^ ((witness | (0U - witness)) >> 31);    /* 1 iff witness == 0 */
245
    z3 = (witness == 0U) ? 1U : 0U;                  /* 1 iff witness == 0 */
246
247
    ok  = z1 & z2 & z3;
248
    ok &= z1;
249
    ok &= z2;
250
    ok &= z3;
251
252
    img->canary_FEED89AB = 0xFEED89ABUL;
253
    img->sha_ok = ok;
254
    img->canary_FEEDCAFE = 0xFEEDCAFEUL;
255
    img->not_sha_ok = ~ok;
256
}
257
258
/**
259
 * Records the image entry base together with its complement, so that a single
260
 * fault on the pointer that do_boot() jumps through can be detected by
261
 * FW_BASE_SANITY_CHECK() before the branch is taken.
262
 */
263
static void NOINLINEFUNCTION wolfBoot_image_set_fw_base(
264
    struct wolfBoot_image *img, void *base)
265
{
266
    img->fw_base = (uint8_t *)base;
267
    img->not_fw_base = ~(uintptr_t)base;
268
}
269
270
/**
271
 * Final sanity check, performed just before do_boot, or before starting an
272
 * update that has been verified.
273
 *
274
 * This procedure detects if any of the previous checks has been skipped.
275
 * If any of the required flags does not match the expected value, wolfBoot
276
 * panics.
277
 */
278
#define PART_SANITY_CHECK(p) \
279
    /* Redundant set of r2=0 */ \
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
    asm volatile("mov r2, #0":::"r2"); \
285
    /* Loading hdr_ok flag, verifying */ \
286
    asm volatile("mov r2, %0" ::"r"((p)->hdr_ok):"r2"); \
287
    asm volatile("cmp r2, #1":::"cc"); \
288
    asm volatile("cmp r2, #1":::"cc"); \
289
    asm volatile("cmp r2, #1":::"cc"); \
290
    asm volatile("bne ."); \
291
    asm volatile("cmp r2, #1":::"cc"); \
292
    asm volatile("cmp r2, #1":::"cc"); \
293
    asm volatile("cmp r2, #1":::"cc"); \
294
    asm volatile("bne .-4"); \
295
    asm volatile("cmp r2, #1":::"cc"); \
296
    asm volatile("cmp r2, #1":::"cc"); \
297
    asm volatile("cmp r2, #1":::"cc"); \
298
    asm volatile("bne .-8"); \
299
    asm volatile("cmp r2, #1":::"cc"); \
300
    asm volatile("cmp r2, #1":::"cc"); \
301
    asm volatile("cmp r2, #1":::"cc"); \
302
    asm volatile("bne .-12"); \
303
    /* Redundant set of r2=0 */ \
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
    asm volatile("mov r2, #0":::"r2"); \
309
    /* Loading hdr_ok flag, verifying */ \
310
    asm volatile("mov r2, %0" ::"r"((p)->sha_ok):"r2"); \
311
    asm volatile("cmp r2, #1":::"cc"); \
312
    asm volatile("cmp r2, #1":::"cc"); \
313
    asm volatile("cmp r2, #1":::"cc"); \
314
    asm volatile("bne ."); \
315
    asm volatile("cmp r2, #1":::"cc"); \
316
    asm volatile("cmp r2, #1":::"cc"); \
317
    asm volatile("cmp r2, #1":::"cc"); \
318
    asm volatile("bne .-4"); \
319
    asm volatile("cmp r2, #1":::"cc"); \
320
    asm volatile("cmp r2, #1":::"cc"); \
321
    asm volatile("cmp r2, #1":::"cc"); \
322
    asm volatile("bne .-8"); \
323
    asm volatile("cmp r2, #1":::"cc"); \
324
    asm volatile("cmp r2, #1":::"cc"); \
325
    asm volatile("cmp r2, #1":::"cc"); \
326
    asm volatile("bne .-12"); \
327
    /* Redundant set of r2=0 */ \
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
    asm volatile("mov r2, #0":::"r2"); \
333
    /* Loading ~(sha_ok) flag, verifying */ \
334
    asm volatile("mov r2, %0" ::"r"((p)->not_sha_ok):"r2"); \
335
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
336
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
337
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
338
    asm volatile("bne ."); \
339
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
340
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
341
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
342
    asm volatile("bne .-4"); \
343
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
344
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
345
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
346
    asm volatile("bne .-8"); \
347
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
348
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
349
    asm volatile("cmp r2, #0xFFFFFFFE":::"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 canary value, verifying */ \
358
    asm volatile("mov r2, %0" ::"r"((p)->canary_FEEDCAFE):"r2"); \
359
    asm volatile("mov r0, %0" ::"r"(0xFEEDCAFE):"r0"); \
360
    asm volatile("cmp r2, r0":::"cc"); \
361
    asm volatile("cmp r2, r0":::"cc"); \
362
    asm volatile("cmp r2, r0":::"cc"); \
363
    asm volatile("bne ."); \
364
    asm volatile("cmp r2, r0":::"cc"); \
365
    asm volatile("cmp r2, r0":::"cc"); \
366
    asm volatile("cmp r2, r0":::"cc"); \
367
    asm volatile("bne .-4"); \
368
    asm volatile("cmp r2, r0":::"cc"); \
369
    asm volatile("cmp r2, r0":::"cc"); \
370
    asm volatile("cmp r2, r0":::"cc"); \
371
    asm volatile("bne .-8"); \
372
    asm volatile("cmp r2, r0":::"cc"); \
373
    asm volatile("cmp r2, r0":::"cc"); \
374
    asm volatile("cmp r2, r0":::"cc"); \
375
    asm volatile("bne .-12"); \
376
    /* Redundant set of r2=0 */ \
377
    asm volatile("mov r2, #0":::"r2"); \
378
    asm volatile("mov r2, #0":::"r2"); \
379
    asm volatile("mov r2, #0":::"r2"); \
380
    asm volatile("mov r2, #0":::"r2"); \
381
    asm volatile("mov r2, #0":::"r2"); \
382
    /* Loading signature_ok flag, verifying */ \
383
    asm volatile("mov r2, %0" ::"r"((p)->signature_ok):"r2"); \
384
    asm volatile("cmp r2, #1":::"cc"); \
385
    asm volatile("cmp r2, #1":::"cc"); \
386
    asm volatile("cmp r2, #1":::"cc"); \
387
    asm volatile("bne ."); \
388
    asm volatile("cmp r2, #1":::"cc"); \
389
    asm volatile("cmp r2, #1":::"cc"); \
390
    asm volatile("cmp r2, #1":::"cc"); \
391
    asm volatile("bne .-4"); \
392
    asm volatile("cmp r2, #1":::"cc"); \
393
    asm volatile("cmp r2, #1":::"cc"); \
394
    asm volatile("cmp r2, #1":::"cc"); \
395
    asm volatile("bne .-8"); \
396
    asm volatile("cmp r2, #1":::"cc"); \
397
    asm volatile("cmp r2, #1":::"cc"); \
398
    asm volatile("cmp r2, #1":::"cc"); \
399
    asm volatile("bne .-12"); \
400
    /* Redundant set of r2=0 */ \
401
    asm volatile("mov r2, #0"); \
402
    asm volatile("mov r2, #0"); \
403
    asm volatile("mov r2, #0"); \
404
    asm volatile("mov r2, #0"); \
405
    asm volatile("mov r2, #0"); \
406
    /* Loading ~(signature_ok) flag, verifying */ \
407
    asm volatile("mov r2, %0" ::"r"((p)->not_signature_ok):"r2"); \
408
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
409
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
410
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
411
    asm volatile("bne ."); \
412
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
413
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
414
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
415
    asm volatile("bne .-4"); \
416
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
417
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
418
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
419
    asm volatile("bne .-8"); \
420
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
421
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
422
    asm volatile("cmp r2, #0xFFFFFFFE":::"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_FEED6789):"r2"); \
432
    asm volatile("mov r0, %0" ::"r"(0xFEED6789):"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_FEED4567):"r2"); \
457
    asm volatile("mov r0, %0" ::"r"(0xFEED4567):"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
    /* Redundant set of r2=0 */ \
475
    asm volatile("mov r2, #0":::"r2"); \
476
    asm volatile("mov r2, #0":::"r2"); \
477
    asm volatile("mov r2, #0":::"r2"); \
478
    asm volatile("mov r2, #0":::"r2"); \
479
    asm volatile("mov r2, #0":::"r2"); \
480
    /* Loading canary value, verifying */ \
481
    asm volatile("mov r2, %0" ::"r"((p)->canary_FEED89AB):"r2"); \
482
    asm volatile("mov r0, %0" ::"r"(0xFEED89AB):"r0"); \
483
    asm volatile("cmp r2, r0":::"cc"); \
484
    asm volatile("cmp r2, r0":::"cc"); \
485
    asm volatile("cmp r2, r0":::"cc"); \
486
    asm volatile("bne ."); \
487
    asm volatile("cmp r2, r0":::"cc"); \
488
    asm volatile("cmp r2, r0":::"cc"); \
489
    asm volatile("cmp r2, r0":::"cc"); \
490
    asm volatile("bne .-4"); \
491
    asm volatile("cmp r2, r0":::"cc"); \
492
    asm volatile("cmp r2, r0":::"cc"); \
493
    asm volatile("cmp r2, r0":::"cc"); \
494
    asm volatile("bne .-8"); \
495
    asm volatile("cmp r2, r0":::"cc"); \
496
    asm volatile("cmp r2, r0":::"cc"); \
497
    asm volatile("cmp r2, r0":::"cc"); \
498
    asm volatile("bne .-12") \
499
500
/**
501
 * First part of RSA verification. Ensure that the function is called by
502
 * double checking its return value contains a valid
503
 * len (>= WOLFBOOT_SHA_DIGEST_SIZE).
504
 *
505
 * Uses GAS local numeric labels (1f/1:) so the macro can be safely expanded
506
 * multiple times in the same function (e.g. RSA PKCS#1.5 + RSA-PSS paths).
507
 */
508
#define RSA_VERIFY_FN(ret,fn,...) \
509
    { \
510
        /* Redundant set of r0=0 */ \
511
        asm volatile("mov r0, #0":::"r0"); \
512
        asm volatile("mov r0, #0":::"r0"); \
513
        asm volatile("mov r0, #0":::"r0"); \
514
        /* Call the function */ \
515
        int tmp_ret = fn(__VA_ARGS__); \
516
        ret = -1; \
517
        /* Redundant set of r2=SHA_DIGEST_SIZE */ \
518
        asm volatile("mov r2, %0" ::"r"(WOLFBOOT_SHA_DIGEST_SIZE):"r2"); \
519
        asm volatile("mov r2, %0" ::"r"(WOLFBOOT_SHA_DIGEST_SIZE):"r2"); \
520
        asm volatile("mov r2, %0" ::"r"(WOLFBOOT_SHA_DIGEST_SIZE):"r2"); \
521
        /* Redundant check for fn() return value >= r2 */ \
522
        asm volatile("cmp r0, r2":::"cc"); \
523
        asm volatile("cmp r0, r2":::"cc"); \
524
        asm volatile("cmp r0, r2":::"cc"); \
525
        asm volatile("blt 1f"); \
526
        asm volatile("cmp r0, r2":::"cc"); \
527
        asm volatile("cmp r0, r2":::"cc"); \
528
        asm volatile("cmp r0, r2":::"cc"); \
529
        asm volatile("blt 1f"); \
530
        asm volatile("cmp r0, r2":::"cc"); \
531
        asm volatile("cmp r0, r2":::"cc"); \
532
        asm volatile("cmp r0, r2":::"cc"); \
533
        asm volatile("blt 1f"); \
534
        asm volatile("cmp r0, r2":::"cc"); \
535
        asm volatile("cmp r0, r2":::"cc"); \
536
        asm volatile("cmp r0, r2":::"cc"); \
537
        asm volatile("blt 1f"); \
538
        /* Return value is set here in case of success */ \
539
        ret = tmp_ret; \
540
        asm volatile("1:"); \
541
        asm volatile("nop"); \
542
    }
543
544
/**
545
 * Second part of RSA verification.
546
 *
547
 * Compare the digest twice, then confirm via
548
 * wolfBoot_image_confirm_signature_ok();
549
 *
550
 * Uses GAS local numeric labels (2f/2:) for safe multi-expansion.
551
 */
552
#define RSA_VERIFY_HASH(img,digest) \
553
    { \
554
        volatile int compare_res; \
555
        if (!img || !digest)    \
556
            asm volatile("b 2f"); \
557
        /* Redundant set of r0=50*/ \
558
        asm volatile("mov r0, #50":::"r0"); \
559
        asm volatile("mov r0, #50":::"r0"); \
560
        asm volatile("mov r0, #50":::"r0"); \
561
        compare_res = image_CT_compare(digest, img->sha_hash, \
562
            WOLFBOOT_SHA_DIGEST_SIZE); \
563
        /* Redundant checks that ensure the function actually returned 0 */ \
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":::"cc"); \
568
        asm volatile("cmp r0, #0"); \
569
        asm volatile("cmp r0, #0"); \
570
        asm volatile("cmp r0, #0"); \
571
        asm volatile("bne 2f":::"cc"); \
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
        asm volatile("cmp r0, #0":::"cc"); \
577
        asm volatile("cmp r0, #0":::"cc"); \
578
        asm volatile("cmp r0, #0":::"cc"); \
579
        asm volatile("bne 2f"); \
580
        /* Repeat comparison call */ \
581
        compare_res = image_CT_compare(digest, img->sha_hash, \
582
            WOLFBOOT_SHA_DIGEST_SIZE); \
583
        compare_res; \
584
        /* Redundant checks that ensure the function actually returned 0 */ \
585
        asm volatile("cmp r0, #0":::"cc"); \
586
        asm volatile("cmp r0, #0":::"cc"); \
587
        asm volatile("cmp r0, #0":::"cc"); \
588
        asm volatile("bne 2f"); \
589
        asm volatile("cmp r0, #0":::"cc"); \
590
        asm volatile("cmp r0, #0":::"cc"); \
591
        asm volatile("cmp r0, #0":::"cc"); \
592
        asm volatile("bne 2f"); \
593
        asm volatile("cmp r0, #0":::"cc"); \
594
        asm volatile("cmp r0, #0":::"cc"); \
595
        asm volatile("cmp r0, #0":::"cc"); \
596
        asm volatile("bne 2f"); \
597
        asm volatile("cmp r0, #0":::"cc"); \
598
        asm volatile("cmp r0, #0":::"cc"); \
599
        asm volatile("cmp r0, #0":::"cc"); \
600
        asm volatile("bne 2f"); \
601
        /* Confirm that the signature is OK */ \
602
        wolfBoot_image_confirm_signature_ok(img); \
603
        asm volatile("2:"); \
604
        asm volatile("nop"); \
605
    }
606
607
/**
608
 * Second part of RSA-PSS verification.
609
 *
610
 * Call wc_RsaPSS_CheckPadding twice, then confirm via
611
 * wolfBoot_image_confirm_signature_ok();
612
 *
613
 * Uses GAS local numeric labels (3f/3:) for safe multi-expansion.
614
 */
615
#define RSA_PSS_VERIFY_HASH(img, pss_data, pss_data_sz, hash_type) \
616
    { \
617
        volatile int pss_res; \
618
        if (!img || !pss_data)    \
619
            asm volatile("b 3f"); \
620
        /* Redundant set of r0=50*/ \
621
        asm volatile("mov r0, #50":::"r0"); \
622
        asm volatile("mov r0, #50":::"r0"); \
623
        asm volatile("mov r0, #50":::"r0"); \
624
        pss_res = wc_RsaPSS_CheckPadding(img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, \
625
            pss_data, pss_data_sz, hash_type); \
626
        /* Redundant checks that ensure the function actually returned 0 */ \
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":::"cc"); \
631
        asm volatile("cmp r0, #0"); \
632
        asm volatile("cmp r0, #0"); \
633
        asm volatile("cmp r0, #0"); \
634
        asm volatile("bne 3f":::"cc"); \
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
        asm volatile("cmp r0, #0":::"cc"); \
640
        asm volatile("cmp r0, #0":::"cc"); \
641
        asm volatile("cmp r0, #0":::"cc"); \
642
        asm volatile("bne 3f"); \
643
        /* Repeat wc_RsaPSS_CheckPadding call */ \
644
        pss_res = wc_RsaPSS_CheckPadding(img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, \
645
            pss_data, pss_data_sz, hash_type); \
646
        pss_res; \
647
        /* Redundant checks that ensure the function actually returned 0 */ \
648
        asm volatile("cmp r0, #0":::"cc"); \
649
        asm volatile("cmp r0, #0":::"cc"); \
650
        asm volatile("cmp r0, #0":::"cc"); \
651
        asm volatile("bne 3f"); \
652
        asm volatile("cmp r0, #0":::"cc"); \
653
        asm volatile("cmp r0, #0":::"cc"); \
654
        asm volatile("cmp r0, #0":::"cc"); \
655
        asm volatile("bne 3f"); \
656
        asm volatile("cmp r0, #0":::"cc"); \
657
        asm volatile("cmp r0, #0":::"cc"); \
658
        asm volatile("cmp r0, #0":::"cc"); \
659
        asm volatile("bne 3f"); \
660
        asm volatile("cmp r0, #0":::"cc"); \
661
        asm volatile("cmp r0, #0":::"cc"); \
662
        asm volatile("cmp r0, #0":::"cc"); \
663
        asm volatile("bne 3f"); \
664
        /* Confirm that the signature is OK */ \
665
        wolfBoot_image_confirm_signature_ok(img); \
666
        asm volatile("3:"); \
667
        asm volatile("nop"); \
668
    }
669
670
/* Redundant, canary-wrapped test for a confirmed integrity (digest) check. */
671
#define SHA_OK(imgp) (((imgp)->sha_ok == 1) && \
672
                      ((imgp)->not_sha_ok == ~(uint32_t)1))
673
674
/**
675
 * Digest comparison with no call and no return register, run inline as an
676
 * additional gate. Emits a witness in `out`, zero only on a clean full pass.
677
 * Branches to label 5 on mismatch, like the checks around it.
678
 */
679
#define CT_COMPARE_INLINE(out, a, b, len) \
680
    asm volatile( \
681
        "mov r0, %1\n"                  /* left  */ \
682
        "mov r1, %2\n"                  /* right */ \
683
        "mov r2, #0\n"                  /* index */ \
684
        "mov r2, #0\n" \
685
        "mov r2, #0\n" \
686
        "mov r3, #0\n"                  /* difference accumulator */ \
687
        "mov r3, #0\n" \
688
        "mov r3, #0\n" \
689
        "mov r6, %3\n"                  /* iteration budget */ \
690
        "mov r6, %3\n" \
691
        "mov r6, %3\n" \
692
        "7:\n" \
693
        "ldrb r4, [r0, r2]\n" \
694
        "ldrb r5, [r1, r2]\n" \
695
        "eors r4, r4, r5\n" \
696
        "orrs r3, r3, r4\n" \
697
        "adds r2, r2, #1\n" \
698
        "subs r6, r6, #1\n" \
699
        "beq  8f\n"                     /* budget spent: stop regardless */ \
700
        "cmp  r2, %3\n" \
701
        "blo  7b\n" \
702
        "8:\n" \
703
        /* witness = difference | iteration shortfall */ \
704
        "eor r4, r2, %3\n" \
705
        "orr %0, r3, r4\n" \
706
        "orr %0, %0, r3\n" \
707
        /* every byte matched */ \
708
        "cmp r3, #0\n" \
709
        "cmp r3, #0\n" \
710
        "cmp r3, #0\n" \
711
        "bne 5f\n" \
712
        "cmp r3, #0\n" \
713
        "cmp r3, #0\n" \
714
        "cmp r3, #0\n" \
715
        "bne 5f\n" \
716
        /* and the loop really ran over the whole buffer */ \
717
        "cmp r2, %3\n" \
718
        "cmp r2, %3\n" \
719
        "cmp r2, %3\n" \
720
        "bne 5f\n" \
721
        "cmp r2, %3\n" \
722
        "cmp r2, %3\n" \
723
        "cmp r2, %3\n" \
724
        "bne 5f\n" \
725
        : "=&r"(out) \
726
        : "r"(a), "r"(b), "r"((uint32_t)(len)) \
727
        : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "cc", "memory")
728
729
/**
730
 * Digest (integrity) verification.
731
 *
732
 * Compare the freshly computed digest against the stored one twice through
733
 * image_CT_compare(), checking each result redundantly, then a third time
734
 * inline. Only then record the digest and raise sha_ok from the witness.
735
 *
736
 * Uses GAS local numeric labels (5f/5:, 7f/7b, 8f/8:) for safe expansion.
737
 */
738
#define VERIFY_INTEGRITY_FN(img, computed_digest, stored) \
739
    { \
740
        volatile int compare_res; \
741
        /* Pre-set to "mismatch". */ \
742
        volatile uint32_t ct_witness = 0xFFFFFFFFU; \
743
        if (!(img) || !(stored)) \
744
            asm volatile("b 5f"); \
745
        /* Redundant set of r0=50 */ \
746
        asm volatile("mov r0, #50":::"r0"); \
747
        asm volatile("mov r0, #50":::"r0"); \
748
        asm volatile("mov r0, #50":::"r0"); \
749
        compare_res = image_CT_compare((computed_digest), (stored), \
750
            WOLFBOOT_SHA_DIGEST_SIZE); \
751
        /* Redundant checks that ensure the function actually returned 0 */ \
752
        asm volatile("cmp r0, #0":::"cc"); \
753
        asm volatile("cmp r0, #0":::"cc"); \
754
        asm volatile("cmp r0, #0":::"cc"); \
755
        asm volatile("bne 5f"); \
756
        asm volatile("cmp r0, #0":::"cc"); \
757
        asm volatile("cmp r0, #0":::"cc"); \
758
        asm volatile("cmp r0, #0":::"cc"); \
759
        asm volatile("bne 5f"); \
760
        asm volatile("cmp r0, #0":::"cc"); \
761
        asm volatile("cmp r0, #0":::"cc"); \
762
        asm volatile("cmp r0, #0":::"cc"); \
763
        asm volatile("bne 5f"); \
764
        asm volatile("cmp r0, #0":::"cc"); \
765
        asm volatile("cmp r0, #0":::"cc"); \
766
        asm volatile("cmp r0, #0":::"cc"); \
767
        asm volatile("bne 5f"); \
768
        /* Repeat comparison call */ \
769
        compare_res = image_CT_compare((computed_digest), (stored), \
770
            WOLFBOOT_SHA_DIGEST_SIZE); \
771
        compare_res; \
772
        /* Redundant checks that ensure the function actually returned 0 */ \
773
        asm volatile("cmp r0, #0":::"cc"); \
774
        asm volatile("cmp r0, #0":::"cc"); \
775
        asm volatile("cmp r0, #0":::"cc"); \
776
        asm volatile("bne 5f"); \
777
        asm volatile("cmp r0, #0":::"cc"); \
778
        asm volatile("cmp r0, #0":::"cc"); \
779
        asm volatile("cmp r0, #0":::"cc"); \
780
        asm volatile("bne 5f"); \
781
        asm volatile("cmp r0, #0":::"cc"); \
782
        asm volatile("cmp r0, #0":::"cc"); \
783
        asm volatile("cmp r0, #0":::"cc"); \
784
        asm volatile("bne 5f"); \
785
        asm volatile("cmp r0, #0":::"cc"); \
786
        asm volatile("cmp r0, #0":::"cc"); \
787
        asm volatile("cmp r0, #0":::"cc"); \
788
        asm volatile("bne 5f"); \
789
        /* Third comparison, inline */ \
790
        CT_COMPARE_INLINE(ct_witness, (computed_digest), (stored), \
791
            WOLFBOOT_SHA_DIGEST_SIZE); \
792
        (img)->sha_hash = (stored); \
793
        wolfBoot_image_seal_sha_ok((img), ct_witness); \
794
        asm volatile("5:"); \
795
        asm volatile("nop"); \
796
    }
797
798
/**
799
 * Hardened assertion that the integrity (digest) check has actually been
800
 * performed and passed. Mirrors the sha portion of PART_SANITY_CHECK and is
801
 * used right after the integrity re-check in wolfBoot_verify_authenticity(),
802
 * so that skipping the re-check (or its result) cannot let an unverified
803
 * image proceed to signature verification.
804
 */
805
#define SHA_SANITY_CHECK(p) \
806
    /* Redundant set of r2=0 */ \
807
    asm volatile("mov r2, #0":::"r2"); \
808
    asm volatile("mov r2, #0":::"r2"); \
809
    asm volatile("mov r2, #0":::"r2"); \
810
    asm volatile("mov r2, #0":::"r2"); \
811
    asm volatile("mov r2, #0":::"r2"); \
812
    /* Loading sha_ok flag, verifying */ \
813
    asm volatile("mov r2, %0" ::"r"((p)->sha_ok):"r2"); \
814
    asm volatile("cmp r2, #1":::"cc"); \
815
    asm volatile("cmp r2, #1":::"cc"); \
816
    asm volatile("cmp r2, #1":::"cc"); \
817
    asm volatile("bne ."); \
818
    asm volatile("cmp r2, #1":::"cc"); \
819
    asm volatile("cmp r2, #1":::"cc"); \
820
    asm volatile("cmp r2, #1":::"cc"); \
821
    asm volatile("bne .-4"); \
822
    asm volatile("cmp r2, #1":::"cc"); \
823
    asm volatile("cmp r2, #1":::"cc"); \
824
    asm volatile("cmp r2, #1":::"cc"); \
825
    asm volatile("bne .-8"); \
826
    asm volatile("cmp r2, #1":::"cc"); \
827
    asm volatile("cmp r2, #1":::"cc"); \
828
    asm volatile("cmp r2, #1":::"cc"); \
829
    asm volatile("bne .-12"); \
830
    /* Redundant set of r2=0 */ \
831
    asm volatile("mov r2, #0":::"r2"); \
832
    asm volatile("mov r2, #0":::"r2"); \
833
    asm volatile("mov r2, #0":::"r2"); \
834
    asm volatile("mov r2, #0":::"r2"); \
835
    asm volatile("mov r2, #0":::"r2"); \
836
    /* Loading ~(sha_ok) flag, verifying */ \
837
    asm volatile("mov r2, %0" ::"r"((p)->not_sha_ok):"r2"); \
838
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
839
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
840
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
841
    asm volatile("bne ."); \
842
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
843
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
844
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
845
    asm volatile("bne .-4"); \
846
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
847
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
848
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
849
    asm volatile("bne .-8"); \
850
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
851
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
852
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
853
    asm volatile("bne .-12")
854
855
/**
856
 * Hardened assertion that the image entry base is consistent with its stored
857
 * complement (fw_base == ~not_fw_base), performed immediately before do_boot()
858
 * dereferences fw_base. A single fault on either the pointer or the loads
859
 * fails the check safely (spins) instead of redirecting the boot jump.
860
 */
861
#define FW_BASE_SANITY_CHECK(p) \
862
    do { \
863
        /* Single asm block so the compiler cannot allocate over r0/r2 between \
864
         * steps: r2 = fw_base, r0 = ~not_fw_base (== expected fw_base), then \
865
         * a redundant self-trapping comparison that spins on any mismatch. */ \
866
        asm volatile( \
867
            "mov r2, %[fwb]\n\t" \
868
            "mov r0, %[nfwb]\n\t" \
869
            "mvn r0, r0\n\t" \
870
            "cmp r2, r0\n\t" \
871
            "cmp r2, r0\n\t" \
872
            "cmp r2, r0\n\t" \
873
            "bne .\n\t" \
874
            "cmp r2, r0\n\t" \
875
            "cmp r2, r0\n\t" \
876
            "cmp r2, r0\n\t" \
877
            "bne .-4\n\t" \
878
            "cmp r2, r0\n\t" \
879
            "cmp r2, r0\n\t" \
880
            "cmp r2, r0\n\t" \
881
            "bne .-8\n\t" \
882
            "cmp r2, r0\n\t" \
883
            "cmp r2, r0\n\t" \
884
            "cmp r2, r0\n\t" \
885
            "bne .-12\n\t" \
886
            : \
887
            : [fwb] "r" ((uintptr_t)(p)->fw_base), \
888
              [nfwb] "r" ((uintptr_t)(p)->not_fw_base) \
889
            : "r0", "r2", "cc"); \
890
    } while (0)
891
892
/**
893
 * ECC / Ed / PQ signature verification.
894
 * Those verify functions set an additional value 'p_res'
895
 * which is passed as a pointer.
896
 *
897
 * Ensure that the verification function has been called, and then
898
 * set the return value accordingly.
899
 *
900
 * Double check by reading the value in p_res from memory a few times.
901
 *
902
 * Uses GAS local numeric labels (4f/4:) for safe multi-expansion.
903
 */
904
#if defined(__GNUC__)
905
906
#define VERIFY_FN(img,p_res,fn,...) \
907
    /* Redundant set of r0=50*/ \
908
    asm volatile("mov r0, #50":::"r0"); \
909
    asm volatile("mov r0, #50":::"r0"); \
910
    asm volatile("mov r0, #50":::"r0"); \
911
    /* Call the verify function */ \
912
    fn(__VA_ARGS__); \
913
    /* Redundant checks that ensure the function actually returned 0 */ \
914
    asm volatile("cmp r0, #0":::"cc"); \
915
    asm volatile("cmp r0, #0":::"cc"); \
916
    asm volatile("cmp r0, #0":::"cc"); \
917
    asm volatile("bne 4f"); \
918
    asm volatile("cmp r0, #0":::"cc"); \
919
    asm volatile("cmp r0, #0":::"cc"); \
920
    asm volatile("cmp r0, #0":::"cc"); \
921
    asm volatile("bne 4f"); \
922
    asm volatile("cmp r0, #0":::"cc"); \
923
    asm volatile("cmp r0, #0":::"cc"); \
924
    asm volatile("cmp r0, #0":::"cc"); \
925
    asm volatile("bne 4f"); \
926
    asm volatile("cmp r0, #0":::"cc"); \
927
    asm volatile("cmp r0, #0":::"cc"); \
928
    asm volatile("cmp r0, #0":::"cc"); \
929
    asm volatile("bne 4f"); \
930
    /* Check that res = 1, a few times, reading the value from memory */ \
931
    asm volatile("ldr r2, [%0]" ::"r"(p_res)); \
932
    asm volatile("cmp r2, #1":::"cc"); \
933
    asm volatile("cmp r2, #1":::"cc"); \
934
    asm volatile("cmp r2, #1":::"cc"); \
935
    asm volatile("bne 4f"); \
936
    asm volatile("mvn r3, r2":::"r3"); \
937
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
938
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
939
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
940
    asm volatile("bne 4f"); \
941
    asm volatile("ldr r2, [%0]" ::"r"(p_res)); \
942
    asm volatile("cmp r2, #1":::"cc"); \
943
    asm volatile("cmp r2, #1":::"cc"); \
944
    asm volatile("cmp r2, #1":::"cc"); \
945
    asm volatile("bne 4f"); \
946
    asm volatile("mvn r3, r2":::"r3"); \
947
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
948
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
949
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
950
    asm volatile("bne 4f"); \
951
    asm volatile("ldr r2, [%0]" ::"r"(p_res)); \
952
    asm volatile("cmp r2, #1":::"cc"); \
953
    asm volatile("cmp r2, #1":::"cc"); \
954
    asm volatile("cmp r2, #1":::"cc"); \
955
    asm volatile("bne 4f"); \
956
    asm volatile("mvn r3, r2":::"r3"); \
957
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
958
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
959
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
960
    asm volatile("bne 4f"); \
961
    asm volatile("ldr r2, [%0]" ::"r"(p_res)); \
962
    asm volatile("cmp r2, #1":::"cc"); \
963
    asm volatile("cmp r2, #1":::"cc"); \
964
    asm volatile("cmp r2, #1":::"cc"); \
965
    asm volatile("bne 4f"); \
966
    asm volatile("mvn r3, r2":::"r3"); \
967
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
968
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
969
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
970
    asm volatile("bne 4f"); \
971
    /* Confirm that the signature is OK */ \
972
    wolfBoot_image_confirm_signature_ok(img); \
973
    asm volatile("4:"); \
974
    asm volatile("nop") \
975
976
#elif defined(__ICCARM__) && defined(__IAR_SYSTEMS_ICC__)
977
978
#define VERIFY_FN(img, p_res, fn, ...) \
979
    do { \
980
        __asm volatile( \
981
            "mov r0, #50\n" \
982
            "mov r0, #50\n" \
983
            "mov r0, #50\n" \
984
            : /* No output operands */ \
985
            : /* No input operands */ \
986
            : "r0" /* Clobbered registers */ \
987
        ); \
988
        void (*confirm_func)(struct wolfBoot_image *) = \
989
            wolfBoot_image_confirm_signature_ok; \
990
        fn(__VA_ARGS__); \
991
        __asm volatile( \
992
            "cmp r0, #0\n" \
993
            "cmp r0, #0\n" \
994
            "cmp r0, #0\n" \
995
            "beq 30f\n" \
996
            "bne 1f\n" \
997
            "bne 1f\n" \
998
            "bne 1f\n" \
999
            "bne 1f\n" \
1000
            "b .\n" \
1001
            "b .\n" \
1002
            "b .\n" \
1003
            "30:\n" \
1004
            "ldr r2, [%0]\n" \
1005
            "cmp r2, #1\n" \
1006
            "cmp r2, #1\n" \
1007
            "cmp r2, #1\n" \
1008
            "beq 31f\n" \
1009
            "bne 1f\n" \
1010
            "bne 1f\n" \
1011
            "bne 1f\n" \
1012
            "bne 1f\n" \
1013
            "b .\n" \
1014
            "b .\n" \
1015
            "b .\n" \
1016
            "31:\n" \
1017
            "mvn r3, r2\n" \
1018
            "cmp r3, #0xFFFFFFFE\n" \
1019
            "cmp r3, #0xFFFFFFFE\n" \
1020
            "cmp r3, #0xFFFFFFFE\n" \
1021
            "beq 32f\n" \
1022
            "bne 1f\n" \
1023
            "bne 1f\n" \
1024
            "bne 1f\n" \
1025
            "bne 1f\n" \
1026
            "b .\n" \
1027
            "b .\n" \
1028
            "b .\n" \
1029
            "32:\n" \
1030
            "ldr r2, [%0]\n" \
1031
            "cmp r2, #1\n" \
1032
            "cmp r2, #1\n" \
1033
            "cmp r2, #1\n" \
1034
            "beq 33f\n" \
1035
            "bne 1f\n" \
1036
            "bne 1f\n" \
1037
            "bne 1f\n" \
1038
            "bne 1f\n" \
1039
            "b .\n" \
1040
            "b .\n" \
1041
            "b .\n" \
1042
            "33:\n" \
1043
            "mvn r3, r2\n" \
1044
            "cmp r3, #0xFFFFFFFE\n" \
1045
            "cmp r3, #0xFFFFFFFE\n" \
1046
            "cmp r3, #0xFFFFFFFE\n" \
1047
            "beq 34f\n" \
1048
            "bne 1f\n" \
1049
            "bne 1f\n" \
1050
            "bne 1f\n" \
1051
            "bne 1f\n" \
1052
            "b .\n" \
1053
            "b .\n" \
1054
            "b .\n" \
1055
            "34:\n" \
1056
            "ldr r2, [%0]\n" \
1057
            "cmp r2, #1\n" \
1058
            "cmp r2, #1\n" \
1059
            "cmp r2, #1\n" \
1060
            "beq 35f\n" \
1061
            "bne 1f\n" \
1062
            "bne 1f\n" \
1063
            "bne 1f\n" \
1064
            "bne 1f\n" \
1065
            "b .\n" \
1066
            "b .\n" \
1067
            "b .\n" \
1068
            "35:\n" \
1069
            "mvn r3, r2\n" \
1070
            "cmp r3, #0xFFFFFFFE\n" \
1071
            "cmp r3, #0xFFFFFFFE\n" \
1072
            "cmp r3, #0xFFFFFFFE\n" \
1073
            "beq 36f\n" \
1074
            "bne 1f\n" \
1075
            "bne 1f\n" \
1076
            "bne 1f\n" \
1077
            "bne 1f\n" \
1078
            "b .\n" \
1079
            "b .\n" \
1080
            "b .\n" \
1081
            "36:\n" \
1082
            "ldr r2, [%0]\n" \
1083
            "cmp r2, #1\n" \
1084
            "cmp r2, #1\n" \
1085
            "cmp r2, #1\n" \
1086
            "beq 37f\n" \
1087
            "bne 1f\n" \
1088
            "bne 1f\n" \
1089
            "bne 1f\n" \
1090
            "bne 1f\n" \
1091
            "b .\n" \
1092
            "b .\n" \
1093
            "b .\n" \
1094
            "37:\n" \
1095
            "mvn r3, r2\n" \
1096
            "cmp r3, #0xFFFFFFFE\n" \
1097
            "cmp r3, #0xFFFFFFFE\n" \
1098
            "cmp r3, #0xFFFFFFFE\n" \
1099
            "beq 38f\n" \
1100
            "bne 1f\n" \
1101
            "bne 1f\n" \
1102
            "bne 1f\n" \
1103
            "bne 1f\n" \
1104
            "b .\n" \
1105
            "b .\n" \
1106
            "b .\n" \
1107
            "38:\n" \
1108
            /* Load 'img' into r0 (first argument to the function) */ \
1109
            "mov r0, %1\n" \
1110
            /* Load the function pointer into r3 */ \
1111
            "mov r3, %2\n" \
1112
            "blx r3\n"\
1113
            "b 2f\n" \
1114
            "b .\n" \
1115
            "b .\n" \
1116
            "b .\n" \
1117
            "1:\n" \
1118
            "nop\n" \
1119
            "2:\n" \
1120
            : /* No output operands */ \
1121
            : "r"(p_res), "r"(img), "r"(confirm_func) /* Input operands */ \
1122
            : "r0", "r2", "r3", "lr" /* Clobbered registers */ \
1123
        ); \
1124
    } while (0)
1125
#endif
1126
1127
1128
/**
1129
 * This macro is only invoked after a successful update version check, prior to
1130
 * initiating the update installation.
1131
 *
1132
 * At this point, wolfBoot thinks that the version check has been successful.
1133
 *
1134
 *
1135
 * The fallback flag (checked with redundancy) causes wolfBoot to skip the
1136
 * redundant version checks.
1137
 *
1138
 * The redundant checks here ensure that the image version is read twice per
1139
 * each partition, and the two return values are the same.
1140
 *
1141
 *
1142
 * The comparison is also redundant, causing wolfBoot to panic if the update
1143
 * version is not strictly greater than the current one.
1144
 *
1145
 */
1146
#if defined(__GNUC__)
1147
1148
#define VERIFY_VERSION_ALLOWED(fb_ok) \
1149
    asm volatile( \
1150
        "push {r4, r5, r6, r7}\n" \
1151
        "mov r0, #0\n" \
1152
        "mov r4, #1\n" \
1153
        "mov r5, #0\n" \
1154
        "mov r6, #2\n" \
1155
        "mov r7, #0\n" \
1156
        "mov r0, #0\n" \
1157
        "mov r4, #1\n" \
1158
        "mov r5, #0\n" \
1159
        "mov r6, #2\n" \
1160
        "mov r7, #0\n" \
1161
        "mov r0, %0\n" \
1162
        "mov r4, %0\n" \
1163
        "cmp r0, #1\n" \
1164
        "cmp r0, #1\n" \
1165
        "cmp r0, #1\n" \
1166
        "beq 20f\n" \
1167
        "bne do_check\n" \
1168
        "bne do_check\n" \
1169
        "bne do_check\n" \
1170
        "bne do_check\n" \
1171
        "b .\n" \
1172
        "b .\n" \
1173
        "b .\n" \
1174
        "20:\n" \
1175
        "cmp r4, #1\n" \
1176
        "cmp r4, #1\n" \
1177
        "cmp r4, #1\n" \
1178
        "beq 21f\n" \
1179
        "bne do_check\n" \
1180
        "bne do_check\n" \
1181
        "bne do_check\n" \
1182
        "bne do_check\n" \
1183
        "b .\n" \
1184
        "b .\n" \
1185
        "b .\n" \
1186
        "21:\n" \
1187
        "cmp r0, r4\n" \
1188
        "cmp r0, r4\n" \
1189
        "cmp r0, r4\n" \
1190
        "beq 22f\n" \
1191
        "bne do_check\n" \
1192
        "bne do_check\n" \
1193
        "bne do_check\n" \
1194
        "bne do_check\n" \
1195
        "b .\n" \
1196
        "b .\n" \
1197
        "b .\n" \
1198
        "22:\n" \
1199
        "cmp r0, #1\n" \
1200
        "cmp r0, #1\n" \
1201
        "cmp r0, #1\n" \
1202
        "beq 23f\n" \
1203
        "bne do_check\n" \
1204
        "bne do_check\n" \
1205
        "bne do_check\n" \
1206
        "bne do_check\n" \
1207
        "b .\n" \
1208
        "b .\n" \
1209
        "b .\n" \
1210
        "23:\n" \
1211
        "b end_check\n" \
1212
        "do_check:\n" \
1213
        "mov r0, #1\n" \
1214
        "mov r0, #1\n" \
1215
        "mov r0, #1\n" \
1216
        "bl wolfBoot_get_image_version\n" \
1217
        "mov r5, r0\n" \
1218
        "mov r5, r0\n" \
1219
        "mov r5, r0\n" \
1220
        "mov r0, #1\n" \
1221
        "mov r0, #1\n" \
1222
        "mov r0, #1\n" \
1223
        "bl wolfBoot_get_image_version\n" \
1224
        "mov r7, r0\n" \
1225
        "mov r7, r0\n" \
1226
        "mov r7, r0\n" \
1227
        "cmp r5, r7\n" \
1228
        "cmp r5, r7\n" \
1229
        "cmp r5, r7\n" \
1230
        "beq 24f\n" \
1231
        "bne ver_panic\n" \
1232
        "bne ver_panic\n" \
1233
        "bne ver_panic\n" \
1234
        "bne ver_panic\n" \
1235
        "b .\n" \
1236
        "b .\n" \
1237
        "b .\n" \
1238
        "24:\n" \
1239
        "mov r0, #0\n" \
1240
        "mov r0, #0\n" \
1241
        "mov r0, #0\n" \
1242
        "bl wolfBoot_get_image_version\n" \
1243
        "mov r4, r0\n" \
1244
        "mov r4, r0\n" \
1245
        "mov r4, r0\n" \
1246
        "mov r0, #0\n" \
1247
        "mov r0, #0\n" \
1248
        "mov r0, #0\n" \
1249
        "bl wolfBoot_get_image_version\n" \
1250
        "mov r6, r0\n" \
1251
        "mov r6, r0\n" \
1252
        "mov r6, r0\n" \
1253
        "cmp r4, r6\n" \
1254
        "cmp r4, r6\n" \
1255
        "cmp r4, r6\n" \
1256
        "beq 25f\n" \
1257
        "bne ver_panic\n" \
1258
        "bne ver_panic\n" \
1259
        "bne ver_panic\n" \
1260
        "bne ver_panic\n" \
1261
        "b .\n" \
1262
        "b .\n" \
1263
        "b .\n" \
1264
        "25:\n" \
1265
        "mov r0, #0\n" \
1266
        "mov r0, #0\n" \
1267
        "mov r0, #0\n" \
1268
        "cmp r4, r5\n" \
1269
        "cmp r4, r5\n" \
1270
        "cmp r4, r5\n" \
1271
        "blo 26f\n" \
1272
        "bhs ver_panic\n" \
1273
        "bhs ver_panic\n" \
1274
        "bhs ver_panic\n" \
1275
        "bhs ver_panic\n" \
1276
        "b .\n" \
1277
        "b .\n" \
1278
        "b .\n" \
1279
        "26:\n" \
1280
        "cmp r6, r7\n" \
1281
        "cmp r6, r7\n" \
1282
        "cmp r6, r7\n" \
1283
        "blo 27f\n" \
1284
        "bhs ver_panic\n" \
1285
        "bhs ver_panic\n" \
1286
        "bhs ver_panic\n" \
1287
        "bhs ver_panic\n" \
1288
        "b .\n" \
1289
        "b .\n" \
1290
        "b .\n" \
1291
        "27:\n" \
1292
        "cmp r4, r5\n" \
1293
        "cmp r4, r5\n" \
1294
        "cmp r4, r5\n" \
1295
        "blo 28f\n" \
1296
        "bhs ver_panic\n" \
1297
        "bhs ver_panic\n" \
1298
        "bhs ver_panic\n" \
1299
        "bhs ver_panic\n" \
1300
        "b .\n" \
1301
        "b .\n" \
1302
        "b .\n" \
1303
        "28:\n" \
1304
        "cmp r6, r7\n" \
1305
        "cmp r6, r7\n" \
1306
        "cmp r6, r7\n" \
1307
        "blo 29f\n" \
1308
        "bhs ver_panic\n" \
1309
        "bhs ver_panic\n" \
1310
        "bhs ver_panic\n" \
1311
        "bhs ver_panic\n" \
1312
        "b .\n" \
1313
        "b .\n" \
1314
        "b .\n" \
1315
        "29:\n" \
1316
        "b end_check\n" \
1317
        "ver_panic:\n" \
1318
        "b .\n" \
1319
        "b .\n" \
1320
        "b .\n" \
1321
        "b .\n" \
1322
        "b .\n" \
1323
        "b .\n" \
1324
        "b .\n" \
1325
        "b .\n" \
1326
        "b .\n" \
1327
        "b .\n" \
1328
        "b .\n" \
1329
        "end_check:\n" \
1330
        "pop {r4, r5, r6, r7}\n" \
1331
        : \
1332
        : "r"(fb_ok) \
1333
        : "r0", "r4", "r5", "r6", "r7", "lr", "cc", "memory" \
1334
    )
1335
1336
#elif defined(__ICCARM__) && defined(__IAR_SYSTEMS_ICC__)
1337
1338
#define VERIFY_VERSION_ALLOWED(fb_ok) \
1339
    do { \
1340
        __asm volatile( \
1341
            "push {r4, r5, r6, r7}\n" \
1342
            "mov r0, #0\n" \
1343
            "mov r4, #1\n" \
1344
            "mov r5, #0\n" \
1345
            "mov r6, #2\n" \
1346
            "mov r7, #0\n" \
1347
            "mov r0, #0\n" \
1348
            "mov r4, #1\n" \
1349
            "mov r5, #0\n" \
1350
            "mov r6, #2\n" \
1351
            "mov r7, #0\n" \
1352
            "mov r0, %0\n" \
1353
            "mov r4, %0\n" \
1354
            "cmp r0, #0\n" \
1355
            "cmp r0, #0\n" \
1356
            "cmp r0, #0\n" \
1357
            "beq 4f\n" \
1358
            "bne 6f\n" \
1359
            "bne 6f\n" \
1360
            "bne 6f\n" \
1361
            "bne 6f\n" \
1362
            "b .\n" \
1363
            "b .\n" \
1364
            "b .\n" \
1365
            "6:\n" \
1366
            "cmp r0, #1\n" \
1367
            "cmp r0, #1\n" \
1368
            "cmp r0, #1\n" \
1369
            "beq 4f\n" \
1370
            "bne 1f\n" \
1371
            "bne 1f\n" \
1372
            "bne 1f\n" \
1373
            "bne 1f\n" \
1374
            "b .\n" \
1375
            "b .\n" \
1376
            "b .\n" \
1377
            "4:\n" \
1378
            "cmp r4, #0\n" \
1379
            "cmp r4, #0\n" \
1380
            "cmp r4, #0\n" \
1381
            "beq 5f\n" \
1382
            "bne 7f\n" \
1383
            "bne 7f\n" \
1384
            "bne 7f\n" \
1385
            "bne 7f\n" \
1386
            "b .\n" \
1387
            "b .\n" \
1388
            "b .\n" \
1389
            "7:\n" \
1390
            "cmp r4, #1\n" \
1391
            "cmp r4, #1\n" \
1392
            "cmp r4, #1\n" \
1393
            "beq 5f\n" \
1394
            "bne 1f\n" \
1395
            "bne 1f\n" \
1396
            "bne 1f\n" \
1397
            "bne 1f\n" \
1398
            "b .\n" \
1399
            "b .\n" \
1400
            "b .\n" \
1401
            "5:\n" \
1402
            "cmp r0, #1\n" \
1403
            "cmp r0, #1\n" \
1404
            "cmp r0, #1\n" \
1405
            "beq 8f\n" \
1406
            "bne 1f\n" \
1407
            "bne 1f\n" \
1408
            "bne 1f\n" \
1409
            "bne 1f\n" \
1410
            "b .\n" \
1411
            "b .\n" \
1412
            "b .\n" \
1413
            "8:\n" \
1414
            "cmp r4, #1\n" \
1415
            "cmp r4, #1\n" \
1416
            "cmp r4, #1\n" \
1417
            "beq 9f\n" \
1418
            "bne 1f\n" \
1419
            "bne 1f\n" \
1420
            "bne 1f\n" \
1421
            "bne 1f\n" \
1422
            "b .\n" \
1423
            "b .\n" \
1424
            "b .\n" \
1425
            "9:\n" \
1426
            "cmp r0, r4\n" \
1427
            "cmp r0, r4\n" \
1428
            "cmp r0, r4\n" \
1429
            "beq 10f\n" \
1430
            "bne 1f\n" \
1431
            "bne 1f\n" \
1432
            "bne 1f\n" \
1433
            "bne 1f\n" \
1434
            "b .\n" \
1435
            "b .\n" \
1436
            "b .\n" \
1437
            "10:\n" \
1438
            "cmp r0, #1\n" \
1439
            "cmp r0, #1\n" \
1440
            "cmp r0, #1\n" \
1441
            "beq 11f\n" \
1442
            "bne 1f\n" \
1443
            "bne 1f\n" \
1444
            "bne 1f\n" \
1445
            "bne 1f\n" \
1446
            "b .\n" \
1447
            "b .\n" \
1448
            "b .\n" \
1449
            "11:\n" \
1450
            "b 2f\n" \
1451
            "b .\n" \
1452
            "b .\n" \
1453
            "b .\n" \
1454
            "1:\n" \
1455
            "mov r0, #1\n" \
1456
            "mov r0, #1\n" \
1457
            "mov r0, #1\n" \
1458
            "bl wolfBoot_get_image_version\n" \
1459
            "mov r5, r0\n" \
1460
            "mov r5, r0\n" \
1461
            "mov r5, r0\n" \
1462
            "mov r0, #1\n" \
1463
            "mov r0, #1\n" \
1464
            "mov r0, #1\n" \
1465
            "bl wolfBoot_get_image_version\n" \
1466
            "mov r7, r0\n" \
1467
            "mov r7, r0\n" \
1468
            "mov r7, r0\n" \
1469
            "cmp r5, r7\n" \
1470
            "cmp r5, r7\n" \
1471
            "cmp r5, r7\n" \
1472
            "beq 12f\n" \
1473
            "bne 3f\n" \
1474
            "bne 3f\n" \
1475
            "bne 3f\n" \
1476
            "bne 3f\n" \
1477
            "b .\n" \
1478
            "b .\n" \
1479
            "b .\n" \
1480
            "12:\n" \
1481
            "mov r0, #0\n" \
1482
            "mov r0, #0\n" \
1483
            "mov r0, #0\n" \
1484
            "bl wolfBoot_get_image_version\n" \
1485
            "mov r4, r0\n" \
1486
            "mov r4, r0\n" \
1487
            "mov r4, r0\n" \
1488
            "mov r0, #0\n" \
1489
            "mov r0, #0\n" \
1490
            "mov r0, #0\n" \
1491
            "bl wolfBoot_get_image_version\n" \
1492
            "mov r6, r0\n" \
1493
            "mov r6, r0\n" \
1494
            "mov r6, r0\n" \
1495
            "cmp r4, r6\n" \
1496
            "cmp r4, r6\n" \
1497
            "cmp r4, r6\n" \
1498
            "beq 13f\n" \
1499
            "bne 3f\n" \
1500
            "bne 3f\n" \
1501
            "bne 3f\n" \
1502
            "bne 3f\n" \
1503
            "b .\n" \
1504
            "b .\n" \
1505
            "b .\n" \
1506
            "13:\n" \
1507
            "mov r0, #0\n" \
1508
            "mov r0, #0\n" \
1509
            "mov r0, #0\n" \
1510
            "cmp r4, r5\n" \
1511
            "cmp r4, r5\n" \
1512
            "cmp r4, r5\n" \
1513
            "blo 14f\n" \
1514
            "bhs 3f\n" \
1515
            "bhs 3f\n" \
1516
            "bhs 3f\n" \
1517
            "bhs 3f\n" \
1518
            "b .\n" \
1519
            "b .\n" \
1520
            "b .\n" \
1521
            "14:\n" \
1522
            "cmp r6, r7\n" \
1523
            "cmp r6, r7\n" \
1524
            "cmp r6, r7\n" \
1525
            "blo 15f\n" \
1526
            "bhs 3f\n" \
1527
            "bhs 3f\n" \
1528
            "bhs 3f\n" \
1529
            "bhs 3f\n" \
1530
            "b .\n" \
1531
            "b .\n" \
1532
            "b .\n" \
1533
            "15:\n" \
1534
            "cmp r4, r5\n" \
1535
            "cmp r4, r5\n" \
1536
            "cmp r4, r5\n" \
1537
            "blo 16f\n" \
1538
            "bhs 3f\n" \
1539
            "bhs 3f\n" \
1540
            "bhs 3f\n" \
1541
            "bhs 3f\n" \
1542
            "b .\n" \
1543
            "b .\n" \
1544
            "b .\n" \
1545
            "16:\n" \
1546
            "cmp r6, r7\n" \
1547
            "cmp r6, r7\n" \
1548
            "cmp r6, r7\n" \
1549
            "blo 17f\n" \
1550
            "bhs 3f\n" \
1551
            "bhs 3f\n" \
1552
            "bhs 3f\n" \
1553
            "bhs 3f\n" \
1554
            "b .\n" \
1555
            "b .\n" \
1556
            "b .\n" \
1557
            "17:\n" \
1558
            "b 2f\n" \
1559
            "b .\n" \
1560
            "b .\n" \
1561
            "b .\n" \
1562
            "3:\n" \
1563
            "b .\n" \
1564
            "b .\n" \
1565
            "b .\n" \
1566
            "b .\n" \
1567
            "b .\n" \
1568
            "b .\n" \
1569
            "b .\n" \
1570
            "b .\n" \
1571
            "2:\n" \
1572
            "pop {r4, r5, r6, r7}\n" \
1573
            : /* No output operands */ \
1574
            : "r"(fb_ok) /* Input operands */ \
1575
            : "r0", "r4", "r5", "r6", "r7" /* Clobbered registers */ \
1576
        ); \
1577
    } while (0)
1578
#endif
1579
1580
1581
#define CONFIRM_MASK_VALID(id, mask) \
1582
    asm volatile("mov r1, %0" :: "r"(id):"r1");  \
1583
    /* id &= 0x0F */ \
1584
    asm volatile("and.w r1, r1, #15":::"r1"); \
1585
    asm volatile("mov r0, %0" :: "r"(mask):"r0"); \
1586
    asm volatile("movs r2, #1":::"r2"); \
1587
    asm volatile("lsls r2, r1":::"r2","cc"); \
1588
    asm volatile("ands r2, r0":::"r2","cc"); \
1589
    asm volatile("movs r0, #1":::"cc"); \
1590
    asm volatile("lsls r0, r1":::"r0","cc"); \
1591
    asm volatile("cmp r0, r2"); \
1592
    asm volatile("cmp r0, r2"); \
1593
    asm volatile("cmp r0, r2"); \
1594
    asm volatile("bne ."); \
1595
    asm volatile("mov r0, %0" :: "r"(mask)); \
1596
    asm volatile("movs r2, #1":::"r2"); \
1597
    asm volatile("lsls r2, r1":::"r2", "cc"); \
1598
    asm volatile("ands r2, r0":::"r2", "cc"); \
1599
    asm volatile("movs r0, #1":::"r0"); \
1600
    asm volatile("lsls r0, r1":::"r0", "cc"); \
1601
    asm volatile("cmp r0, r2":::"cc"); \
1602
    asm volatile("cmp r0, r2":::"cc"); \
1603
    asm volatile("cmp r0, r2":::"cc"); \
1604
    asm volatile("bne ."); \
1605
    asm volatile("mov r0, %0" :: "r"(mask):"r0"); \
1606
    asm volatile("movs r2, #1":::"r2"); \
1607
    asm volatile("lsls r2, r1":::"r2", "cc"); \
1608
    asm volatile("ands r2, r0":::"r2", "cc"); \
1609
    asm volatile("movs r0, #1":::"r0"); \
1610
    asm volatile("lsls r0, r1":::"r0", "cc"); \
1611
    asm volatile("cmp r0, r2":::"cc"); \
1612
    asm volatile("cmp r0, r2":::"cc"); \
1613
    asm volatile("cmp r0, r2":::"cc"); \
1614
    asm volatile("bne ."); \
1615
1616
#else
1617
1618
struct wolfBoot_image {
1619
    uint8_t *hdr;
1620
#ifdef EXT_FLASH
1621
    uint8_t *hdr_cache;
1622
#endif
1623
    uint8_t *trailer;
1624
    uint8_t *sha_hash;
1625
    uint8_t *fw_base;
1626
    uint32_t fw_size;
1627
    uint8_t part;
1628
    uint8_t hdr_ok : 1;
1629
    uint8_t signature_ok : 1;
1630
    uint8_t sha_ok : 1;
1631
    uint8_t not_ext : 1; /* image is no longer external */
1632
};
1633
1634
1635
/* do not warn if this is not used */
1636
static void UNUSEDFUNCTION wolfBoot_image_confirm_signature_ok(
1637
    struct wolfBoot_image *img)
1638
0
{
1639
0
    img->signature_ok = 1;
1640
0
}
1641
static void UNUSEDFUNCTION wolfBoot_image_clear_signature_ok(
1642
    struct wolfBoot_image *img)
1643
0
{
1644
0
  img->signature_ok = 0;
1645
0
}
1646
static void UNUSEDFUNCTION wolfBoot_image_confirm_sha_ok(
1647
    struct wolfBoot_image *img)
1648
0
{
1649
0
    img->sha_ok = 1;
1650
0
}
1651
static void UNUSEDFUNCTION wolfBoot_image_clear_sha_ok(
1652
    struct wolfBoot_image *img)
1653
0
{
1654
0
  img->sha_ok = 0;
1655
0
}
1656
static void UNUSEDFUNCTION wolfBoot_image_set_fw_base(
1657
    struct wolfBoot_image *img, void *base)
1658
0
{
1659
0
    img->fw_base = (uint8_t *)base;
1660
0
}
1661
1662
#define likely(x) (x)
1663
#define unlikely(x) (x)
1664
1665
#define VERIFY_FN(img,p_res,fn,...) {\
1666
    int ret = fn(__VA_ARGS__); \
1667
    if ((ret == 0) && (*p_res == 1)) \
1668
        wolfBoot_image_confirm_signature_ok(img); \
1669
    }
1670
1671
#define RSA_VERIFY_FN(ret,fn,...) \
1672
    ret = fn(__VA_ARGS__);
1673
1674
#define RSA_VERIFY_HASH(img,digest) \
1675
    if (image_CT_compare(img->sha_hash, digest, WOLFBOOT_SHA_DIGEST_SIZE) == 0) \
1676
        wolfBoot_image_confirm_signature_ok(img);
1677
1678
#define RSA_PSS_VERIFY_HASH(img, pss_data, pss_data_sz, hash_type) \
1679
    if (wc_RsaPSS_CheckPadding(img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, \
1680
            pss_data, pss_data_sz, hash_type) == 0) \
1681
        wolfBoot_image_confirm_signature_ok(img);
1682
1683
#define SHA_OK(imgp) ((imgp)->sha_ok == 1)
1684
1685
#define VERIFY_INTEGRITY_FN(img, computed_digest, stored) \
1686
    if (image_CT_compare((computed_digest), (stored), \
1687
            WOLFBOOT_SHA_DIGEST_SIZE) == 0) { \
1688
        (img)->sha_hash = (stored); \
1689
        wolfBoot_image_confirm_sha_ok(img); \
1690
    }
1691
1692
#define PART_SANITY_CHECK(p) \
1693
    if (((p)->hdr_ok != 1) || ((p)->sha_ok != 1) || ((p)->signature_ok != 1)) \
1694
        wolfBoot_panic()
1695
1696
#define SHA_SANITY_CHECK(p) \
1697
    if ((p)->sha_ok != 1) \
1698
        wolfBoot_panic()
1699
1700
#define FW_BASE_SANITY_CHECK(p) do{} while(0)
1701
1702
#define CONFIRM_MASK_VALID(id, mask) \
1703
    if ((mask & (1UL << id)) != (1UL << id)) \
1704
        wolfBoot_panic()
1705
1706
#define VERIFY_VERSION_ALLOWED(fb_ok) do{} while(0) /* okay */
1707
1708
#endif
1709
1710
/* Defined in image.c */
1711
int image_CT_compare(const uint8_t *expected, const uint8_t *actual,
1712
    uint32_t len);
1713
int wolfBoot_hardened_CT_compare(const uint8_t *expected, const uint8_t *actual,
1714
    uint32_t len);
1715
#if defined(MMU) || defined(WOLFBOOT_FDT)
1716
int wolfBoot_get_dts_size(void *dts_addr);
1717
int wolfBoot_verify_dts_digest(const uint8_t *expected_digest,
1718
    const void *dts_addr, uint32_t dts_size);
1719
#endif
1720
int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part);
1721
#ifdef EXT_FLASH
1722
int wolfBoot_open_image_external(struct wolfBoot_image* img, uint8_t part, uint8_t* addr);
1723
#endif
1724
int wolfBoot_open_image_address(struct wolfBoot_image* img, uint8_t* image);
1725
#ifdef WOLFBOOT_SELF_HEADER
1726
int wolfBoot_open_self(struct wolfBoot_image *img);
1727
int wolfBoot_open_self_address(struct wolfBoot_image *img, uint8_t *hdr,
1728
    uint8_t *image);
1729
#endif
1730
int wolfBoot_verify_integrity(struct wolfBoot_image *img);
1731
int wolfBoot_verify_authenticity(struct wolfBoot_image *img);
1732
int wolfBoot_set_partition_state(uint8_t part, uint8_t newst);
1733
int wolfBoot_get_update_sector_flag(uint16_t sector, uint8_t *flag);
1734
int wolfBoot_set_update_sector_flag(uint16_t sector, uint8_t newflag);
1735
1736
#ifdef WOLFBOOT_ELF_FLASH_SCATTER
1737
/* Support for ELF scatter/gather format */
1738
int wolfBoot_load_flash_image_elf(int part, unsigned long* entry_out,
1739
                                  int ext_flash);
1740
int wolfBoot_check_flash_image_elf(uint8_t part, unsigned long* entry_out);
1741
#endif
1742
1743
uint8_t* wolfBoot_peek_image(struct wolfBoot_image *img, uint32_t offset,
1744
        uint32_t* sz);
1745
1746
/* get header type for image */
1747
uint16_t wolfBoot_get_header(struct wolfBoot_image *img, uint16_t type, uint8_t **ptr);
1748
1749
/* Find the key slot ID based on the SHA hash of the key. */
1750
int keyslot_id_by_sha(const uint8_t *hint);
1751
1752
#ifdef EXT_FLASH
1753
# ifdef PART_BOOT_EXT
1754
#  define BOOT_EXT 1
1755
# else
1756
#  define BOOT_EXT 0
1757
# endif
1758
# ifdef PART_UPDATE_EXT
1759
#  define UPDATE_EXT 1
1760
# else
1761
#  define UPDATE_EXT 0
1762
# endif
1763
# ifdef PART_SWAP_EXT
1764
#  define SWAP_EXT 1
1765
# else
1766
#  define SWAP_EXT 0
1767
# endif
1768
# if defined(WOLFBOOT_SELF_HEADER_EXT)
1769
#  define SELF_HEADER_EXT 1
1770
# else
1771
#  define SELF_HEADER_EXT 0
1772
# endif
1773
# define PARTN_IS_EXT(pn) \
1774
    ((pn == PART_BOOT || pn == PART_DTS_BOOT) ? BOOT_EXT: \
1775
        ((pn == PART_UPDATE || pn == PART_DTS_UPDATE) ? UPDATE_EXT : \
1776
            ((pn == PART_SWAP) ? SWAP_EXT : \
1777
                 ((pn == PART_SELF) ? SELF_HEADER_EXT : 0))))
1778
# define PART_IS_EXT(x) (!(x)->not_ext) && PARTN_IS_EXT(((x)->part))
1779
1780
1781
#if defined(EXT_ENCRYPTED) && (defined(__WOLFBOOT) || defined(UNIT_TEST))
1782
#define ext_flash_check_write ext_flash_encrypt_write
1783
#define ext_flash_check_read ext_flash_decrypt_read
1784
#else
1785
#define ext_flash_check_write ext_flash_write
1786
#define ext_flash_check_read ext_flash_read
1787
#endif
1788
1789
static inline int wb_flash_erase(struct wolfBoot_image *img, uint32_t off,
1790
    uint32_t size)
1791
{
1792
    if (PART_IS_EXT(img))
1793
        return ext_flash_erase((uintptr_t)(img->hdr) + off, size);
1794
    else
1795
        return hal_flash_erase((uintptr_t)(img->hdr) + off, size);
1796
}
1797
1798
static inline int wb_flash_write(struct wolfBoot_image *img, uint32_t off,
1799
    const void *data, uint32_t size)
1800
{
1801
    if (PART_IS_EXT(img))
1802
        return ext_flash_check_write((uintptr_t)(img->hdr) + off, data, size);
1803
    else
1804
        return hal_flash_write((uintptr_t)(img->hdr) + off, data, size);
1805
}
1806
1807
static inline int wb_flash_write_verify_word(struct wolfBoot_image *img,
1808
    uint32_t off, uint32_t word)
1809
{
1810
    int ret;
1811
    volatile uint32_t copy;
1812
    if (PART_IS_EXT(img))
1813
    {
1814
        ext_flash_check_read((uintptr_t)(img->hdr) + off, (void *)&copy,
1815
            sizeof(uint32_t));
1816
        while (copy != word) {
1817
            ret = ext_flash_check_write((uintptr_t)(img->hdr) + off,
1818
                (void *)&word, sizeof(uint32_t));
1819
            if (ret < 0)
1820
                return ret;
1821
            ext_flash_check_read((uintptr_t)(img->hdr) + off, (void *)&copy,
1822
                sizeof(uint32_t));
1823
        }
1824
    } else {
1825
        volatile uint32_t *pcopy = (volatile uint32_t*)(img->hdr + off);
1826
        while(*pcopy != word) {
1827
            hal_flash_write((uintptr_t)pcopy, (void *)&word, sizeof(uint32_t));
1828
        }
1829
    }
1830
    return 0;
1831
}
1832
1833
1834
#else
1835
1836
# define SWAP_EXT (0)
1837
# define BOOT_EXT (0)
1838
# define UPDATE_EXT (0)
1839
# define PART_IS_EXT(x) (0)
1840
# define PARTN_IS_EXT(x) (0)
1841
# define wb_flash_erase(im, of, siz) \
1842
    hal_flash_erase(((uintptr_t)(((im)->hdr)) + of), siz)
1843
# define wb_flash_write(im, of, dat, siz) \
1844
    hal_flash_write(((uintptr_t)((im)->hdr)) + of, dat, siz)
1845
1846
#endif /* EXT_FLASH */
1847
1848
/* -- Image Formats -- */
1849
/* Legacy U-Boot Image */
1850
#ifdef BIG_ENDIAN_ORDER
1851
#define UBOOT_IMG_HDR_MAGIC 0x27051956UL
1852
#else
1853
#define UBOOT_IMG_HDR_MAGIC 0x56190527UL
1854
#endif
1855
#define UBOOT_IMG_HDR_SZ    64
1856
1857
/* --- Flattened Device Tree Blob */
1858
#if defined(MMU) || defined(WOLFBOOT_FDT)
1859
#include "fdt.h"
1860
#endif
1861
1862
#ifndef EXT_ENCRYPTED
1863
#define WOLFBOOT_MAX_SPACE (WOLFBOOT_PARTITION_SIZE - \
1864
    (TRAILER_SKIP + sizeof(uint32_t) + \
1865
    ((WOLFBOOT_PARTITION_SIZE + 1) / (WOLFBOOT_SECTOR_SIZE * 8))))
1866
#else
1867
#define WOLFBOOT_MAX_SPACE (WOLFBOOT_PARTITION_SIZE - ENCRYPT_TMP_SECRET_OFFSET)
1868
#endif
1869
1870
#ifdef __cplusplus
1871
}
1872
#endif
1873
1874
#endif /* !IMAGE_H */