1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2021 Philippe Reynes <philippe.reynes@softathome.com>
4 */
5
6 #ifdef USE_HOSTCC
7 #include "mkimage.h"
8 #else
9 #include <asm/global_data.h>
10 #include <env.h>
11 #include <mapmem.h>
12 DECLARE_GLOBAL_DATA_PTR;
13 #endif /* !USE_HOSTCC*/
14
15 #include <image.h>
16 #include <u-boot/sha256.h>
17
18 #ifdef USE_HOSTCC
19 /* Define compat stuff for use in tools. */
20 typedef uint8_t u8;
21 typedef uint16_t u16;
22 typedef uint32_t u32;
23 #endif
24
25 /*
26 * Offset of the image
27 *
28 * This value is used to skip the header before really launching the image
29 */
30 ulong image_load_offset;
31
32 #ifdef USE_HOSTCC
33 /* Host tools use these implementations to setup information related to the
34 * pre-load signatures
35 */
36 static struct image_sig_info *host_info;
37
38 #define log_info(fmt, args...) printf(fmt, ##args)
39 #define log_err(fmt, args...) printf(fmt, ##args)
40
image_pre_load_sig_set_info(struct image_sig_info * info)41 void image_pre_load_sig_set_info(struct image_sig_info *info)
42 {
43 host_info = info;
44 }
45
46 /*
47 * This function sets a pointer to information for the signature check.
48 * It expects that host_info has been initially provision by the host
49 * application.
50 *
51 * return:
52 * < 0 => an error has occurred
53 * 0 => OK
54 */
image_pre_load_sig_setup(struct image_sig_info * info)55 static int image_pre_load_sig_setup(struct image_sig_info *info)
56 {
57 if (!info) {
58 log_err("ERROR: info is NULL\n");
59 return -EINVAL;
60 }
61
62 if (!host_info) {
63 log_err("ERROR: host_info is NULL\n");
64 log_err("ERROR: Set it with image_pre_load_sig_set_info()\n");
65 return -EINVAL;
66 }
67
68 memcpy(info, host_info, sizeof(struct image_sig_info));
69
70 return 0;
71 }
72 #else
73 /*
74 * This function gathers information about the signature check
75 * that could be done before launching the image.
76 *
77 * return:
78 * < 0 => an error has occurred
79 * 0 => OK
80 * 1 => no setup
81 */
image_pre_load_sig_setup(struct image_sig_info * info)82 static int image_pre_load_sig_setup(struct image_sig_info *info)
83 {
84 const void *algo_name, *padding_name, *key, *mandatory;
85 const u32 *sig_size;
86 int key_len;
87 int node, ret = 0;
88 char *sig_info_path = NULL;
89
90 if (!info) {
91 log_err("ERROR: info is NULL for image pre-load sig check\n");
92 ret = -EINVAL;
93 goto out;
94 }
95
96 memset(info, 0, sizeof(*info));
97
98 sig_info_path = env_get("pre_load_sig_info_path");
99 if (!sig_info_path)
100 sig_info_path = IMAGE_PRE_LOAD_PATH;
101
102 node = fdt_path_offset(gd_fdt_blob(), sig_info_path);
103 if (node < 0) {
104 log_info("INFO: no info for image pre-load sig check\n");
105 ret = 1;
106 goto out;
107 }
108
109 algo_name = fdt_getprop(gd_fdt_blob(), node,
110 IMAGE_PRE_LOAD_PROP_ALGO_NAME, NULL);
111 if (!algo_name) {
112 printf("ERROR: no algo_name for image pre-load sig check\n");
113 ret = -EINVAL;
114 goto out;
115 }
116
117 padding_name = fdt_getprop(gd_fdt_blob(), node,
118 IMAGE_PRE_LOAD_PROP_PADDING_NAME, NULL);
119 if (!padding_name) {
120 log_info("INFO: no padding_name provided, so using pkcs-1.5\n");
121 padding_name = "pkcs-1.5";
122 }
123
124 sig_size = fdt_getprop(gd_fdt_blob(), node,
125 IMAGE_PRE_LOAD_PROP_SIG_SIZE, NULL);
126 if (!sig_size) {
127 log_err("ERROR: no signature-size for image pre-load sig check\n");
128 ret = -EINVAL;
129 goto out;
130 }
131
132 key = fdt_getprop(gd_fdt_blob(), node,
133 IMAGE_PRE_LOAD_PROP_PUBLIC_KEY, &key_len);
134 if (!key) {
135 log_err("ERROR: no key for image pre-load sig check\n");
136 ret = -EINVAL;
137 goto out;
138 }
139
140 info->algo_name = (char *)algo_name;
141 info->padding_name = (char *)padding_name;
142 info->key = (uint8_t *)key;
143 info->key_len = key_len;
144 info->sig_size = fdt32_to_cpu(*sig_size);
145
146 mandatory = fdt_getprop(gd_fdt_blob(), node,
147 IMAGE_PRE_LOAD_PROP_MANDATORY, NULL);
148 if (mandatory && !strcmp((char *)mandatory, "yes"))
149 info->mandatory = 1;
150
151 /* Compute signature information */
152 info->sig_info.name = info->algo_name;
153 info->sig_info.padding = image_get_padding_algo(info->padding_name);
154 info->sig_info.checksum = image_get_checksum_algo(info->sig_info.name);
155 info->sig_info.crypto = image_get_crypto_algo(info->sig_info.name);
156 info->sig_info.key = info->key;
157 info->sig_info.keylen = info->key_len;
158
159 out:
160 return ret;
161 }
162 #endif /* !USE_HOSTCC */
163
image_pre_load_sig_get_magic(ulong addr,u32 * magic)164 static int image_pre_load_sig_get_magic(ulong addr, u32 *magic)
165 {
166 struct sig_header_s *sig_header;
167 int ret = 0;
168
169 sig_header = (struct sig_header_s *)map_sysmem(addr, SIG_HEADER_LEN);
170 if (!sig_header) {
171 log_err("ERROR: can't map first header\n");
172 ret = -EFAULT;
173 goto out;
174 }
175
176 *magic = fdt32_to_cpu(sig_header->magic);
177
178 unmap_sysmem(sig_header);
179
180 out:
181 return ret;
182 }
183
image_pre_load_sig_get_header_size(ulong addr,u32 * header_size)184 static int image_pre_load_sig_get_header_size(ulong addr, u32 *header_size)
185 {
186 struct sig_header_s *sig_header;
187 int ret = 0;
188
189 sig_header = (struct sig_header_s *)map_sysmem(addr, SIG_HEADER_LEN);
190 if (!sig_header) {
191 log_err("ERROR: can't map first header\n");
192 ret = -EFAULT;
193 goto out;
194 }
195
196 *header_size = fdt32_to_cpu(sig_header->header_size);
197
198 unmap_sysmem(sig_header);
199
200 out:
201 return ret;
202 }
203
204 /*
205 * return:
206 * < 0 => no magic and magic mandatory (or error when reading magic)
207 * 0 => magic found
208 * 1 => magic NOT found
209 */
image_pre_load_sig_check_magic(struct image_sig_info * info,ulong addr)210 static int image_pre_load_sig_check_magic(struct image_sig_info *info, ulong addr)
211 {
212 u32 magic;
213 int ret = 1;
214
215 ret = image_pre_load_sig_get_magic(addr, &magic);
216 if (ret < 0)
217 goto out;
218
219 if (magic != IMAGE_PRE_LOAD_SIG_MAGIC) {
220 if (info->mandatory) {
221 log_err("ERROR: signature is mandatory\n");
222 ret = -EINVAL;
223 goto out;
224 }
225 ret = 1;
226 goto out;
227 }
228
229 ret = 0; /* magic found */
230
231 out:
232 return ret;
233 }
234
image_pre_load_sig_check_header_sig(struct image_sig_info * info,ulong addr)235 static int image_pre_load_sig_check_header_sig(struct image_sig_info *info, ulong addr)
236 {
237 void *header;
238 struct image_region reg;
239 u32 sig_len;
240 u8 *sig;
241 int ret = 0;
242
243 /* Only map header of the header and its signature */
244 header = (void *)map_sysmem(addr, SIG_HEADER_LEN + info->sig_size);
245 if (!header) {
246 log_err("ERROR: can't map header\n");
247 ret = -EFAULT;
248 goto out;
249 }
250
251 reg.data = header;
252 reg.size = SIG_HEADER_LEN;
253
254 sig = (uint8_t *)header + SIG_HEADER_LEN;
255 sig_len = info->sig_size;
256
257 ret = info->sig_info.crypto->verify(&info->sig_info, ®, 1, sig, sig_len);
258 if (ret) {
259 log_err("ERROR: header signature check has failed (err=%d)\n", ret);
260 ret = -EINVAL;
261 goto out_unmap;
262 }
263
264 out_unmap:
265 unmap_sysmem(header);
266
267 out:
268 return ret;
269 }
270
image_pre_load_sig_check_img_sig_sha256(struct image_sig_info * info,ulong addr)271 static int image_pre_load_sig_check_img_sig_sha256(struct image_sig_info *info, ulong addr)
272 {
273 struct sig_header_s *sig_header;
274 u32 header_size, offset_img_sig;
275 void *header;
276 u8 sha256_img_sig[SHA256_SUM_LEN];
277 int ret = 0;
278
279 sig_header = (struct sig_header_s *)map_sysmem(addr, SIG_HEADER_LEN);
280 if (!sig_header) {
281 log_err("ERROR: can't map first header\n");
282 ret = -EFAULT;
283 goto out;
284 }
285
286 header_size = fdt32_to_cpu(sig_header->header_size);
287 offset_img_sig = fdt32_to_cpu(sig_header->offset_img_sig);
288
289 header = (void *)map_sysmem(addr, header_size);
290 if (!header) {
291 log_err("ERROR: can't map header\n");
292 ret = -EFAULT;
293 goto out_sig_header;
294 }
295
296 sha256_csum_wd(header + offset_img_sig, info->sig_size,
297 sha256_img_sig, CHUNKSZ_SHA256);
298
299 ret = memcmp(sig_header->sha256_img_sig, sha256_img_sig, SHA256_SUM_LEN);
300 if (ret) {
301 log_err("ERROR: sha256 of image signature is invalid\n");
302 ret = -EFAULT;
303 goto out_header;
304 }
305
306 out_header:
307 unmap_sysmem(header);
308 out_sig_header:
309 unmap_sysmem(sig_header);
310 out:
311 return ret;
312 }
313
image_pre_load_sig_check_img_sig(struct image_sig_info * info,ulong addr)314 static int image_pre_load_sig_check_img_sig(struct image_sig_info *info, ulong addr)
315 {
316 struct sig_header_s *sig_header;
317 u32 header_size, image_size, offset_img_sig;
318 void *image;
319 struct image_region reg;
320 u32 sig_len;
321 u8 *sig;
322 int ret = 0;
323
324 sig_header = (struct sig_header_s *)map_sysmem(addr, SIG_HEADER_LEN);
325 if (!sig_header) {
326 log_err("ERROR: can't map first header\n");
327 ret = -EFAULT;
328 goto out;
329 }
330
331 header_size = fdt32_to_cpu(sig_header->header_size);
332 image_size = fdt32_to_cpu(sig_header->image_size);
333 offset_img_sig = fdt32_to_cpu(sig_header->offset_img_sig);
334
335 unmap_sysmem(sig_header);
336
337 image = (void *)map_sysmem(addr, header_size + image_size);
338 if (!image) {
339 log_err("ERROR: can't map full image\n");
340 ret = -EFAULT;
341 goto out;
342 }
343
344 reg.data = image + header_size;
345 reg.size = image_size;
346
347 sig = (uint8_t *)image + offset_img_sig;
348 sig_len = info->sig_size;
349
350 ret = info->sig_info.crypto->verify(&info->sig_info, ®, 1, sig, sig_len);
351 if (ret) {
352 log_err("ERROR: signature check has failed (err=%d)\n", ret);
353 ret = -EINVAL;
354 goto out_unmap_image;
355 }
356
357 log_info("INFO: signature check has succeed\n");
358
359 out_unmap_image:
360 unmap_sysmem(image);
361
362 out:
363 return ret;
364 }
365
image_pre_load_sig(ulong addr)366 int image_pre_load_sig(ulong addr)
367 {
368 struct image_sig_info info;
369 int ret;
370
371 ret = image_pre_load_sig_setup(&info);
372 if (ret < 0)
373 goto out;
374 if (ret > 0) {
375 ret = 0;
376 goto out;
377 }
378
379 ret = image_pre_load_sig_check_magic(&info, addr);
380 if (ret < 0)
381 goto out;
382 if (ret > 0) {
383 ret = 0;
384 goto out;
385 }
386
387 /* Check the signature of the signature header */
388 ret = image_pre_load_sig_check_header_sig(&info, addr);
389 if (ret < 0)
390 goto out;
391
392 /* Check sha256 of the image signature */
393 ret = image_pre_load_sig_check_img_sig_sha256(&info, addr);
394 if (ret < 0)
395 goto out;
396
397 /* Check the image signature */
398 ret = image_pre_load_sig_check_img_sig(&info, addr);
399 if (!ret) {
400 u32 header_size;
401
402 ret = image_pre_load_sig_get_header_size(addr, &header_size);
403 if (ret) {
404 log_err("%s: can't get header size\n", __func__);
405 ret = -EINVAL;
406 goto out;
407 }
408
409 image_load_offset += header_size;
410 }
411
412 out:
413 return ret;
414 }
415
image_pre_load(ulong addr)416 int image_pre_load(ulong addr)
417 {
418 int ret = 0;
419
420 image_load_offset = 0;
421
422 if (CONFIG_IS_ENABLED(IMAGE_PRE_LOAD_SIG))
423 ret = image_pre_load_sig(addr);
424
425 return ret;
426 }
427