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