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