blob: 5cb4b4986d06ca4bcdd888c2bc1fa4f8b0a2346e [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"
36
Tamas Banf70ef8c2017-12-19 15:35:09 +000037#ifdef MCUBOOT_SIGN_RSA
38#include "mbedtls/rsa.h"
39#endif
Tamas Ban581034a2017-12-19 19:54:37 +000040
Tamas Banf70ef8c2017-12-19 15:35:09 +000041#include "mbedtls/asn1.h"
42
43#include "bootutil_priv.h"
44
45/*
46 * Compute SHA256 over the image.
47 */
48static int
49bootutil_img_hash(struct image_header *hdr, const struct flash_area *fap,
50 uint8_t *tmp_buf, uint32_t tmp_buf_sz,
51 uint8_t *hash_result, uint8_t *seed, int seed_len)
52{
53 bootutil_sha256_context sha256_ctx;
54 uint32_t blk_sz;
55 uint32_t size;
56 uint32_t off;
Tamas Banf70ef8c2017-12-19 15:35:09 +000057
58 bootutil_sha256_init(&sha256_ctx);
59
60 /* in some cases (split image) the hash is seeded with data from
61 * the loader image */
Tamas Ban581034a2017-12-19 19:54:37 +000062 if (seed && (seed_len > 0)) {
Tamas Banf70ef8c2017-12-19 15:35:09 +000063 bootutil_sha256_update(&sha256_ctx, seed, seed_len);
64 }
65
Tamas Banf70ef8c2017-12-19 15:35:09 +000066 /*
67 * Hash is computed over image header and image itself. No TLV is
68 * included ATM.
69 */
David Vincze39e78552018-10-10 17:10:01 +020070 size = hdr->ih_img_size + hdr->ih_hdr_size;
Tamas Banf70ef8c2017-12-19 15:35:09 +000071 for (off = 0; off < size; off += blk_sz) {
72 blk_sz = size - off;
73 if (blk_sz > tmp_buf_sz) {
74 blk_sz = tmp_buf_sz;
75 }
Oliver Swedef9982442018-08-24 18:37:44 +010076
77#ifdef MCUBOOT_RAM_LOADING
78 if (fap == NULL) { /* The image is in SRAM */
79 memcpy(tmp_buf, (uint32_t *)(hdr->ih_load_addr + off), blk_sz);
80 } else { /* The image is in flash */
81#endif
82 if(flash_area_read(fap, off, tmp_buf, blk_sz)) {
83 return -1;
84 }
85#ifdef MCUBOOT_RAM_LOADING
Tamas Banf70ef8c2017-12-19 15:35:09 +000086 }
Oliver Swedef9982442018-08-24 18:37:44 +010087#endif
88
Tamas Banf70ef8c2017-12-19 15:35:09 +000089 bootutil_sha256_update(&sha256_ctx, tmp_buf, blk_sz);
90 }
91 bootutil_sha256_finish(&sha256_ctx, hash_result);
92
93 return 0;
94}
95
96/*
97 * Currently, we only support being able to verify one type of
98 * signature, because there is a single verification function that we
99 * call. List the type of TLV we are expecting. If we aren't
100 * configured for any signature, don't define this macro.
101 */
102#if defined(MCUBOOT_SIGN_RSA)
103# define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS
104# define EXPECTED_SIG_LEN(x) ((x) == 256) /* 2048 bits */
Tamas Banf70ef8c2017-12-19 15:35:09 +0000105#endif
106
107#ifdef EXPECTED_SIG_TLV
108static int
109bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len)
110{
111 bootutil_sha256_context sha256_ctx;
112 int i;
113 const struct bootutil_key *key;
114 uint8_t hash[32];
115
116 assert(keyhash_len <= 32);
117
118 for (i = 0; i < bootutil_key_cnt; i++) {
119 key = &bootutil_keys[i];
120 bootutil_sha256_init(&sha256_ctx);
121 bootutil_sha256_update(&sha256_ctx, key->key, *key->len);
122 bootutil_sha256_finish(&sha256_ctx, hash);
123 if (!memcmp(hash, keyhash, keyhash_len)) {
124 return i;
125 }
126 }
127 return -1;
128}
129#endif
130
Oliver Swedef9982442018-08-24 18:37:44 +0100131#ifdef MCUBOOT_RAM_LOADING
132/* Check the hash of an image after it has been copied to SRAM */
133int
134bootutil_check_hash_after_loading(struct image_header *hdr)
135{
136 uint32_t off;
137 uint32_t end;
138 int sha256_valid = 0;
139 struct image_tlv_info info;
140 struct image_tlv tlv;
141 uint8_t tmp_buf[BOOT_TMPBUF_SZ];
142 uint8_t hash[32] = {0};
143 int rc;
144 uint32_t load_address;
145 uint32_t tlv_sz;
146
147 rc = bootutil_img_hash(hdr, NULL, tmp_buf, BOOT_TMPBUF_SZ, hash, NULL, 0);
148
149 if (rc) {
150 return rc;
151 }
152
153 load_address = (uint32_t) hdr->ih_load_addr;
154
155 /* The TLVs come after the image. */
156 off = hdr->ih_img_size + hdr->ih_hdr_size;
157
158 info = *((struct image_tlv_info *)(load_address + off));
159
160 if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
161 return -1;
162 }
163 end = off + info.it_tlv_tot;
164 off += sizeof(info);
165
166 /*
167 * Traverse through all of the TLVs, performing any checks we know
168 * and are able to do.
169 */
170 for (; off < end; off += sizeof(tlv) + tlv.it_len) {
171 tlv = *((struct image_tlv *)(load_address + off));
172 tlv_sz = sizeof(tlv);
173
174 if (tlv.it_type == IMAGE_TLV_SHA256) {
175 /*
176 * Verify the SHA256 image hash. This must always be present.
177 */
178 if (tlv.it_len != sizeof(hash)) {
179 return -1;
180 }
181
182 if (memcmp(hash, (uint32_t *)(load_address + off + tlv_sz),
183 sizeof(hash))) {
184 return -1;
185 }
186
187 sha256_valid = 1;
188 }
189 }
190
191 if (!sha256_valid) {
192 return -1;
193 }
194
195 return 0;
196}
197#endif /* MCUBOOT_RAM_LOADING */
198
Tamas Banf70ef8c2017-12-19 15:35:09 +0000199/*
200 * Verify the integrity of the image.
201 * Return non-zero if image could not be validated/does not validate.
202 */
203int
204bootutil_img_validate(struct image_header *hdr, const struct flash_area *fap,
205 uint8_t *tmp_buf, uint32_t tmp_buf_sz,
206 uint8_t *seed, int seed_len, uint8_t *out_hash)
207{
208 uint32_t off;
209 uint32_t end;
210 int sha256_valid = 0;
211 struct image_tlv_info info;
212#ifdef EXPECTED_SIG_TLV
213 int valid_signature = 0;
214 int key_id = -1;
215#endif
216 struct image_tlv tlv;
217 uint8_t buf[256];
Tamas Ban581034a2017-12-19 19:54:37 +0000218 uint8_t hash[32] = {0};
Tamas Banf70ef8c2017-12-19 15:35:09 +0000219 int rc;
220
221 rc = bootutil_img_hash(hdr, fap, tmp_buf, tmp_buf_sz, hash,
222 seed, seed_len);
223 if (rc) {
224 return rc;
225 }
226
227 if (out_hash) {
228 memcpy(out_hash, hash, 32);
229 }
230
231 /* The TLVs come after the image. */
232 /* After image there are TLVs. */
233 off = hdr->ih_img_size + hdr->ih_hdr_size;
234
235 rc = flash_area_read(fap, off, &info, sizeof(info));
236 if (rc) {
237 return rc;
238 }
239 if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
240 return -1;
241 }
242 end = off + info.it_tlv_tot;
243 off += sizeof(info);
244
245 /*
246 * Traverse through all of the TLVs, performing any checks we know
247 * and are able to do.
248 */
249 for (; off < end; off += sizeof(tlv) + tlv.it_len) {
Tamas Ban581034a2017-12-19 19:54:37 +0000250 rc = flash_area_read(fap, off, &tlv, sizeof(tlv));
Tamas Banf70ef8c2017-12-19 15:35:09 +0000251 if (rc) {
252 return rc;
253 }
254
255 if (tlv.it_type == IMAGE_TLV_SHA256) {
256 /*
257 * Verify the SHA256 image hash. This must always be
258 * present.
259 */
260 if (tlv.it_len != sizeof(hash)) {
261 return -1;
262 }
Tamas Ban581034a2017-12-19 19:54:37 +0000263 rc = flash_area_read(fap, off + sizeof(tlv), buf, sizeof(hash));
Tamas Banf70ef8c2017-12-19 15:35:09 +0000264 if (rc) {
265 return rc;
266 }
267 if (memcmp(hash, buf, sizeof(hash))) {
268 return -1;
269 }
270
271 sha256_valid = 1;
272#ifdef EXPECTED_SIG_TLV
273 } else if (tlv.it_type == IMAGE_TLV_KEYHASH) {
274 /*
275 * Determine which key we should be checking.
276 */
277 if (tlv.it_len > 32) {
278 return -1;
279 }
Tamas Ban581034a2017-12-19 19:54:37 +0000280 rc = flash_area_read(fap, off + sizeof(tlv), buf, tlv.it_len);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000281 if (rc) {
282 return rc;
283 }
284 key_id = bootutil_find_key(buf, tlv.it_len);
285 /*
286 * The key may not be found, which is acceptable. There
287 * can be multiple signatures, each preceded by a key.
288 */
289 } else if (tlv.it_type == EXPECTED_SIG_TLV) {
290 /* Ignore this signature if it is out of bounds. */
291 if (key_id < 0 || key_id >= bootutil_key_cnt) {
292 key_id = -1;
293 continue;
294 }
295 if (!EXPECTED_SIG_LEN(tlv.it_len) || tlv.it_len > sizeof(buf)) {
296 return -1;
297 }
298 rc = flash_area_read(fap, off + sizeof(tlv), buf, tlv.it_len);
299 if (rc) {
300 return -1;
301 }
Tamas Ban581034a2017-12-19 19:54:37 +0000302 rc = bootutil_verify_sig(hash, sizeof(hash), buf, tlv.it_len,
303 key_id);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000304 if (rc == 0) {
305 valid_signature = 1;
306 }
307 key_id = -1;
308#endif
309 }
310 }
311
312 if (!sha256_valid) {
313 return -1;
314 }
315
316#ifdef EXPECTED_SIG_TLV
317 if (!valid_signature) {
318 return -1;
319 }
320#endif
321
322 return 0;
323}