blob: 32f43c2d32bd40368d0d59ea164ffdd3f3ea20d7 [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 Utzig99dfc782018-10-15 15:10:55 -070030extern int sim_flash_erase(uint8_t flash_id, uint32_t offset, uint32_t size);
31extern int sim_flash_read(uint8_t flash_id, uint32_t offset, uint8_t *dest,
32 uint32_t size);
33extern int sim_flash_write(uint8_t flash_id, uint32_t offset, const uint8_t *src,
34 uint32_t size);
Fabio Utzig73ffc442018-10-24 21:49:09 -030035extern uint8_t sim_flash_align(uint8_t flash_id);
36extern uint8_t sim_flash_erased_val(uint8_t flash_id);
David Brownde7729e2017-01-09 10:41:35 -070037
David Brownde7729e2017-01-09 10:41:35 -070038static jmp_buf boot_jmpbuf;
39int flash_counter;
40
41int jumped = 0;
Fabio Utzig9b0ee902017-11-23 19:49:00 -020042uint8_t c_asserts = 0;
43uint8_t c_catch_asserts = 0;
David Brownde7729e2017-01-09 10:41:35 -070044
Fabio Utzig1e48b912018-09-18 09:04:18 -030045#ifdef MCUBOOT_ENCRYPT_RSA
46static int
47parse_pubkey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
48{
49 int rc;
50 size_t len;
51
52 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
53 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
54 return -1;
55 }
56
57 if (*p + len != end) {
58 return -2;
59 }
60
61 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
62 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
63 return -3;
64 }
65
66 *p += len;
67
68 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
69 return -4;
70 }
71
72 if (**p != MBEDTLS_ASN1_PRIMITIVE) {
73 return -5;
74 }
75
76 *p += 1;
77
78 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
79 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
80 return -6;
81 }
82
83 if (mbedtls_asn1_get_mpi(p, end, &ctx->N) != 0) {
84 return -7;
85 }
86
87 if (mbedtls_asn1_get_mpi(p, end, &ctx->E) != 0) {
88 return -8;
89 }
90
91 ctx->len = mbedtls_mpi_size(&ctx->N);
92
93 if (*p != end) {
94 return -9;
95 }
96
97 if (mbedtls_rsa_check_pubkey(ctx) != 0) {
98 return -10;
99 }
100
101 return 0;
102}
103
104static int
105fake_rng(void *p_rng, unsigned char *output, size_t len)
106{
107 size_t i;
108
109 (void)p_rng;
110 for (i = 0; i < len; i++) {
111 output[i] = (char)i;
112 }
113
114 return 0;
115}
116#endif
117
118int mbedtls_platform_set_calloc_free(void * (*calloc_func)(size_t, size_t),
119 void (*free_func)(void *));
120
121int rsa_oaep_encrypt_(const uint8_t *pubkey, unsigned pubkey_len,
122 const uint8_t *seckey, unsigned seckey_len,
123 uint8_t *encbuf)
124{
125#ifdef MCUBOOT_ENCRYPT_RSA
126 mbedtls_rsa_context ctx;
127 uint8_t *cp;
128 uint8_t *cpend;
129 int rc;
130
131 mbedtls_platform_set_calloc_free(calloc, free);
132
133 mbedtls_rsa_init(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
134
135 cp = (uint8_t *)pubkey;
136 cpend = cp + pubkey_len;
137
138 rc = parse_pubkey(&ctx, &cp, cpend);
139 if (rc) {
140 goto done;
141 }
142
143 rc = mbedtls_rsa_rsaes_oaep_encrypt(&ctx, fake_rng, NULL, MBEDTLS_RSA_PUBLIC,
144 NULL, 0, seckey_len, seckey, encbuf);
145 if (rc) {
146 goto done;
147 }
148
149done:
150 mbedtls_rsa_free(&ctx);
151 return rc;
152
153#else
154 (void)pubkey;
155 (void)pubkey_len;
156 (void)seckey;
157 (void)seckey_len;
158 (void)encbuf;
159 return 0;
160#endif
161}
162
163int kw_encrypt_(const uint8_t *kek, const uint8_t *seckey, uint8_t *encbuf)
164{
165#ifdef MCUBOOT_ENCRYPT_KW
166 mbedtls_nist_kw_context kw;
167 size_t olen;
168 int rc;
169
170 mbedtls_platform_set_calloc_free(calloc, free);
171
172 mbedtls_nist_kw_init(&kw);
173
174 rc = mbedtls_nist_kw_setkey(&kw, MBEDTLS_CIPHER_ID_AES, kek, 128, 1);
175 if (rc) {
176 goto done;
177 }
178
179 rc = mbedtls_nist_kw_wrap(&kw, MBEDTLS_KW_MODE_KW, seckey, 16, encbuf,
180 &olen, 24);
181
182done:
183 mbedtls_nist_kw_free(&kw);
184 return rc;
185
186#else
187 (void)kek;
188 (void)seckey;
189 (void)encbuf;
190 return 0;
191#endif
192}
193
David Brown5acda262017-01-23 15:42:19 -0700194uint8_t flash_area_align(const struct flash_area *area)
195{
Fabio Utzig73ffc442018-10-24 21:49:09 -0300196 return sim_flash_align(area->fa_device_id);
David Brown5acda262017-01-23 15:42:19 -0700197}
198
Fabio Utzigea0290b2018-08-09 14:23:01 -0300199uint8_t flash_area_erased_val(const struct flash_area *area)
200{
Fabio Utzig73ffc442018-10-24 21:49:09 -0300201 return sim_flash_erased_val(area->fa_device_id);
Fabio Utzigea0290b2018-08-09 14:23:01 -0300202}
203
David Brownde7729e2017-01-09 10:41:35 -0700204struct area {
David Brown7ad80882017-06-20 15:30:36 -0600205 struct flash_area whole;
206 struct flash_area *areas;
207 uint32_t num_areas;
208 uint8_t id;
David Brownde7729e2017-01-09 10:41:35 -0700209};
210
211struct area_desc {
David Brown7ad80882017-06-20 15:30:36 -0600212 struct area slots[16];
213 uint32_t num_slots;
David Brownde7729e2017-01-09 10:41:35 -0700214};
215
216static struct area_desc *flash_areas;
217
David Brownbdb6db72017-07-06 10:14:37 -0600218int invoke_boot_go(struct area_desc *adesc)
David Brownde7729e2017-01-09 10:41:35 -0700219{
David Brown7ad80882017-06-20 15:30:36 -0600220 int res;
221 struct boot_rsp rsp;
David Brownde7729e2017-01-09 10:41:35 -0700222
Fabio Utzig1e48b912018-09-18 09:04:18 -0300223#if defined(MCUBOOT_SIGN_RSA)
Fabio Utzigb04afa92018-09-12 15:27:04 -0300224 mbedtls_platform_set_calloc_free(calloc, free);
225#endif
David Brown7e701d82017-07-11 13:24:25 -0600226
David Brown7ad80882017-06-20 15:30:36 -0600227 flash_areas = adesc;
228 if (setjmp(boot_jmpbuf) == 0) {
229 res = boot_go(&rsp);
David Brownbdb6db72017-07-06 10:14:37 -0600230 flash_areas = NULL;
David Brown7ad80882017-06-20 15:30:36 -0600231 /* printf("boot_go off: %d (0x%08x)\n", res, rsp.br_image_off); */
232 return res;
233 } else {
David Brownbdb6db72017-07-06 10:14:37 -0600234 flash_areas = NULL;
David Brown7ad80882017-06-20 15:30:36 -0600235 return -0x13579;
236 }
David Brownde7729e2017-01-09 10:41:35 -0700237}
238
David Brownde7729e2017-01-09 10:41:35 -0700239void *os_malloc(size_t size)
240{
David Brown7ad80882017-06-20 15:30:36 -0600241 // printf("os_malloc 0x%x bytes\n", size);
242 return malloc(size);
David Brownde7729e2017-01-09 10:41:35 -0700243}
244
Fabio Utzigb0f04732019-07-31 09:49:19 -0300245int flash_area_id_from_multi_image_slot(int image_index, int slot)
David Brownde7729e2017-01-09 10:41:35 -0700246{
Fabio Utzigb0f04732019-07-31 09:49:19 -0300247 switch (slot) {
248 case 0: return FLASH_AREA_IMAGE_PRIMARY(image_index);
249 case 1: return FLASH_AREA_IMAGE_SECONDARY(image_index);
250 case 2: return FLASH_AREA_IMAGE_SCRATCH;
David Vincze6c9b4162019-03-21 19:18:08 +0100251 }
252
253 printf("Image flash area ID not found\n");
254 return -1; /* flash_area_open will fail on that */
David Brownde7729e2017-01-09 10:41:35 -0700255}
256
257int flash_area_open(uint8_t id, const struct flash_area **area)
258{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200259 uint32_t i;
David Brownde7729e2017-01-09 10:41:35 -0700260
David Brown7ad80882017-06-20 15:30:36 -0600261 for (i = 0; i < flash_areas->num_slots; i++) {
262 if (flash_areas->slots[i].id == id)
263 break;
264 }
265 if (i == flash_areas->num_slots) {
266 printf("Unsupported area\n");
267 abort();
268 }
David Brownde7729e2017-01-09 10:41:35 -0700269
David Brown7ad80882017-06-20 15:30:36 -0600270 /* Unsure if this is right, just returning the first area. */
271 *area = &flash_areas->slots[i].whole;
272 return 0;
David Brownde7729e2017-01-09 10:41:35 -0700273}
274
275void flash_area_close(const struct flash_area *area)
276{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200277 (void)area;
David Brownde7729e2017-01-09 10:41:35 -0700278}
279
280/*
281 * Read/write/erase. Offset is relative from beginning of flash area.
282 */
283int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
David Brown7ad80882017-06-20 15:30:36 -0600284 uint32_t len)
David Brownde7729e2017-01-09 10:41:35 -0700285{
David Brown7ad80882017-06-20 15:30:36 -0600286 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x",
287 __func__, area->fa_id, off, len);
Fabio Utzig99dfc782018-10-15 15:10:55 -0700288 return sim_flash_read(area->fa_device_id, area->fa_off + off, dst, len);
David Brownde7729e2017-01-09 10:41:35 -0700289}
290
291int flash_area_write(const struct flash_area *area, uint32_t off, const void *src,
David Brown7ad80882017-06-20 15:30:36 -0600292 uint32_t len)
David Brownde7729e2017-01-09 10:41:35 -0700293{
David Brown7ad80882017-06-20 15:30:36 -0600294 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
295 area->fa_id, off, len);
Fabio Utzig99dfc782018-10-15 15:10:55 -0700296 if (--flash_counter == 0) {
297 jumped++;
298 longjmp(boot_jmpbuf, 1);
299 }
300 return sim_flash_write(area->fa_device_id, area->fa_off + off, src, len);
David Brownde7729e2017-01-09 10:41:35 -0700301}
302
303int flash_area_erase(const struct flash_area *area, uint32_t off, uint32_t len)
304{
David Brown7ad80882017-06-20 15:30:36 -0600305 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
306 area->fa_id, off, len);
Fabio Utzig99dfc782018-10-15 15:10:55 -0700307 if (--flash_counter == 0) {
308 jumped++;
309 longjmp(boot_jmpbuf, 1);
310 }
311 return sim_flash_erase(area->fa_device_id, area->fa_off + off, len);
David Brownde7729e2017-01-09 10:41:35 -0700312}
313
Fabio Utzig35d31b42018-09-19 08:09:37 -0300314int flash_area_read_is_empty(const struct flash_area *area, uint32_t off,
315 void *dst, uint32_t len)
316{
317 uint8_t i;
318 uint8_t *u8dst;
319 int rc;
320
321 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__, area->fa_id, off, len);
322
Fabio Utzig99dfc782018-10-15 15:10:55 -0700323 rc = sim_flash_read(area->fa_device_id, area->fa_off + off, dst, len);
Fabio Utzig35d31b42018-09-19 08:09:37 -0300324 if (rc) {
325 return -1;
326 }
327
328 for (i = 0, u8dst = (uint8_t *)dst; i < len; i++) {
Fabio Utzig73ffc442018-10-24 21:49:09 -0300329 if (u8dst[i] != sim_flash_erased_val(area->fa_device_id)) {
Fabio Utzig35d31b42018-09-19 08:09:37 -0300330 return 0;
331 }
332 }
333
334 return 1;
335}
336
David Brownde7729e2017-01-09 10:41:35 -0700337int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret)
338{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200339 uint32_t i;
David Brown7ad80882017-06-20 15:30:36 -0600340 struct area *slot;
David Brownde7729e2017-01-09 10:41:35 -0700341
David Brown7ad80882017-06-20 15:30:36 -0600342 for (i = 0; i < flash_areas->num_slots; i++) {
343 if (flash_areas->slots[i].id == idx)
344 break;
345 }
346 if (i == flash_areas->num_slots) {
347 printf("Unsupported area\n");
348 abort();
349 }
David Brownde7729e2017-01-09 10:41:35 -0700350
David Brown7ad80882017-06-20 15:30:36 -0600351 slot = &flash_areas->slots[i];
David Brownde7729e2017-01-09 10:41:35 -0700352
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200353 if (slot->num_areas > (uint32_t)*cnt) {
David Brown7ad80882017-06-20 15:30:36 -0600354 printf("Too many areas in slot\n");
355 abort();
356 }
David Brownde7729e2017-01-09 10:41:35 -0700357
David Brown7ad80882017-06-20 15:30:36 -0600358 *cnt = slot->num_areas;
359 memcpy(ret, slot->areas, slot->num_areas * sizeof(struct flash_area));
David Brownde7729e2017-01-09 10:41:35 -0700360
David Brown7ad80882017-06-20 15:30:36 -0600361 return 0;
David Brownde7729e2017-01-09 10:41:35 -0700362}
363
David Brown60399f62017-05-11 10:20:34 -0600364int flash_area_get_sectors(int fa_id, uint32_t *count,
365 struct flash_sector *sectors)
366{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200367 uint32_t i;
David Brown7ad80882017-06-20 15:30:36 -0600368 struct area *slot;
David Brown60399f62017-05-11 10:20:34 -0600369
David Brown7ad80882017-06-20 15:30:36 -0600370 for (i = 0; i < flash_areas->num_slots; i++) {
371 if (flash_areas->slots[i].id == fa_id)
372 break;
373 }
374 if (i == flash_areas->num_slots) {
375 printf("Unsupported area\n");
376 abort();
377 }
David Brown60399f62017-05-11 10:20:34 -0600378
David Brown7ad80882017-06-20 15:30:36 -0600379 slot = &flash_areas->slots[i];
David Brown60399f62017-05-11 10:20:34 -0600380
David Brown7ad80882017-06-20 15:30:36 -0600381 if (slot->num_areas > *count) {
382 printf("Too many areas in slot\n");
383 abort();
384 }
David Brown60399f62017-05-11 10:20:34 -0600385
David Brown7ad80882017-06-20 15:30:36 -0600386 for (i = 0; i < slot->num_areas; i++) {
387 sectors[i].fs_off = slot->areas[i].fa_off -
388 slot->whole.fa_off;
389 sectors[i].fs_size = slot->areas[i].fa_size;
390 }
391 *count = slot->num_areas;
David Brown60399f62017-05-11 10:20:34 -0600392
David Brown7ad80882017-06-20 15:30:36 -0600393 return 0;
David Brown60399f62017-05-11 10:20:34 -0600394}
Fabio Utzig9b0ee902017-11-23 19:49:00 -0200395
Fabio Utzigb0f04732019-07-31 09:49:19 -0300396int flash_area_id_to_multi_image_slot(int image_index, int area_id)
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100397{
Fabio Utzigb0f04732019-07-31 09:49:19 -0300398 if (area_id == FLASH_AREA_IMAGE_PRIMARY(image_index)) {
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100399 return 0;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100400 }
Fabio Utzigb0f04732019-07-31 09:49:19 -0300401 if (area_id == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
David Vinczeb75c12a2019-03-22 14:58:33 +0100402 return 1;
403 }
404
405 printf("Unsupported image area ID\n");
406 abort();
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100407}
408
Fabio Utzig9b0ee902017-11-23 19:49:00 -0200409void sim_assert(int x, const char *assertion, const char *file, unsigned int line, const char *function)
410{
411 if (!(x)) {
412 if (c_catch_asserts) {
413 c_asserts++;
414 } else {
415 BOOT_LOG_ERR("%s:%d: %s: Assertion `%s' failed.", file, line, function, assertion);
416
417 /* NOTE: if the assert below is triggered, the place where it was originally
418 * asserted is printed by the message above...
419 */
420 assert(x);
421 }
422 }
423}