blob: cb219faf9c7b265c0ba793970f66c09c65df1e19 [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 Utzig92be3fb2017-12-05 08:52:53 -020016#ifdef MCUBOOT_SIGN_EC256
17#include "../../../ext/tinycrypt/lib/include/tinycrypt/ecc_dsa.h"
18#endif
19
Fabio Utzig1e48b912018-09-18 09:04:18 -030020#ifdef MCUBOOT_ENCRYPT_RSA
21#include "mbedtls/rsa.h"
22#include "mbedtls/asn1.h"
23#endif
24
25#ifdef MCUBOOT_ENCRYPT_KW
26#include "mbedtls/nist_kw.h"
27#endif
28
David Brown54b77792017-05-05 09:40:01 -060029#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_ERROR
David Brown75fd5dc2017-05-04 09:04:47 -060030#include <bootutil/bootutil_log.h>
31
Fabio Utzig99dfc782018-10-15 15:10:55 -070032extern int sim_flash_erase(uint8_t flash_id, uint32_t offset, uint32_t size);
33extern int sim_flash_read(uint8_t flash_id, uint32_t offset, uint8_t *dest,
34 uint32_t size);
35extern int sim_flash_write(uint8_t flash_id, uint32_t offset, const uint8_t *src,
36 uint32_t size);
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 Utzig92be3fb2017-12-05 08:52:53 -020045int ecdsa256_sign_(const uint8_t *privkey, const uint8_t *hash,
46 unsigned hash_len, uint8_t *signature)
47{
48#ifdef MCUBOOT_SIGN_EC256
49 return uECC_sign(privkey, hash, hash_len, signature, uECC_secp256r1());
50#else
51 (void)privkey;
52 (void)hash;
53 (void)hash_len;
54 (void)signature;
55 return 0;
56#endif
57}
58
Fabio Utzig1e48b912018-09-18 09:04:18 -030059#ifdef MCUBOOT_ENCRYPT_RSA
60static int
61parse_pubkey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
62{
63 int rc;
64 size_t len;
65
66 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
67 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
68 return -1;
69 }
70
71 if (*p + len != end) {
72 return -2;
73 }
74
75 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
76 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
77 return -3;
78 }
79
80 *p += len;
81
82 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
83 return -4;
84 }
85
86 if (**p != MBEDTLS_ASN1_PRIMITIVE) {
87 return -5;
88 }
89
90 *p += 1;
91
92 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
93 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
94 return -6;
95 }
96
97 if (mbedtls_asn1_get_mpi(p, end, &ctx->N) != 0) {
98 return -7;
99 }
100
101 if (mbedtls_asn1_get_mpi(p, end, &ctx->E) != 0) {
102 return -8;
103 }
104
105 ctx->len = mbedtls_mpi_size(&ctx->N);
106
107 if (*p != end) {
108 return -9;
109 }
110
111 if (mbedtls_rsa_check_pubkey(ctx) != 0) {
112 return -10;
113 }
114
115 return 0;
116}
117
118static int
119fake_rng(void *p_rng, unsigned char *output, size_t len)
120{
121 size_t i;
122
123 (void)p_rng;
124 for (i = 0; i < len; i++) {
125 output[i] = (char)i;
126 }
127
128 return 0;
129}
130#endif
131
132int mbedtls_platform_set_calloc_free(void * (*calloc_func)(size_t, size_t),
133 void (*free_func)(void *));
134
135int rsa_oaep_encrypt_(const uint8_t *pubkey, unsigned pubkey_len,
136 const uint8_t *seckey, unsigned seckey_len,
137 uint8_t *encbuf)
138{
139#ifdef MCUBOOT_ENCRYPT_RSA
140 mbedtls_rsa_context ctx;
141 uint8_t *cp;
142 uint8_t *cpend;
143 int rc;
144
145 mbedtls_platform_set_calloc_free(calloc, free);
146
147 mbedtls_rsa_init(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
148
149 cp = (uint8_t *)pubkey;
150 cpend = cp + pubkey_len;
151
152 rc = parse_pubkey(&ctx, &cp, cpend);
153 if (rc) {
154 goto done;
155 }
156
157 rc = mbedtls_rsa_rsaes_oaep_encrypt(&ctx, fake_rng, NULL, MBEDTLS_RSA_PUBLIC,
158 NULL, 0, seckey_len, seckey, encbuf);
159 if (rc) {
160 goto done;
161 }
162
163done:
164 mbedtls_rsa_free(&ctx);
165 return rc;
166
167#else
168 (void)pubkey;
169 (void)pubkey_len;
170 (void)seckey;
171 (void)seckey_len;
172 (void)encbuf;
173 return 0;
174#endif
175}
176
177int kw_encrypt_(const uint8_t *kek, const uint8_t *seckey, uint8_t *encbuf)
178{
179#ifdef MCUBOOT_ENCRYPT_KW
180 mbedtls_nist_kw_context kw;
181 size_t olen;
182 int rc;
183
184 mbedtls_platform_set_calloc_free(calloc, free);
185
186 mbedtls_nist_kw_init(&kw);
187
188 rc = mbedtls_nist_kw_setkey(&kw, MBEDTLS_CIPHER_ID_AES, kek, 128, 1);
189 if (rc) {
190 goto done;
191 }
192
193 rc = mbedtls_nist_kw_wrap(&kw, MBEDTLS_KW_MODE_KW, seckey, 16, encbuf,
194 &olen, 24);
195
196done:
197 mbedtls_nist_kw_free(&kw);
198 return rc;
199
200#else
201 (void)kek;
202 (void)seckey;
203 (void)encbuf;
204 return 0;
205#endif
206}
207
David Brown5acda262017-01-23 15:42:19 -0700208uint8_t sim_flash_align = 1;
209uint8_t flash_area_align(const struct flash_area *area)
210{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200211 (void)area;
David Brown7ad80882017-06-20 15:30:36 -0600212 return sim_flash_align;
David Brown5acda262017-01-23 15:42:19 -0700213}
214
Fabio Utzigea0290b2018-08-09 14:23:01 -0300215uint8_t sim_flash_erased_val = 0xff;
216uint8_t flash_area_erased_val(const struct flash_area *area)
217{
218 (void)area;
219 return sim_flash_erased_val;
220}
221
David Brownde7729e2017-01-09 10:41:35 -0700222struct area {
David Brown7ad80882017-06-20 15:30:36 -0600223 struct flash_area whole;
224 struct flash_area *areas;
225 uint32_t num_areas;
226 uint8_t id;
David Brownde7729e2017-01-09 10:41:35 -0700227};
228
229struct area_desc {
David Brown7ad80882017-06-20 15:30:36 -0600230 struct area slots[16];
231 uint32_t num_slots;
David Brownde7729e2017-01-09 10:41:35 -0700232};
233
234static struct area_desc *flash_areas;
235
David Brownbdb6db72017-07-06 10:14:37 -0600236int invoke_boot_go(struct area_desc *adesc)
David Brownde7729e2017-01-09 10:41:35 -0700237{
David Brown7ad80882017-06-20 15:30:36 -0600238 int res;
239 struct boot_rsp rsp;
David Brownde7729e2017-01-09 10:41:35 -0700240
Fabio Utzig1e48b912018-09-18 09:04:18 -0300241#if defined(MCUBOOT_SIGN_RSA)
Fabio Utzigb04afa92018-09-12 15:27:04 -0300242 mbedtls_platform_set_calloc_free(calloc, free);
243#endif
David Brown7e701d82017-07-11 13:24:25 -0600244
David Brown7ad80882017-06-20 15:30:36 -0600245 flash_areas = adesc;
246 if (setjmp(boot_jmpbuf) == 0) {
247 res = boot_go(&rsp);
David Brownbdb6db72017-07-06 10:14:37 -0600248 flash_areas = NULL;
David Brown7ad80882017-06-20 15:30:36 -0600249 /* printf("boot_go off: %d (0x%08x)\n", res, rsp.br_image_off); */
250 return res;
251 } else {
David Brownbdb6db72017-07-06 10:14:37 -0600252 flash_areas = NULL;
David Brown7ad80882017-06-20 15:30:36 -0600253 return -0x13579;
254 }
David Brownde7729e2017-01-09 10:41:35 -0700255}
256
David Brownde7729e2017-01-09 10:41:35 -0700257void *os_malloc(size_t size)
258{
David Brown7ad80882017-06-20 15:30:36 -0600259 // printf("os_malloc 0x%x bytes\n", size);
260 return malloc(size);
David Brownde7729e2017-01-09 10:41:35 -0700261}
262
263int flash_area_id_from_image_slot(int slot)
264{
David Brown7ad80882017-06-20 15:30:36 -0600265 return slot + 1;
David Brownde7729e2017-01-09 10:41:35 -0700266}
267
268int flash_area_open(uint8_t id, const struct flash_area **area)
269{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200270 uint32_t i;
David Brownde7729e2017-01-09 10:41:35 -0700271
David Brown7ad80882017-06-20 15:30:36 -0600272 for (i = 0; i < flash_areas->num_slots; i++) {
273 if (flash_areas->slots[i].id == id)
274 break;
275 }
276 if (i == flash_areas->num_slots) {
277 printf("Unsupported area\n");
278 abort();
279 }
David Brownde7729e2017-01-09 10:41:35 -0700280
David Brown7ad80882017-06-20 15:30:36 -0600281 /* Unsure if this is right, just returning the first area. */
282 *area = &flash_areas->slots[i].whole;
283 return 0;
David Brownde7729e2017-01-09 10:41:35 -0700284}
285
286void flash_area_close(const struct flash_area *area)
287{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200288 (void)area;
David Brownde7729e2017-01-09 10:41:35 -0700289}
290
291/*
292 * Read/write/erase. Offset is relative from beginning of flash area.
293 */
294int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
David Brown7ad80882017-06-20 15:30:36 -0600295 uint32_t len)
David Brownde7729e2017-01-09 10:41:35 -0700296{
David Brown7ad80882017-06-20 15:30:36 -0600297 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x",
298 __func__, area->fa_id, off, len);
Fabio Utzig99dfc782018-10-15 15:10:55 -0700299 return sim_flash_read(area->fa_device_id, area->fa_off + off, dst, len);
David Brownde7729e2017-01-09 10:41:35 -0700300}
301
302int flash_area_write(const struct flash_area *area, uint32_t off, const void *src,
David Brown7ad80882017-06-20 15:30:36 -0600303 uint32_t len)
David Brownde7729e2017-01-09 10:41:35 -0700304{
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_write(area->fa_device_id, area->fa_off + off, src, len);
David Brownde7729e2017-01-09 10:41:35 -0700312}
313
314int flash_area_erase(const struct flash_area *area, uint32_t off, uint32_t len)
315{
David Brown7ad80882017-06-20 15:30:36 -0600316 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
317 area->fa_id, off, len);
Fabio Utzig99dfc782018-10-15 15:10:55 -0700318 if (--flash_counter == 0) {
319 jumped++;
320 longjmp(boot_jmpbuf, 1);
321 }
322 return sim_flash_erase(area->fa_device_id, area->fa_off + off, len);
David Brownde7729e2017-01-09 10:41:35 -0700323}
324
Fabio Utzig35d31b42018-09-19 08:09:37 -0300325int flash_area_read_is_empty(const struct flash_area *area, uint32_t off,
326 void *dst, uint32_t len)
327{
328 uint8_t i;
329 uint8_t *u8dst;
330 int rc;
331
332 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__, area->fa_id, off, len);
333
Fabio Utzig99dfc782018-10-15 15:10:55 -0700334 rc = sim_flash_read(area->fa_device_id, area->fa_off + off, dst, len);
Fabio Utzig35d31b42018-09-19 08:09:37 -0300335 if (rc) {
336 return -1;
337 }
338
339 for (i = 0, u8dst = (uint8_t *)dst; i < len; i++) {
340 if (u8dst[i] != sim_flash_erased_val) {
341 return 0;
342 }
343 }
344
345 return 1;
346}
347
David Brownde7729e2017-01-09 10:41:35 -0700348int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret)
349{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200350 uint32_t i;
David Brown7ad80882017-06-20 15:30:36 -0600351 struct area *slot;
David Brownde7729e2017-01-09 10:41:35 -0700352
David Brown7ad80882017-06-20 15:30:36 -0600353 for (i = 0; i < flash_areas->num_slots; i++) {
354 if (flash_areas->slots[i].id == idx)
355 break;
356 }
357 if (i == flash_areas->num_slots) {
358 printf("Unsupported area\n");
359 abort();
360 }
David Brownde7729e2017-01-09 10:41:35 -0700361
David Brown7ad80882017-06-20 15:30:36 -0600362 slot = &flash_areas->slots[i];
David Brownde7729e2017-01-09 10:41:35 -0700363
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200364 if (slot->num_areas > (uint32_t)*cnt) {
David Brown7ad80882017-06-20 15:30:36 -0600365 printf("Too many areas in slot\n");
366 abort();
367 }
David Brownde7729e2017-01-09 10:41:35 -0700368
David Brown7ad80882017-06-20 15:30:36 -0600369 *cnt = slot->num_areas;
370 memcpy(ret, slot->areas, slot->num_areas * sizeof(struct flash_area));
David Brownde7729e2017-01-09 10:41:35 -0700371
David Brown7ad80882017-06-20 15:30:36 -0600372 return 0;
David Brownde7729e2017-01-09 10:41:35 -0700373}
374
David Brown60399f62017-05-11 10:20:34 -0600375int flash_area_get_sectors(int fa_id, uint32_t *count,
376 struct flash_sector *sectors)
377{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200378 uint32_t i;
David Brown7ad80882017-06-20 15:30:36 -0600379 struct area *slot;
David Brown60399f62017-05-11 10:20:34 -0600380
David Brown7ad80882017-06-20 15:30:36 -0600381 for (i = 0; i < flash_areas->num_slots; i++) {
382 if (flash_areas->slots[i].id == fa_id)
383 break;
384 }
385 if (i == flash_areas->num_slots) {
386 printf("Unsupported area\n");
387 abort();
388 }
David Brown60399f62017-05-11 10:20:34 -0600389
David Brown7ad80882017-06-20 15:30:36 -0600390 slot = &flash_areas->slots[i];
David Brown60399f62017-05-11 10:20:34 -0600391
David Brown7ad80882017-06-20 15:30:36 -0600392 if (slot->num_areas > *count) {
393 printf("Too many areas in slot\n");
394 abort();
395 }
David Brown60399f62017-05-11 10:20:34 -0600396
David Brown7ad80882017-06-20 15:30:36 -0600397 for (i = 0; i < slot->num_areas; i++) {
398 sectors[i].fs_off = slot->areas[i].fa_off -
399 slot->whole.fa_off;
400 sectors[i].fs_size = slot->areas[i].fa_size;
401 }
402 *count = slot->num_areas;
David Brown60399f62017-05-11 10:20:34 -0600403
David Brown7ad80882017-06-20 15:30:36 -0600404 return 0;
David Brown60399f62017-05-11 10:20:34 -0600405}
Fabio Utzig9b0ee902017-11-23 19:49:00 -0200406
407void sim_assert(int x, const char *assertion, const char *file, unsigned int line, const char *function)
408{
409 if (!(x)) {
410 if (c_catch_asserts) {
411 c_asserts++;
412 } else {
413 BOOT_LOG_ERR("%s:%d: %s: Assertion `%s' failed.", file, line, function, assertion);
414
415 /* NOTE: if the assert below is triggered, the place where it was originally
416 * asserted is printed by the message above...
417 */
418 assert(x);
419 }
420 }
421}