Coverage Report

Created: 2026-06-15 06:15

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 not_ext; /* image is no longer external */
175
};
176
177
178
/**
179
 * This function sets the flag that indicates the signature is valid for the
180
 * wolfBoot_image.
181
 *
182
 * With ARMORED setup, the flag is redundant, and the information is wrapped in
183
 * between canary variables, to mitigate attacks based on memory corruptions.
184
 */
185
static void NOINLINEFUNCTION wolfBoot_image_confirm_signature_ok(
186
    struct wolfBoot_image *img)
187
{
188
    img->canary_FEED4567 = 0xFEED4567UL;
189
    img->signature_ok = 1UL;
190
    img->canary_FEED6789 = 0xFEED6789UL;
191
    img->not_signature_ok = ~(1UL);
192
    img->canary_FEED89AB = 0xFEED89ABUL;
193
}
194
195
static void NOINLINEFUNCTION wolfBoot_image_clear_signature_ok(
196
  struct wolfBoot_image *img)
197
{
198
  img->canary_FEED4567 = 0xFEED4567UL;
199
  img->signature_ok = 0UL;
200
  img->canary_FEED6789 = 0xFEED6789UL;
201
  img->not_signature_ok = 1UL;
202
  img->canary_FEED89AB = 0xFEED89ABUL;
203
}
204
205
/**
206
 * Final sanity check, performed just before do_boot, or before starting an
207
 * update that has been verified.
208
 *
209
 * This procedure detects if any of the previous checks has been skipped.
210
 * If any of the required flags does not match the expected value, wolfBoot
211
 * panics.
212
 */
213
#define PART_SANITY_CHECK(p) \
214
    /* Redundant set of r2=0 */ \
215
    asm volatile("mov r2, #0":::"r2"); \
216
    asm volatile("mov r2, #0":::"r2"); \
217
    asm volatile("mov r2, #0":::"r2"); \
218
    asm volatile("mov r2, #0":::"r2"); \
219
    asm volatile("mov r2, #0":::"r2"); \
220
    /* Loading hdr_ok flag, verifying */ \
221
    asm volatile("mov r2, %0" ::"r"((p)->hdr_ok):"r2"); \
222
    asm volatile("cmp r2, #1":::"cc"); \
223
    asm volatile("cmp r2, #1":::"cc"); \
224
    asm volatile("cmp r2, #1":::"cc"); \
225
    asm volatile("bne ."); \
226
    asm volatile("cmp r2, #1":::"cc"); \
227
    asm volatile("cmp r2, #1":::"cc"); \
228
    asm volatile("cmp r2, #1":::"cc"); \
229
    asm volatile("bne .-4"); \
230
    asm volatile("cmp r2, #1":::"cc"); \
231
    asm volatile("cmp r2, #1":::"cc"); \
232
    asm volatile("cmp r2, #1":::"cc"); \
233
    asm volatile("bne .-8"); \
234
    asm volatile("cmp r2, #1":::"cc"); \
235
    asm volatile("cmp r2, #1":::"cc"); \
236
    asm volatile("cmp r2, #1":::"cc"); \
237
    asm volatile("bne .-12"); \
238
    /* Redundant set of r2=0 */ \
239
    asm volatile("mov r2, #0":::"r2"); \
240
    asm volatile("mov r2, #0":::"r2"); \
241
    asm volatile("mov r2, #0":::"r2"); \
242
    asm volatile("mov r2, #0":::"r2"); \
243
    asm volatile("mov r2, #0":::"r2"); \
244
    /* Loading hdr_ok flag, verifying */ \
245
    asm volatile("mov r2, %0" ::"r"((p)->sha_ok):"r2"); \
246
    asm volatile("cmp r2, #1":::"cc"); \
247
    asm volatile("cmp r2, #1":::"cc"); \
248
    asm volatile("cmp r2, #1":::"cc"); \
249
    asm volatile("bne ."); \
250
    asm volatile("cmp r2, #1":::"cc"); \
251
    asm volatile("cmp r2, #1":::"cc"); \
252
    asm volatile("cmp r2, #1":::"cc"); \
253
    asm volatile("bne .-4"); \
254
    asm volatile("cmp r2, #1":::"cc"); \
255
    asm volatile("cmp r2, #1":::"cc"); \
256
    asm volatile("cmp r2, #1":::"cc"); \
257
    asm volatile("bne .-8"); \
258
    asm volatile("cmp r2, #1":::"cc"); \
259
    asm volatile("cmp r2, #1":::"cc"); \
260
    asm volatile("cmp r2, #1":::"cc"); \
261
    asm volatile("bne .-12"); \
262
    /* Redundant set of r2=0 */ \
263
    asm volatile("mov r2, #0":::"r2"); \
264
    asm volatile("mov r2, #0":::"r2"); \
265
    asm volatile("mov r2, #0":::"r2"); \
266
    asm volatile("mov r2, #0":::"r2"); \
267
    asm volatile("mov r2, #0":::"r2"); \
268
    /* Loading signature_ok flag, verifying */ \
269
    asm volatile("mov r2, %0" ::"r"((p)->signature_ok):"r2"); \
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 ."); \
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 .-4"); \
278
    asm volatile("cmp r2, #1":::"cc"); \
279
    asm volatile("cmp r2, #1":::"cc"); \
280
    asm volatile("cmp r2, #1":::"cc"); \
281
    asm volatile("bne .-8"); \
282
    asm volatile("cmp r2, #1":::"cc"); \
283
    asm volatile("cmp r2, #1":::"cc"); \
284
    asm volatile("cmp r2, #1":::"cc"); \
285
    asm volatile("bne .-12"); \
286
    /* Redundant set of r2=0 */ \
287
    asm volatile("mov r2, #0"); \
288
    asm volatile("mov r2, #0"); \
289
    asm volatile("mov r2, #0"); \
290
    asm volatile("mov r2, #0"); \
291
    asm volatile("mov r2, #0"); \
292
    /* Loading ~(signature_ok) flag, verifying */ \
293
    asm volatile("mov r2, %0" ::"r"((p)->not_signature_ok):"r2"); \
294
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
295
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
296
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
297
    asm volatile("bne ."); \
298
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
299
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
300
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
301
    asm volatile("bne .-4"); \
302
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
303
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
304
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
305
    asm volatile("bne .-8"); \
306
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
307
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
308
    asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
309
    asm volatile("bne .-12"); \
310
    /* Redundant set of r2=0 */ \
311
    asm volatile("mov r2, #0":::"r2"); \
312
    asm volatile("mov r2, #0":::"r2"); \
313
    asm volatile("mov r2, #0":::"r2"); \
314
    asm volatile("mov r2, #0":::"r2"); \
315
    asm volatile("mov r2, #0":::"r2"); \
316
    /* Loading canary value, verifying */ \
317
    asm volatile("mov r2, %0" ::"r"((p)->canary_FEED6789):"r2"); \
318
    asm volatile("mov r0, %0" ::"r"(0xFEED6789):"r0"); \
319
    asm volatile("cmp r2, r0":::"cc"); \
320
    asm volatile("cmp r2, r0":::"cc"); \
321
    asm volatile("cmp r2, r0":::"cc"); \
322
    asm volatile("bne ."); \
323
    asm volatile("cmp r2, r0":::"cc"); \
324
    asm volatile("cmp r2, r0":::"cc"); \
325
    asm volatile("cmp r2, r0":::"cc"); \
326
    asm volatile("bne .-4"); \
327
    asm volatile("cmp r2, r0":::"cc"); \
328
    asm volatile("cmp r2, r0":::"cc"); \
329
    asm volatile("cmp r2, r0":::"cc"); \
330
    asm volatile("bne .-8"); \
331
    asm volatile("cmp r2, r0":::"cc"); \
332
    asm volatile("cmp r2, r0":::"cc"); \
333
    asm volatile("cmp r2, r0":::"cc"); \
334
    asm volatile("bne .-12"); \
335
    /* Redundant set of r2=0 */ \
336
    asm volatile("mov r2, #0":::"r2"); \
337
    asm volatile("mov r2, #0":::"r2"); \
338
    asm volatile("mov r2, #0":::"r2"); \
339
    asm volatile("mov r2, #0":::"r2"); \
340
    asm volatile("mov r2, #0":::"r2"); \
341
    /* Loading canary value, verifying */ \
342
    asm volatile("mov r2, %0" ::"r"((p)->canary_FEED4567):"r2"); \
343
    asm volatile("mov r0, %0" ::"r"(0xFEED4567):"r0"); \
344
    asm volatile("cmp r2, r0":::"cc"); \
345
    asm volatile("cmp r2, r0":::"cc"); \
346
    asm volatile("cmp r2, r0":::"cc"); \
347
    asm volatile("bne ."); \
348
    asm volatile("cmp r2, r0":::"cc"); \
349
    asm volatile("cmp r2, r0":::"cc"); \
350
    asm volatile("cmp r2, r0":::"cc"); \
351
    asm volatile("bne .-4"); \
352
    asm volatile("cmp r2, r0":::"cc"); \
353
    asm volatile("cmp r2, r0":::"cc"); \
354
    asm volatile("cmp r2, r0":::"cc"); \
355
    asm volatile("bne .-8"); \
356
    asm volatile("cmp r2, r0":::"cc"); \
357
    asm volatile("cmp r2, r0":::"cc"); \
358
    asm volatile("cmp r2, r0":::"cc"); \
359
    asm volatile("bne .-12"); \
360
    /* Redundant set of r2=0 */ \
361
    asm volatile("mov r2, #0":::"r2"); \
362
    asm volatile("mov r2, #0":::"r2"); \
363
    asm volatile("mov r2, #0":::"r2"); \
364
    asm volatile("mov r2, #0":::"r2"); \
365
    asm volatile("mov r2, #0":::"r2"); \
366
    /* Loading canary value, verifying */ \
367
    asm volatile("mov r2, %0" ::"r"((p)->canary_FEED89AB):"r2"); \
368
    asm volatile("mov r0, %0" ::"r"(0xFEED89AB):"r0"); \
369
    asm volatile("cmp r2, r0":::"cc"); \
370
    asm volatile("cmp r2, r0":::"cc"); \
371
    asm volatile("cmp r2, r0":::"cc"); \
372
    asm volatile("bne ."); \
373
    asm volatile("cmp r2, r0":::"cc"); \
374
    asm volatile("cmp r2, r0":::"cc"); \
375
    asm volatile("cmp r2, r0":::"cc"); \
376
    asm volatile("bne .-4"); \
377
    asm volatile("cmp r2, r0":::"cc"); \
378
    asm volatile("cmp r2, r0":::"cc"); \
379
    asm volatile("cmp r2, r0":::"cc"); \
380
    asm volatile("bne .-8"); \
381
    asm volatile("cmp r2, r0":::"cc"); \
382
    asm volatile("cmp r2, r0":::"cc"); \
383
    asm volatile("cmp r2, r0":::"cc"); \
384
    asm volatile("bne .-12") \
385
386
/**
387
 * First part of RSA verification. Ensure that the function is called by
388
 * double checking its return value contains a valid
389
 * len (>= WOLFBOOT_SHA_DIGEST_SIZE).
390
 *
391
 * Uses GAS local numeric labels (1f/1:) so the macro can be safely expanded
392
 * multiple times in the same function (e.g. RSA PKCS#1.5 + RSA-PSS paths).
393
 */
394
#define RSA_VERIFY_FN(ret,fn,...) \
395
    { \
396
        /* Redundant set of r0=0 */ \
397
        asm volatile("mov r0, #0":::"r0"); \
398
        asm volatile("mov r0, #0":::"r0"); \
399
        asm volatile("mov r0, #0":::"r0"); \
400
        /* Call the function */ \
401
        int tmp_ret = fn(__VA_ARGS__); \
402
        ret = -1; \
403
        /* Redundant set of r2=SHA_DIGEST_SIZE */ \
404
        asm volatile("mov r2, %0" ::"r"(WOLFBOOT_SHA_DIGEST_SIZE):"r2"); \
405
        asm volatile("mov r2, %0" ::"r"(WOLFBOOT_SHA_DIGEST_SIZE):"r2"); \
406
        asm volatile("mov r2, %0" ::"r"(WOLFBOOT_SHA_DIGEST_SIZE):"r2"); \
407
        /* Redundant check for fn() return value >= r2 */ \
408
        asm volatile("cmp r0, r2":::"cc"); \
409
        asm volatile("cmp r0, r2":::"cc"); \
410
        asm volatile("cmp r0, r2":::"cc"); \
411
        asm volatile("blt 1f"); \
412
        asm volatile("cmp r0, r2":::"cc"); \
413
        asm volatile("cmp r0, r2":::"cc"); \
414
        asm volatile("cmp r0, r2":::"cc"); \
415
        asm volatile("blt 1f"); \
416
        asm volatile("cmp r0, r2":::"cc"); \
417
        asm volatile("cmp r0, r2":::"cc"); \
418
        asm volatile("cmp r0, r2":::"cc"); \
419
        asm volatile("blt 1f"); \
420
        asm volatile("cmp r0, r2":::"cc"); \
421
        asm volatile("cmp r0, r2":::"cc"); \
422
        asm volatile("cmp r0, r2":::"cc"); \
423
        asm volatile("blt 1f"); \
424
        /* Return value is set here in case of success */ \
425
        ret = tmp_ret; \
426
        asm volatile("1:"); \
427
        asm volatile("nop"); \
428
    }
429
430
/**
431
 * Second part of RSA verification.
432
 *
433
 * Compare the digest twice, then confirm via
434
 * wolfBoot_image_confirm_signature_ok();
435
 *
436
 * Uses GAS local numeric labels (2f/2:) for safe multi-expansion.
437
 */
438
#define RSA_VERIFY_HASH(img,digest) \
439
    { \
440
        volatile int compare_res; \
441
        if (!img || !digest)    \
442
            asm volatile("b 2f"); \
443
        /* Redundant set of r0=50*/ \
444
        asm volatile("mov r0, #50":::"r0"); \
445
        asm volatile("mov r0, #50":::"r0"); \
446
        asm volatile("mov r0, #50":::"r0"); \
447
        compare_res = image_CT_compare(digest, img->sha_hash, \
448
            WOLFBOOT_SHA_DIGEST_SIZE); \
449
        /* Redundant checks that ensure the function actually returned 0 */ \
450
        asm volatile("cmp r0, #0":::"cc"); \
451
        asm volatile("cmp r0, #0":::"cc"); \
452
        asm volatile("cmp r0, #0":::"cc"); \
453
        asm volatile("bne 2f":::"cc"); \
454
        asm volatile("cmp r0, #0"); \
455
        asm volatile("cmp r0, #0"); \
456
        asm volatile("cmp r0, #0"); \
457
        asm volatile("bne 2f":::"cc"); \
458
        asm volatile("cmp r0, #0":::"cc"); \
459
        asm volatile("cmp r0, #0":::"cc"); \
460
        asm volatile("cmp r0, #0":::"cc"); \
461
        asm volatile("bne 2f"); \
462
        asm volatile("cmp r0, #0":::"cc"); \
463
        asm volatile("cmp r0, #0":::"cc"); \
464
        asm volatile("cmp r0, #0":::"cc"); \
465
        asm volatile("bne 2f"); \
466
        /* Repeat comparison call */ \
467
        compare_res = image_CT_compare(digest, img->sha_hash, \
468
            WOLFBOOT_SHA_DIGEST_SIZE); \
469
        compare_res; \
470
        /* Redundant checks that ensure the function actually returned 0 */ \
471
        asm volatile("cmp r0, #0":::"cc"); \
472
        asm volatile("cmp r0, #0":::"cc"); \
473
        asm volatile("cmp r0, #0":::"cc"); \
474
        asm volatile("bne 2f"); \
475
        asm volatile("cmp r0, #0":::"cc"); \
476
        asm volatile("cmp r0, #0":::"cc"); \
477
        asm volatile("cmp r0, #0":::"cc"); \
478
        asm volatile("bne 2f"); \
479
        asm volatile("cmp r0, #0":::"cc"); \
480
        asm volatile("cmp r0, #0":::"cc"); \
481
        asm volatile("cmp r0, #0":::"cc"); \
482
        asm volatile("bne 2f"); \
483
        asm volatile("cmp r0, #0":::"cc"); \
484
        asm volatile("cmp r0, #0":::"cc"); \
485
        asm volatile("cmp r0, #0":::"cc"); \
486
        asm volatile("bne 2f"); \
487
        /* Confirm that the signature is OK */ \
488
        wolfBoot_image_confirm_signature_ok(img); \
489
        asm volatile("2:"); \
490
        asm volatile("nop"); \
491
    }
492
493
/**
494
 * Second part of RSA-PSS verification.
495
 *
496
 * Call wc_RsaPSS_CheckPadding twice, then confirm via
497
 * wolfBoot_image_confirm_signature_ok();
498
 *
499
 * Uses GAS local numeric labels (3f/3:) for safe multi-expansion.
500
 */
501
#define RSA_PSS_VERIFY_HASH(img, pss_data, pss_data_sz, hash_type) \
502
    { \
503
        volatile int pss_res; \
504
        if (!img || !pss_data)    \
505
            asm volatile("b 3f"); \
506
        /* Redundant set of r0=50*/ \
507
        asm volatile("mov r0, #50":::"r0"); \
508
        asm volatile("mov r0, #50":::"r0"); \
509
        asm volatile("mov r0, #50":::"r0"); \
510
        pss_res = wc_RsaPSS_CheckPadding(img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, \
511
            pss_data, pss_data_sz, hash_type); \
512
        /* Redundant checks that ensure the function actually returned 0 */ \
513
        asm volatile("cmp r0, #0":::"cc"); \
514
        asm volatile("cmp r0, #0":::"cc"); \
515
        asm volatile("cmp r0, #0":::"cc"); \
516
        asm volatile("bne 3f":::"cc"); \
517
        asm volatile("cmp r0, #0"); \
518
        asm volatile("cmp r0, #0"); \
519
        asm volatile("cmp r0, #0"); \
520
        asm volatile("bne 3f":::"cc"); \
521
        asm volatile("cmp r0, #0":::"cc"); \
522
        asm volatile("cmp r0, #0":::"cc"); \
523
        asm volatile("cmp r0, #0":::"cc"); \
524
        asm volatile("bne 3f"); \
525
        asm volatile("cmp r0, #0":::"cc"); \
526
        asm volatile("cmp r0, #0":::"cc"); \
527
        asm volatile("cmp r0, #0":::"cc"); \
528
        asm volatile("bne 3f"); \
529
        /* Repeat wc_RsaPSS_CheckPadding call */ \
530
        pss_res = wc_RsaPSS_CheckPadding(img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, \
531
            pss_data, pss_data_sz, hash_type); \
532
        pss_res; \
533
        /* Redundant checks that ensure the function actually returned 0 */ \
534
        asm volatile("cmp r0, #0":::"cc"); \
535
        asm volatile("cmp r0, #0":::"cc"); \
536
        asm volatile("cmp r0, #0":::"cc"); \
537
        asm volatile("bne 3f"); \
538
        asm volatile("cmp r0, #0":::"cc"); \
539
        asm volatile("cmp r0, #0":::"cc"); \
540
        asm volatile("cmp r0, #0":::"cc"); \
541
        asm volatile("bne 3f"); \
542
        asm volatile("cmp r0, #0":::"cc"); \
543
        asm volatile("cmp r0, #0":::"cc"); \
544
        asm volatile("cmp r0, #0":::"cc"); \
545
        asm volatile("bne 3f"); \
546
        asm volatile("cmp r0, #0":::"cc"); \
547
        asm volatile("cmp r0, #0":::"cc"); \
548
        asm volatile("cmp r0, #0":::"cc"); \
549
        asm volatile("bne 3f"); \
550
        /* Confirm that the signature is OK */ \
551
        wolfBoot_image_confirm_signature_ok(img); \
552
        asm volatile("3:"); \
553
        asm volatile("nop"); \
554
    }
555
556
/**
557
 * ECC / Ed / PQ signature verification.
558
 * Those verify functions set an additional value 'p_res'
559
 * which is passed as a pointer.
560
 *
561
 * Ensure that the verification function has been called, and then
562
 * set the return value accordingly.
563
 *
564
 * Double check by reading the value in p_res from memory a few times.
565
 *
566
 * Uses GAS local numeric labels (4f/4:) for safe multi-expansion.
567
 */
568
#if defined(__GNUC__)
569
570
#define VERIFY_FN(img,p_res,fn,...) \
571
    /* Redundant set of r0=50*/ \
572
    asm volatile("mov r0, #50":::"r0"); \
573
    asm volatile("mov r0, #50":::"r0"); \
574
    asm volatile("mov r0, #50":::"r0"); \
575
    /* Call the verify function */ \
576
    fn(__VA_ARGS__); \
577
    /* Redundant checks that ensure the function actually returned 0 */ \
578
    asm volatile("cmp r0, #0":::"cc"); \
579
    asm volatile("cmp r0, #0":::"cc"); \
580
    asm volatile("cmp r0, #0":::"cc"); \
581
    asm volatile("bne 4f"); \
582
    asm volatile("cmp r0, #0":::"cc"); \
583
    asm volatile("cmp r0, #0":::"cc"); \
584
    asm volatile("cmp r0, #0":::"cc"); \
585
    asm volatile("bne 4f"); \
586
    asm volatile("cmp r0, #0":::"cc"); \
587
    asm volatile("cmp r0, #0":::"cc"); \
588
    asm volatile("cmp r0, #0":::"cc"); \
589
    asm volatile("bne 4f"); \
590
    asm volatile("cmp r0, #0":::"cc"); \
591
    asm volatile("cmp r0, #0":::"cc"); \
592
    asm volatile("cmp r0, #0":::"cc"); \
593
    asm volatile("bne 4f"); \
594
    /* Check that res = 1, a few times, reading the value from memory */ \
595
    asm volatile("ldr r2, [%0]" ::"r"(p_res)); \
596
    asm volatile("cmp r2, #1":::"cc"); \
597
    asm volatile("cmp r2, #1":::"cc"); \
598
    asm volatile("cmp r2, #1":::"cc"); \
599
    asm volatile("bne 4f"); \
600
    asm volatile("mvn r3, r2":::"r3"); \
601
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
602
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
603
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
604
    asm volatile("bne 4f"); \
605
    asm volatile("ldr r2, [%0]" ::"r"(p_res)); \
606
    asm volatile("cmp r2, #1":::"cc"); \
607
    asm volatile("cmp r2, #1":::"cc"); \
608
    asm volatile("cmp r2, #1":::"cc"); \
609
    asm volatile("bne 4f"); \
610
    asm volatile("mvn r3, r2":::"r3"); \
611
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
612
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
613
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
614
    asm volatile("bne 4f"); \
615
    asm volatile("ldr r2, [%0]" ::"r"(p_res)); \
616
    asm volatile("cmp r2, #1":::"cc"); \
617
    asm volatile("cmp r2, #1":::"cc"); \
618
    asm volatile("cmp r2, #1":::"cc"); \
619
    asm volatile("bne 4f"); \
620
    asm volatile("mvn r3, r2":::"r3"); \
621
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
622
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
623
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
624
    asm volatile("bne 4f"); \
625
    asm volatile("ldr r2, [%0]" ::"r"(p_res)); \
626
    asm volatile("cmp r2, #1":::"cc"); \
627
    asm volatile("cmp r2, #1":::"cc"); \
628
    asm volatile("cmp r2, #1":::"cc"); \
629
    asm volatile("bne 4f"); \
630
    asm volatile("mvn r3, r2":::"r3"); \
631
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
632
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
633
    asm volatile("cmp r3, #0xFFFFFFFE":::"cc"); \
634
    asm volatile("bne 4f"); \
635
    /* Confirm that the signature is OK */ \
636
    wolfBoot_image_confirm_signature_ok(img); \
637
    asm volatile("4:"); \
638
    asm volatile("nop") \
639
640
#elif defined(__ICCARM__) && defined(__IAR_SYSTEMS_ICC__)
641
642
#define VERIFY_FN(img, p_res, fn, ...) \
643
    do { \
644
        __asm volatile( \
645
            "mov r0, #50\n" \
646
            "mov r0, #50\n" \
647
            "mov r0, #50\n" \
648
            : /* No output operands */ \
649
            : /* No input operands */ \
650
            : "r0" /* Clobbered registers */ \
651
        ); \
652
        void (*confirm_func)(struct wolfBoot_image *) = \
653
            wolfBoot_image_confirm_signature_ok; \
654
        fn(__VA_ARGS__); \
655
        __asm volatile( \
656
            "cmp r0, #0\n" \
657
            "cmp r0, #0\n" \
658
            "cmp r0, #0\n" \
659
            "beq 30f\n" \
660
            "bne 1f\n" \
661
            "bne 1f\n" \
662
            "bne 1f\n" \
663
            "bne 1f\n" \
664
            "b .\n" \
665
            "b .\n" \
666
            "b .\n" \
667
            "30:\n" \
668
            "ldr r2, [%0]\n" \
669
            "cmp r2, #1\n" \
670
            "cmp r2, #1\n" \
671
            "cmp r2, #1\n" \
672
            "beq 31f\n" \
673
            "bne 1f\n" \
674
            "bne 1f\n" \
675
            "bne 1f\n" \
676
            "bne 1f\n" \
677
            "b .\n" \
678
            "b .\n" \
679
            "b .\n" \
680
            "31:\n" \
681
            "mvn r3, r2\n" \
682
            "cmp r3, #0xFFFFFFFE\n" \
683
            "cmp r3, #0xFFFFFFFE\n" \
684
            "cmp r3, #0xFFFFFFFE\n" \
685
            "beq 32f\n" \
686
            "bne 1f\n" \
687
            "bne 1f\n" \
688
            "bne 1f\n" \
689
            "bne 1f\n" \
690
            "b .\n" \
691
            "b .\n" \
692
            "b .\n" \
693
            "32:\n" \
694
            "ldr r2, [%0]\n" \
695
            "cmp r2, #1\n" \
696
            "cmp r2, #1\n" \
697
            "cmp r2, #1\n" \
698
            "beq 33f\n" \
699
            "bne 1f\n" \
700
            "bne 1f\n" \
701
            "bne 1f\n" \
702
            "bne 1f\n" \
703
            "b .\n" \
704
            "b .\n" \
705
            "b .\n" \
706
            "33:\n" \
707
            "mvn r3, r2\n" \
708
            "cmp r3, #0xFFFFFFFE\n" \
709
            "cmp r3, #0xFFFFFFFE\n" \
710
            "cmp r3, #0xFFFFFFFE\n" \
711
            "beq 34f\n" \
712
            "bne 1f\n" \
713
            "bne 1f\n" \
714
            "bne 1f\n" \
715
            "bne 1f\n" \
716
            "b .\n" \
717
            "b .\n" \
718
            "b .\n" \
719
            "34:\n" \
720
            "ldr r2, [%0]\n" \
721
            "cmp r2, #1\n" \
722
            "cmp r2, #1\n" \
723
            "cmp r2, #1\n" \
724
            "beq 35f\n" \
725
            "bne 1f\n" \
726
            "bne 1f\n" \
727
            "bne 1f\n" \
728
            "bne 1f\n" \
729
            "b .\n" \
730
            "b .\n" \
731
            "b .\n" \
732
            "35:\n" \
733
            "mvn r3, r2\n" \
734
            "cmp r3, #0xFFFFFFFE\n" \
735
            "cmp r3, #0xFFFFFFFE\n" \
736
            "cmp r3, #0xFFFFFFFE\n" \
737
            "beq 36f\n" \
738
            "bne 1f\n" \
739
            "bne 1f\n" \
740
            "bne 1f\n" \
741
            "bne 1f\n" \
742
            "b .\n" \
743
            "b .\n" \
744
            "b .\n" \
745
            "36:\n" \
746
            "ldr r2, [%0]\n" \
747
            "cmp r2, #1\n" \
748
            "cmp r2, #1\n" \
749
            "cmp r2, #1\n" \
750
            "beq 37f\n" \
751
            "bne 1f\n" \
752
            "bne 1f\n" \
753
            "bne 1f\n" \
754
            "bne 1f\n" \
755
            "b .\n" \
756
            "b .\n" \
757
            "b .\n" \
758
            "37:\n" \
759
            "mvn r3, r2\n" \
760
            "cmp r3, #0xFFFFFFFE\n" \
761
            "cmp r3, #0xFFFFFFFE\n" \
762
            "cmp r3, #0xFFFFFFFE\n" \
763
            "beq 38f\n" \
764
            "bne 1f\n" \
765
            "bne 1f\n" \
766
            "bne 1f\n" \
767
            "bne 1f\n" \
768
            "b .\n" \
769
            "b .\n" \
770
            "b .\n" \
771
            "38:\n" \
772
            /* Load 'img' into r0 (first argument to the function) */ \
773
            "mov r0, %1\n" \
774
            /* Load the function pointer into r3 */ \
775
            "mov r3, %2\n" \
776
            "blx r3\n"\
777
            "b 2f\n" \
778
            "b .\n" \
779
            "b .\n" \
780
            "b .\n" \
781
            "1:\n" \
782
            "nop\n" \
783
            "2:\n" \
784
            : /* No output operands */ \
785
            : "r"(p_res), "r"(img), "r"(confirm_func) /* Input operands */ \
786
            : "r0", "r2", "r3", "lr" /* Clobbered registers */ \
787
        ); \
788
    } while (0)
789
#endif
790
791
792
/**
793
 * This macro is only invoked after a successful update version check, prior to
794
 * initiating the update installation.
795
 *
796
 * At this point, wolfBoot thinks that the version check has been successful.
797
 *
798
 *
799
 * The fallback flag (checked with redundancy) causes wolfBoot to skip the
800
 * redundant version checks.
801
 *
802
 * The redundant checks here ensure that the image version is read twice per
803
 * each partition, and the two return values are the same.
804
 *
805
 *
806
 * The comparison is also redundant, causing wolfBoot to panic if the update
807
 * version is not strictly greater than the current one.
808
 *
809
 */
810
#if defined(__GNUC__)
811
812
#define VERIFY_VERSION_ALLOWED(fb_ok) \
813
    asm volatile( \
814
        "push {r4, r5, r6, r7}\n" \
815
        "mov r0, #0\n" \
816
        "mov r4, #1\n" \
817
        "mov r5, #0\n" \
818
        "mov r6, #2\n" \
819
        "mov r7, #0\n" \
820
        "mov r0, #0\n" \
821
        "mov r4, #1\n" \
822
        "mov r5, #0\n" \
823
        "mov r6, #2\n" \
824
        "mov r7, #0\n" \
825
        "mov r0, %0\n" \
826
        "mov r4, %0\n" \
827
        "cmp r0, #1\n" \
828
        "cmp r0, #1\n" \
829
        "cmp r0, #1\n" \
830
        "beq 20f\n" \
831
        "bne do_check\n" \
832
        "bne do_check\n" \
833
        "bne do_check\n" \
834
        "bne do_check\n" \
835
        "b .\n" \
836
        "b .\n" \
837
        "b .\n" \
838
        "20:\n" \
839
        "cmp r4, #1\n" \
840
        "cmp r4, #1\n" \
841
        "cmp r4, #1\n" \
842
        "beq 21f\n" \
843
        "bne do_check\n" \
844
        "bne do_check\n" \
845
        "bne do_check\n" \
846
        "bne do_check\n" \
847
        "b .\n" \
848
        "b .\n" \
849
        "b .\n" \
850
        "21:\n" \
851
        "cmp r0, r4\n" \
852
        "cmp r0, r4\n" \
853
        "cmp r0, r4\n" \
854
        "beq 22f\n" \
855
        "bne do_check\n" \
856
        "bne do_check\n" \
857
        "bne do_check\n" \
858
        "bne do_check\n" \
859
        "b .\n" \
860
        "b .\n" \
861
        "b .\n" \
862
        "22:\n" \
863
        "cmp r0, #1\n" \
864
        "cmp r0, #1\n" \
865
        "cmp r0, #1\n" \
866
        "beq 23f\n" \
867
        "bne do_check\n" \
868
        "bne do_check\n" \
869
        "bne do_check\n" \
870
        "bne do_check\n" \
871
        "b .\n" \
872
        "b .\n" \
873
        "b .\n" \
874
        "23:\n" \
875
        "b end_check\n" \
876
        "do_check:\n" \
877
        "mov r0, #1\n" \
878
        "mov r0, #1\n" \
879
        "mov r0, #1\n" \
880
        "bl wolfBoot_get_image_version\n" \
881
        "mov r5, r0\n" \
882
        "mov r5, r0\n" \
883
        "mov r5, r0\n" \
884
        "mov r0, #1\n" \
885
        "mov r0, #1\n" \
886
        "mov r0, #1\n" \
887
        "bl wolfBoot_get_image_version\n" \
888
        "mov r7, r0\n" \
889
        "mov r7, r0\n" \
890
        "mov r7, r0\n" \
891
        "cmp r5, r7\n" \
892
        "cmp r5, r7\n" \
893
        "cmp r5, r7\n" \
894
        "beq 24f\n" \
895
        "bne ver_panic\n" \
896
        "bne ver_panic\n" \
897
        "bne ver_panic\n" \
898
        "bne ver_panic\n" \
899
        "b .\n" \
900
        "b .\n" \
901
        "b .\n" \
902
        "24:\n" \
903
        "mov r0, #0\n" \
904
        "mov r0, #0\n" \
905
        "mov r0, #0\n" \
906
        "bl wolfBoot_get_image_version\n" \
907
        "mov r4, r0\n" \
908
        "mov r4, r0\n" \
909
        "mov r4, r0\n" \
910
        "mov r0, #0\n" \
911
        "mov r0, #0\n" \
912
        "mov r0, #0\n" \
913
        "bl wolfBoot_get_image_version\n" \
914
        "mov r6, r0\n" \
915
        "mov r6, r0\n" \
916
        "mov r6, r0\n" \
917
        "cmp r4, r6\n" \
918
        "cmp r4, r6\n" \
919
        "cmp r4, r6\n" \
920
        "beq 25f\n" \
921
        "bne ver_panic\n" \
922
        "bne ver_panic\n" \
923
        "bne ver_panic\n" \
924
        "bne ver_panic\n" \
925
        "b .\n" \
926
        "b .\n" \
927
        "b .\n" \
928
        "25:\n" \
929
        "mov r0, #0\n" \
930
        "mov r0, #0\n" \
931
        "mov r0, #0\n" \
932
        "cmp r4, r5\n" \
933
        "cmp r4, r5\n" \
934
        "cmp r4, r5\n" \
935
        "blo 26f\n" \
936
        "bhs ver_panic\n" \
937
        "bhs ver_panic\n" \
938
        "bhs ver_panic\n" \
939
        "bhs ver_panic\n" \
940
        "b .\n" \
941
        "b .\n" \
942
        "b .\n" \
943
        "26:\n" \
944
        "cmp r6, r7\n" \
945
        "cmp r6, r7\n" \
946
        "cmp r6, r7\n" \
947
        "blo 27f\n" \
948
        "bhs ver_panic\n" \
949
        "bhs ver_panic\n" \
950
        "bhs ver_panic\n" \
951
        "bhs ver_panic\n" \
952
        "b .\n" \
953
        "b .\n" \
954
        "b .\n" \
955
        "27:\n" \
956
        "cmp r4, r5\n" \
957
        "cmp r4, r5\n" \
958
        "cmp r4, r5\n" \
959
        "blo 28f\n" \
960
        "bhs ver_panic\n" \
961
        "bhs ver_panic\n" \
962
        "bhs ver_panic\n" \
963
        "bhs ver_panic\n" \
964
        "b .\n" \
965
        "b .\n" \
966
        "b .\n" \
967
        "28:\n" \
968
        "cmp r6, r7\n" \
969
        "cmp r6, r7\n" \
970
        "cmp r6, r7\n" \
971
        "blo 29f\n" \
972
        "bhs ver_panic\n" \
973
        "bhs ver_panic\n" \
974
        "bhs ver_panic\n" \
975
        "bhs ver_panic\n" \
976
        "b .\n" \
977
        "b .\n" \
978
        "b .\n" \
979
        "29:\n" \
980
        "b end_check\n" \
981
        "ver_panic:\n" \
982
        "b .\n" \
983
        "b .\n" \
984
        "b .\n" \
985
        "b .\n" \
986
        "b .\n" \
987
        "b .\n" \
988
        "b .\n" \
989
        "b .\n" \
990
        "b .\n" \
991
        "b .\n" \
992
        "b .\n" \
993
        "end_check:\n" \
994
        "pop {r4, r5, r6, r7}\n" \
995
        : \
996
        : "r"(fb_ok) \
997
        : "r0", "r4", "r5", "r6", "r7", "lr", "cc", "memory" \
998
    )
999
1000
#elif defined(__ICCARM__) && defined(__IAR_SYSTEMS_ICC__)
1001
1002
#define VERIFY_VERSION_ALLOWED(fb_ok) \
1003
    do { \
1004
        __asm volatile( \
1005
            "push {r4, r5, r6, r7}\n" \
1006
            "mov r0, #0\n" \
1007
            "mov r4, #1\n" \
1008
            "mov r5, #0\n" \
1009
            "mov r6, #2\n" \
1010
            "mov r7, #0\n" \
1011
            "mov r0, #0\n" \
1012
            "mov r4, #1\n" \
1013
            "mov r5, #0\n" \
1014
            "mov r6, #2\n" \
1015
            "mov r7, #0\n" \
1016
            "mov r0, %0\n" \
1017
            "mov r4, %0\n" \
1018
            "cmp r0, #0\n" \
1019
            "cmp r0, #0\n" \
1020
            "cmp r0, #0\n" \
1021
            "beq 4f\n" \
1022
            "bne 6f\n" \
1023
            "bne 6f\n" \
1024
            "bne 6f\n" \
1025
            "bne 6f\n" \
1026
            "b .\n" \
1027
            "b .\n" \
1028
            "b .\n" \
1029
            "6:\n" \
1030
            "cmp r0, #1\n" \
1031
            "cmp r0, #1\n" \
1032
            "cmp r0, #1\n" \
1033
            "beq 4f\n" \
1034
            "bne 1f\n" \
1035
            "bne 1f\n" \
1036
            "bne 1f\n" \
1037
            "bne 1f\n" \
1038
            "b .\n" \
1039
            "b .\n" \
1040
            "b .\n" \
1041
            "4:\n" \
1042
            "cmp r4, #0\n" \
1043
            "cmp r4, #0\n" \
1044
            "cmp r4, #0\n" \
1045
            "beq 5f\n" \
1046
            "bne 7f\n" \
1047
            "bne 7f\n" \
1048
            "bne 7f\n" \
1049
            "bne 7f\n" \
1050
            "b .\n" \
1051
            "b .\n" \
1052
            "b .\n" \
1053
            "7:\n" \
1054
            "cmp r4, #1\n" \
1055
            "cmp r4, #1\n" \
1056
            "cmp r4, #1\n" \
1057
            "beq 5f\n" \
1058
            "bne 1f\n" \
1059
            "bne 1f\n" \
1060
            "bne 1f\n" \
1061
            "bne 1f\n" \
1062
            "b .\n" \
1063
            "b .\n" \
1064
            "b .\n" \
1065
            "5:\n" \
1066
            "cmp r0, #1\n" \
1067
            "cmp r0, #1\n" \
1068
            "cmp r0, #1\n" \
1069
            "beq 8f\n" \
1070
            "bne 1f\n" \
1071
            "bne 1f\n" \
1072
            "bne 1f\n" \
1073
            "bne 1f\n" \
1074
            "b .\n" \
1075
            "b .\n" \
1076
            "b .\n" \
1077
            "8:\n" \
1078
            "cmp r4, #1\n" \
1079
            "cmp r4, #1\n" \
1080
            "cmp r4, #1\n" \
1081
            "beq 9f\n" \
1082
            "bne 1f\n" \
1083
            "bne 1f\n" \
1084
            "bne 1f\n" \
1085
            "bne 1f\n" \
1086
            "b .\n" \
1087
            "b .\n" \
1088
            "b .\n" \
1089
            "9:\n" \
1090
            "cmp r0, r4\n" \
1091
            "cmp r0, r4\n" \
1092
            "cmp r0, r4\n" \
1093
            "beq 10f\n" \
1094
            "bne 1f\n" \
1095
            "bne 1f\n" \
1096
            "bne 1f\n" \
1097
            "bne 1f\n" \
1098
            "b .\n" \
1099
            "b .\n" \
1100
            "b .\n" \
1101
            "10:\n" \
1102
            "cmp r0, #1\n" \
1103
            "cmp r0, #1\n" \
1104
            "cmp r0, #1\n" \
1105
            "beq 11f\n" \
1106
            "bne 1f\n" \
1107
            "bne 1f\n" \
1108
            "bne 1f\n" \
1109
            "bne 1f\n" \
1110
            "b .\n" \
1111
            "b .\n" \
1112
            "b .\n" \
1113
            "11:\n" \
1114
            "b 2f\n" \
1115
            "b .\n" \
1116
            "b .\n" \
1117
            "b .\n" \
1118
            "1:\n" \
1119
            "mov r0, #1\n" \
1120
            "mov r0, #1\n" \
1121
            "mov r0, #1\n" \
1122
            "bl wolfBoot_get_image_version\n" \
1123
            "mov r5, r0\n" \
1124
            "mov r5, r0\n" \
1125
            "mov r5, r0\n" \
1126
            "mov r0, #1\n" \
1127
            "mov r0, #1\n" \
1128
            "mov r0, #1\n" \
1129
            "bl wolfBoot_get_image_version\n" \
1130
            "mov r7, r0\n" \
1131
            "mov r7, r0\n" \
1132
            "mov r7, r0\n" \
1133
            "cmp r5, r7\n" \
1134
            "cmp r5, r7\n" \
1135
            "cmp r5, r7\n" \
1136
            "beq 12f\n" \
1137
            "bne 3f\n" \
1138
            "bne 3f\n" \
1139
            "bne 3f\n" \
1140
            "bne 3f\n" \
1141
            "b .\n" \
1142
            "b .\n" \
1143
            "b .\n" \
1144
            "12:\n" \
1145
            "mov r0, #0\n" \
1146
            "mov r0, #0\n" \
1147
            "mov r0, #0\n" \
1148
            "bl wolfBoot_get_image_version\n" \
1149
            "mov r4, r0\n" \
1150
            "mov r4, r0\n" \
1151
            "mov r4, r0\n" \
1152
            "mov r0, #0\n" \
1153
            "mov r0, #0\n" \
1154
            "mov r0, #0\n" \
1155
            "bl wolfBoot_get_image_version\n" \
1156
            "mov r6, r0\n" \
1157
            "mov r6, r0\n" \
1158
            "mov r6, r0\n" \
1159
            "cmp r4, r6\n" \
1160
            "cmp r4, r6\n" \
1161
            "cmp r4, r6\n" \
1162
            "beq 13f\n" \
1163
            "bne 3f\n" \
1164
            "bne 3f\n" \
1165
            "bne 3f\n" \
1166
            "bne 3f\n" \
1167
            "b .\n" \
1168
            "b .\n" \
1169
            "b .\n" \
1170
            "13:\n" \
1171
            "mov r0, #0\n" \
1172
            "mov r0, #0\n" \
1173
            "mov r0, #0\n" \
1174
            "cmp r4, r5\n" \
1175
            "cmp r4, r5\n" \
1176
            "cmp r4, r5\n" \
1177
            "blo 14f\n" \
1178
            "bhs 3f\n" \
1179
            "bhs 3f\n" \
1180
            "bhs 3f\n" \
1181
            "bhs 3f\n" \
1182
            "b .\n" \
1183
            "b .\n" \
1184
            "b .\n" \
1185
            "14:\n" \
1186
            "cmp r6, r7\n" \
1187
            "cmp r6, r7\n" \
1188
            "cmp r6, r7\n" \
1189
            "blo 15f\n" \
1190
            "bhs 3f\n" \
1191
            "bhs 3f\n" \
1192
            "bhs 3f\n" \
1193
            "bhs 3f\n" \
1194
            "b .\n" \
1195
            "b .\n" \
1196
            "b .\n" \
1197
            "15:\n" \
1198
            "cmp r4, r5\n" \
1199
            "cmp r4, r5\n" \
1200
            "cmp r4, r5\n" \
1201
            "blo 16f\n" \
1202
            "bhs 3f\n" \
1203
            "bhs 3f\n" \
1204
            "bhs 3f\n" \
1205
            "bhs 3f\n" \
1206
            "b .\n" \
1207
            "b .\n" \
1208
            "b .\n" \
1209
            "16:\n" \
1210
            "cmp r6, r7\n" \
1211
            "cmp r6, r7\n" \
1212
            "cmp r6, r7\n" \
1213
            "blo 17f\n" \
1214
            "bhs 3f\n" \
1215
            "bhs 3f\n" \
1216
            "bhs 3f\n" \
1217
            "bhs 3f\n" \
1218
            "b .\n" \
1219
            "b .\n" \
1220
            "b .\n" \
1221
            "17:\n" \
1222
            "b 2f\n" \
1223
            "b .\n" \
1224
            "b .\n" \
1225
            "b .\n" \
1226
            "3:\n" \
1227
            "b .\n" \
1228
            "b .\n" \
1229
            "b .\n" \
1230
            "b .\n" \
1231
            "b .\n" \
1232
            "b .\n" \
1233
            "b .\n" \
1234
            "b .\n" \
1235
            "2:\n" \
1236
            "pop {r4, r5, r6, r7}\n" \
1237
            : /* No output operands */ \
1238
            : "r"(fb_ok) /* Input operands */ \
1239
            : "r0", "r4", "r5", "r6", "r7" /* Clobbered registers */ \
1240
        ); \
1241
    } while (0)
1242
#endif
1243
1244
1245
#define CONFIRM_MASK_VALID(id, mask) \
1246
    asm volatile("mov r1, %0" :: "r"(id):"r1");  \
1247
    /* id &= 0x0F */ \
1248
    asm volatile("and.w r1, r1, #15":::"r1"); \
1249
    asm volatile("mov r0, %0" :: "r"(mask):"r0"); \
1250
    asm volatile("movs r2, #1":::"r2"); \
1251
    asm volatile("lsls r2, r1":::"r2","cc"); \
1252
    asm volatile("ands r2, r0":::"r2","cc"); \
1253
    asm volatile("movs r0, #1":::"cc"); \
1254
    asm volatile("lsls r0, r1":::"r0","cc"); \
1255
    asm volatile("cmp r0, r2"); \
1256
    asm volatile("cmp r0, r2"); \
1257
    asm volatile("cmp r0, r2"); \
1258
    asm volatile("bne ."); \
1259
    asm volatile("mov r0, %0" :: "r"(mask)); \
1260
    asm volatile("movs r2, #1":::"r2"); \
1261
    asm volatile("lsls r2, r1":::"r2", "cc"); \
1262
    asm volatile("ands r2, r0":::"r2", "cc"); \
1263
    asm volatile("movs r0, #1":::"r0"); \
1264
    asm volatile("lsls r0, r1":::"r0", "cc"); \
1265
    asm volatile("cmp r0, r2":::"cc"); \
1266
    asm volatile("cmp r0, r2":::"cc"); \
1267
    asm volatile("cmp r0, r2":::"cc"); \
1268
    asm volatile("bne ."); \
1269
    asm volatile("mov r0, %0" :: "r"(mask):"r0"); \
1270
    asm volatile("movs r2, #1":::"r2"); \
1271
    asm volatile("lsls r2, r1":::"r2", "cc"); \
1272
    asm volatile("ands r2, r0":::"r2", "cc"); \
1273
    asm volatile("movs r0, #1":::"r0"); \
1274
    asm volatile("lsls r0, r1":::"r0", "cc"); \
1275
    asm volatile("cmp r0, r2":::"cc"); \
1276
    asm volatile("cmp r0, r2":::"cc"); \
1277
    asm volatile("cmp r0, r2":::"cc"); \
1278
    asm volatile("bne ."); \
1279
1280
#else
1281
1282
struct wolfBoot_image {
1283
    uint8_t *hdr;
1284
#ifdef EXT_FLASH
1285
    uint8_t *hdr_cache;
1286
#endif
1287
    uint8_t *trailer;
1288
    uint8_t *sha_hash;
1289
    uint8_t *fw_base;
1290
    uint32_t fw_size;
1291
    uint8_t part;
1292
    uint8_t hdr_ok : 1;
1293
    uint8_t signature_ok : 1;
1294
    uint8_t sha_ok : 1;
1295
    uint8_t not_ext : 1; /* image is no longer external */
1296
};
1297
1298
1299
/* do not warn if this is not used */
1300
static void UNUSEDFUNCTION wolfBoot_image_confirm_signature_ok(
1301
    struct wolfBoot_image *img)
1302
0
{
1303
0
    img->signature_ok = 1;
1304
0
}
1305
static void UNUSEDFUNCTION wolfBoot_image_clear_signature_ok(
1306
    struct wolfBoot_image *img)
1307
0
{
1308
0
  img->signature_ok = 0;
1309
0
}
1310
1311
#define likely(x) (x)
1312
#define unlikely(x) (x)
1313
1314
#define VERIFY_FN(img,p_res,fn,...) {\
1315
    int ret = fn(__VA_ARGS__); \
1316
    if ((ret == 0) && (*p_res == 1)) \
1317
        wolfBoot_image_confirm_signature_ok(img); \
1318
    }
1319
1320
#define RSA_VERIFY_FN(ret,fn,...) \
1321
    ret = fn(__VA_ARGS__);
1322
1323
#define RSA_VERIFY_HASH(img,digest) \
1324
    if (image_CT_compare(img->sha_hash, digest, WOLFBOOT_SHA_DIGEST_SIZE) == 0) \
1325
        wolfBoot_image_confirm_signature_ok(img);
1326
1327
#define RSA_PSS_VERIFY_HASH(img, pss_data, pss_data_sz, hash_type) \
1328
    if (wc_RsaPSS_CheckPadding(img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, \
1329
            pss_data, pss_data_sz, hash_type) == 0) \
1330
        wolfBoot_image_confirm_signature_ok(img);
1331
1332
#define PART_SANITY_CHECK(p) \
1333
    if (((p)->hdr_ok != 1) || ((p)->sha_ok != 1) || ((p)->signature_ok != 1)) \
1334
        wolfBoot_panic()
1335
1336
#define CONFIRM_MASK_VALID(id, mask) \
1337
    if ((mask & (1UL << id)) != (1UL << id)) \
1338
        wolfBoot_panic()
1339
1340
#define VERIFY_VERSION_ALLOWED(fb_ok) do{} while(0) /* okay */
1341
1342
#endif
1343
1344
/* Defined in image.c */
1345
int image_CT_compare(const uint8_t *expected, const uint8_t *actual,
1346
    uint32_t len);
1347
int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part);
1348
#ifdef EXT_FLASH
1349
int wolfBoot_open_image_external(struct wolfBoot_image* img, uint8_t part, uint8_t* addr);
1350
#endif
1351
int wolfBoot_open_image_address(struct wolfBoot_image* img, uint8_t* image);
1352
#ifdef WOLFBOOT_SELF_HEADER
1353
int wolfBoot_open_self(struct wolfBoot_image *img);
1354
int wolfBoot_open_self_address(struct wolfBoot_image *img, uint8_t *hdr,
1355
    uint8_t *image);
1356
#endif
1357
int wolfBoot_verify_integrity(struct wolfBoot_image *img);
1358
int wolfBoot_verify_authenticity(struct wolfBoot_image *img);
1359
int wolfBoot_set_partition_state(uint8_t part, uint8_t newst);
1360
int wolfBoot_get_update_sector_flag(uint16_t sector, uint8_t *flag);
1361
int wolfBoot_set_update_sector_flag(uint16_t sector, uint8_t newflag);
1362
1363
#ifdef WOLFBOOT_ELF_FLASH_SCATTER
1364
/* Support for ELF scatter/gather format */
1365
int wolfBoot_load_flash_image_elf(int part, unsigned long* entry_out,
1366
                                  int ext_flash);
1367
int wolfBoot_check_flash_image_elf(uint8_t part, unsigned long* entry_out);
1368
#endif
1369
1370
uint8_t* wolfBoot_peek_image(struct wolfBoot_image *img, uint32_t offset,
1371
        uint32_t* sz);
1372
1373
/* get header type for image */
1374
uint16_t wolfBoot_get_header(struct wolfBoot_image *img, uint16_t type, uint8_t **ptr);
1375
1376
/* Find the key slot ID based on the SHA hash of the key. */
1377
int keyslot_id_by_sha(const uint8_t *hint);
1378
1379
#ifdef EXT_FLASH
1380
# ifdef PART_BOOT_EXT
1381
#  define BOOT_EXT 1
1382
# else
1383
#  define BOOT_EXT 0
1384
# endif
1385
# ifdef PART_UPDATE_EXT
1386
#  define UPDATE_EXT 1
1387
# else
1388
#  define UPDATE_EXT 0
1389
# endif
1390
# ifdef PART_SWAP_EXT
1391
#  define SWAP_EXT 1
1392
# else
1393
#  define SWAP_EXT 0
1394
# endif
1395
# if defined(WOLFBOOT_SELF_HEADER_EXT)
1396
#  define SELF_HEADER_EXT 1
1397
# else
1398
#  define SELF_HEADER_EXT 0
1399
# endif
1400
# define PARTN_IS_EXT(pn) \
1401
    ((pn == PART_BOOT || pn == PART_DTS_BOOT) ? BOOT_EXT: \
1402
        ((pn == PART_UPDATE || pn == PART_DTS_UPDATE) ? UPDATE_EXT : \
1403
            ((pn == PART_SWAP) ? SWAP_EXT : \
1404
                 ((pn == PART_SELF) ? SELF_HEADER_EXT : 0))))
1405
# define PART_IS_EXT(x) (!(x)->not_ext) && PARTN_IS_EXT(((x)->part))
1406
1407
1408
#if defined(EXT_ENCRYPTED) && (defined(__WOLFBOOT) || defined(UNIT_TEST))
1409
#define ext_flash_check_write ext_flash_encrypt_write
1410
#define ext_flash_check_read ext_flash_decrypt_read
1411
#else
1412
#define ext_flash_check_write ext_flash_write
1413
#define ext_flash_check_read ext_flash_read
1414
#endif
1415
1416
static inline int wb_flash_erase(struct wolfBoot_image *img, uint32_t off,
1417
    uint32_t size)
1418
{
1419
    if (PART_IS_EXT(img))
1420
        return ext_flash_erase((uintptr_t)(img->hdr) + off, size);
1421
    else
1422
        return hal_flash_erase((uintptr_t)(img->hdr) + off, size);
1423
}
1424
1425
static inline int wb_flash_write(struct wolfBoot_image *img, uint32_t off,
1426
    const void *data, uint32_t size)
1427
{
1428
    if (PART_IS_EXT(img))
1429
        return ext_flash_check_write((uintptr_t)(img->hdr) + off, data, size);
1430
    else
1431
        return hal_flash_write((uintptr_t)(img->hdr) + off, data, size);
1432
}
1433
1434
static inline int wb_flash_write_verify_word(struct wolfBoot_image *img,
1435
    uint32_t off, uint32_t word)
1436
{
1437
    int ret;
1438
    volatile uint32_t copy;
1439
    if (PART_IS_EXT(img))
1440
    {
1441
        ext_flash_check_read((uintptr_t)(img->hdr) + off, (void *)&copy,
1442
            sizeof(uint32_t));
1443
        while (copy != word) {
1444
            ret = ext_flash_check_write((uintptr_t)(img->hdr) + off,
1445
                (void *)&word, sizeof(uint32_t));
1446
            if (ret < 0)
1447
                return ret;
1448
            ext_flash_check_read((uintptr_t)(img->hdr) + off, (void *)&copy,
1449
                sizeof(uint32_t));
1450
        }
1451
    } else {
1452
        volatile uint32_t *pcopy = (volatile uint32_t*)(img->hdr + off);
1453
        while(*pcopy != word) {
1454
            hal_flash_write((uintptr_t)pcopy, (void *)&word, sizeof(uint32_t));
1455
        }
1456
    }
1457
    return 0;
1458
}
1459
1460
1461
#else
1462
1463
# define SWAP_EXT (0)
1464
# define BOOT_EXT (0)
1465
# define UPDATE_EXT (0)
1466
# define PART_IS_EXT(x) (0)
1467
# define PARTN_IS_EXT(x) (0)
1468
# define wb_flash_erase(im, of, siz) \
1469
    hal_flash_erase(((uintptr_t)(((im)->hdr)) + of), siz)
1470
# define wb_flash_write(im, of, dat, siz) \
1471
    hal_flash_write(((uintptr_t)((im)->hdr)) + of, dat, siz)
1472
1473
#endif /* EXT_FLASH */
1474
1475
/* -- Image Formats -- */
1476
/* Legacy U-Boot Image */
1477
#ifdef BIG_ENDIAN_ORDER
1478
#define UBOOT_IMG_HDR_MAGIC 0x27051956UL
1479
#else
1480
#define UBOOT_IMG_HDR_MAGIC 0x56190527UL
1481
#endif
1482
#define UBOOT_IMG_HDR_SZ    64
1483
1484
/* --- Flattened Device Tree Blob */
1485
#ifdef MMU
1486
#include "fdt.h"
1487
#endif
1488
1489
#ifndef EXT_ENCRYPTED
1490
#define WOLFBOOT_MAX_SPACE (WOLFBOOT_PARTITION_SIZE - \
1491
    (TRAILER_SKIP + sizeof(uint32_t) + \
1492
    ((WOLFBOOT_PARTITION_SIZE + 1) / (WOLFBOOT_SECTOR_SIZE * 8))))
1493
#else
1494
#define WOLFBOOT_MAX_SPACE (WOLFBOOT_PARTITION_SIZE - ENCRYPT_TMP_SECRET_OFFSET)
1495
#endif
1496
1497
#ifdef __cplusplus
1498
}
1499
#endif
1500
1501
#endif /* !IMAGE_H */