blob: 2dca5bdbba9de0760c9baf8e2d1ea1b156818e05 [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
20#include <assert.h>
21#include <stddef.h>
22#include <inttypes.h>
23#include <string.h>
24
25#include "hal/hal_flash.h"
26#include "flash_map/flash_map.h"
27#include "bootutil/image.h"
28#include "bootutil/sha256.h"
29#include "bootutil/sign_key.h"
30
Tamas Banf70ef8c2017-12-19 15:35:09 +000031#ifdef MCUBOOT_SIGN_RSA
32#include "mbedtls/rsa.h"
33#endif
Tamas Ban581034a2017-12-19 19:54:37 +000034
Tamas Banf70ef8c2017-12-19 15:35:09 +000035#include "mbedtls/asn1.h"
36
37#include "bootutil_priv.h"
38
39/*
40 * Compute SHA256 over the image.
41 */
42static int
43bootutil_img_hash(struct image_header *hdr, const struct flash_area *fap,
44 uint8_t *tmp_buf, uint32_t tmp_buf_sz,
45 uint8_t *hash_result, uint8_t *seed, int seed_len)
46{
47 bootutil_sha256_context sha256_ctx;
48 uint32_t blk_sz;
49 uint32_t size;
50 uint32_t off;
51 int rc;
52
53 bootutil_sha256_init(&sha256_ctx);
54
55 /* in some cases (split image) the hash is seeded with data from
56 * the loader image */
Tamas Ban581034a2017-12-19 19:54:37 +000057 if (seed && (seed_len > 0)) {
Tamas Banf70ef8c2017-12-19 15:35:09 +000058 bootutil_sha256_update(&sha256_ctx, seed, seed_len);
59 }
60
61 size = hdr->ih_img_size + hdr->ih_hdr_size;
62
63 /*
64 * Hash is computed over image header and image itself. No TLV is
65 * included ATM.
66 */
67 size = hdr->ih_img_size + hdr->ih_hdr_size;
68 for (off = 0; off < size; off += blk_sz) {
69 blk_sz = size - off;
70 if (blk_sz > tmp_buf_sz) {
71 blk_sz = tmp_buf_sz;
72 }
73 rc = flash_area_read(fap, off, tmp_buf, blk_sz);
74 if (rc) {
75 return rc;
76 }
77 bootutil_sha256_update(&sha256_ctx, tmp_buf, blk_sz);
78 }
79 bootutil_sha256_finish(&sha256_ctx, hash_result);
80
81 return 0;
82}
83
84/*
85 * Currently, we only support being able to verify one type of
86 * signature, because there is a single verification function that we
87 * call. List the type of TLV we are expecting. If we aren't
88 * configured for any signature, don't define this macro.
89 */
90#if defined(MCUBOOT_SIGN_RSA)
91# define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS
92# define EXPECTED_SIG_LEN(x) ((x) == 256) /* 2048 bits */
Tamas Banf70ef8c2017-12-19 15:35:09 +000093#endif
94
95#ifdef EXPECTED_SIG_TLV
96static int
97bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len)
98{
99 bootutil_sha256_context sha256_ctx;
100 int i;
101 const struct bootutil_key *key;
102 uint8_t hash[32];
103
104 assert(keyhash_len <= 32);
105
106 for (i = 0; i < bootutil_key_cnt; i++) {
107 key = &bootutil_keys[i];
108 bootutil_sha256_init(&sha256_ctx);
109 bootutil_sha256_update(&sha256_ctx, key->key, *key->len);
110 bootutil_sha256_finish(&sha256_ctx, hash);
111 if (!memcmp(hash, keyhash, keyhash_len)) {
112 return i;
113 }
114 }
115 return -1;
116}
117#endif
118
119/*
120 * Verify the integrity of the image.
121 * Return non-zero if image could not be validated/does not validate.
122 */
123int
124bootutil_img_validate(struct image_header *hdr, const struct flash_area *fap,
125 uint8_t *tmp_buf, uint32_t tmp_buf_sz,
126 uint8_t *seed, int seed_len, uint8_t *out_hash)
127{
128 uint32_t off;
129 uint32_t end;
130 int sha256_valid = 0;
131 struct image_tlv_info info;
132#ifdef EXPECTED_SIG_TLV
133 int valid_signature = 0;
134 int key_id = -1;
135#endif
136 struct image_tlv tlv;
137 uint8_t buf[256];
Tamas Ban581034a2017-12-19 19:54:37 +0000138 uint8_t hash[32] = {0};
Tamas Banf70ef8c2017-12-19 15:35:09 +0000139 int rc;
140
141 rc = bootutil_img_hash(hdr, fap, tmp_buf, tmp_buf_sz, hash,
142 seed, seed_len);
143 if (rc) {
144 return rc;
145 }
146
147 if (out_hash) {
148 memcpy(out_hash, hash, 32);
149 }
150
151 /* The TLVs come after the image. */
152 /* After image there are TLVs. */
153 off = hdr->ih_img_size + hdr->ih_hdr_size;
154
155 rc = flash_area_read(fap, off, &info, sizeof(info));
156 if (rc) {
157 return rc;
158 }
159 if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
160 return -1;
161 }
162 end = off + info.it_tlv_tot;
163 off += sizeof(info);
164
165 /*
166 * Traverse through all of the TLVs, performing any checks we know
167 * and are able to do.
168 */
169 for (; off < end; off += sizeof(tlv) + tlv.it_len) {
Tamas Ban581034a2017-12-19 19:54:37 +0000170 rc = flash_area_read(fap, off, &tlv, sizeof(tlv));
Tamas Banf70ef8c2017-12-19 15:35:09 +0000171 if (rc) {
172 return rc;
173 }
174
175 if (tlv.it_type == IMAGE_TLV_SHA256) {
176 /*
177 * Verify the SHA256 image hash. This must always be
178 * present.
179 */
180 if (tlv.it_len != sizeof(hash)) {
181 return -1;
182 }
Tamas Ban581034a2017-12-19 19:54:37 +0000183 rc = flash_area_read(fap, off + sizeof(tlv), buf, sizeof(hash));
Tamas Banf70ef8c2017-12-19 15:35:09 +0000184 if (rc) {
185 return rc;
186 }
187 if (memcmp(hash, buf, sizeof(hash))) {
188 return -1;
189 }
190
191 sha256_valid = 1;
192#ifdef EXPECTED_SIG_TLV
193 } else if (tlv.it_type == IMAGE_TLV_KEYHASH) {
194 /*
195 * Determine which key we should be checking.
196 */
197 if (tlv.it_len > 32) {
198 return -1;
199 }
Tamas Ban581034a2017-12-19 19:54:37 +0000200 rc = flash_area_read(fap, off + sizeof(tlv), buf, tlv.it_len);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000201 if (rc) {
202 return rc;
203 }
204 key_id = bootutil_find_key(buf, tlv.it_len);
205 /*
206 * The key may not be found, which is acceptable. There
207 * can be multiple signatures, each preceded by a key.
208 */
209 } else if (tlv.it_type == EXPECTED_SIG_TLV) {
210 /* Ignore this signature if it is out of bounds. */
211 if (key_id < 0 || key_id >= bootutil_key_cnt) {
212 key_id = -1;
213 continue;
214 }
215 if (!EXPECTED_SIG_LEN(tlv.it_len) || tlv.it_len > sizeof(buf)) {
216 return -1;
217 }
218 rc = flash_area_read(fap, off + sizeof(tlv), buf, tlv.it_len);
219 if (rc) {
220 return -1;
221 }
Tamas Ban581034a2017-12-19 19:54:37 +0000222 rc = bootutil_verify_sig(hash, sizeof(hash), buf, tlv.it_len,
223 key_id);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000224 if (rc == 0) {
225 valid_signature = 1;
226 }
227 key_id = -1;
228#endif
229 }
230 }
231
232 if (!sha256_valid) {
233 return -1;
234 }
235
236#ifdef EXPECTED_SIG_TLV
237 if (!valid_signature) {
238 return -1;
239 }
240#endif
241
242 return 0;
243}