blob: 7e246921d1dc5a13b4c5076746d7e1f6ac8d847c [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);
Fabio Utzig73ffc442018-10-24 21:49:09 -030037extern uint8_t sim_flash_align(uint8_t flash_id);
38extern uint8_t sim_flash_erased_val(uint8_t flash_id);
David Brownde7729e2017-01-09 10:41:35 -070039
David Brownde7729e2017-01-09 10:41:35 -070040static jmp_buf boot_jmpbuf;
41int flash_counter;
42
43int jumped = 0;
Fabio Utzig9b0ee902017-11-23 19:49:00 -020044uint8_t c_asserts = 0;
45uint8_t c_catch_asserts = 0;
David Brownde7729e2017-01-09 10:41:35 -070046
Fabio Utzig92be3fb2017-12-05 08:52:53 -020047int ecdsa256_sign_(const uint8_t *privkey, const uint8_t *hash,
48 unsigned hash_len, uint8_t *signature)
49{
50#ifdef MCUBOOT_SIGN_EC256
51 return uECC_sign(privkey, hash, hash_len, signature, uECC_secp256r1());
52#else
53 (void)privkey;
54 (void)hash;
55 (void)hash_len;
56 (void)signature;
57 return 0;
58#endif
59}
60
Fabio Utzig1e48b912018-09-18 09:04:18 -030061#ifdef MCUBOOT_ENCRYPT_RSA
62static int
63parse_pubkey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
64{
65 int rc;
66 size_t len;
67
68 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
69 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
70 return -1;
71 }
72
73 if (*p + len != end) {
74 return -2;
75 }
76
77 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
78 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
79 return -3;
80 }
81
82 *p += len;
83
84 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
85 return -4;
86 }
87
88 if (**p != MBEDTLS_ASN1_PRIMITIVE) {
89 return -5;
90 }
91
92 *p += 1;
93
94 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
95 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
96 return -6;
97 }
98
99 if (mbedtls_asn1_get_mpi(p, end, &ctx->N) != 0) {
100 return -7;
101 }
102
103 if (mbedtls_asn1_get_mpi(p, end, &ctx->E) != 0) {
104 return -8;
105 }
106
107 ctx->len = mbedtls_mpi_size(&ctx->N);
108
109 if (*p != end) {
110 return -9;
111 }
112
113 if (mbedtls_rsa_check_pubkey(ctx) != 0) {
114 return -10;
115 }
116
117 return 0;
118}
119
120static int
121fake_rng(void *p_rng, unsigned char *output, size_t len)
122{
123 size_t i;
124
125 (void)p_rng;
126 for (i = 0; i < len; i++) {
127 output[i] = (char)i;
128 }
129
130 return 0;
131}
132#endif
133
134int mbedtls_platform_set_calloc_free(void * (*calloc_func)(size_t, size_t),
135 void (*free_func)(void *));
136
137int rsa_oaep_encrypt_(const uint8_t *pubkey, unsigned pubkey_len,
138 const uint8_t *seckey, unsigned seckey_len,
139 uint8_t *encbuf)
140{
141#ifdef MCUBOOT_ENCRYPT_RSA
142 mbedtls_rsa_context ctx;
143 uint8_t *cp;
144 uint8_t *cpend;
145 int rc;
146
147 mbedtls_platform_set_calloc_free(calloc, free);
148
149 mbedtls_rsa_init(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
150
151 cp = (uint8_t *)pubkey;
152 cpend = cp + pubkey_len;
153
154 rc = parse_pubkey(&ctx, &cp, cpend);
155 if (rc) {
156 goto done;
157 }
158
159 rc = mbedtls_rsa_rsaes_oaep_encrypt(&ctx, fake_rng, NULL, MBEDTLS_RSA_PUBLIC,
160 NULL, 0, seckey_len, seckey, encbuf);
161 if (rc) {
162 goto done;
163 }
164
165done:
166 mbedtls_rsa_free(&ctx);
167 return rc;
168
169#else
170 (void)pubkey;
171 (void)pubkey_len;
172 (void)seckey;
173 (void)seckey_len;
174 (void)encbuf;
175 return 0;
176#endif
177}
178
179int kw_encrypt_(const uint8_t *kek, const uint8_t *seckey, uint8_t *encbuf)
180{
181#ifdef MCUBOOT_ENCRYPT_KW
182 mbedtls_nist_kw_context kw;
183 size_t olen;
184 int rc;
185
186 mbedtls_platform_set_calloc_free(calloc, free);
187
188 mbedtls_nist_kw_init(&kw);
189
190 rc = mbedtls_nist_kw_setkey(&kw, MBEDTLS_CIPHER_ID_AES, kek, 128, 1);
191 if (rc) {
192 goto done;
193 }
194
195 rc = mbedtls_nist_kw_wrap(&kw, MBEDTLS_KW_MODE_KW, seckey, 16, encbuf,
196 &olen, 24);
197
198done:
199 mbedtls_nist_kw_free(&kw);
200 return rc;
201
202#else
203 (void)kek;
204 (void)seckey;
205 (void)encbuf;
206 return 0;
207#endif
208}
209
David Brown5acda262017-01-23 15:42:19 -0700210uint8_t flash_area_align(const struct flash_area *area)
211{
Fabio Utzig73ffc442018-10-24 21:49:09 -0300212 return sim_flash_align(area->fa_device_id);
David Brown5acda262017-01-23 15:42:19 -0700213}
214
Fabio Utzigea0290b2018-08-09 14:23:01 -0300215uint8_t flash_area_erased_val(const struct flash_area *area)
216{
Fabio Utzig73ffc442018-10-24 21:49:09 -0300217 return sim_flash_erased_val(area->fa_device_id);
Fabio Utzigea0290b2018-08-09 14:23:01 -0300218}
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
David Brownde7729e2017-01-09 10:41:35 -0700255void *os_malloc(size_t size)
256{
David Brown7ad80882017-06-20 15:30:36 -0600257 // printf("os_malloc 0x%x bytes\n", size);
258 return malloc(size);
David Brownde7729e2017-01-09 10:41:35 -0700259}
260
261int flash_area_id_from_image_slot(int slot)
262{
David Brown7ad80882017-06-20 15:30:36 -0600263 return slot + 1;
David Brownde7729e2017-01-09 10:41:35 -0700264}
265
266int flash_area_open(uint8_t id, const struct flash_area **area)
267{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200268 uint32_t i;
David Brownde7729e2017-01-09 10:41:35 -0700269
David Brown7ad80882017-06-20 15:30:36 -0600270 for (i = 0; i < flash_areas->num_slots; i++) {
271 if (flash_areas->slots[i].id == id)
272 break;
273 }
274 if (i == flash_areas->num_slots) {
275 printf("Unsupported area\n");
276 abort();
277 }
David Brownde7729e2017-01-09 10:41:35 -0700278
David Brown7ad80882017-06-20 15:30:36 -0600279 /* Unsure if this is right, just returning the first area. */
280 *area = &flash_areas->slots[i].whole;
281 return 0;
David Brownde7729e2017-01-09 10:41:35 -0700282}
283
284void flash_area_close(const struct flash_area *area)
285{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200286 (void)area;
David Brownde7729e2017-01-09 10:41:35 -0700287}
288
289/*
290 * Read/write/erase. Offset is relative from beginning of flash area.
291 */
292int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
David Brown7ad80882017-06-20 15:30:36 -0600293 uint32_t len)
David Brownde7729e2017-01-09 10:41:35 -0700294{
David Brown7ad80882017-06-20 15:30:36 -0600295 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x",
296 __func__, area->fa_id, off, len);
Fabio Utzig99dfc782018-10-15 15:10:55 -0700297 return sim_flash_read(area->fa_device_id, area->fa_off + off, dst, len);
David Brownde7729e2017-01-09 10:41:35 -0700298}
299
300int flash_area_write(const struct flash_area *area, uint32_t off, const void *src,
David Brown7ad80882017-06-20 15:30:36 -0600301 uint32_t len)
David Brownde7729e2017-01-09 10:41:35 -0700302{
David Brown7ad80882017-06-20 15:30:36 -0600303 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
304 area->fa_id, off, len);
Fabio Utzig99dfc782018-10-15 15:10:55 -0700305 if (--flash_counter == 0) {
306 jumped++;
307 longjmp(boot_jmpbuf, 1);
308 }
309 return sim_flash_write(area->fa_device_id, area->fa_off + off, src, len);
David Brownde7729e2017-01-09 10:41:35 -0700310}
311
312int flash_area_erase(const struct flash_area *area, uint32_t off, uint32_t len)
313{
David Brown7ad80882017-06-20 15:30:36 -0600314 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
315 area->fa_id, off, len);
Fabio Utzig99dfc782018-10-15 15:10:55 -0700316 if (--flash_counter == 0) {
317 jumped++;
318 longjmp(boot_jmpbuf, 1);
319 }
320 return sim_flash_erase(area->fa_device_id, area->fa_off + off, len);
David Brownde7729e2017-01-09 10:41:35 -0700321}
322
Fabio Utzig35d31b42018-09-19 08:09:37 -0300323int flash_area_read_is_empty(const struct flash_area *area, uint32_t off,
324 void *dst, uint32_t len)
325{
326 uint8_t i;
327 uint8_t *u8dst;
328 int rc;
329
330 BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__, area->fa_id, off, len);
331
Fabio Utzig99dfc782018-10-15 15:10:55 -0700332 rc = sim_flash_read(area->fa_device_id, area->fa_off + off, dst, len);
Fabio Utzig35d31b42018-09-19 08:09:37 -0300333 if (rc) {
334 return -1;
335 }
336
337 for (i = 0, u8dst = (uint8_t *)dst; i < len; i++) {
Fabio Utzig73ffc442018-10-24 21:49:09 -0300338 if (u8dst[i] != sim_flash_erased_val(area->fa_device_id)) {
Fabio Utzig35d31b42018-09-19 08:09:37 -0300339 return 0;
340 }
341 }
342
343 return 1;
344}
345
David Brownde7729e2017-01-09 10:41:35 -0700346int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret)
347{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200348 uint32_t i;
David Brown7ad80882017-06-20 15:30:36 -0600349 struct area *slot;
David Brownde7729e2017-01-09 10:41:35 -0700350
David Brown7ad80882017-06-20 15:30:36 -0600351 for (i = 0; i < flash_areas->num_slots; i++) {
352 if (flash_areas->slots[i].id == idx)
353 break;
354 }
355 if (i == flash_areas->num_slots) {
356 printf("Unsupported area\n");
357 abort();
358 }
David Brownde7729e2017-01-09 10:41:35 -0700359
David Brown7ad80882017-06-20 15:30:36 -0600360 slot = &flash_areas->slots[i];
David Brownde7729e2017-01-09 10:41:35 -0700361
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200362 if (slot->num_areas > (uint32_t)*cnt) {
David Brown7ad80882017-06-20 15:30:36 -0600363 printf("Too many areas in slot\n");
364 abort();
365 }
David Brownde7729e2017-01-09 10:41:35 -0700366
David Brown7ad80882017-06-20 15:30:36 -0600367 *cnt = slot->num_areas;
368 memcpy(ret, slot->areas, slot->num_areas * sizeof(struct flash_area));
David Brownde7729e2017-01-09 10:41:35 -0700369
David Brown7ad80882017-06-20 15:30:36 -0600370 return 0;
David Brownde7729e2017-01-09 10:41:35 -0700371}
372
David Brown60399f62017-05-11 10:20:34 -0600373int flash_area_get_sectors(int fa_id, uint32_t *count,
374 struct flash_sector *sectors)
375{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200376 uint32_t i;
David Brown7ad80882017-06-20 15:30:36 -0600377 struct area *slot;
David Brown60399f62017-05-11 10:20:34 -0600378
David Brown7ad80882017-06-20 15:30:36 -0600379 for (i = 0; i < flash_areas->num_slots; i++) {
380 if (flash_areas->slots[i].id == fa_id)
381 break;
382 }
383 if (i == flash_areas->num_slots) {
384 printf("Unsupported area\n");
385 abort();
386 }
David Brown60399f62017-05-11 10:20:34 -0600387
David Brown7ad80882017-06-20 15:30:36 -0600388 slot = &flash_areas->slots[i];
David Brown60399f62017-05-11 10:20:34 -0600389
David Brown7ad80882017-06-20 15:30:36 -0600390 if (slot->num_areas > *count) {
391 printf("Too many areas in slot\n");
392 abort();
393 }
David Brown60399f62017-05-11 10:20:34 -0600394
David Brown7ad80882017-06-20 15:30:36 -0600395 for (i = 0; i < slot->num_areas; i++) {
396 sectors[i].fs_off = slot->areas[i].fa_off -
397 slot->whole.fa_off;
398 sectors[i].fs_size = slot->areas[i].fa_size;
399 }
400 *count = slot->num_areas;
David Brown60399f62017-05-11 10:20:34 -0600401
David Brown7ad80882017-06-20 15:30:36 -0600402 return 0;
David Brown60399f62017-05-11 10:20:34 -0600403}
Fabio Utzig9b0ee902017-11-23 19:49:00 -0200404
405void sim_assert(int x, const char *assertion, const char *file, unsigned int line, const char *function)
406{
407 if (!(x)) {
408 if (c_catch_asserts) {
409 c_asserts++;
410 } else {
411 BOOT_LOG_ERR("%s:%d: %s: Assertion `%s' failed.", file, line, function, assertion);
412
413 /* NOTE: if the assert below is triggered, the place where it was originally
414 * asserted is printed by the message above...
415 */
416 assert(x);
417 }
418 }
419}