blob: 2bea140012a65bba088825ec92e789aec5f70c70 [file] [log] [blame]
David Brownde7729e2017-01-09 10:41:35 -07001/* Run the boot image. */
2
Fabio Utzig9b0ee902017-11-23 19:49:00 -02003#include <assert.h>
David Brownde7729e2017-01-09 10:41:35 -07004#include <setjmp.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <bootutil/bootutil.h>
9#include <bootutil/image.h>
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +020010
11#include <flash_map_backend/flash_map_backend.h>
David Brownde7729e2017-01-09 10:41:35 -070012
David Brownd2b18532017-07-12 09:51:31 -060013#include "../../../boot/bootutil/src/bootutil_priv.h"
Fabio Utzig57c40f72017-12-12 21:48:30 -020014#include "bootsim.h"
David Brownde7729e2017-01-09 10:41:35 -070015
Fabio Utzig1e48b912018-09-18 09:04:18 -030016#ifdef MCUBOOT_ENCRYPT_RSA
17#include "mbedtls/rsa.h"
18#include "mbedtls/asn1.h"
19#endif
20
21#ifdef MCUBOOT_ENCRYPT_KW
22#include "mbedtls/nist_kw.h"
23#endif
24
David Brown54b77792017-05-05 09:40:01 -060025#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_ERROR
David Brown75fd5dc2017-05-04 09:04:47 -060026#include <bootutil/bootutil_log.h>
27
David Vincze6c9b4162019-03-21 19:18:08 +010028#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
29
Fabio Utzig8000e322019-08-05 08:14:32 -030030struct area_desc;
31extern struct area_desc *sim_get_flash_areas(void);
32extern void sim_set_flash_areas(struct area_desc *areas);
33extern void sim_reset_flash_areas(void);
34
35struct sim_context;
36extern struct sim_context *sim_get_context(void);
37extern void sim_set_context(struct sim_context *ctx);
38extern void sim_reset_context(void);
39
Fabio Utzig99dfc782018-10-15 15:10:55 -070040extern int sim_flash_erase(uint8_t flash_id, uint32_t offset, uint32_t size);
41extern int sim_flash_read(uint8_t flash_id, uint32_t offset, uint8_t *dest,
42 uint32_t size);
43extern int sim_flash_write(uint8_t flash_id, uint32_t offset, const uint8_t *src,
44 uint32_t size);
Fabio Utzig1edb7882020-10-04 11:51:53 -030045extern uint16_t sim_flash_align(uint8_t flash_id);
Fabio Utzig73ffc442018-10-24 21:49:09 -030046extern uint8_t sim_flash_erased_val(uint8_t flash_id);
David Brownde7729e2017-01-09 10:41:35 -070047
Fabio Utzig8000e322019-08-05 08:14:32 -030048struct sim_context {
49 int flash_counter;
50 int jumped;
51 uint8_t c_asserts;
52 uint8_t c_catch_asserts;
53 jmp_buf boot_jmpbuf;
54};
David Brownde7729e2017-01-09 10:41:35 -070055
Fabio Utzig1e48b912018-09-18 09:04:18 -030056#ifdef MCUBOOT_ENCRYPT_RSA
57static int
58parse_pubkey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
59{
60 int rc;
61 size_t len;
62
63 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
64 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
65 return -1;
66 }
67
68 if (*p + len != end) {
69 return -2;
70 }
71
72 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
73 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
74 return -3;
75 }
76
77 *p += len;
78
79 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
80 return -4;
81 }
82
83 if (**p != MBEDTLS_ASN1_PRIMITIVE) {
84 return -5;
85 }
86
87 *p += 1;
88
89 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
90 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
91 return -6;
92 }
93
94 if (mbedtls_asn1_get_mpi(p, end, &ctx->N) != 0) {
95 return -7;
96 }
97
98 if (mbedtls_asn1_get_mpi(p, end, &ctx->E) != 0) {
99 return -8;
100 }
101
102 ctx->len = mbedtls_mpi_size(&ctx->N);
103
104 if (*p != end) {
105 return -9;
106 }
107
108 if (mbedtls_rsa_check_pubkey(ctx) != 0) {
109 return -10;
110 }
111
112 return 0;
113}
114
115static int
116fake_rng(void *p_rng, unsigned char *output, size_t len)
117{
118 size_t i;
119
120 (void)p_rng;
121 for (i = 0; i < len; i++) {
122 output[i] = (char)i;
123 }
124
125 return 0;
126}
127#endif
128
129int mbedtls_platform_set_calloc_free(void * (*calloc_func)(size_t, size_t),
130 void (*free_func)(void *));
131
132int rsa_oaep_encrypt_(const uint8_t *pubkey, unsigned pubkey_len,
133 const uint8_t *seckey, unsigned seckey_len,
134 uint8_t *encbuf)
135{
136#ifdef MCUBOOT_ENCRYPT_RSA
137 mbedtls_rsa_context ctx;
138 uint8_t *cp;
139 uint8_t *cpend;
140 int rc;
141
142 mbedtls_platform_set_calloc_free(calloc, free);
143
144 mbedtls_rsa_init(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
145
146 cp = (uint8_t *)pubkey;
147 cpend = cp + pubkey_len;
148
149 rc = parse_pubkey(&ctx, &cp, cpend);
150 if (rc) {
151 goto done;
152 }
153
154 rc = mbedtls_rsa_rsaes_oaep_encrypt(&ctx, fake_rng, NULL, MBEDTLS_RSA_PUBLIC,
155 NULL, 0, seckey_len, seckey, encbuf);
156 if (rc) {
157 goto done;
158 }
159
160done:
161 mbedtls_rsa_free(&ctx);
162 return rc;
163
164#else
165 (void)pubkey;
166 (void)pubkey_len;
167 (void)seckey;
168 (void)seckey_len;
169 (void)encbuf;
170 return 0;
171#endif
172}
173
174int kw_encrypt_(const uint8_t *kek, const uint8_t *seckey, uint8_t *encbuf)
175{
176#ifdef MCUBOOT_ENCRYPT_KW
177 mbedtls_nist_kw_context kw;
178 size_t olen;
179 int rc;
180
181 mbedtls_platform_set_calloc_free(calloc, free);
182
183 mbedtls_nist_kw_init(&kw);
184
185 rc = mbedtls_nist_kw_setkey(&kw, MBEDTLS_CIPHER_ID_AES, kek, 128, 1);
186 if (rc) {
187 goto done;
188 }
189
190 rc = mbedtls_nist_kw_wrap(&kw, MBEDTLS_KW_MODE_KW, seckey, 16, encbuf,
191 &olen, 24);
192
193done:
194 mbedtls_nist_kw_free(&kw);
195 return rc;
196
197#else
198 (void)kek;
199 (void)seckey;
200 (void)encbuf;
201 return 0;
202#endif
203}
204
Fabio Utzig1edb7882020-10-04 11:51:53 -0300205uint16_t flash_area_align(const struct flash_area *area)
David Brown5acda262017-01-23 15:42:19 -0700206{
Fabio Utzig73ffc442018-10-24 21:49:09 -0300207 return sim_flash_align(area->fa_device_id);
David Brown5acda262017-01-23 15:42:19 -0700208}
209
Fabio Utzigea0290b2018-08-09 14:23:01 -0300210uint8_t flash_area_erased_val(const struct flash_area *area)
211{
Fabio Utzig73ffc442018-10-24 21:49:09 -0300212 return sim_flash_erased_val(area->fa_device_id);
Fabio Utzigea0290b2018-08-09 14:23:01 -0300213}
214
David Brownde7729e2017-01-09 10:41:35 -0700215struct area {
David Brown7ad80882017-06-20 15:30:36 -0600216 struct flash_area whole;
217 struct flash_area *areas;
218 uint32_t num_areas;
219 uint8_t id;
David Brownde7729e2017-01-09 10:41:35 -0700220};
221
222struct area_desc {
David Brown7ad80882017-06-20 15:30:36 -0600223 struct area slots[16];
224 uint32_t num_slots;
David Brownde7729e2017-01-09 10:41:35 -0700225};
226
Fabio Utzig8000e322019-08-05 08:14:32 -0300227int invoke_boot_go(struct sim_context *ctx, struct area_desc *adesc)
David Brownde7729e2017-01-09 10:41:35 -0700228{
David Brown7ad80882017-06-20 15:30:36 -0600229 int res;
230 struct boot_rsp rsp;
Fabio Utzig8000e322019-08-05 08:14:32 -0300231 struct boot_loader_state *state;
David Brownde7729e2017-01-09 10:41:35 -0700232
David Brown641af452021-02-19 12:16:48 -0700233#if defined(MCUBOOT_SIGN_RSA) || \
Fabio Utzig6c553d62021-05-06 19:56:18 -0300234 (defined(MCUBOOT_SIGN_EC256) && defined(MCUBOOT_USE_MBED_TLS)) ||\
235 (defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS))
Fabio Utzigb04afa92018-09-12 15:27:04 -0300236 mbedtls_platform_set_calloc_free(calloc, free);
237#endif
David Brown7e701d82017-07-11 13:24:25 -0600238
Fabio Utzig8000e322019-08-05 08:14:32 -0300239 // NOTE: cleared internally by context_boot_go
240 state = malloc(sizeof(struct boot_loader_state));
241
242 sim_set_flash_areas(adesc);
243 sim_set_context(ctx);
244
245 if (setjmp(ctx->boot_jmpbuf) == 0) {
246 res = context_boot_go(state, &rsp);
247 sim_reset_flash_areas();
248 sim_reset_context();
249 free(state);
David Brown7ad80882017-06-20 15:30:36 -0600250 /* printf("boot_go off: %d (0x%08x)\n", res, rsp.br_image_off); */
251 return res;
252 } else {
Fabio Utzig8000e322019-08-05 08:14:32 -0300253 sim_reset_flash_areas();
254 sim_reset_context();
255 free(state);
David Brown7ad80882017-06-20 15:30:36 -0600256 return -0x13579;
257 }
David Brownde7729e2017-01-09 10:41:35 -0700258}
259
David Brownde7729e2017-01-09 10:41:35 -0700260void *os_malloc(size_t size)
261{
David Brown7ad80882017-06-20 15:30:36 -0600262 // printf("os_malloc 0x%x bytes\n", size);
263 return malloc(size);
David Brownde7729e2017-01-09 10:41:35 -0700264}
265
Fabio Utzigb0f04732019-07-31 09:49:19 -0300266int flash_area_id_from_multi_image_slot(int image_index, int slot)
David Brownde7729e2017-01-09 10:41:35 -0700267{
Fabio Utzigb0f04732019-07-31 09:49:19 -0300268 switch (slot) {
269 case 0: return FLASH_AREA_IMAGE_PRIMARY(image_index);
270 case 1: return FLASH_AREA_IMAGE_SECONDARY(image_index);
271 case 2: return FLASH_AREA_IMAGE_SCRATCH;
David Vincze6c9b4162019-03-21 19:18:08 +0100272 }
273
274 printf("Image flash area ID not found\n");
275 return -1; /* flash_area_open will fail on that */
David Brownde7729e2017-01-09 10:41:35 -0700276}
277
278int flash_area_open(uint8_t id, const struct flash_area **area)
279{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200280 uint32_t i;
Fabio Utzig8000e322019-08-05 08:14:32 -0300281 struct area_desc *flash_areas;
David Brownde7729e2017-01-09 10:41:35 -0700282
Fabio Utzig8000e322019-08-05 08:14:32 -0300283 flash_areas = sim_get_flash_areas();
David Brown7ad80882017-06-20 15:30:36 -0600284 for (i = 0; i < flash_areas->num_slots; i++) {
285 if (flash_areas->slots[i].id == id)
286 break;
287 }
288 if (i == flash_areas->num_slots) {
289 printf("Unsupported area\n");
290 abort();
291 }
David Brownde7729e2017-01-09 10:41:35 -0700292
David Brown7ad80882017-06-20 15:30:36 -0600293 /* Unsure if this is right, just returning the first area. */
294 *area = &flash_areas->slots[i].whole;
295 return 0;
David Brownde7729e2017-01-09 10:41:35 -0700296}
297
298void flash_area_close(const struct flash_area *area)
299{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200300 (void)area;
David Brownde7729e2017-01-09 10:41:35 -0700301}
302
303/*
304 * Read/write/erase. Offset is relative from beginning of flash area.
305 */
306int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
David Brown7ad80882017-06-20 15:30:36 -0600307 uint32_t len)
David Brownde7729e2017-01-09 10:41:35 -0700308{
Fabio Utzig6fa2d402019-12-10 14:34:18 -0300309 BOOT_LOG_SIM("%s: area=%d, off=%x, len=%x",
David Brown7ad80882017-06-20 15:30:36 -0600310 __func__, area->fa_id, off, len);
Fabio Utzig99dfc782018-10-15 15:10:55 -0700311 return sim_flash_read(area->fa_device_id, area->fa_off + off, dst, len);
David Brownde7729e2017-01-09 10:41:35 -0700312}
313
314int flash_area_write(const struct flash_area *area, uint32_t off, const void *src,
David Brown7ad80882017-06-20 15:30:36 -0600315 uint32_t len)
David Brownde7729e2017-01-09 10:41:35 -0700316{
Fabio Utzig6fa2d402019-12-10 14:34:18 -0300317 BOOT_LOG_SIM("%s: area=%d, off=%x, len=%x", __func__,
David Brown7ad80882017-06-20 15:30:36 -0600318 area->fa_id, off, len);
Fabio Utzig8000e322019-08-05 08:14:32 -0300319 struct sim_context *ctx = sim_get_context();
320 if (--(ctx->flash_counter) == 0) {
321 ctx->jumped++;
322 longjmp(ctx->boot_jmpbuf, 1);
Fabio Utzig99dfc782018-10-15 15:10:55 -0700323 }
324 return sim_flash_write(area->fa_device_id, area->fa_off + off, src, len);
David Brownde7729e2017-01-09 10:41:35 -0700325}
326
327int flash_area_erase(const struct flash_area *area, uint32_t off, uint32_t len)
328{
Fabio Utzig6fa2d402019-12-10 14:34:18 -0300329 BOOT_LOG_SIM("%s: area=%d, off=%x, len=%x", __func__,
David Brown7ad80882017-06-20 15:30:36 -0600330 area->fa_id, off, len);
Fabio Utzig8000e322019-08-05 08:14:32 -0300331 struct sim_context *ctx = sim_get_context();
332 if (--(ctx->flash_counter) == 0) {
333 ctx->jumped++;
334 longjmp(ctx->boot_jmpbuf, 1);
Fabio Utzig99dfc782018-10-15 15:10:55 -0700335 }
336 return sim_flash_erase(area->fa_device_id, area->fa_off + off, len);
David Brownde7729e2017-01-09 10:41:35 -0700337}
338
339int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret)
340{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200341 uint32_t i;
David Brown7ad80882017-06-20 15:30:36 -0600342 struct area *slot;
Fabio Utzig8000e322019-08-05 08:14:32 -0300343 struct area_desc *flash_areas;
David Brownde7729e2017-01-09 10:41:35 -0700344
Fabio Utzig8000e322019-08-05 08:14:32 -0300345 flash_areas = sim_get_flash_areas();
David Brown7ad80882017-06-20 15:30:36 -0600346 for (i = 0; i < flash_areas->num_slots; i++) {
347 if (flash_areas->slots[i].id == idx)
348 break;
349 }
350 if (i == flash_areas->num_slots) {
351 printf("Unsupported area\n");
352 abort();
353 }
David Brownde7729e2017-01-09 10:41:35 -0700354
David Brown7ad80882017-06-20 15:30:36 -0600355 slot = &flash_areas->slots[i];
David Brownde7729e2017-01-09 10:41:35 -0700356
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200357 if (slot->num_areas > (uint32_t)*cnt) {
David Brown7ad80882017-06-20 15:30:36 -0600358 printf("Too many areas in slot\n");
359 abort();
360 }
David Brownde7729e2017-01-09 10:41:35 -0700361
David Brown7ad80882017-06-20 15:30:36 -0600362 *cnt = slot->num_areas;
363 memcpy(ret, slot->areas, slot->num_areas * sizeof(struct flash_area));
David Brownde7729e2017-01-09 10:41:35 -0700364
David Brown7ad80882017-06-20 15:30:36 -0600365 return 0;
David Brownde7729e2017-01-09 10:41:35 -0700366}
367
David Brown60399f62017-05-11 10:20:34 -0600368int flash_area_get_sectors(int fa_id, uint32_t *count,
369 struct flash_sector *sectors)
370{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200371 uint32_t i;
David Brown7ad80882017-06-20 15:30:36 -0600372 struct area *slot;
Fabio Utzig8000e322019-08-05 08:14:32 -0300373 struct area_desc *flash_areas;
David Brown60399f62017-05-11 10:20:34 -0600374
Fabio Utzig8000e322019-08-05 08:14:32 -0300375 flash_areas = sim_get_flash_areas();
David Brown7ad80882017-06-20 15:30:36 -0600376 for (i = 0; i < flash_areas->num_slots; i++) {
377 if (flash_areas->slots[i].id == fa_id)
378 break;
379 }
380 if (i == flash_areas->num_slots) {
381 printf("Unsupported area\n");
382 abort();
383 }
David Brown60399f62017-05-11 10:20:34 -0600384
David Brown7ad80882017-06-20 15:30:36 -0600385 slot = &flash_areas->slots[i];
David Brown60399f62017-05-11 10:20:34 -0600386
David Brown7ad80882017-06-20 15:30:36 -0600387 if (slot->num_areas > *count) {
388 printf("Too many areas in slot\n");
389 abort();
390 }
David Brown60399f62017-05-11 10:20:34 -0600391
David Brown7ad80882017-06-20 15:30:36 -0600392 for (i = 0; i < slot->num_areas; i++) {
393 sectors[i].fs_off = slot->areas[i].fa_off -
394 slot->whole.fa_off;
395 sectors[i].fs_size = slot->areas[i].fa_size;
396 }
397 *count = slot->num_areas;
David Brown60399f62017-05-11 10:20:34 -0600398
David Brown7ad80882017-06-20 15:30:36 -0600399 return 0;
David Brown60399f62017-05-11 10:20:34 -0600400}
Fabio Utzig9b0ee902017-11-23 19:49:00 -0200401
Fabio Utzigb0f04732019-07-31 09:49:19 -0300402int flash_area_id_to_multi_image_slot(int image_index, int area_id)
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100403{
Fabio Utzigb0f04732019-07-31 09:49:19 -0300404 if (area_id == FLASH_AREA_IMAGE_PRIMARY(image_index)) {
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100405 return 0;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100406 }
Fabio Utzigb0f04732019-07-31 09:49:19 -0300407 if (area_id == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
David Vinczeb75c12a2019-03-22 14:58:33 +0100408 return 1;
409 }
410
411 printf("Unsupported image area ID\n");
412 abort();
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100413}
414
Fabio Utzig9b0ee902017-11-23 19:49:00 -0200415void sim_assert(int x, const char *assertion, const char *file, unsigned int line, const char *function)
416{
417 if (!(x)) {
Fabio Utzig8000e322019-08-05 08:14:32 -0300418 struct sim_context *ctx = sim_get_context();
419 if (ctx->c_catch_asserts) {
420 ctx->c_asserts++;
Fabio Utzig9b0ee902017-11-23 19:49:00 -0200421 } else {
422 BOOT_LOG_ERR("%s:%d: %s: Assertion `%s' failed.", file, line, function, assertion);
423
424 /* NOTE: if the assert below is triggered, the place where it was originally
425 * asserted is printed by the message above...
426 */
427 assert(x);
428 }
429 }
430}
David Browne0bb1f92019-10-01 15:57:01 -0600431
432uint32_t boot_max_align(void)
433{
434 return BOOT_MAX_ALIGN;
435}
David Brown2b8a6952019-10-01 16:14:53 -0600436
437uint32_t boot_magic_sz(void)
438{
439 return BOOT_MAGIC_SZ;
440}