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