blob: 191eb53d04ad63298bf121d7c2d77e2f4c2289d5 [file] [log] [blame]
developer23f9f0f2023-06-15 13:06:25 +08001--- a/include/image.mk
2+++ b/include/image.mk
3@@ -443,7 +443,10 @@ endif
4 ROOTFS_ENCRYPT = $(if $(ROE_KEY_DIR),$(wildcard $(ROE_KEY_DIR)/$(ROE_KEY_NAME).key),)
5
6 DEVICE_CHECK_FIT_KEY = $(if $(wildcard $(FIT_KEY_DIR)/$(FIT_KEY_NAME).key),install-images,install-disabled)
7-DEVICE_CHECK_FIT_DIR = $(if $(FIT_KEY_DIR),$(DEVICE_CHECK_FIT_KEY),install-images)
8+DEVICE_CHECK_FIT_DIR = $(if $(FIT_KEY_DIR),$(DEVICE_CHECK_FIT_KEY),install-disabled)
9+
10+DEVICE_CHECK_OFFLINE_FIT_KEY = $(if $(filter offline%,$(FIT_KEY_NAME)),install-images,$(DEVICE_CHECK_FIT_DIR))
11+DEVICE_CHECK_FIT_KEY_NAME = $(if $(FIT_KEY_NAME),$(DEVICE_CHECK_OFFLINE_FIT_KEY),install-images)
12
13 DEVICE_EXTRA_PACKAGES = $(call qstrip,$(CONFIG_TARGET_DEVICE_PACKAGES_$(call target_conf,$(BOARD)$(if $(SUBTARGET),_$(SUBTARGET)))_DEVICE_$(1)))
14
15@@ -467,7 +470,7 @@ endef
16 define Device/Check
17 $(Device/Check/Common)
18 KDIR_KERNEL_IMAGE := $(KDIR)/$(1)$$(KERNEL_SUFFIX)
19- _TARGET := $$(if $$(_PROFILE_SET),$$(DEVICE_CHECK_FIT_DIR),install-disabled)
20+ _TARGET := $$(if $$(_PROFILE_SET),$$(DEVICE_CHECK_FIT_KEY_NAME),install-disabled)
21 ifndef IB
22 _COMPILE_TARGET := $$(if $(CONFIG_IB)$$(_PROFILE_SET),compile,compile-disabled)
23 endif
24--- a/scripts/mkits.sh
25+++ b/scripts/mkits.sh
26@@ -164,11 +164,17 @@ fi
27
28 # Conditionally create signature information
29 if [ -n "${KEY_NAME_HINT}" ]; then
30+ if [[ "${KEY_NAME_HINT}" == "offline,"* ]]; then
31+ KEY_NAME_HINT=$(echo -n "${KEY_NAME_HINT}" | sed "s/^.*[,]//g")
32+ SIGN_OFFLINE="
33+ sign-offline = <1>;"
34+ fi
35 SIGNATURE="\
36 signature {
37 algo = \"sha1,rsa2048\";
38 key-name-hint = \"${KEY_NAME_HINT}\";
39 ${SIGN_IMAGES}
40+${SIGN_OFFLINE}
41 };\
42 "
43 fi
44--- /dev/null
45+++ b/tools/mkimage/patches/901-mtk-mkimage-add-offline-sign-support.patch
46@@ -0,0 +1,382 @@
47+--- a/tools/image-host.c
48++++ b/tools/image-host.c
49+@@ -168,6 +168,9 @@ static int fit_image_setup_sig(struct im
50+ {
51+ const char *node_name;
52+ const char *padding_name;
53++ const char *offline;
54++ const char offline_suffix[] = ",offline";
55++ char *offline_algo_name = NULL;
56+
57+ node_name = fit_get_name(fit, noffset, NULL);
58+ if (!algo_name) {
59+@@ -188,7 +191,21 @@ static int fit_image_setup_sig(struct im
60+ info->node_offset = noffset;
61+ info->name = strdup(algo_name);
62+ info->checksum = image_get_checksum_algo(algo_name);
63+- info->crypto = image_get_crypto_algo(algo_name);
64++
65++ offline = fdt_getprop(fit, noffset, "sign-offline", NULL);
66++ if (offline) {
67++ offline_algo_name = calloc(strlen(algo_name) + strlen(offline_suffix) + 1, sizeof(char));
68++ if (!offline_algo_name)
69++ return -ENOMEM;
70++
71++ strcpy(offline_algo_name, algo_name);
72++ strcat(offline_algo_name, offline_suffix);
73++
74++ info->crypto = image_get_crypto_algo(offline_algo_name);
75++ } else {
76++ info->crypto = image_get_crypto_algo(algo_name);
77++ }
78++
79+ info->padding = image_get_padding_algo(padding_name);
80+ info->require_keys = require_keys;
81+ info->engine_id = engine_id;
82+--- a/tools/image-sig-host.c
83++++ b/tools/image-sig-host.c
84+@@ -11,6 +11,7 @@
85+ #include <u-boot/ecdsa.h>
86+ #include <u-boot/rsa.h>
87+ #include <u-boot/hash-checksum.h>
88++#include "signoffline.h"
89+
90+ struct checksum_algo checksum_algos[] = {
91+ {
92+@@ -76,6 +77,27 @@ struct crypto_algo crypto_algos[] = {
93+ .add_verify_data = ecdsa_add_verify_data,
94+ .verify = ecdsa_verify,
95+ },
96++ {
97++ .name = "rsa2048,offline",
98++ .key_len = RSA2048_BYTES,
99++ .sign = offline_sign,
100++ .add_verify_data = rsa_add_verify_data,
101++ .verify = offline_verify,
102++ },
103++ {
104++ .name = "rsa3072,offline",
105++ .key_len = RSA3072_BYTES,
106++ .sign = offline_sign,
107++ .add_verify_data = rsa_add_verify_data,
108++ .verify = offline_verify,
109++ },
110++ {
111++ .name = "rsa4096,offline",
112++ .key_len = RSA4096_BYTES,
113++ .sign = offline_sign,
114++ .add_verify_data = rsa_add_verify_data,
115++ .verify = offline_verify,
116++ },
117+ };
118+
119+ struct padding_algo padding_algos[] = {
120+--- a/tools/Makefile
121++++ b/tools/Makefile
122+@@ -89,6 +89,8 @@ RSA_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := $(
123+ rsa-sign.o rsa-verify.o \
124+ rsa-mod-exp.o)
125+
126++SIGNOFFLINE_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := signoffline.o
127++
128+ ECDSA_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := $(addprefix lib/ecdsa/, ecdsa-libcrypto.o)
129+
130+ AES_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := $(addprefix lib/aes/, \
131+@@ -149,7 +151,8 @@ dumpimage-mkimage-objs := aisimage.o \
132+ mtk_image.o \
133+ $(ECDSA_OBJS-y) \
134+ $(RSA_OBJS-y) \
135+- $(AES_OBJS-y)
136++ $(AES_OBJS-y) \
137++ $(SIGNOFFLINE_OBJS-y)
138+
139+ dumpimage-objs := $(dumpimage-mkimage-objs) dumpimage.o
140+ mkimage-objs := $(dumpimage-mkimage-objs) mkimage.o
141+--- /dev/null
142++++ b/tools/signoffline.h
143+@@ -0,0 +1,18 @@
144++// SPDX-License-Identifier: GPL-2.0+
145++/*
146++ * Copyright (C) 2022 MediaTek Incorporation. All Rights Reserved.
147++ *
148++ */
149++
150++#ifndef SIGNOFFLINE_H_
151++#define SIGNOFFLINE_H_
152++
153++int offline_sign(struct image_sign_info *info,
154++ const struct image_region region[], int region_count,
155++ uint8_t **sigp, uint *sig_len);
156++
157++int offline_verify(struct image_sign_info *info,
158++ const struct image_region region[], int region_count,
159++ uint8_t *sig, uint sig_len);
160++
161++#endif /* SIGNOFFLINE_H_ */
162+--- /dev/null
163++++ b/tools/signoffline.c
164+@@ -0,0 +1,264 @@
165++// SPDX-License-Identifier: GPL-2.0+
166++/*
167++ * Copyright (C) 2022 MediaTek Incorporation. All Rights Reserved.
168++ *
169++ */
170++#include <stdio.h>
171++#include <stdint.h>
172++#include <image.h>
173++#include <linux/libfdt.h>
174++#include <malloc.h>
175++#include <u-boot/sha512.h>
176++#include "mkimage.h"
177++
178++#define OFFSIGN_MSG_FILE ".msg"
179++#define OFFSIGN_SIG_FILE ".sig"
180++#define OFFSIGN_MAX_TMPFILE_LEN 256
181++#define OFFSIGN_MAX_CMDLINE_LEN 3 * OFFSIGN_MAX_TMPFILE_LEN + 128 + 1
182++#define OPENSSL_PKEYUTL_CMD "openssl pkeyutl"
183++#define OPENSSL_PKEYUTL_OPER "-sign"
184++#define OPENSSL_PKEYUTL_PADDING "-pkeyopt rsa_padding_mode"
185++#define OPENSSL_PKEYUTL_SALT "-pkeyopt rsa_pss_saltlen:32"
186++
187++static char img_prefix[OFFSIGN_MAX_TMPFILE_LEN];
188++
189++static int get_fit_identifier(const void *fit, char *img_prefix)
190++{
191++ int ret = 0;
192++ int noffset = 0;
193++ int img_noffset = 0;
194++ int len = 0;
195++ const char *prop = NULL;
196++ char *p = NULL, *end_p = NULL;
197++
198++ img_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
199++ if (img_noffset < 0) {
200++ fprintf(stderr, "Can't find image parent node: %s\n", FIT_IMAGES_PATH);
201++ return img_noffset;
202++ }
203++
204++ noffset = fdt_subnode_offset(fit, img_noffset, "fdt-1");
205++ if (noffset < 0) {
206++ fprintf(stderr, "Can't find fdt-1 node in %s\n", FIT_IMAGES_PATH);
207++ return noffset;
208++ }
209++
210++ prop = fdt_getprop(fit, noffset, FIT_DESC_PROP, &len);
211++ if (!prop) {
212++ fprintf(stderr, "Can't find %s property in node: fdt-1\n", FIT_DESC_PROP);
213++ return -EINVAL;
214++ }
215++
216++ /* find FIT image name as tmpfile prefix */
217++ p = strstr(prop, "OpenWrt ");
218++ if (!p)
219++ return -EINVAL;
220++
221++ p = strchr(p, ' ');
222++ if (!p)
223++ return -EINVAL;
224++ p += 1;
225++
226++ end_p = strchr(p, ' ');
227++ if (!end_p)
228++ return -EINVAL;
229++
230++ if ((end_p - p) >= OFFSIGN_MAX_TMPFILE_LEN)
231++ return -EINVAL;
232++
233++ strncpy(img_prefix, p, end_p - p);
234++
235++ return ret;
236++}
237++
238++static int prepare_offline_sign(struct image_sign_info *info,
239++ const struct image_region region[],
240++ int region_count)
241++{
242++ int ret = 0;
243++ size_t len = 0;
244++ FILE *f = NULL;
245++ char msg_file[OFFSIGN_MAX_TMPFILE_LEN] = {0};
246++ uint8_t checksum[SHA512_SUM_LEN] = {0};
247++
248++ ret = get_fit_identifier(info->fit, img_prefix);
249++ if (ret)
250++ return ret;
251++
252++ len = snprintf(msg_file, sizeof(msg_file),
253++ "%s/%s%s", info->keydir, img_prefix, OFFSIGN_MSG_FILE);
254++ if (len < 0)
255++ return -EINVAL;
256++
257++ /* calculate digest */
258++ ret = info->checksum->calculate(info->checksum->name, region,
259++ region_count, checksum);
260++ if (ret) {
261++ fprintf(stderr, "Failed to calculate checksum of regions\n");
262++ return ret;
263++ }
264++
265++ /* write message to be signed to msg_file */
266++ f = fopen(msg_file, "w");
267++ if (!f) {
268++ fprintf(stderr, "Failed to open %s\n", msg_file);
269++ return -EINVAL;
270++ }
271++
272++ len = fwrite(checksum, sizeof(uint8_t),
273++ info->checksum->checksum_len, f);
274++ if (len < 0) {
275++ fprintf(stderr, "Failed to write to %s\n", msg_file);
276++ ret = -EINVAL;
277++ }
278++
279++ fclose(f);
280++
281++ return ret;
282++}
283++
284++static int sign_offline(struct image_sign_info *info,
285++ const struct image_region region[],
286++ int region_count,
287++ uint8_t **sigp, uint *sig_len)
288++{
289++ int ret = 0;
290++ size_t len = 0;
291++ char cmd[OFFSIGN_MAX_CMDLINE_LEN] = {0};
292++ char padding[8] = {0};
293++
294++ /* check padding */
295++ if (info->padding && !strcmp(info->padding->name, "pss"))
296++ strncpy(padding, "pss", sizeof(padding));
297++ else
298++ strncpy(padding, "pkcs1", sizeof(padding));
299++
300++ len = snprintf(cmd, sizeof(cmd),
301++ "%s %s -in %s/%s%s -inkey %s/%s.key -out %s/%s%s -pkeyopt digest:%s %s:%s",
302++ OPENSSL_PKEYUTL_CMD,
303++ OPENSSL_PKEYUTL_OPER,
304++ info->keydir,
305++ img_prefix,
306++ OFFSIGN_MSG_FILE,
307++ info->keydir,
308++ info->keyname,
309++ info->keydir,
310++ img_prefix,
311++ OFFSIGN_SIG_FILE,
312++ info->checksum->name,
313++ OPENSSL_PKEYUTL_PADDING,
314++ padding);
315++ if (len < 0)
316++ return -EINVAL;
317++
318++ if (!strcmp(padding, "pss")) {
319++ len = snprintf(cmd + len, sizeof(cmd), "%s", OPENSSL_PKEYUTL_SALT);
320++ if (len < 0)
321++ return -EINVAL;
322++ }
323++
324++ printf("%s\n", cmd);
325++
326++ /* execute openssl command */
327++ if (system(cmd) == -1) {
328++ fprintf(stderr,"%s: failed to sign FIT\n", OPENSSL_PKEYUTL_CMD);
329++ return -EINVAL;
330++ }
331++
332++ return ret;
333++}
334++
335++static int post_offline_sign(struct image_sign_info *info,
336++ uint8_t **sigp, uint *sig_len)
337++{
338++ int ret = 0;
339++ FILE *f = NULL;
340++ size_t len = 0;
341++ void *sig = NULL;
342++ char sig_file[OFFSIGN_MAX_TMPFILE_LEN] = {0};
343++
344++ len = snprintf(sig_file, sizeof(sig_file),
345++ "%s/%s%s", info->keydir, img_prefix, OFFSIGN_SIG_FILE);
346++ if (len < 0)
347++ return -EINVAL;
348++
349++ /* read signature from sig_file */
350++ f = fopen(sig_file, "rb");
351++ if (!f) {
352++ fprintf(stderr, "Failed to open %s\n", sig_file);
353++ return -EINVAL;
354++ }
355++
356++ sig = calloc(info->crypto->key_len, sizeof(uint8_t));
357++ if (!sig) {
358++ ret = -ENOMEM;
359++ goto post_offline_sign_err;
360++ }
361++
362++ len = fread(sig, sizeof(uint8_t), info->crypto->key_len, f);
363++ if (len < 0) {
364++ fprintf(stderr, "Failed to read from %s\n", sig_file);
365++ ret = -EINVAL;
366++ goto post_offline_sign_err;
367++ }
368++
369++ if (len != info->crypto->key_len) {
370++ fprintf(stderr, "Signature length is invalid\n");
371++ ret = -EINVAL;
372++ goto post_offline_sign_err;
373++ }
374++
375++ fclose(f);
376++
377++ *sigp = sig;
378++ *sig_len= info->crypto->key_len;
379++
380++ return 0;
381++
382++post_offline_sign_err:
383++ fclose(f);
384++ if (sig)
385++ free(sig);
386++
387++ return ret;
388++}
389++
390++int offline_sign(struct image_sign_info *info,
391++ const struct image_region region[], int region_count,
392++ uint8_t **sigp, uint *sig_len)
393++{
394++ int ret = 0;
395++
396++ printf("%s:\n", __func__);
397++
398++ ret = prepare_offline_sign(info, region, region_count);
399++ if (ret) {
400++ fprintf(stderr, "prepare_offline_sign() failed\n");
401++ return -EINVAL;
402++ }
403++
404++ ret = sign_offline(info, region, region_count, sigp, sig_len);
405++ if (ret) {
406++ fprintf(stderr, "sign_offline() failed\n");
407++ return -EINVAL;
408++ }
409++
410++ ret = post_offline_sign(info, sigp, sig_len);
411++ if (ret) {
412++ fprintf(stderr, "post_offline_sign() failed\n");
413++ return -EINVAL;
414++ }
415++
416++ return ret;
417++}
418++
419++int offline_verify(struct image_sign_info *info,
420++ const struct image_region region[], int region_count,
421++ uint8_t *sig, uint sig_len)
422++{
423++ int ret = 0;
424++
425++ printf("%s:\n", __func__);
426++
427++ return ret;
428++}