blob: f8aaccd0a2071c5aebd6ded0eda1a41a88a56977 [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
David Brownbdb6db72017-07-06 10:14:37 -060032extern int sim_flash_erase(uint32_t offset, uint32_t size);
33extern int sim_flash_read(uint32_t offset, uint8_t *dest, uint32_t size);
34extern int sim_flash_write(uint32_t offset, const uint8_t *src, uint32_t size);
David Brownde7729e2017-01-09 10:41:35 -070035
David Brownde7729e2017-01-09 10:41:35 -070036static jmp_buf boot_jmpbuf;
37int flash_counter;
38
39int jumped = 0;
Fabio Utzig9b0ee902017-11-23 19:49:00 -020040uint8_t c_asserts = 0;
41uint8_t c_catch_asserts = 0;
David Brownde7729e2017-01-09 10:41:35 -070042
Fabio Utzig92be3fb2017-12-05 08:52:53 -020043int ecdsa256_sign_(const uint8_t *privkey, const uint8_t *hash,
44 unsigned hash_len, uint8_t *signature)
45{
46#ifdef MCUBOOT_SIGN_EC256
47 return uECC_sign(privkey, hash, hash_len, signature, uECC_secp256r1());
48#else
49 (void)privkey;
50 (void)hash;
51 (void)hash_len;
52 (void)signature;
53 return 0;
54#endif
55}
56
Fabio Utzig1e48b912018-09-18 09:04:18 -030057#ifdef MCUBOOT_ENCRYPT_RSA
58static int
59parse_pubkey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
60{
61 int rc;
62 size_t len;
63
64 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
65 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
66 return -1;
67 }
68
69 if (*p + len != end) {
70 return -2;
71 }
72
73 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
74 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
75 return -3;
76 }
77
78 *p += len;
79
80 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
81 return -4;
82 }
83
84 if (**p != MBEDTLS_ASN1_PRIMITIVE) {
85 return -5;
86 }
87
88 *p += 1;
89
90 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
91 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
92 return -6;
93 }
94
95 if (mbedtls_asn1_get_mpi(p, end, &ctx->N) != 0) {
96 return -7;
97 }
98
99 if (mbedtls_asn1_get_mpi(p, end, &ctx->E) != 0) {
100 return -8;
101 }
102
103 ctx->len = mbedtls_mpi_size(&ctx->N);
104
105 if (*p != end) {
106 return -9;
107 }
108
109 if (mbedtls_rsa_check_pubkey(ctx) != 0) {
110 return -10;
111 }
112
113 return 0;
114}
115
116static int
117fake_rng(void *p_rng, unsigned char *output, size_t len)
118{
119 size_t i;
120
121 (void)p_rng;
122 for (i = 0; i < len; i++) {
123 output[i] = (char)i;
124 }
125
126 return 0;
127}
128#endif
129
130int mbedtls_platform_set_calloc_free(void * (*calloc_func)(size_t, size_t),
131 void (*free_func)(void *));
132
133int rsa_oaep_encrypt_(const uint8_t *pubkey, unsigned pubkey_len,
134 const uint8_t *seckey, unsigned seckey_len,
135 uint8_t *encbuf)
136{
137#ifdef MCUBOOT_ENCRYPT_RSA
138 mbedtls_rsa_context ctx;
139 uint8_t *cp;
140 uint8_t *cpend;
141 int rc;
142
143 mbedtls_platform_set_calloc_free(calloc, free);
144
145 mbedtls_rsa_init(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
146
147 cp = (uint8_t *)pubkey;
148 cpend = cp + pubkey_len;
149
150 rc = parse_pubkey(&ctx, &cp, cpend);
151 if (rc) {
152 goto done;
153 }
154
155 rc = mbedtls_rsa_rsaes_oaep_encrypt(&ctx, fake_rng, NULL, MBEDTLS_RSA_PUBLIC,
156 NULL, 0, seckey_len, seckey, encbuf);
157 if (rc) {
158 goto done;
159 }
160
161done:
162 mbedtls_rsa_free(&ctx);
163 return rc;
164
165#else
166 (void)pubkey;
167 (void)pubkey_len;
168 (void)seckey;
169 (void)seckey_len;
170 (void)encbuf;
171 return 0;
172#endif
173}
174
175int kw_encrypt_(const uint8_t *kek, const uint8_t *seckey, uint8_t *encbuf)
176{
177#ifdef MCUBOOT_ENCRYPT_KW
178 mbedtls_nist_kw_context kw;
179 size_t olen;
180 int rc;
181
182 mbedtls_platform_set_calloc_free(calloc, free);
183
184 mbedtls_nist_kw_init(&kw);
185
186 rc = mbedtls_nist_kw_setkey(&kw, MBEDTLS_CIPHER_ID_AES, kek, 128, 1);
187 if (rc) {
188 goto done;
189 }
190
191 rc = mbedtls_nist_kw_wrap(&kw, MBEDTLS_KW_MODE_KW, seckey, 16, encbuf,
192 &olen, 24);
193
194done:
195 mbedtls_nist_kw_free(&kw);
196 return rc;
197
198#else
199 (void)kek;
200 (void)seckey;
201 (void)encbuf;
202 return 0;
203#endif
204}
205
David Brown5acda262017-01-23 15:42:19 -0700206uint8_t sim_flash_align = 1;
207uint8_t flash_area_align(const struct flash_area *area)
208{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200209 (void)area;
David Brown7ad80882017-06-20 15:30:36 -0600210 return sim_flash_align;
David Brown5acda262017-01-23 15:42:19 -0700211}
212
Fabio Utzigea0290b2018-08-09 14:23:01 -0300213uint8_t sim_flash_erased_val = 0xff;
214uint8_t flash_area_erased_val(const struct flash_area *area)
215{
216 (void)area;
217 return sim_flash_erased_val;
218}
219
David Brownde7729e2017-01-09 10:41:35 -0700220struct area {
David Brown7ad80882017-06-20 15:30:36 -0600221 struct flash_area whole;
222 struct flash_area *areas;
223 uint32_t num_areas;
224 uint8_t id;
David Brownde7729e2017-01-09 10:41:35 -0700225};
226
227struct area_desc {
David Brown7ad80882017-06-20 15:30:36 -0600228 struct area slots[16];
229 uint32_t num_slots;
David Brownde7729e2017-01-09 10:41:35 -0700230};
231
232static struct area_desc *flash_areas;
233
David Brownbdb6db72017-07-06 10:14:37 -0600234int invoke_boot_go(struct area_desc *adesc)
David Brownde7729e2017-01-09 10:41:35 -0700235{
David Brown7ad80882017-06-20 15:30:36 -0600236 int res;
237 struct boot_rsp rsp;
David Brownde7729e2017-01-09 10:41:35 -0700238
Fabio Utzig1e48b912018-09-18 09:04:18 -0300239#if defined(MCUBOOT_SIGN_RSA)
Fabio Utzigb04afa92018-09-12 15:27:04 -0300240 mbedtls_platform_set_calloc_free(calloc, free);
241#endif
David Brown7e701d82017-07-11 13:24:25 -0600242
David Brown7ad80882017-06-20 15:30:36 -0600243 flash_areas = adesc;
244 if (setjmp(boot_jmpbuf) == 0) {
245 res = boot_go(&rsp);
David Brownbdb6db72017-07-06 10:14:37 -0600246 flash_areas = NULL;
David Brown7ad80882017-06-20 15:30:36 -0600247 /* printf("boot_go off: %d (0x%08x)\n", res, rsp.br_image_off); */
248 return res;
249 } else {
David Brownbdb6db72017-07-06 10:14:37 -0600250 flash_areas = NULL;
David Brown7ad80882017-06-20 15:30:36 -0600251 return -0x13579;
252 }
David Brownde7729e2017-01-09 10:41:35 -0700253}
254
255int hal_flash_read(uint8_t flash_id, uint32_t address, void *dst,
David Brown7ad80882017-06-20 15:30:36 -0600256 uint32_t num_bytes)
David Brownde7729e2017-01-09 10:41:35 -0700257{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200258 (void)flash_id;
David Brown7ad80882017-06-20 15:30:36 -0600259 // printf("hal_flash_read: %d, 0x%08x (0x%x)\n",
260 // flash_id, address, num_bytes);
David Brownbdb6db72017-07-06 10:14:37 -0600261 return sim_flash_read(address, dst, num_bytes);
David Brownde7729e2017-01-09 10:41:35 -0700262}
263
264int hal_flash_write(uint8_t flash_id, uint32_t address,
David Brown7ad80882017-06-20 15:30:36 -0600265 const void *src, int32_t num_bytes)
David Brownde7729e2017-01-09 10:41:35 -0700266{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200267 (void)flash_id;
David Brown7ad80882017-06-20 15:30:36 -0600268 // printf("hal_flash_write: 0x%08x (0x%x)\n", address, num_bytes);
269 // fflush(stdout);
270 if (--flash_counter == 0) {
271 jumped++;
272 longjmp(boot_jmpbuf, 1);
273 }
David Brownbdb6db72017-07-06 10:14:37 -0600274 return sim_flash_write(address, src, num_bytes);
David Brownde7729e2017-01-09 10:41:35 -0700275}
276
277int hal_flash_erase(uint8_t flash_id, uint32_t address,
David Brown7ad80882017-06-20 15:30:36 -0600278 uint32_t num_bytes)
David Brownde7729e2017-01-09 10:41:35 -0700279{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200280 (void)flash_id;
David Brown7ad80882017-06-20 15:30:36 -0600281 // printf("hal_flash_erase: 0x%08x, (0x%x)\n", address, num_bytes);
282 // fflush(stdout);
283 if (--flash_counter == 0) {
284 jumped++;
285 longjmp(boot_jmpbuf, 1);
286 }
David Brownbdb6db72017-07-06 10:14:37 -0600287 return sim_flash_erase(address, num_bytes);
David Brownde7729e2017-01-09 10:41:35 -0700288}
289
David Brownde7729e2017-01-09 10:41:35 -0700290void *os_malloc(size_t size)
291{
David Brown7ad80882017-06-20 15:30:36 -0600292 // printf("os_malloc 0x%x bytes\n", size);
293 return malloc(size);
David Brownde7729e2017-01-09 10:41:35 -0700294}
295
296int flash_area_id_from_image_slot(int slot)
297{
David Brown7ad80882017-06-20 15:30:36 -0600298 return slot + 1;
David Brownde7729e2017-01-09 10:41:35 -0700299}
300
301int flash_area_open(uint8_t id, const struct flash_area **area)
302{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200303 uint32_t i;
David Brownde7729e2017-01-09 10:41:35 -0700304
David Brown7ad80882017-06-20 15:30:36 -0600305 for (i = 0; i < flash_areas->num_slots; i++) {
306 if (flash_areas->slots[i].id == id)
307 break;
308 }
309 if (i == flash_areas->num_slots) {
310 printf("Unsupported area\n");
311 abort();
312 }
David Brownde7729e2017-01-09 10:41:35 -0700313
David Brown7ad80882017-06-20 15:30:36 -0600314 /* Unsure if this is right, just returning the first area. */
315 *area = &flash_areas->slots[i].whole;
316 return 0;
David Brownde7729e2017-01-09 10:41:35 -0700317}
318
319void flash_area_close(const struct flash_area *area)
320{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200321 (void)area;
David Brownde7729e2017-01-09 10:41:35 -0700322}
323
324/*
325 * Read/write/erase. Offset is relative from beginning of flash area.
326 */
327int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
David Brown7ad80882017-06-20 15:30:36 -0600328 uint32_t len)
David Brownde7729e2017-01-09 10:41:35 -0700329{
David Brown7ad80882017-06-20 15:30:36 -0600330 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x",
331 __func__, area->fa_id, off, len);
332 return hal_flash_read(area->fa_id,
333 area->fa_off + off,
334 dst, len);
David Brownde7729e2017-01-09 10:41:35 -0700335}
336
337int flash_area_write(const struct flash_area *area, uint32_t off, const void *src,
David Brown7ad80882017-06-20 15:30:36 -0600338 uint32_t len)
David Brownde7729e2017-01-09 10:41:35 -0700339{
David Brown7ad80882017-06-20 15:30:36 -0600340 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
341 area->fa_id, off, len);
342 return hal_flash_write(area->fa_id,
343 area->fa_off + off,
344 src, len);
David Brownde7729e2017-01-09 10:41:35 -0700345}
346
347int flash_area_erase(const struct flash_area *area, uint32_t off, uint32_t len)
348{
David Brown7ad80882017-06-20 15:30:36 -0600349 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
350 area->fa_id, off, len);
351 return hal_flash_erase(area->fa_id,
352 area->fa_off + off,
353 len);
David Brownde7729e2017-01-09 10:41:35 -0700354}
355
Fabio Utzig35d31b42018-09-19 08:09:37 -0300356int flash_area_read_is_empty(const struct flash_area *area, uint32_t off,
357 void *dst, uint32_t len)
358{
359 uint8_t i;
360 uint8_t *u8dst;
361 int rc;
362
363 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__, area->fa_id, off, len);
364
365 rc = hal_flash_read(area->fa_device_id, area->fa_off + off, dst, len);
366 if (rc) {
367 return -1;
368 }
369
370 for (i = 0, u8dst = (uint8_t *)dst; i < len; i++) {
371 if (u8dst[i] != sim_flash_erased_val) {
372 return 0;
373 }
374 }
375
376 return 1;
377}
378
David Brownde7729e2017-01-09 10:41:35 -0700379int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret)
380{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200381 uint32_t i;
David Brown7ad80882017-06-20 15:30:36 -0600382 struct area *slot;
David Brownde7729e2017-01-09 10:41:35 -0700383
David Brown7ad80882017-06-20 15:30:36 -0600384 for (i = 0; i < flash_areas->num_slots; i++) {
385 if (flash_areas->slots[i].id == idx)
386 break;
387 }
388 if (i == flash_areas->num_slots) {
389 printf("Unsupported area\n");
390 abort();
391 }
David Brownde7729e2017-01-09 10:41:35 -0700392
David Brown7ad80882017-06-20 15:30:36 -0600393 slot = &flash_areas->slots[i];
David Brownde7729e2017-01-09 10:41:35 -0700394
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200395 if (slot->num_areas > (uint32_t)*cnt) {
David Brown7ad80882017-06-20 15:30:36 -0600396 printf("Too many areas in slot\n");
397 abort();
398 }
David Brownde7729e2017-01-09 10:41:35 -0700399
David Brown7ad80882017-06-20 15:30:36 -0600400 *cnt = slot->num_areas;
401 memcpy(ret, slot->areas, slot->num_areas * sizeof(struct flash_area));
David Brownde7729e2017-01-09 10:41:35 -0700402
David Brown7ad80882017-06-20 15:30:36 -0600403 return 0;
David Brownde7729e2017-01-09 10:41:35 -0700404}
405
David Brown60399f62017-05-11 10:20:34 -0600406int flash_area_get_sectors(int fa_id, uint32_t *count,
407 struct flash_sector *sectors)
408{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200409 uint32_t i;
David Brown7ad80882017-06-20 15:30:36 -0600410 struct area *slot;
David Brown60399f62017-05-11 10:20:34 -0600411
David Brown7ad80882017-06-20 15:30:36 -0600412 for (i = 0; i < flash_areas->num_slots; i++) {
413 if (flash_areas->slots[i].id == fa_id)
414 break;
415 }
416 if (i == flash_areas->num_slots) {
417 printf("Unsupported area\n");
418 abort();
419 }
David Brown60399f62017-05-11 10:20:34 -0600420
David Brown7ad80882017-06-20 15:30:36 -0600421 slot = &flash_areas->slots[i];
David Brown60399f62017-05-11 10:20:34 -0600422
David Brown7ad80882017-06-20 15:30:36 -0600423 if (slot->num_areas > *count) {
424 printf("Too many areas in slot\n");
425 abort();
426 }
David Brown60399f62017-05-11 10:20:34 -0600427
David Brown7ad80882017-06-20 15:30:36 -0600428 for (i = 0; i < slot->num_areas; i++) {
429 sectors[i].fs_off = slot->areas[i].fa_off -
430 slot->whole.fa_off;
431 sectors[i].fs_size = slot->areas[i].fa_size;
432 }
433 *count = slot->num_areas;
David Brown60399f62017-05-11 10:20:34 -0600434
David Brown7ad80882017-06-20 15:30:36 -0600435 return 0;
David Brown60399f62017-05-11 10:20:34 -0600436}
Fabio Utzig9b0ee902017-11-23 19:49:00 -0200437
438void sim_assert(int x, const char *assertion, const char *file, unsigned int line, const char *function)
439{
440 if (!(x)) {
441 if (c_catch_asserts) {
442 c_asserts++;
443 } else {
444 BOOT_LOG_ERR("%s:%d: %s: Assertion `%s' failed.", file, line, function, assertion);
445
446 /* NOTE: if the assert below is triggered, the place where it was originally
447 * asserted is printed by the message above...
448 */
449 assert(x);
450 }
451 }
452}