cmd: pxe: use strdup to copy config
[platform/kernel/u-boot.git] / boot / image-pre-load.c
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>
8 DECLARE_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  */
19 ulong 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  */
30 static 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
111 static 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
131 static 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  */
157 static 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
182 static 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
218 static 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
261 static 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
313 int 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
363 int 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 }