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