Coverage Report

Created: 2026-07-09 06:20

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 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 *)&copy,
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 *)&copy,
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 */