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, &reg, 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, &reg, 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