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