blob: 68f1c405d223814deec97d95b79d68821c935284 [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
David Vinczedb32b212019-04-16 17:43:57 +020066 /* Hash is computed over image header and image itself. */
David Vincze39e78552018-10-10 17:10:01 +020067 size = hdr->ih_img_size + hdr->ih_hdr_size;
David Vinczedb32b212019-04-16 17:43:57 +020068
69 /* If a security counter TLV is present then the TLV info header and the
70 * security counter are also protected and must be included in the hash
71 * calculation.
72 */
73 if (hdr->ih_protect_tlv_size != 0) {
74 size += hdr->ih_protect_tlv_size;
75 }
76
Tamas Banf70ef8c2017-12-19 15:35:09 +000077 for (off = 0; off < size; off += blk_sz) {
78 blk_sz = size - off;
79 if (blk_sz > tmp_buf_sz) {
80 blk_sz = tmp_buf_sz;
81 }
Oliver Swedef9982442018-08-24 18:37:44 +010082
83#ifdef MCUBOOT_RAM_LOADING
84 if (fap == NULL) { /* The image is in SRAM */
85 memcpy(tmp_buf, (uint32_t *)(hdr->ih_load_addr + off), blk_sz);
86 } else { /* The image is in flash */
87#endif
88 if(flash_area_read(fap, off, tmp_buf, blk_sz)) {
89 return -1;
90 }
91#ifdef MCUBOOT_RAM_LOADING
Tamas Banf70ef8c2017-12-19 15:35:09 +000092 }
Oliver Swedef9982442018-08-24 18:37:44 +010093#endif
94
Tamas Banf70ef8c2017-12-19 15:35:09 +000095 bootutil_sha256_update(&sha256_ctx, tmp_buf, blk_sz);
96 }
97 bootutil_sha256_finish(&sha256_ctx, hash_result);
98
99 return 0;
100}
101
102/*
103 * Currently, we only support being able to verify one type of
104 * signature, because there is a single verification function that we
105 * call. List the type of TLV we are expecting. If we aren't
106 * configured for any signature, don't define this macro.
107 */
108#if defined(MCUBOOT_SIGN_RSA)
109# define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS
110# define EXPECTED_SIG_LEN(x) ((x) == 256) /* 2048 bits */
Tamas Banf70ef8c2017-12-19 15:35:09 +0000111#endif
112
113#ifdef EXPECTED_SIG_TLV
114static int
115bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len)
116{
117 bootutil_sha256_context sha256_ctx;
118 int i;
119 const struct bootutil_key *key;
120 uint8_t hash[32];
121
122 assert(keyhash_len <= 32);
123
124 for (i = 0; i < bootutil_key_cnt; i++) {
125 key = &bootutil_keys[i];
126 bootutil_sha256_init(&sha256_ctx);
127 bootutil_sha256_update(&sha256_ctx, key->key, *key->len);
128 bootutil_sha256_finish(&sha256_ctx, hash);
129 if (!memcmp(hash, keyhash, keyhash_len)) {
130 return i;
131 }
132 }
133 return -1;
134}
135#endif
136
Oliver Swedef9982442018-08-24 18:37:44 +0100137#ifdef MCUBOOT_RAM_LOADING
138/* Check the hash of an image after it has been copied to SRAM */
139int
140bootutil_check_hash_after_loading(struct image_header *hdr)
141{
142 uint32_t off;
143 uint32_t end;
144 int sha256_valid = 0;
145 struct image_tlv_info info;
146 struct image_tlv tlv;
147 uint8_t tmp_buf[BOOT_TMPBUF_SZ];
148 uint8_t hash[32] = {0};
149 int rc;
150 uint32_t load_address;
151 uint32_t tlv_sz;
152
153 rc = bootutil_img_hash(hdr, NULL, tmp_buf, BOOT_TMPBUF_SZ, hash, NULL, 0);
154
155 if (rc) {
156 return rc;
157 }
158
159 load_address = (uint32_t) hdr->ih_load_addr;
160
161 /* The TLVs come after the image. */
162 off = hdr->ih_img_size + hdr->ih_hdr_size;
163
164 info = *((struct image_tlv_info *)(load_address + off));
165
166 if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
167 return -1;
168 }
169 end = off + info.it_tlv_tot;
170 off += sizeof(info);
171
172 /*
173 * Traverse through all of the TLVs, performing any checks we know
174 * and are able to do.
175 */
176 for (; off < end; off += sizeof(tlv) + tlv.it_len) {
177 tlv = *((struct image_tlv *)(load_address + off));
178 tlv_sz = sizeof(tlv);
179
180 if (tlv.it_type == IMAGE_TLV_SHA256) {
181 /*
182 * Verify the SHA256 image hash. This must always be present.
183 */
184 if (tlv.it_len != sizeof(hash)) {
185 return -1;
186 }
187
188 if (memcmp(hash, (uint32_t *)(load_address + off + tlv_sz),
189 sizeof(hash))) {
190 return -1;
191 }
192
193 sha256_valid = 1;
194 }
195 }
196
197 if (!sha256_valid) {
198 return -1;
199 }
200
201 return 0;
202}
203#endif /* MCUBOOT_RAM_LOADING */
204
Tamas Banf70ef8c2017-12-19 15:35:09 +0000205/*
206 * Verify the integrity of the image.
207 * Return non-zero if image could not be validated/does not validate.
208 */
209int
210bootutil_img_validate(struct image_header *hdr, const struct flash_area *fap,
211 uint8_t *tmp_buf, uint32_t tmp_buf_sz,
212 uint8_t *seed, int seed_len, uint8_t *out_hash)
213{
214 uint32_t off;
215 uint32_t end;
216 int sha256_valid = 0;
217 struct image_tlv_info info;
218#ifdef EXPECTED_SIG_TLV
219 int valid_signature = 0;
220 int key_id = -1;
221#endif
222 struct image_tlv tlv;
223 uint8_t buf[256];
Tamas Ban581034a2017-12-19 19:54:37 +0000224 uint8_t hash[32] = {0};
Tamas Banf70ef8c2017-12-19 15:35:09 +0000225 int rc;
226
227 rc = bootutil_img_hash(hdr, fap, tmp_buf, tmp_buf_sz, hash,
228 seed, seed_len);
229 if (rc) {
230 return rc;
231 }
232
233 if (out_hash) {
234 memcpy(out_hash, hash, 32);
235 }
236
237 /* The TLVs come after the image. */
Tamas Banf70ef8c2017-12-19 15:35:09 +0000238 off = hdr->ih_img_size + hdr->ih_hdr_size;
239
240 rc = flash_area_read(fap, off, &info, sizeof(info));
241 if (rc) {
242 return rc;
243 }
244 if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
245 return -1;
246 }
247 end = off + info.it_tlv_tot;
248 off += sizeof(info);
249
250 /*
251 * Traverse through all of the TLVs, performing any checks we know
252 * and are able to do.
253 */
254 for (; off < end; off += sizeof(tlv) + tlv.it_len) {
Tamas Ban581034a2017-12-19 19:54:37 +0000255 rc = flash_area_read(fap, off, &tlv, sizeof(tlv));
Tamas Banf70ef8c2017-12-19 15:35:09 +0000256 if (rc) {
257 return rc;
258 }
259
260 if (tlv.it_type == IMAGE_TLV_SHA256) {
261 /*
262 * Verify the SHA256 image hash. This must always be
263 * present.
264 */
265 if (tlv.it_len != sizeof(hash)) {
266 return -1;
267 }
Tamas Ban581034a2017-12-19 19:54:37 +0000268 rc = flash_area_read(fap, off + sizeof(tlv), buf, sizeof(hash));
Tamas Banf70ef8c2017-12-19 15:35:09 +0000269 if (rc) {
270 return rc;
271 }
272 if (memcmp(hash, buf, sizeof(hash))) {
273 return -1;
274 }
275
276 sha256_valid = 1;
277#ifdef EXPECTED_SIG_TLV
278 } else if (tlv.it_type == IMAGE_TLV_KEYHASH) {
279 /*
280 * Determine which key we should be checking.
281 */
282 if (tlv.it_len > 32) {
283 return -1;
284 }
Tamas Ban581034a2017-12-19 19:54:37 +0000285 rc = flash_area_read(fap, off + sizeof(tlv), buf, tlv.it_len);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000286 if (rc) {
287 return rc;
288 }
289 key_id = bootutil_find_key(buf, tlv.it_len);
290 /*
291 * The key may not be found, which is acceptable. There
292 * can be multiple signatures, each preceded by a key.
293 */
294 } else if (tlv.it_type == EXPECTED_SIG_TLV) {
295 /* Ignore this signature if it is out of bounds. */
296 if (key_id < 0 || key_id >= bootutil_key_cnt) {
297 key_id = -1;
298 continue;
299 }
300 if (!EXPECTED_SIG_LEN(tlv.it_len) || tlv.it_len > sizeof(buf)) {
301 return -1;
302 }
303 rc = flash_area_read(fap, off + sizeof(tlv), buf, tlv.it_len);
304 if (rc) {
305 return -1;
306 }
Tamas Ban581034a2017-12-19 19:54:37 +0000307 rc = bootutil_verify_sig(hash, sizeof(hash), buf, tlv.it_len,
308 key_id);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000309 if (rc == 0) {
310 valid_signature = 1;
311 }
312 key_id = -1;
313#endif
314 }
315 }
316
317 if (!sha256_valid) {
318 return -1;
319 }
320
321#ifdef EXPECTED_SIG_TLV
322 if (!valid_signature) {
323 return -1;
324 }
325#endif
326
327 return 0;
328}