blob: b9db6de5aa283b5ef5d2cf19443707f16906f816 [file] [log] [blame]
Tamas Banf70ef8c2017-12-19 15:35:09 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
Oliver Swedef9982442018-08-24 18:37:44 +010020/*
21 * Original code taken from mcuboot project at:
David Vincze39e78552018-10-10 17:10:01 +020022 * https://github.com/JuulLabs-OSS/mcuboot
23 * Git SHA of the original version: 178be54bd6e5f035cc60e98205535682acd26e64
24 * Modifications are Copyright (c) 2018-2019 Arm Limited.
Oliver Swedef9982442018-08-24 18:37:44 +010025 */
26
Tamas Banf70ef8c2017-12-19 15:35:09 +000027#include <assert.h>
28#include <stddef.h>
29#include <inttypes.h>
30#include <string.h>
31
Tamas Banf70ef8c2017-12-19 15:35:09 +000032#include "flash_map/flash_map.h"
33#include "bootutil/image.h"
34#include "bootutil/sha256.h"
35#include "bootutil/sign_key.h"
David Vincze060968d2019-05-23 01:13:14 +020036#include "security_cnt.h"
Tamas Banf70ef8c2017-12-19 15:35:09 +000037
Tamas Banf70ef8c2017-12-19 15:35:09 +000038#ifdef MCUBOOT_SIGN_RSA
39#include "mbedtls/rsa.h"
40#endif
Tamas Ban581034a2017-12-19 19:54:37 +000041
Tamas Banf70ef8c2017-12-19 15:35:09 +000042#include "mbedtls/asn1.h"
43
44#include "bootutil_priv.h"
45
46/*
47 * Compute SHA256 over the image.
48 */
49static int
50bootutil_img_hash(struct image_header *hdr, const struct flash_area *fap,
51 uint8_t *tmp_buf, uint32_t tmp_buf_sz,
52 uint8_t *hash_result, uint8_t *seed, int seed_len)
53{
54 bootutil_sha256_context sha256_ctx;
55 uint32_t blk_sz;
56 uint32_t size;
57 uint32_t off;
Tamas Banf70ef8c2017-12-19 15:35:09 +000058
59 bootutil_sha256_init(&sha256_ctx);
60
61 /* in some cases (split image) the hash is seeded with data from
62 * the loader image */
Tamas Ban581034a2017-12-19 19:54:37 +000063 if (seed && (seed_len > 0)) {
Tamas Banf70ef8c2017-12-19 15:35:09 +000064 bootutil_sha256_update(&sha256_ctx, seed, seed_len);
65 }
66
David Vinczedb32b212019-04-16 17:43:57 +020067 /* Hash is computed over image header and image itself. */
David Vincze39e78552018-10-10 17:10:01 +020068 size = hdr->ih_img_size + hdr->ih_hdr_size;
David Vinczedb32b212019-04-16 17:43:57 +020069
70 /* If a security counter TLV is present then the TLV info header and the
71 * security counter are also protected and must be included in the hash
72 * calculation.
73 */
74 if (hdr->ih_protect_tlv_size != 0) {
75 size += hdr->ih_protect_tlv_size;
76 }
77
Tamas Banf70ef8c2017-12-19 15:35:09 +000078 for (off = 0; off < size; off += blk_sz) {
79 blk_sz = size - off;
80 if (blk_sz > tmp_buf_sz) {
81 blk_sz = tmp_buf_sz;
82 }
Oliver Swedef9982442018-08-24 18:37:44 +010083
84#ifdef MCUBOOT_RAM_LOADING
85 if (fap == NULL) { /* The image is in SRAM */
86 memcpy(tmp_buf, (uint32_t *)(hdr->ih_load_addr + off), blk_sz);
87 } else { /* The image is in flash */
88#endif
89 if(flash_area_read(fap, off, tmp_buf, blk_sz)) {
90 return -1;
91 }
92#ifdef MCUBOOT_RAM_LOADING
Tamas Banf70ef8c2017-12-19 15:35:09 +000093 }
Oliver Swedef9982442018-08-24 18:37:44 +010094#endif
95
Tamas Banf70ef8c2017-12-19 15:35:09 +000096 bootutil_sha256_update(&sha256_ctx, tmp_buf, blk_sz);
97 }
98 bootutil_sha256_finish(&sha256_ctx, hash_result);
99
100 return 0;
101}
102
103/*
104 * Currently, we only support being able to verify one type of
105 * signature, because there is a single verification function that we
106 * call. List the type of TLV we are expecting. If we aren't
107 * configured for any signature, don't define this macro.
108 */
109#if defined(MCUBOOT_SIGN_RSA)
110# define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS
111# define EXPECTED_SIG_LEN(x) ((x) == 256) /* 2048 bits */
Tamas Banf70ef8c2017-12-19 15:35:09 +0000112#endif
113
114#ifdef EXPECTED_SIG_TLV
115static int
116bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len)
117{
118 bootutil_sha256_context sha256_ctx;
119 int i;
120 const struct bootutil_key *key;
121 uint8_t hash[32];
122
123 assert(keyhash_len <= 32);
124
125 for (i = 0; i < bootutil_key_cnt; i++) {
126 key = &bootutil_keys[i];
127 bootutil_sha256_init(&sha256_ctx);
128 bootutil_sha256_update(&sha256_ctx, key->key, *key->len);
129 bootutil_sha256_finish(&sha256_ctx, hash);
130 if (!memcmp(hash, keyhash, keyhash_len)) {
131 return i;
132 }
133 }
134 return -1;
135}
136#endif
137
Oliver Swedef9982442018-08-24 18:37:44 +0100138#ifdef MCUBOOT_RAM_LOADING
139/* Check the hash of an image after it has been copied to SRAM */
140int
141bootutil_check_hash_after_loading(struct image_header *hdr)
142{
143 uint32_t off;
144 uint32_t end;
145 int sha256_valid = 0;
146 struct image_tlv_info info;
147 struct image_tlv tlv;
148 uint8_t tmp_buf[BOOT_TMPBUF_SZ];
149 uint8_t hash[32] = {0};
150 int rc;
151 uint32_t load_address;
152 uint32_t tlv_sz;
153
154 rc = bootutil_img_hash(hdr, NULL, tmp_buf, BOOT_TMPBUF_SZ, hash, NULL, 0);
155
156 if (rc) {
157 return rc;
158 }
159
160 load_address = (uint32_t) hdr->ih_load_addr;
161
162 /* The TLVs come after the image. */
163 off = hdr->ih_img_size + hdr->ih_hdr_size;
164
165 info = *((struct image_tlv_info *)(load_address + off));
166
167 if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
David Vincze060968d2019-05-23 01:13:14 +0200168 return BOOT_EBADMAGIC;
Oliver Swedef9982442018-08-24 18:37:44 +0100169 }
170 end = off + info.it_tlv_tot;
171 off += sizeof(info);
172
173 /*
174 * Traverse through all of the TLVs, performing any checks we know
175 * and are able to do.
176 */
David Vincze060968d2019-05-23 01:13:14 +0200177 while (off < end) {
Oliver Swedef9982442018-08-24 18:37:44 +0100178 tlv = *((struct image_tlv *)(load_address + off));
179 tlv_sz = sizeof(tlv);
180
181 if (tlv.it_type == IMAGE_TLV_SHA256) {
182 /*
183 * Verify the SHA256 image hash. This must always be present.
184 */
185 if (tlv.it_len != sizeof(hash)) {
186 return -1;
187 }
188
189 if (memcmp(hash, (uint32_t *)(load_address + off + tlv_sz),
190 sizeof(hash))) {
191 return -1;
192 }
193
194 sha256_valid = 1;
195 }
David Vincze060968d2019-05-23 01:13:14 +0200196
197 /* Avoid integer overflow. */
198 if ((UINT32_MAX - off) < (sizeof(tlv) + tlv.it_len)) {
199 /* Potential overflow. */
200 break;
201 } else {
202 off += sizeof(tlv) + tlv.it_len;
203 }
Oliver Swedef9982442018-08-24 18:37:44 +0100204 }
205
206 if (!sha256_valid) {
207 return -1;
208 }
209
210 return 0;
211}
212#endif /* MCUBOOT_RAM_LOADING */
213
David Vincze060968d2019-05-23 01:13:14 +0200214/**
215 * Reads the value of an image's security counter.
216 *
217 * @param hdr Pointer to the image header structure.
218 * @param fap Pointer to a description structure of the image's
219 * flash area.
220 * @param security_cnt Pointer to store the security counter value.
221 *
222 * @return 0 on success; nonzero on failure.
223 */
224int32_t
225bootutil_get_img_security_cnt(struct image_header *hdr,
226 const struct flash_area *fap,
227 uint32_t *img_security_cnt)
228{
229 struct image_tlv_info info;
230 struct image_tlv tlv;
231 uint32_t off;
232 uint32_t end;
233 uint32_t found = 0;
234 int32_t rc;
235
236 if ((hdr == NULL) ||
237 (fap == NULL) ||
238 (img_security_cnt == NULL)) {
239 /* Invalid parameter. */
240 return BOOT_EBADARGS;
241 }
242
243 /* The TLVs come after the image. */
244 off = hdr->ih_hdr_size + hdr->ih_img_size;
245
246 /* The TLV area always starts with an image_tlv_info structure. */
247 rc = flash_area_read(fap, off, &info, sizeof(info));
248 if (rc != 0) {
249 return BOOT_EFLASH;
250 }
251
252 if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
253 return BOOT_EBADMAGIC;
254 }
255
256 /* The security counter TLV is in the protected part of the TLV area. */
257 if (hdr->ih_protect_tlv_size != 0) {
258 end = off + (uint32_t)hdr->ih_protect_tlv_size;
259 off += sizeof(info);
260
261 /* Traverse through the protected TLV area to find the
262 * security counter TLV.
263 */
264 while (off < end) {
265 rc = flash_area_read(fap, off, &tlv, sizeof(tlv));
266 if (rc != 0) {
267 return BOOT_EFLASH;
268 }
269
270 if (tlv.it_type == IMAGE_TLV_SEC_CNT) {
271
272 if (tlv.it_len != sizeof(*img_security_cnt)) {
273 /* Security counter is not valid. */
274 break;
275 }
276
277 rc = flash_area_read(fap, off + sizeof(tlv),
278 img_security_cnt, tlv.it_len);
279 if (rc != 0) {
280 return BOOT_EFLASH;
281 }
282
283 /* Security counter has been found. */
284 found = 1;
285 break;
286 }
287
288 /* Avoid integer overflow. */
289 if ((UINT32_MAX - off) < (sizeof(tlv) + tlv.it_len)) {
290 /* Potential overflow. */
291 break;
292 } else {
293 off += sizeof(tlv) + tlv.it_len;
294 }
295 }
296 }
297
298 if (found) {
299 return 0;
300 }
301
302 return -1;
303}
304
Tamas Banf70ef8c2017-12-19 15:35:09 +0000305/*
306 * Verify the integrity of the image.
307 * Return non-zero if image could not be validated/does not validate.
308 */
309int
310bootutil_img_validate(struct image_header *hdr, const struct flash_area *fap,
311 uint8_t *tmp_buf, uint32_t tmp_buf_sz,
312 uint8_t *seed, int seed_len, uint8_t *out_hash)
313{
314 uint32_t off;
315 uint32_t end;
316 int sha256_valid = 0;
317 struct image_tlv_info info;
318#ifdef EXPECTED_SIG_TLV
319 int valid_signature = 0;
320 int key_id = -1;
321#endif
322 struct image_tlv tlv;
323 uint8_t buf[256];
Tamas Ban581034a2017-12-19 19:54:37 +0000324 uint8_t hash[32] = {0};
David Vincze060968d2019-05-23 01:13:14 +0200325 uint32_t security_cnt;
326 uint32_t img_security_cnt;
327 int32_t security_counter_valid = 0;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000328 int rc;
329
330 rc = bootutil_img_hash(hdr, fap, tmp_buf, tmp_buf_sz, hash,
331 seed, seed_len);
332 if (rc) {
333 return rc;
334 }
335
336 if (out_hash) {
337 memcpy(out_hash, hash, 32);
338 }
339
340 /* The TLVs come after the image. */
Tamas Banf70ef8c2017-12-19 15:35:09 +0000341 off = hdr->ih_img_size + hdr->ih_hdr_size;
342
343 rc = flash_area_read(fap, off, &info, sizeof(info));
344 if (rc) {
345 return rc;
346 }
347 if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
David Vincze060968d2019-05-23 01:13:14 +0200348 return BOOT_EBADMAGIC;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000349 }
350 end = off + info.it_tlv_tot;
351 off += sizeof(info);
352
353 /*
354 * Traverse through all of the TLVs, performing any checks we know
355 * and are able to do.
356 */
David Vincze060968d2019-05-23 01:13:14 +0200357 while (off < end) {
Tamas Ban581034a2017-12-19 19:54:37 +0000358 rc = flash_area_read(fap, off, &tlv, sizeof(tlv));
Tamas Banf70ef8c2017-12-19 15:35:09 +0000359 if (rc) {
360 return rc;
361 }
362
363 if (tlv.it_type == IMAGE_TLV_SHA256) {
364 /*
365 * Verify the SHA256 image hash. This must always be
366 * present.
367 */
368 if (tlv.it_len != sizeof(hash)) {
369 return -1;
370 }
Tamas Ban581034a2017-12-19 19:54:37 +0000371 rc = flash_area_read(fap, off + sizeof(tlv), buf, sizeof(hash));
Tamas Banf70ef8c2017-12-19 15:35:09 +0000372 if (rc) {
373 return rc;
374 }
375 if (memcmp(hash, buf, sizeof(hash))) {
376 return -1;
377 }
378
379 sha256_valid = 1;
380#ifdef EXPECTED_SIG_TLV
381 } else if (tlv.it_type == IMAGE_TLV_KEYHASH) {
382 /*
383 * Determine which key we should be checking.
384 */
385 if (tlv.it_len > 32) {
386 return -1;
387 }
Tamas Ban581034a2017-12-19 19:54:37 +0000388 rc = flash_area_read(fap, off + sizeof(tlv), buf, tlv.it_len);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000389 if (rc) {
390 return rc;
391 }
392 key_id = bootutil_find_key(buf, tlv.it_len);
393 /*
394 * The key may not be found, which is acceptable. There
395 * can be multiple signatures, each preceded by a key.
396 */
397 } else if (tlv.it_type == EXPECTED_SIG_TLV) {
398 /* Ignore this signature if it is out of bounds. */
399 if (key_id < 0 || key_id >= bootutil_key_cnt) {
400 key_id = -1;
401 continue;
402 }
403 if (!EXPECTED_SIG_LEN(tlv.it_len) || tlv.it_len > sizeof(buf)) {
404 return -1;
405 }
406 rc = flash_area_read(fap, off + sizeof(tlv), buf, tlv.it_len);
407 if (rc) {
408 return -1;
409 }
Tamas Ban581034a2017-12-19 19:54:37 +0000410 rc = bootutil_verify_sig(hash, sizeof(hash), buf, tlv.it_len,
411 key_id);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000412 if (rc == 0) {
413 valid_signature = 1;
414 }
415 key_id = -1;
416#endif
David Vincze060968d2019-05-23 01:13:14 +0200417 } else if (tlv.it_type == IMAGE_TLV_SEC_CNT) {
418 /*
419 * Verify the image's security counter.
420 * This must always be present.
421 */
422 if (tlv.it_len != sizeof(img_security_cnt)) {
423 /* Security counter is not valid. */
424 return -1;
425 }
426
427 rc = flash_area_read(fap, off + sizeof(tlv),
428 &img_security_cnt, tlv.it_len);
429 if (rc) {
430 return rc;
431 }
432
433 rc = boot_nv_security_counter_get(0, &security_cnt);
434 if (rc) {
435 return rc;
436 }
437
438 /* Compare the new image's security counter value against the
439 * stored security counter value.
440 */
441 if (img_security_cnt < security_cnt) {
442 /* The image's security counter is not accepted. */
443 return -1;
444 }
445
446 /* The image's security counter has been successfully verified. */
447 security_counter_valid = 1;
448 }
449
450 /* Avoid integer overflow. */
451 if ((UINT32_MAX - off) < (sizeof(tlv) + tlv.it_len)) {
452 /* Potential overflow. */
453 break;
454 } else {
455 off += sizeof(tlv) + tlv.it_len;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000456 }
457 }
458
David Vincze060968d2019-05-23 01:13:14 +0200459 if (!sha256_valid || !security_counter_valid) {
Tamas Banf70ef8c2017-12-19 15:35:09 +0000460 return -1;
461 }
462
463#ifdef EXPECTED_SIG_TLV
464 if (!valid_signature) {
465 return -1;
466 }
467#endif
468
469 return 0;
470}