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