* [PATCH v4] FIT support
@ 2016-01-22 7:32 Sascha Hauer
2016-01-22 7:32 ` [PATCH 01/14] ARM: zImage: add missing free() in appended device tree code Sascha Hauer
` (13 more replies)
0 siblings, 14 replies; 15+ messages in thread
From: Sascha Hauer @ 2016-01-22 7:32 UTC (permalink / raw)
To: Barebox List
This is the fourth version of the FIT image support. Changes to last series
include:
Changes since v3:
- Add option to force booting signed images
- Add reference to U-Boot in RSA support commit message and file
- Add reference to U-Boot in FIT image support
- Write some more Kconfig doc
Changes since v2:
- Integrate FIT support more deeply into bootm remove complexity
from the architecture handlers
- Cleanup bootm support
- Add support for configuration names as suggested by Yegor Yefremov
- Allow to boot unsigned FIT images
----------------------------------------------------------------
Jan Luebbe (1):
bootm: add initial FIT support
Sascha Hauer (13):
ARM: zImage: add missing free() in appended device tree code
bootm: Do not call uimage_close twice
bootm: introduce bootm_get_os_size
bootm: use names instead of numbers for image parts
ARM: bootm: Use kernel handler to start barebox image
bootm: Push dryrun to handlers
bootm: move initrd code together
bootm: move oftree code together
bootm: Initialize bootm_data defaults in single place
crypto: add digest_alloc_by_algo()
crypto: add RSA support
bootm: make verifying/hashing configurable
bootm: Add option to force booting signed images
arch/arm/crypto/sha1_glue.c | 1 +
arch/arm/crypto/sha256_glue.c | 2 +
arch/arm/lib/bootm.c | 52 ++--
arch/arm/mach-omap/omap_generic.c | 5 +
arch/blackfin/lib/blackfin_linux.c | 3 +
arch/efi/efi/efi-image.c | 9 +-
arch/mips/lib/bootm.c | 5 +
arch/nios2/lib/bootm.c | 3 +
arch/ppc/lib/ppclinux.c | 3 +
commands/Kconfig | 25 ++
commands/boot.c | 14 +-
commands/bootm.c | 46 +--
common/Kconfig | 9 +
common/Makefile | 1 +
common/bootm.c | 482 ++++++++++++++++++------------
common/image-fit.c | 584 +++++++++++++++++++++++++++++++++++++
crypto/Kconfig | 3 +
crypto/Makefile | 1 +
crypto/digest.c | 43 ++-
crypto/md5.c | 1 +
crypto/rsa.c | 422 +++++++++++++++++++++++++++
crypto/sha1.c | 1 +
crypto/sha2.c | 2 +
crypto/sha4.c | 2 +
include/asm-generic/errno.h | 5 +
include/boot.h | 28 +-
include/digest.h | 23 ++
include/image-fit.h | 45 +++
include/rsa.h | 54 ++++
29 files changed, 1599 insertions(+), 275 deletions(-)
create mode 100644 common/image-fit.c
create mode 100644 crypto/rsa.c
create mode 100644 include/image-fit.h
create mode 100644 include/rsa.h
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 01/14] ARM: zImage: add missing free() in appended device tree code
2016-01-22 7:32 [PATCH v4] FIT support Sascha Hauer
@ 2016-01-22 7:32 ` Sascha Hauer
2016-01-22 7:32 ` [PATCH 02/14] bootm: Do not call uimage_close twice Sascha Hauer
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2016-01-22 7:32 UTC (permalink / raw)
To: Barebox List
oftree must be freed when the tree is successfully unflattened.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/lib/bootm.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 7bb9b43..2439c36 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -223,6 +223,7 @@ static int do_bootz_linux_fdt(int fd, struct image_data *data)
ret = -EINVAL;
goto err_free;
}
+ free(oftree);
} else {
data->oftree = oftree;
}
--
2.7.0.rc3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 02/14] bootm: Do not call uimage_close twice
2016-01-22 7:32 [PATCH v4] FIT support Sascha Hauer
2016-01-22 7:32 ` [PATCH 01/14] ARM: zImage: add missing free() in appended device tree code Sascha Hauer
@ 2016-01-22 7:32 ` Sascha Hauer
2016-01-22 7:32 ` [PATCH 03/14] bootm: introduce bootm_get_os_size Sascha Hauer
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2016-01-22 7:32 UTC (permalink / raw)
To: Barebox List
uimage_close() is called on bootm cleanup, so do not close it
in the failure path in bootm_open_os_uimage().
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/bootm.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/common/bootm.c b/common/bootm.c
index 08125e7..affab24 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -208,7 +208,6 @@ static int bootm_open_os_uimage(struct image_data *data)
if (data->os->header.ih_arch != IH_ARCH) {
printf("Unsupported Architecture 0x%x\n",
data->os->header.ih_arch);
- uimage_close(data->os);
return -EINVAL;
}
--
2.7.0.rc3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 03/14] bootm: introduce bootm_get_os_size
2016-01-22 7:32 [PATCH v4] FIT support Sascha Hauer
2016-01-22 7:32 ` [PATCH 01/14] ARM: zImage: add missing free() in appended device tree code Sascha Hauer
2016-01-22 7:32 ` [PATCH 02/14] bootm: Do not call uimage_close twice Sascha Hauer
@ 2016-01-22 7:32 ` Sascha Hauer
2016-01-22 7:32 ` [PATCH 04/14] bootm: use names instead of numbers for image parts Sascha Hauer
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2016-01-22 7:32 UTC (permalink / raw)
To: Barebox List
ARM do_bootm_linux is not only called with uImages but also with
raw images, so we can't use uimage_get_size() here. Introduce
bootm_get_os_size() which handles the different image types.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/lib/bootm.c | 2 +-
common/bootm.c | 19 +++++++++++++++++++
include/boot.h | 1 +
3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 2439c36..0855907 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -135,7 +135,7 @@ static int do_bootm_linux(struct image_data *data)
* relocate itself before decompression.
*/
load_address = mem_start + PAGE_ALIGN(
- uimage_get_size(data->os, data->os_num) * 4);
+ bootm_get_os_size(data) * 4);
if (bootm_verbose(data))
printf("no OS load address, defaulting to 0x%08lx\n",
load_address);
diff --git a/common/bootm.c b/common/bootm.c
index affab24..a38d7e0 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -19,6 +19,7 @@
#include <libfile.h>
#include <globalvar.h>
#include <init.h>
+#include <linux/stat.h>
static LIST_HEAD(handler_list);
@@ -185,6 +186,24 @@ int bootm_load_devicetree(struct image_data *data, unsigned long load_address)
return 0;
}
+int bootm_get_os_size(struct image_data *data)
+{
+ int ret;
+
+ if (data->os)
+ return uimage_get_size(data->os, data->os_num);
+
+ if (data->os_file) {
+ struct stat s;
+ ret = stat(data->os_file, &s);
+ if (ret)
+ return ret;
+ return s.st_size;
+ }
+
+ return -EINVAL;
+}
+
static int bootm_open_os_uimage(struct image_data *data)
{
int ret;
diff --git a/include/boot.h b/include/boot.h
index bdd5477..b172c05 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -112,6 +112,7 @@ static inline int linux_bootargs_overwrite(const char *bootargs)
int bootm_load_os(struct image_data *data, unsigned long load_address);
int bootm_load_initrd(struct image_data *data, unsigned long load_address);
int bootm_load_devicetree(struct image_data *data, unsigned long load_address);
+int bootm_get_os_size(struct image_data *data);
#define UIMAGE_SOME_ADDRESS (UIMAGE_INVALID_ADDRESS - 1)
--
2.7.0.rc3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 04/14] bootm: use names instead of numbers for image parts
2016-01-22 7:32 [PATCH v4] FIT support Sascha Hauer
` (2 preceding siblings ...)
2016-01-22 7:32 ` [PATCH 03/14] bootm: introduce bootm_get_os_size Sascha Hauer
@ 2016-01-22 7:32 ` Sascha Hauer
2016-01-22 7:32 ` [PATCH 05/14] ARM: bootm: Use kernel handler to start barebox image Sascha Hauer
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2016-01-22 7:32 UTC (permalink / raw)
To: Barebox List
The uImage format uses numbers for to identify the different
parts of a image, but the FIT image format uses names. To better
integrate the FIT image format into bootm always use names and
convert them to numbers when necessary.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/bootm.c | 43 +++++++++++++++++++++++++++----------------
include/boot.h | 6 +++---
2 files changed, 30 insertions(+), 19 deletions(-)
diff --git a/common/bootm.c b/common/bootm.c
index a38d7e0..f8d9330 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -68,8 +68,12 @@ int bootm_load_os(struct image_data *data, unsigned long load_address)
return -EINVAL;
if (data->os) {
+ int num;
+
+ num = simple_strtoul(data->os_part, NULL, 0);
+
data->os_res = uimage_load_to_sdram(data->os,
- data->os_num, load_address);
+ num, load_address);
if (!data->os_res)
return -ENOMEM;
@@ -106,8 +110,12 @@ int bootm_load_initrd(struct image_data *data, unsigned long load_address)
return 0;
if (data->initrd) {
+ int num;
+
+ num = simple_strtoul(data->initrd_part, NULL, 0);
+
data->initrd_res = uimage_load_to_sdram(data->initrd,
- data->initrd_num, load_address);
+ num, load_address);
if (!data->initrd_res)
return -ENOMEM;
@@ -191,7 +199,8 @@ int bootm_get_os_size(struct image_data *data)
int ret;
if (data->os)
- return uimage_get_size(data->os, data->os_num);
+ return uimage_get_size(data->os,
+ simple_strtoul(data->os_part, NULL, 0));
if (data->os_file) {
struct stat s;
@@ -268,7 +277,7 @@ static int bootm_open_oftree_uimage(struct image_data *data)
struct fdt_header *fdt;
enum filetype ft;
const char *oftree = data->oftree_file;
- int num = data->oftree_num;
+ int num = simple_strtoul(data->oftree_part, NULL, 0);
struct uimage_handle *of_handle;
int release = 0;
size_t size;
@@ -358,7 +367,7 @@ static void bootm_print_info(struct image_data *data)
data->initrd_file);
if (initrd_type == filetype_uimage &&
data->initrd->header.ih_type == IH_TYPE_MULTI)
- printf(", multifile image %d", data->initrd_num);
+ printf(", multifile image %s", data->initrd_part);
printf("\n");
if (data->initrd_res)
printf("initrd is at " PRINTF_CONVERSION_RESOURCE "-" PRINTF_CONVERSION_RESOURCE "\n",
@@ -369,25 +378,27 @@ static void bootm_print_info(struct image_data *data)
}
}
-static char *bootm_image_name_and_no(const char *name, int *no)
+static int bootm_image_name_and_part(const char *name, char **filename, char **part)
{
char *at, *ret;
if (!name || !*name)
- return NULL;
-
- *no = 0;
+ return -EINVAL;
ret = xstrdup(name);
+
+ *filename = ret;
+ *part = NULL;
+
at = strchr(ret, '@');
if (!at)
- return ret;
+ return 0;
*at++ = 0;
- *no = simple_strtoul(at, NULL, 10);
+ *part = at;
- return ret;
+ return 0;
}
/*
@@ -408,9 +419,9 @@ int bootm_boot(struct bootm_data *bootm_data)
data = xzalloc(sizeof(*data));
- data->os_file = bootm_image_name_and_no(bootm_data->os_file, &data->os_num);
- data->oftree_file = bootm_image_name_and_no(bootm_data->oftree_file, &data->oftree_num);
- data->initrd_file = bootm_image_name_and_no(bootm_data->initrd_file, &data->initrd_num);
+ bootm_image_name_and_part(bootm_data->os_file, &data->os_file, &data->os_part);
+ bootm_image_name_and_part(bootm_data->oftree_file, &data->oftree_part, &data->os_part);
+ bootm_image_name_and_part(bootm_data->initrd_file, &data->initrd_part, &data->os_part);
data->verbose = bootm_data->verbose;
data->verify = bootm_data->verify;
data->force = bootm_data->force;
@@ -479,7 +490,7 @@ int bootm_boot(struct bootm_data *bootm_data)
data->os_file);
if (os_type == filetype_uimage &&
data->os->header.ih_type == IH_TYPE_MULTI)
- printf(", multifile image %d", data->os_num);
+ printf(", multifile image %s", data->os_part);
printf("\n");
if (IS_ENABLED(CONFIG_OFTREE)) {
diff --git a/include/boot.h b/include/boot.h
index b172c05..9ddb18b 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -28,7 +28,7 @@ struct image_data {
/* if os is an uImage this will be provided */
struct uimage_handle *os;
- int os_num;
+ char *os_part;
/* otherwise only the filename will be provided */
char *os_file;
@@ -49,7 +49,7 @@ struct image_data {
/* if initrd is an uImage this will be provided */
struct uimage_handle *initrd;
- int initrd_num;
+ char *initrd_part;
/* otherwise only the filename will be provided */
char *initrd_file;
@@ -57,7 +57,7 @@ struct image_data {
unsigned long initrd_address;
char *oftree_file;
- int oftree_num;
+ char *oftree_part;
struct device_node *of_root_node;
struct fdt_header *oftree;
--
2.7.0.rc3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 05/14] ARM: bootm: Use kernel handler to start barebox image
2016-01-22 7:32 [PATCH v4] FIT support Sascha Hauer
` (3 preceding siblings ...)
2016-01-22 7:32 ` [PATCH 04/14] bootm: use names instead of numbers for image parts Sascha Hauer
@ 2016-01-22 7:32 ` Sascha Hauer
2016-01-22 7:32 ` [PATCH 06/14] bootm: Push dryrun to handlers Sascha Hauer
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2016-01-22 7:32 UTC (permalink / raw)
To: Barebox List
barebox can be called with the kernel calling convention, so
we can reuse the handler instead of creating a barebox specific
handler.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/lib/bootm.c | 30 +-----------------------------
1 file changed, 1 insertion(+), 29 deletions(-)
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 0855907..010b668 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -355,37 +355,9 @@ static struct image_handler zimage_handler = {
.filetype = filetype_arm_zimage,
};
-static int do_bootm_barebox(struct image_data *data)
-{
- void *barebox;
-
- barebox = read_file(data->os_file, NULL);
- if (!barebox)
- return -EINVAL;
-
- if (IS_ENABLED(CONFIG_OFTREE) && data->of_root_node) {
- data->oftree = of_get_fixed_tree(data->of_root_node);
- fdt_add_reserve_map(data->oftree);
- of_print_cmdline(data->of_root_node);
- if (bootm_verbose(data) > 1)
- of_print_nodes(data->of_root_node, 0);
- }
-
- if (bootm_verbose(data)) {
- printf("\nStarting barebox at 0x%p", barebox);
- if (data->oftree)
- printf(", oftree at 0x%p", data->oftree);
- printf("...\n");
- }
-
- start_linux(barebox, 0, 0, 0, data->oftree);
-
- restart_machine();
-}
-
static struct image_handler barebox_handler = {
.name = "ARM barebox",
- .bootm = do_bootm_barebox,
+ .bootm = do_bootm_linux,
.filetype = filetype_arm_barebox,
};
--
2.7.0.rc3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 06/14] bootm: Push dryrun to handlers
2016-01-22 7:32 [PATCH v4] FIT support Sascha Hauer
` (4 preceding siblings ...)
2016-01-22 7:32 ` [PATCH 05/14] ARM: bootm: Use kernel handler to start barebox image Sascha Hauer
@ 2016-01-22 7:32 ` Sascha Hauer
2016-01-22 7:32 ` [PATCH 07/14] bootm: move initrd code together Sascha Hauer
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2016-01-22 7:32 UTC (permalink / raw)
To: Barebox List
We can make the dryrun option more useful by calling into the handlers.
With this we can detect more cases that can go wrong during boot.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/lib/bootm.c | 3 +++
arch/arm/mach-omap/omap_generic.c | 5 +++++
arch/blackfin/lib/blackfin_linux.c | 3 +++
arch/efi/efi/efi-image.c | 9 ++++++++-
arch/mips/lib/bootm.c | 5 +++++
arch/nios2/lib/bootm.c | 3 +++
arch/ppc/lib/ppclinux.c | 3 +++
commands/bootm.c | 3 ---
common/bootm.c | 6 +++---
9 files changed, 33 insertions(+), 7 deletions(-)
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 010b668..eef906a 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -110,6 +110,9 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem, int
printf("...\n");
}
+ if (data->dryrun)
+ return 0;
+
start_linux((void *)kernel, swap, initrd_start, initrd_size, data->oftree);
restart_machine();
diff --git a/arch/arm/mach-omap/omap_generic.c b/arch/arm/mach-omap/omap_generic.c
index 4e26c6b..34ed940 100644
--- a/arch/arm/mach-omap/omap_generic.c
+++ b/arch/arm/mach-omap/omap_generic.c
@@ -79,6 +79,11 @@ static int do_bootm_omap_barebox(struct image_data *data)
if (!barebox)
return -EINVAL;
+ if (data->dryrun) {
+ free(barebox);
+ return 0;
+ }
+
omap_start_barebox(barebox);
}
diff --git a/arch/blackfin/lib/blackfin_linux.c b/arch/blackfin/lib/blackfin_linux.c
index 2561a7e..da2f78b 100644
--- a/arch/blackfin/lib/blackfin_linux.c
+++ b/arch/blackfin/lib/blackfin_linux.c
@@ -50,6 +50,9 @@ static int do_bootm_linux(struct image_data *idata)
appl = (void *)(idata->os_address + idata->os_entry);
printf("Starting Kernel at 0x%p\n", appl);
+ if (idata->dryrun)
+ return 0;
+
icache_disable();
strncpy(cmdlinedest, cmdline, 0x1000);
diff --git a/arch/efi/efi/efi-image.c b/arch/efi/efi/efi-image.c
index b6437f4..c78043b 100644
--- a/arch/efi/efi/efi-image.c
+++ b/arch/efi/efi/efi-image.c
@@ -190,7 +190,7 @@ static inline void linux_efi_handover(efi_handle_t handle,
static int do_bootm_efi(struct image_data *data)
{
void *tmp;
- void *initrd;
+ void *initrd = NULL;
size_t size;
efi_handle_t handle;
int ret;
@@ -244,6 +244,13 @@ static int do_bootm_efi(struct image_data *data)
printf("...\n");
}
+ if (data->dryrun) {
+ BS->unload_image(handle);
+ free(boot_header);
+ free(initrd);
+ return 0;
+ }
+
efi_set_variable_usec("LoaderTimeExecUSec", &efi_systemd_vendor_guid,
get_time_ns()/1000);
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 84f72f5..ce1521f 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -17,6 +17,11 @@ static int do_bootm_barebox(struct image_data *data)
if (!barebox)
return -EINVAL;
+ if (data->dryrun) {
+ free(barebox)
+ return 0;
+ }
+
shutdown_barebox();
barebox();
diff --git a/arch/nios2/lib/bootm.c b/arch/nios2/lib/bootm.c
index 77da119..231568f 100644
--- a/arch/nios2/lib/bootm.c
+++ b/arch/nios2/lib/bootm.c
@@ -42,6 +42,9 @@ static int do_bootm_linux(struct image_data *idata)
if (ret)
return ret;
+ if (data->dryrun)
+ return 0;
+
kernel = (void *)(idata->os_address + idata->os_entry);
/* kernel parameters passing
diff --git a/arch/ppc/lib/ppclinux.c b/arch/ppc/lib/ppclinux.c
index 409c0cf..a36682c 100644
--- a/arch/ppc/lib/ppclinux.c
+++ b/arch/ppc/lib/ppclinux.c
@@ -60,6 +60,9 @@ static int do_bootm_linux(struct image_data *data)
return -EINVAL;
}
+ if (data->dryrun)
+ return 0;
+
/* Relocate the device tree if outside the initial
* Linux mapped TLB.
*/
diff --git a/commands/bootm.c b/commands/bootm.c
index 75849a1..063da62 100644
--- a/commands/bootm.c
+++ b/commands/bootm.c
@@ -133,9 +133,6 @@ static int do_bootm(int argc, char *argv[])
goto err_out;
}
- if (data.dryrun)
- printf("Dryrun. Aborted\n");
-
err_out:
return ret ? 1 : 0;
}
diff --git a/common/bootm.c b/common/bootm.c
index f8d9330..7f6533b 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -526,10 +526,10 @@ int bootm_boot(struct bootm_data *bootm_data)
printf("Passing control to %s handler\n", handler->name);
}
+ ret = handler->bootm(data);
if (data->dryrun)
- ret = 0;
- else
- ret = handler->bootm(data);
+ printf("Dryrun. Aborted\n");
+
err_out:
if (data->os_res)
release_sdram_region(data->os_res);
--
2.7.0.rc3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 07/14] bootm: move initrd code together
2016-01-22 7:32 [PATCH v4] FIT support Sascha Hauer
` (5 preceding siblings ...)
2016-01-22 7:32 ` [PATCH 06/14] bootm: Push dryrun to handlers Sascha Hauer
@ 2016-01-22 7:32 ` Sascha Hauer
2016-01-22 7:32 ` [PATCH 08/14] bootm: move oftree " Sascha Hauer
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2016-01-22 7:32 UTC (permalink / raw)
To: Barebox List
The initrd code is distributed in several places in the bootm code.
Move it all together in bootm_load_initrd().
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/lib/bootm.c | 8 ++-
common/bootm.c | 151 +++++++++++++++++++++++++--------------------------
include/boot.h | 3 +
3 files changed, 83 insertions(+), 79 deletions(-)
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index eef906a..4dfe148 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -86,9 +86,11 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem, int
}
}
- ret = bootm_load_initrd(data, initrd_start);
- if (ret)
- return ret;
+ if (bootm_has_initrd(data)) {
+ ret = bootm_load_initrd(data, initrd_start);
+ if (ret)
+ return ret;
+ }
if (data->initrd_res) {
initrd_start = data->initrd_res->start;
diff --git a/common/bootm.c b/common/bootm.c
index 7f6533b..06f1f8a 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -91,6 +91,41 @@ int bootm_load_os(struct image_data *data, unsigned long load_address)
return -EINVAL;
}
+bool bootm_has_initrd(struct image_data *data)
+{
+ if (!IS_ENABLED(CONFIG_CMD_BOOTM_INITRD))
+ return false;
+
+ if (data->initrd_file)
+ return true;
+
+ return false;
+}
+
+static int bootm_open_initrd_uimage(struct image_data *data)
+{
+ int ret;
+
+ if (strcmp(data->os_file, data->initrd_file)) {
+ data->initrd = uimage_open(data->initrd_file);
+ if (!data->initrd)
+ return -EINVAL;
+
+ if (data->verify) {
+ ret = uimage_verify(data->initrd);
+ if (ret) {
+ printf("Checking data crc failed with %s\n",
+ strerror(-ret));
+ }
+ }
+ uimage_print_contents(data->initrd);
+ } else {
+ data->initrd = data->os;
+ }
+
+ return 0;
+}
+
/*
* bootm_load_initrd() - load initrd to RAM
*
@@ -106,11 +141,34 @@ int bootm_load_os(struct image_data *data, unsigned long load_address)
*/
int bootm_load_initrd(struct image_data *data, unsigned long load_address)
{
+ enum filetype type;
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_CMD_BOOTM_INITRD))
+ return -ENOSYS;
+
+ if (!bootm_has_initrd(data))
+ return -EINVAL;
+
if (data->initrd_res)
return 0;
- if (data->initrd) {
+ type = file_name_detect_type(data->initrd_file);
+
+ if ((int)type < 0) {
+ printf("could not open %s: %s\n", data->initrd_file,
+ strerror(-type));
+ return (int)type;
+ }
+
+ if (type == filetype_uimage) {
int num;
+ ret = bootm_open_initrd_uimage(data);
+ if (ret) {
+ printf("loading initrd failed with %s\n",
+ strerror(-ret));
+ return ret;
+ }
num = simple_strtoul(data->initrd_part, NULL, 0);
@@ -119,16 +177,24 @@ int bootm_load_initrd(struct image_data *data, unsigned long load_address)
if (!data->initrd_res)
return -ENOMEM;
- return 0;
+ goto done;
}
- if (data->initrd_file) {
- data->initrd_res = file_to_sdram(data->initrd_file, load_address);
- if (!data->initrd_res)
- return -ENOMEM;
+ data->initrd_res = file_to_sdram(data->initrd_file, load_address);
+ if (!data->initrd_res)
+ return -ENOMEM;
- return 0;
- }
+done:
+
+ printf("Loaded initrd %s '%s'", file_type_to_string(type),
+ data->initrd_file);
+ if (type == filetype_uimage && data->initrd->header.ih_type == IH_TYPE_MULTI)
+ printf(", multifile image %s", data->initrd_part);
+ printf("\n");
+
+ printf("initrd is at " PRINTF_CONVERSION_RESOURCE "-" PRINTF_CONVERSION_RESOURCE "\n",
+ data->initrd_res->start,
+ data->initrd_res->end);
return 0;
}
@@ -245,33 +311,6 @@ static int bootm_open_os_uimage(struct image_data *data)
return 0;
}
-static int bootm_open_initrd_uimage(struct image_data *data)
-{
- int ret;
-
- if (!data->initrd_file)
- return 0;
-
- if (strcmp(data->os_file, data->initrd_file)) {
- data->initrd = uimage_open(data->initrd_file);
- if (!data->initrd)
- return -EINVAL;
-
- if (data->verify) {
- ret = uimage_verify(data->initrd);
- if (ret) {
- printf("Checking data crc failed with %s\n",
- strerror(-ret));
- }
- }
- uimage_print_contents(data->initrd);
- } else {
- data->initrd = data->os;
- }
-
- return 0;
-}
-
static int bootm_open_oftree_uimage(struct image_data *data)
{
struct fdt_header *fdt;
@@ -358,24 +397,6 @@ static void bootm_print_info(struct image_data *data)
data->os_res->end);
else
printf("OS image not yet relocated\n");
-
- if (data->initrd_file) {
- enum filetype initrd_type = file_name_detect_type(data->initrd_file);
-
- printf("Loading initrd %s '%s'",
- file_type_to_string(initrd_type),
- data->initrd_file);
- if (initrd_type == filetype_uimage &&
- data->initrd->header.ih_type == IH_TYPE_MULTI)
- printf(", multifile image %s", data->initrd_part);
- printf("\n");
- if (data->initrd_res)
- printf("initrd is at " PRINTF_CONVERSION_RESOURCE "-" PRINTF_CONVERSION_RESOURCE "\n",
- data->initrd_res->start,
- data->initrd_res->end);
- else
- printf("initrd image not yet relocated\n");
- }
}
static int bootm_image_name_and_part(const char *name, char **filename, char **part)
@@ -409,7 +430,7 @@ int bootm_boot(struct bootm_data *bootm_data)
struct image_data *data;
struct image_handler *handler;
int ret;
- enum filetype os_type, initrd_type = filetype_unknown;
+ enum filetype os_type;
enum filetype oftree_type = filetype_unknown;
if (!bootm_data->os_file) {
@@ -444,17 +465,6 @@ int bootm_boot(struct bootm_data *bootm_data)
goto err_out;
}
- if (IS_ENABLED(CONFIG_CMD_BOOTM_INITRD) && data->initrd_file) {
- initrd_type = file_name_detect_type(data->initrd_file);
-
- if ((int)initrd_type < 0) {
- printf("could not open %s: %s\n", data->initrd_file,
- strerror(-initrd_type));
- ret = (int)initrd_type;
- goto err_out;
- }
- }
-
if (IS_ENABLED(CONFIG_OFTREE) && data->oftree_file) {
oftree_type = file_name_detect_type(data->oftree_file);
@@ -475,17 +485,6 @@ int bootm_boot(struct bootm_data *bootm_data)
}
}
- if (IS_ENABLED(CONFIG_CMD_BOOTM_INITRD) && data->initrd_file) {
- if (initrd_type == filetype_uimage) {
- ret = bootm_open_initrd_uimage(data);
- if (ret) {
- printf("loading initrd failed with %s\n",
- strerror(-ret));
- goto err_out;
- }
- }
- }
-
printf("\nLoading %s '%s'", file_type_to_string(os_type),
data->os_file);
if (os_type == filetype_uimage &&
diff --git a/include/boot.h b/include/boot.h
index 9ddb18b..7c6d9c8 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -110,7 +110,10 @@ static inline int linux_bootargs_overwrite(const char *bootargs)
#endif
int bootm_load_os(struct image_data *data, unsigned long load_address);
+
+bool bootm_has_initrd(struct image_data *data);
int bootm_load_initrd(struct image_data *data, unsigned long load_address);
+
int bootm_load_devicetree(struct image_data *data, unsigned long load_address);
int bootm_get_os_size(struct image_data *data);
--
2.7.0.rc3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 08/14] bootm: move oftree code together
2016-01-22 7:32 [PATCH v4] FIT support Sascha Hauer
` (6 preceding siblings ...)
2016-01-22 7:32 ` [PATCH 07/14] bootm: move initrd code together Sascha Hauer
@ 2016-01-22 7:32 ` Sascha Hauer
2016-01-22 7:32 ` [PATCH 09/14] bootm: Initialize bootm_data defaults in single place Sascha Hauer
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2016-01-22 7:32 UTC (permalink / raw)
To: Barebox List
The device tree code is distributed in several places in the bootm code.
Move it all together in bootm_load_devicetree().
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/bootm.c | 193 +++++++++++++++++++++++++--------------------------------
1 file changed, 86 insertions(+), 107 deletions(-)
diff --git a/common/bootm.c b/common/bootm.c
index 06f1f8a..e399a6a 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -199,6 +199,47 @@ done:
return 0;
}
+static int bootm_open_oftree_uimage(struct image_data *data, size_t *size,
+ struct fdt_header **fdt)
+{
+ enum filetype ft;
+ const char *oftree = data->oftree_file;
+ int num = simple_strtoul(data->oftree_part, NULL, 0);
+ struct uimage_handle *of_handle;
+ int release = 0;
+
+ printf("Loading devicetree from '%s'@%d\n", oftree, num);
+
+ if (!IS_ENABLED(CONFIG_CMD_BOOTM_OFTREE_UIMAGE))
+ return -EINVAL;
+
+ if (!strcmp(data->os_file, oftree)) {
+ of_handle = data->os;
+ } else if (!strcmp(data->initrd_file, oftree)) {
+ of_handle = data->initrd;
+ } else {
+ of_handle = uimage_open(oftree);
+ if (!of_handle)
+ return -ENODEV;
+ uimage_print_contents(of_handle);
+ release = 1;
+ }
+
+ *fdt = uimage_load_to_buf(of_handle, num, size);
+
+ if (release)
+ uimage_close(of_handle);
+
+ ft = file_detect_type(*fdt, *size);
+ if (ft != filetype_oftree) {
+ printf("%s is not an oftree but %s\n",
+ data->oftree_file, file_type_to_string(ft));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/*
* bootm_load_devicetree() - load devicetree
*
@@ -212,8 +253,10 @@ done:
*/
int bootm_load_devicetree(struct image_data *data, unsigned long load_address)
{
+ enum filetype type;
int fdt_size;
struct fdt_header *oftree;
+ int ret;
if (data->oftree)
return 0;
@@ -221,8 +264,49 @@ int bootm_load_devicetree(struct image_data *data, unsigned long load_address)
if (!IS_ENABLED(CONFIG_OFTREE))
return 0;
- if (!data->of_root_node)
- return 0;
+ if (data->oftree_file) {
+ size_t size;
+
+ type = file_name_detect_type(data->oftree_file);
+
+ if ((int)type < 0) {
+ printf("could not open %s: %s\n", data->oftree_file,
+ strerror(-type));
+ return (int)type;
+ }
+
+ switch (type) {
+ case filetype_uimage:
+ ret = bootm_open_oftree_uimage(data, &size, &oftree);
+ break;
+ case filetype_oftree:
+ ret = read_file_2(data->oftree_file, &size, (void *)&oftree,
+ FILESIZE_MAX);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (ret)
+ return ret;
+
+ data->of_root_node = of_unflatten_dtb(oftree);
+
+ free(oftree);
+
+ if (!data->of_root_node) {
+ pr_err("unable to unflatten devicetree\n");
+ return -EINVAL;
+ }
+
+ } else {
+ data->of_root_node = of_get_root_node();
+ if (!data->of_root_node)
+ return 0;
+
+ if (bootm_verbose(data) > 1 && data->of_root_node)
+ printf("using internal devicetree\n");
+ }
if (data->initrd_res) {
of_add_initrd(data->of_root_node, data->initrd_res->start,
@@ -311,84 +395,6 @@ static int bootm_open_os_uimage(struct image_data *data)
return 0;
}
-static int bootm_open_oftree_uimage(struct image_data *data)
-{
- struct fdt_header *fdt;
- enum filetype ft;
- const char *oftree = data->oftree_file;
- int num = simple_strtoul(data->oftree_part, NULL, 0);
- struct uimage_handle *of_handle;
- int release = 0;
- size_t size;
-
- printf("Loading devicetree from '%s'@%d\n", oftree, num);
-
- if (IS_ENABLED(CONFIG_CMD_BOOTM_OFTREE_UIMAGE)) {
- if (!strcmp(data->os_file, oftree)) {
- of_handle = data->os;
- } else if (!strcmp(data->initrd_file, oftree)) {
- of_handle = data->initrd;
- } else {
- of_handle = uimage_open(oftree);
- if (!of_handle)
- return -ENODEV;
- uimage_print_contents(of_handle);
- release = 1;
- }
-
- fdt = uimage_load_to_buf(of_handle, num, &size);
-
- if (release)
- uimage_close(of_handle);
-
- ft = file_detect_type(fdt, size);
- if (ft != filetype_oftree) {
- printf("%s is not an oftree but %s\n",
- data->oftree_file, file_type_to_string(ft));
- return -EINVAL;
- }
-
- data->of_root_node = of_unflatten_dtb(fdt);
- if (!data->of_root_node) {
- pr_err("unable to unflatten devicetree\n");
- free(fdt);
- return -EINVAL;
- }
-
- free(fdt);
-
- return 0;
- } else {
- return -EINVAL;
- }
-}
-
-static int bootm_open_oftree(struct image_data *data)
-{
- struct fdt_header *fdt;
- const char *oftree = data->oftree_file;
- size_t size;
-
- printf("Loading devicetree from '%s'\n", oftree);
-
- fdt = read_file(oftree, &size);
- if (!fdt) {
- perror("open");
- return -ENODEV;
- }
-
- data->of_root_node = of_unflatten_dtb(fdt);
- if (!data->of_root_node) {
- pr_err("unable to unflatten devicetree\n");
- free(fdt);
- return -EINVAL;
- }
-
- free(fdt);
-
- return 0;
-}
-
static void bootm_print_info(struct image_data *data)
{
if (data->os_res)
@@ -431,7 +437,6 @@ int bootm_boot(struct bootm_data *bootm_data)
struct image_handler *handler;
int ret;
enum filetype os_type;
- enum filetype oftree_type = filetype_unknown;
if (!bootm_data->os_file) {
printf("no image given\n");
@@ -465,17 +470,6 @@ int bootm_boot(struct bootm_data *bootm_data)
goto err_out;
}
- if (IS_ENABLED(CONFIG_OFTREE) && data->oftree_file) {
- oftree_type = file_name_detect_type(data->oftree_file);
-
- if ((int)oftree_type < 0) {
- printf("could not open %s: %s\n", data->oftree_file,
- strerror(-oftree_type));
- ret = (int) oftree_type;
- goto err_out;
- }
- }
-
if (os_type == filetype_uimage) {
ret = bootm_open_os_uimage(data);
if (ret) {
@@ -492,21 +486,6 @@ int bootm_boot(struct bootm_data *bootm_data)
printf(", multifile image %s", data->os_part);
printf("\n");
- if (IS_ENABLED(CONFIG_OFTREE)) {
- if (data->oftree_file) {
- if (oftree_type == filetype_uimage)
- ret = bootm_open_oftree_uimage(data);
- if (oftree_type == filetype_oftree)
- ret = bootm_open_oftree(data);
- if (ret)
- goto err_out;
- } else {
- data->of_root_node = of_get_root_node();
- if (bootm_verbose(data) > 1 && data->of_root_node)
- printf("using internal devicetree\n");
- }
- }
-
if (data->os_address == UIMAGE_SOME_ADDRESS)
data->os_address = UIMAGE_INVALID_ADDRESS;
--
2.7.0.rc3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 09/14] bootm: Initialize bootm_data defaults in single place
2016-01-22 7:32 [PATCH v4] FIT support Sascha Hauer
` (7 preceding siblings ...)
2016-01-22 7:32 ` [PATCH 08/14] bootm: move oftree " Sascha Hauer
@ 2016-01-22 7:32 ` Sascha Hauer
2016-01-22 7:32 ` [PATCH 10/14] crypto: add digest_alloc_by_algo() Sascha Hauer
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2016-01-22 7:32 UTC (permalink / raw)
To: Barebox List
Both the bootm and the boot code initialize the struct bootm_data
with defaults from the bootm global variables. Create a common
function for doing this.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
commands/boot.c | 14 ++------------
commands/bootm.c | 31 +++++--------------------------
common/bootm.c | 11 +++++++++++
include/boot.h | 2 ++
4 files changed, 20 insertions(+), 38 deletions(-)
diff --git a/commands/boot.c b/commands/boot.c
index fd58824..f403010 100644
--- a/commands/boot.c
+++ b/commands/boot.c
@@ -42,13 +42,9 @@ static int timeout;
static int boot_script(char *path)
{
int ret;
- struct bootm_data data = {
- .os_address = UIMAGE_SOME_ADDRESS,
- .initrd_address = UIMAGE_SOME_ADDRESS,
- };
+ struct bootm_data data = {};
globalvar_set_match("linux.bootargs.dyn.", "");
- globalvar_set_match("bootm.", "");
ret = run_command(path);
if (ret) {
@@ -56,15 +52,9 @@ static int boot_script(char *path)
goto out;
}
- data.initrd_address = UIMAGE_INVALID_ADDRESS;
- data.os_address = UIMAGE_SOME_ADDRESS;
- data.oftree_file = getenv_nonempty("global.bootm.oftree");
- data.os_file = getenv_nonempty("global.bootm.image");
- getenv_ul("global.bootm.image.loadaddr", &data.os_address);
- getenv_ul("global.bootm.initrd.loadaddr", &data.initrd_address);
- data.initrd_file = getenv_nonempty("global.bootm.initrd");
data.verbose = verbose;
data.dryrun = dryrun;
+ bootm_data_init_defaults(&data);
ret = bootm_boot(&data);
if (ret)
diff --git a/commands/bootm.c b/commands/bootm.c
index 063da62..6db0e65 100644
--- a/commands/bootm.c
+++ b/commands/bootm.c
@@ -59,19 +59,8 @@ static int do_bootm(int argc, char *argv[])
int opt;
struct bootm_data data = {};
int ret = 1;
- const char *oftree = NULL, *initrd_file = NULL, *os_file = NULL;
- data.initrd_address = UIMAGE_INVALID_ADDRESS;
- data.os_address = UIMAGE_SOME_ADDRESS;
- data.verify = 0;
- data.verbose = 0;
-
- oftree = getenv("global.bootm.oftree");
- os_file = getenv("global.bootm.image");
- getenv_ul("global.bootm.image.loadaddr", &data.os_address);
- getenv_ul("global.bootm.initrd.loadaddr", &data.initrd_address);
- if (IS_ENABLED(CONFIG_CMD_BOOTM_INITRD))
- initrd_file = getenv("global.bootm.initrd");
+ bootm_data_init_defaults(&data);
while ((opt = getopt(argc, argv, BOOTM_OPTS)) > 0) {
switch(opt) {
@@ -83,7 +72,7 @@ static int do_bootm(int argc, char *argv[])
data.initrd_address = simple_strtoul(optarg, NULL, 0);
break;
case 'r':
- initrd_file = optarg;
+ data.initrd_file = optarg;
break;
#endif
case 'a':
@@ -96,7 +85,7 @@ static int do_bootm(int argc, char *argv[])
data.verbose++;
break;
case 'o':
- oftree = optarg;
+ data.oftree_file = optarg;
break;
case 'f':
data.force = 1;
@@ -110,23 +99,13 @@ static int do_bootm(int argc, char *argv[])
}
if (optind != argc)
- os_file = argv[optind];
+ data.os_file = argv[optind];
- if (!os_file || !*os_file) {
+ if (!data.os_file) {
printf("no boot image given\n");
goto err_out;
}
- if (initrd_file && !*initrd_file)
- initrd_file = NULL;
-
- if (oftree && !*oftree)
- oftree = NULL;
-
- data.os_file = os_file;
- data.oftree_file = oftree;
- data.initrd_file = initrd_file;
-
ret = bootm_boot(&data);
if (ret) {
printf("handler failed with: %s\n", strerror(-ret));
diff --git a/common/bootm.c b/common/bootm.c
index e399a6a..4409a8b 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -47,6 +47,17 @@ static struct image_handler *bootm_find_handler(enum filetype filetype,
return NULL;
}
+void bootm_data_init_defaults(struct bootm_data *data)
+{
+ data->initrd_address = UIMAGE_INVALID_ADDRESS;
+ data->os_address = UIMAGE_SOME_ADDRESS;
+ data->oftree_file = getenv_nonempty("global.bootm.oftree");
+ data->os_file = getenv_nonempty("global.bootm.image");
+ getenv_ul("global.bootm.image.loadaddr", &data->os_address);
+ getenv_ul("global.bootm.initrd.loadaddr", &data->initrd_address);
+ data->initrd_file = getenv_nonempty("global.bootm.initrd");
+}
+
/*
* bootm_load_os() - load OS to RAM
*
diff --git a/include/boot.h b/include/boot.h
index 7c6d9c8..0c0febe 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -109,6 +109,8 @@ static inline int linux_bootargs_overwrite(const char *bootargs)
}
#endif
+void bootm_data_init_defaults(struct bootm_data *data);
+
int bootm_load_os(struct image_data *data, unsigned long load_address);
bool bootm_has_initrd(struct image_data *data);
--
2.7.0.rc3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 10/14] crypto: add digest_alloc_by_algo()
2016-01-22 7:32 [PATCH v4] FIT support Sascha Hauer
` (8 preceding siblings ...)
2016-01-22 7:32 ` [PATCH 09/14] bootm: Initialize bootm_data defaults in single place Sascha Hauer
@ 2016-01-22 7:32 ` Sascha Hauer
2016-01-22 7:32 ` [PATCH 11/14] crypto: add RSA support Sascha Hauer
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2016-01-22 7:32 UTC (permalink / raw)
To: Barebox List
In barebox the function digest_alloc() allocates a digest based on a string.
When a subsystem already uses an integer value to identify a digest it makes no
sense to create a string and pass it to digest_alloc(), where it is parsed
again. This patch adds the possibility to get a digest by an enum.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/crypto/sha1_glue.c | 1 +
arch/arm/crypto/sha256_glue.c | 2 ++
crypto/digest.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
crypto/md5.c | 1 +
crypto/sha1.c | 1 +
crypto/sha2.c | 2 ++
crypto/sha4.c | 2 ++
include/digest.h | 23 +++++++++++++++++++++++
8 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/arch/arm/crypto/sha1_glue.c b/arch/arm/crypto/sha1_glue.c
index 176aa9e..57cd9d1 100644
--- a/arch/arm/crypto/sha1_glue.c
+++ b/arch/arm/crypto/sha1_glue.c
@@ -119,6 +119,7 @@ static struct digest_algo m = {
.name = "sha1",
.driver_name = "sha1-asm",
.priority = 150,
+ .algo = HASH_ALGO_SHA1,
},
.init = sha1_init,
diff --git a/arch/arm/crypto/sha256_glue.c b/arch/arm/crypto/sha256_glue.c
index f8086f6..e649609 100644
--- a/arch/arm/crypto/sha256_glue.c
+++ b/arch/arm/crypto/sha256_glue.c
@@ -173,6 +173,7 @@ static struct digest_algo sha224 = {
.name = "sha224",
.driver_name = "sha224-asm",
.priority = 150,
+ .algo = HASH_ALGO_SHA224,
},
.length = SHA224_DIGEST_SIZE,
@@ -195,6 +196,7 @@ static struct digest_algo sha256 = {
.name = "sha256",
.driver_name = "sha256-asm",
.priority = 150,
+ .algo = HASH_ALGO_SHA256,
},
.length = SHA256_DIGEST_SIZE,
diff --git a/crypto/digest.c b/crypto/digest.c
index a90e4ff..46600f2 100644
--- a/crypto/digest.c
+++ b/crypto/digest.c
@@ -116,7 +116,27 @@ static struct digest_algo *digest_algo_get_by_name(const char *name)
list_for_each_entry(tmp, &digests, list) {
if (strcmp(tmp->base.name, name) != 0)
continue;
-
+
+ if (tmp->base.priority <= priority)
+ continue;
+
+ d = tmp;
+ priority = tmp->base.priority;
+ }
+
+ return d;
+}
+
+static struct digest_algo *digest_algo_get_by_algo(enum hash_algo algo)
+{
+ struct digest_algo *d = NULL;
+ struct digest_algo *tmp;
+ int priority = -1;
+
+ list_for_each_entry(tmp, &digests, list) {
+ if (tmp->base.algo != algo)
+ continue;
+
if (tmp->base.priority <= priority)
continue;
@@ -160,6 +180,27 @@ struct digest *digest_alloc(const char *name)
}
EXPORT_SYMBOL_GPL(digest_alloc);
+struct digest *digest_alloc_by_algo(enum hash_algo hash_algo)
+{
+ struct digest *d;
+ struct digest_algo *algo;
+
+ algo = digest_algo_get_by_algo(hash_algo);
+ if (!algo)
+ return NULL;
+
+ d = xzalloc(sizeof(*d));
+ d->algo = algo;
+ d->ctx = xzalloc(algo->ctx_length);
+ if (d->algo->alloc(d)) {
+ digest_free(d);
+ return NULL;
+ }
+
+ return d;
+}
+EXPORT_SYMBOL_GPL(digest_alloc_by_algo);
+
void digest_free(struct digest *d)
{
if (!d)
diff --git a/crypto/md5.c b/crypto/md5.c
index 23892ba..f8f52bf 100644
--- a/crypto/md5.c
+++ b/crypto/md5.c
@@ -293,6 +293,7 @@ static struct digest_algo md5 = {
.name = "md5",
.driver_name = "md5-generic",
.priority = 0,
+ .algo = HASH_ALGO_MD5,
},
.init = digest_md5_init,
.update = digest_md5_update,
diff --git a/crypto/sha1.c b/crypto/sha1.c
index a3de271..cbde4d2 100644
--- a/crypto/sha1.c
+++ b/crypto/sha1.c
@@ -287,6 +287,7 @@ static struct digest_algo m = {
.name = "sha1",
.driver_name = "sha1-generic",
.priority = 0,
+ .algo = HASH_ALGO_SHA1,
},
.init = sha1_init,
diff --git a/crypto/sha2.c b/crypto/sha2.c
index 6ac5527..df566c8 100644
--- a/crypto/sha2.c
+++ b/crypto/sha2.c
@@ -327,6 +327,7 @@ static struct digest_algo m224 = {
.name = "sha224",
.driver_name = "sha224-generic",
.priority = 0,
+ .algo = HASH_ALGO_SHA224,
},
.init = sha224_init,
@@ -352,6 +353,7 @@ static struct digest_algo m256 = {
.name = "sha256",
.driver_name = "sha256-generic",
.priority = 0,
+ .algo = HASH_ALGO_SHA256,
},
.init = sha256_init,
diff --git a/crypto/sha4.c b/crypto/sha4.c
index 187a91e..4ce37b7 100644
--- a/crypto/sha4.c
+++ b/crypto/sha4.c
@@ -246,6 +246,7 @@ static struct digest_algo m384 = {
.name = "sha384",
.driver_name = "sha384-generic",
.priority = 0,
+ .algo = HASH_ALGO_SHA384,
},
.init = sha384_init,
@@ -272,6 +273,7 @@ static struct digest_algo m512 = {
.name = "sha512",
.driver_name = "sha512-generic",
.priority = 0,
+ .algo = HASH_ALGO_SHA512,
},
.init = sha512_init,
diff --git a/include/digest.h b/include/digest.h
index 3a9d305..fe30cc2 100644
--- a/include/digest.h
+++ b/include/digest.h
@@ -23,12 +23,34 @@
struct digest;
+enum hash_algo {
+ HASH_ALGO_MD4,
+ HASH_ALGO_MD5,
+ HASH_ALGO_SHA1,
+ HASH_ALGO_RIPE_MD_160,
+ HASH_ALGO_SHA224,
+ HASH_ALGO_SHA256,
+ HASH_ALGO_SHA384,
+ HASH_ALGO_SHA512,
+ HASH_ALGO_RIPE_MD_128,
+ HASH_ALGO_RIPE_MD_256,
+ HASH_ALGO_RIPE_MD_320,
+ HASH_ALGO_WP_256,
+ HASH_ALGO_WP_384,
+ HASH_ALGO_WP_512,
+ HASH_ALGO_TGR_128,
+ HASH_ALGO_TGR_160,
+ HASH_ALGO_TGR_192,
+ HASH_ALGO__LAST
+};
+
struct crypto_alg {
char *name;
char *driver_name;
int priority;
#define DIGEST_ALGO_NEED_KEY (1 << 0)
unsigned int flags;
+ enum hash_algo algo;
};
struct digest_algo {
@@ -65,6 +87,7 @@ void digest_algo_unregister(struct digest_algo *d);
void digest_algo_prints(const char *prefix);
struct digest *digest_alloc(const char *name);
+struct digest *digest_alloc_by_algo(enum hash_algo);
void digest_free(struct digest *d);
int digest_file_window(struct digest *d, const char *filename,
--
2.7.0.rc3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 11/14] crypto: add RSA support
2016-01-22 7:32 [PATCH v4] FIT support Sascha Hauer
` (9 preceding siblings ...)
2016-01-22 7:32 ` [PATCH 10/14] crypto: add digest_alloc_by_algo() Sascha Hauer
@ 2016-01-22 7:32 ` Sascha Hauer
2016-01-22 7:32 ` [PATCH 12/14] bootm: make verifying/hashing configurable Sascha Hauer
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2016-01-22 7:32 UTC (permalink / raw)
To: Barebox List
Taken from U-Boot and adopted to barebox with little changes.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
crypto/Kconfig | 3 +
crypto/Makefile | 1 +
crypto/rsa.c | 422 ++++++++++++++++++++++++++++++++++++++++++++
include/asm-generic/errno.h | 5 +
include/rsa.h | 54 ++++++
5 files changed, 485 insertions(+)
create mode 100644 crypto/rsa.c
create mode 100644 include/rsa.h
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 41145a3..ca6f03a 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -87,6 +87,9 @@ config CRYPTO_PBKDF2
select DIGEST_SHA1_GENERIC
bool
+config CRYPTO_RSA
+ bool
+
config CRYPTO_KEYSTORE
bool "Keystore"
help
diff --git a/crypto/Makefile b/crypto/Makefile
index c6d1778..b4fb3d8 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -11,4 +11,5 @@ obj-$(CONFIG_DIGEST_SHA384_GENERIC) += sha4.o
obj-$(CONFIG_DIGEST_SHA512_GENERIC) += sha4.o
obj-$(CONFIG_CRYPTO_PBKDF2) += pbkdf2.o
+obj-$(CONFIG_CRYPTO_RSA) += rsa.o
obj-$(CONFIG_CRYPTO_KEYSTORE) += keystore.o
diff --git a/crypto/rsa.c b/crypto/rsa.c
new file mode 100644
index 0000000..07bd5e3
--- /dev/null
+++ b/crypto/rsa.c
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ *
+ * This code is ported from U-Boot code.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <of.h>
+#include <digest.h>
+#include <asm/types.h>
+#include <asm/byteorder.h>
+#include <errno.h>
+#include <rsa.h>
+#include <asm/types.h>
+#include <asm/unaligned.h>
+
+#define UINT64_MULT32(v, multby) (((uint64_t)(v)) * ((uint32_t)(multby)))
+
+#define get_unaligned_be32(a) fdt32_to_cpu(*(uint32_t *)a)
+#define put_unaligned_be32(a, b) (*(uint32_t *)(b) = cpu_to_fdt32(a))
+
+/* Default public exponent for backward compatibility */
+#define RSA_DEFAULT_PUBEXP 65537
+
+/* This is the minimum/maximum key size we support, in bits */
+#define RSA_MIN_KEY_BITS 1024
+#define RSA_MAX_KEY_BITS 4096
+
+/**
+ * subtract_modulus() - subtract modulus from the given value
+ *
+ * @key: Key containing modulus to subtract
+ * @num: Number to subtract modulus from, as little endian word array
+ */
+static void subtract_modulus(const struct rsa_public_key *key, uint32_t num[])
+{
+ int64_t acc = 0;
+ uint i;
+
+ for (i = 0; i < key->len; i++) {
+ acc += (uint64_t)num[i] - key->modulus[i];
+ num[i] = (uint32_t)acc;
+ acc >>= 32;
+ }
+}
+
+/**
+ * greater_equal_modulus() - check if a value is >= modulus
+ *
+ * @key: Key containing modulus to check
+ * @num: Number to check against modulus, as little endian word array
+ * @return 0 if num < modulus, 1 if num >= modulus
+ */
+static int greater_equal_modulus(const struct rsa_public_key *key,
+ uint32_t num[])
+{
+ int i;
+
+ for (i = (int)key->len - 1; i >= 0; i--) {
+ if (num[i] < key->modulus[i])
+ return 0;
+ if (num[i] > key->modulus[i])
+ return 1;
+ }
+
+ return 1; /* equal */
+}
+
+/**
+ * montgomery_mul_add_step() - Perform montgomery multiply-add step
+ *
+ * Operation: montgomery result[] += a * b[] / n0inv % modulus
+ *
+ * @key: RSA key
+ * @result: Place to put result, as little endian word array
+ * @a: Multiplier
+ * @b: Multiplicand, as little endian word array
+ */
+static void montgomery_mul_add_step(const struct rsa_public_key *key,
+ uint32_t result[], const uint32_t a, const uint32_t b[])
+{
+ uint64_t acc_a, acc_b;
+ uint32_t d0;
+ uint i;
+
+ acc_a = (uint64_t)a * b[0] + result[0];
+ d0 = (uint32_t)acc_a * key->n0inv;
+ acc_b = (uint64_t)d0 * key->modulus[0] + (uint32_t)acc_a;
+ for (i = 1; i < key->len; i++) {
+ acc_a = (acc_a >> 32) + (uint64_t)a * b[i] + result[i];
+ acc_b = (acc_b >> 32) + (uint64_t)d0 * key->modulus[i] +
+ (uint32_t)acc_a;
+ result[i - 1] = (uint32_t)acc_b;
+ }
+
+ acc_a = (acc_a >> 32) + (acc_b >> 32);
+
+ result[i - 1] = (uint32_t)acc_a;
+
+ if (acc_a >> 32)
+ subtract_modulus(key, result);
+}
+
+/**
+ * montgomery_mul() - Perform montgomery mutitply
+ *
+ * Operation: montgomery result[] = a[] * b[] / n0inv % modulus
+ *
+ * @key: RSA key
+ * @result: Place to put result, as little endian word array
+ * @a: Multiplier, as little endian word array
+ * @b: Multiplicand, as little endian word array
+ */
+static void montgomery_mul(const struct rsa_public_key *key,
+ uint32_t result[], uint32_t a[], const uint32_t b[])
+{
+ uint i;
+
+ for (i = 0; i < key->len; ++i)
+ result[i] = 0;
+ for (i = 0; i < key->len; ++i)
+ montgomery_mul_add_step(key, result, a[i], b);
+}
+
+/**
+ * num_pub_exponent_bits() - Number of bits in the public exponent
+ *
+ * @key: RSA key
+ * @num_bits: Storage for the number of public exponent bits
+ */
+static int num_public_exponent_bits(const struct rsa_public_key *key,
+ int *num_bits)
+{
+ uint64_t exponent;
+ int exponent_bits;
+ const uint max_bits = (sizeof(exponent) * 8);
+
+ exponent = key->exponent;
+ exponent_bits = 0;
+
+ if (!exponent) {
+ *num_bits = exponent_bits;
+ return 0;
+ }
+
+ for (exponent_bits = 1; exponent_bits < max_bits + 1; ++exponent_bits)
+ if (!(exponent >>= 1)) {
+ *num_bits = exponent_bits;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/**
+ * is_public_exponent_bit_set() - Check if a bit in the public exponent is set
+ *
+ * @key: RSA key
+ * @pos: The bit position to check
+ */
+static int is_public_exponent_bit_set(const struct rsa_public_key *key,
+ int pos)
+{
+ return key->exponent & (1ULL << pos);
+}
+
+/**
+ * pow_mod() - in-place public exponentiation
+ *
+ * @key: RSA key
+ * @inout: Big-endian word array containing value and result
+ */
+static int pow_mod(const struct rsa_public_key *key, void *__inout)
+{
+ uint32_t *inout = __inout;
+ uint32_t *result, *ptr;
+ uint i;
+ int j, k;
+ uint32_t val[RSA_MAX_KEY_BITS / 32], acc[RSA_MAX_KEY_BITS / 32], tmp[RSA_MAX_KEY_BITS / 32];
+ uint32_t a_scaled[RSA_MAX_KEY_BITS / 32];
+
+ /* Sanity check for stack size - key->len is in 32-bit words */
+ if (key->len > RSA_MAX_KEY_BITS / 32) {
+ debug("RSA key words %u exceeds maximum %d\n", key->len,
+ RSA_MAX_KEY_BITS / 32);
+ return -EINVAL;
+ }
+
+ result = tmp; /* Re-use location. */
+
+ /* Convert from big endian byte array to little endian word array. */
+ for (i = 0, ptr = inout + key->len - 1; i < key->len; i++, ptr--)
+ val[i] = get_unaligned_be32(ptr);
+
+ if (0 != num_public_exponent_bits(key, &k))
+ return -EINVAL;
+
+ if (k < 2) {
+ debug("Public exponent is too short (%d bits, minimum 2)\n",
+ k);
+ return -EINVAL;
+ }
+
+ if (!is_public_exponent_bit_set(key, 0)) {
+ debug("LSB of RSA public exponent must be set.\n");
+ return -EINVAL;
+ }
+
+ /* the bit at e[k-1] is 1 by definition, so start with: C := M */
+ montgomery_mul(key, acc, val, key->rr); /* acc = a * RR / R mod n */
+ /* retain scaled version for intermediate use */
+ memcpy(a_scaled, acc, key->len * sizeof(a_scaled[0]));
+
+ for (j = k - 2; j > 0; --j) {
+ montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
+
+ if (is_public_exponent_bit_set(key, j)) {
+ /* acc = tmp * val / R mod n */
+ montgomery_mul(key, acc, tmp, a_scaled);
+ } else {
+ /* e[j] == 0, copy tmp back to acc for next operation */
+ memcpy(acc, tmp, key->len * sizeof(acc[0]));
+ }
+ }
+
+ /* the bit at e[0] is always 1 */
+ montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
+ montgomery_mul(key, acc, tmp, val); /* acc = tmp * a / R mod M */
+ memcpy(result, acc, key->len * sizeof(result[0]));
+
+ /* Make sure result < mod; result is at most 1x mod too large. */
+ if (greater_equal_modulus(key, result))
+ subtract_modulus(key, result);
+
+ /* Convert to bigendian byte array */
+ for (i = key->len - 1, ptr = inout; (int)i >= 0; i--, ptr++)
+ put_unaligned_be32(result[i], ptr);
+ return 0;
+}
+
+/*
+ * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
+ */
+static const u8 RSA_digest_info_MD5[] = {
+ 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08,
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */
+ 0x05, 0x00, 0x04, 0x10
+};
+
+static const u8 RSA_digest_info_SHA1[] = {
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+ 0x2B, 0x0E, 0x03, 0x02, 0x1A,
+ 0x05, 0x00, 0x04, 0x14
+};
+
+static const u8 RSA_digest_info_RIPE_MD_160[] = {
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+ 0x2B, 0x24, 0x03, 0x02, 0x01,
+ 0x05, 0x00, 0x04, 0x14
+};
+
+static const u8 RSA_digest_info_SHA224[] = {
+ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
+ 0x05, 0x00, 0x04, 0x1C
+};
+
+static const u8 RSA_digest_info_SHA256[] = {
+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
+ 0x05, 0x00, 0x04, 0x20
+};
+
+static const u8 RSA_digest_info_SHA384[] = {
+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
+ 0x05, 0x00, 0x04, 0x30
+};
+
+static const u8 RSA_digest_info_SHA512[] = {
+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
+ 0x05, 0x00, 0x04, 0x40
+};
+
+static const struct {
+ const u8 *data;
+ size_t size;
+} RSA_ASN1_templates[] = {
+#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) }
+ [HASH_ALGO_MD5] = _(MD5),
+ [HASH_ALGO_SHA1] = _(SHA1),
+ [HASH_ALGO_RIPE_MD_160] = _(RIPE_MD_160),
+ [HASH_ALGO_SHA256] = _(SHA256),
+ [HASH_ALGO_SHA384] = _(SHA384),
+ [HASH_ALGO_SHA512] = _(SHA512),
+ [HASH_ALGO_SHA224] = _(SHA224),
+#undef _
+};
+
+int rsa_verify(const struct rsa_public_key *key, const uint8_t *sig,
+ const uint32_t sig_len, const uint8_t *hash,
+ enum hash_algo algo)
+{
+ int ret = 0;
+ uint8_t buf[RSA_MAX_SIG_BITS / 8];
+ int i;
+ unsigned PS_end, T_offset;
+ const u8 *asn1_template = RSA_ASN1_templates[algo].data;
+ size_t asn1_size = RSA_ASN1_templates[algo].size;
+ struct digest *d = digest_alloc_by_algo(algo);
+
+ if (!d)
+ return -EOPNOTSUPP;
+
+ if (sig_len != (key->len * sizeof(uint32_t))) {
+ debug("Signature is of incorrect length %d, should be %d\n", sig_len,
+ key->len * sizeof(uint32_t));
+ ret = -EINVAL;
+ goto out_free_digest;
+ }
+
+ /* Sanity check for stack size */
+ if (sig_len > RSA_MAX_SIG_BITS / 8) {
+ debug("Signature length %u exceeds maximum %d\n", sig_len,
+ RSA_MAX_SIG_BITS / 8);
+ ret = -EINVAL;
+ goto out_free_digest;
+ }
+
+ memcpy(buf, sig, sig_len);
+
+ ret = pow_mod(key, buf);
+ if (ret)
+ goto out_free_digest;
+
+ T_offset = sig_len - (asn1_size + digest_length(d));
+
+ PS_end = T_offset - 1;
+ if (buf[PS_end] != 0x00) {
+ pr_err(" = -EBADMSG [EM[T-1] == %02u]", buf[PS_end]);
+ ret = -EBADMSG;
+ goto out_free_digest;
+ }
+
+ for (i = 2; i < PS_end; i++) {
+ if (buf[i] != 0xff) {
+ pr_err(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, buf[i]);
+ ret = -EBADMSG;
+ goto out_free_digest;
+ }
+ }
+
+ if (memcmp(asn1_template, buf + T_offset, asn1_size) != 0) {
+ pr_err(" = -EBADMSG [EM[T] ASN.1 mismatch]");
+ ret = -EBADMSG;
+ goto out_free_digest;
+ }
+
+ if (memcmp(hash, buf + T_offset + asn1_size, digest_length(d)) != 0) {
+ pr_err(" = -EKEYREJECTED [EM[T] hash mismatch]");
+ ret = -EKEYREJECTED;
+ goto out_free_digest;
+ }
+
+ out_free_digest:
+ digest_free(d);
+
+ return ret;
+}
+
+static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ dst[i] = fdt32_to_cpu(src[len - 1 - i]);
+}
+
+int rsa_of_read_key(struct device_node *node, struct rsa_public_key *key)
+{
+ const void *modulus, *rr;
+ const uint64_t *public_exponent;
+ int length;
+
+ of_property_read_u32(node, "rsa,num-bits", &key->len);
+ of_property_read_u32(node, "rsa,n0-inverse", &key->n0inv);
+
+ public_exponent = of_get_property(node, "rsa,exponent", &length);
+ if (!public_exponent || length < sizeof(*public_exponent))
+ key->exponent = RSA_DEFAULT_PUBEXP;
+ else
+ key->exponent = fdt64_to_cpu(*public_exponent);
+
+ modulus = of_get_property(node, "rsa,modulus", NULL);
+ rr = of_get_property(node, "rsa,r-squared", NULL);
+
+ if (!key->len || !modulus || !rr) {
+ debug("%s: Missing RSA key info", __func__);
+ return -EFAULT;
+ }
+
+ /* Sanity check for stack size */
+ if (key->len > RSA_MAX_KEY_BITS || key->len < RSA_MIN_KEY_BITS) {
+ debug("RSA key bits %u outside allowed range %d..%d\n",
+ key->len, RSA_MIN_KEY_BITS, RSA_MAX_KEY_BITS);
+ return -EFAULT;
+ }
+
+ key->len /= sizeof(uint32_t) * 8;
+
+ key->modulus = xzalloc(RSA_MAX_KEY_BITS / 8);
+ key->rr = xzalloc(RSA_MAX_KEY_BITS / 8);
+
+ rsa_convert_big_endian(key->modulus, modulus, key->len);
+ rsa_convert_big_endian(key->rr, rr, key->len);
+
+ return 0;
+}
diff --git a/include/asm-generic/errno.h b/include/asm-generic/errno.h
index 6072f7b..7d99a95 100644
--- a/include/asm-generic/errno.h
+++ b/include/asm-generic/errno.h
@@ -126,6 +126,11 @@
#define ENOMEDIUM 123 /* No medium found */
#define EMEDIUMTYPE 124 /* Wrong medium type */
+#define ECANCELED 125 /* Operation Canceled */
+#define ENOKEY 126 /* Required key not available */
+#define EKEYEXPIRED 127 /* Key has expired */
+#define EKEYREVOKED 128 /* Key has been revoked */
+#define EKEYREJECTED 129 /* Key was rejected by service */
/* Should never be seen by user programs */
#define ERESTARTSYS 512
diff --git a/include/rsa.h b/include/rsa.h
new file mode 100644
index 0000000..feb8c31
--- /dev/null
+++ b/include/rsa.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ *
+ * (C) Copyright 2008 Semihalf
+ *
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _RSA_H
+#define _RSA_H
+
+#include <errno.h>
+#include <digest.h>
+
+/**
+ * struct rsa_public_key - holder for a public key
+ *
+ * An RSA public key consists of a modulus (typically called N), the inverse
+ * and R^2, where R is 2^(# key bits).
+ */
+
+struct rsa_public_key {
+ uint len; /* len of modulus[] in number of uint32_t */
+ uint32_t n0inv; /* -1 / modulus[0] mod 2^32 */
+ uint32_t *modulus; /* modulus as little endian array */
+ uint32_t *rr; /* R^2 as little endian array */
+ uint64_t exponent; /* public exponent */
+};
+
+/**
+ * rsa_verify() - Verify a signature against some data
+ *
+ * Verify a RSA PKCS1.5 signature against an expected hash.
+ *
+ * @info: Specifies key and FIT information
+ * @data: Pointer to the input data
+ * @data_len: Data length
+ * @sig: Signature
+ * @sig_len: Number of bytes in signature
+ * @return 0 if verified, -ve on error
+ */
+int rsa_verify(const struct rsa_public_key *key, const uint8_t *sig,
+ const uint32_t sig_len, const uint8_t *hash,
+ enum hash_algo algo);
+
+/* This is the maximum signature length that we support, in bits */
+#define RSA_MAX_SIG_BITS 4096
+
+int rsa_of_read_key(struct device_node *node, struct rsa_public_key *key);
+
+#endif
--
2.7.0.rc3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 12/14] bootm: make verifying/hashing configurable
2016-01-22 7:32 [PATCH v4] FIT support Sascha Hauer
` (10 preceding siblings ...)
2016-01-22 7:32 ` [PATCH 11/14] crypto: add RSA support Sascha Hauer
@ 2016-01-22 7:32 ` Sascha Hauer
2016-01-22 7:32 ` [PATCH 13/14] bootm: add initial FIT support Sascha Hauer
2016-01-22 7:32 ` [PATCH 14/14] bootm: Add option to force booting signed images Sascha Hauer
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2016-01-22 7:32 UTC (permalink / raw)
To: Barebox List
So long struct bootm_data.verify is a bool which enables CRC checking
(hashing). Extend this to a enum and add support for signature checking
in the same option. This also adds the corresponding globalvar and a
-s option to bootm.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
commands/bootm.c | 12 +++++++++---
common/bootm.c | 20 ++++++++++++++++++--
include/boot.h | 12 ++++++++++--
3 files changed, 37 insertions(+), 7 deletions(-)
diff --git a/commands/bootm.c b/commands/bootm.c
index 6db0e65..7a19fa2 100644
--- a/commands/bootm.c
+++ b/commands/bootm.c
@@ -46,7 +46,7 @@
#include <magicvar.h>
#include <asm-generic/memory_layout.h>
-#define BOOTM_OPTS_COMMON "ca:e:vo:fd"
+#define BOOTM_OPTS_COMMON "sca:e:vo:fd"
#ifdef CONFIG_CMD_BOOTM_INITRD
#define BOOTM_OPTS BOOTM_OPTS_COMMON "L:r:"
@@ -65,7 +65,11 @@ static int do_bootm(int argc, char *argv[])
while ((opt = getopt(argc, argv, BOOTM_OPTS)) > 0) {
switch(opt) {
case 'c':
- data.verify = 1;
+ if (data.verify < BOOTM_VERIFY_HASH)
+ data.verify = BOOTM_VERIFY_HASH;
+ break;
+ case 's':
+ data.verify = BOOTM_VERIFY_SIGNATURE;
break;
#ifdef CONFIG_CMD_BOOTM_INITRD
case 'L':
@@ -118,7 +122,8 @@ err_out:
BAREBOX_CMD_HELP_START(bootm)
BAREBOX_CMD_HELP_TEXT("Options:")
-BAREBOX_CMD_HELP_OPT ("-c\t", "crc check uImage data")
+BAREBOX_CMD_HELP_OPT ("-c\t", "hash check image integrity")
+BAREBOX_CMD_HELP_OPT ("-s\t", "check signature of image")
BAREBOX_CMD_HELP_OPT ("-d\t", "dry run: check data, but do not run")
BAREBOX_CMD_HELP_OPT ("-f\t", "load images even if type is undetectable")
#ifdef CONFIG_CMD_BOOTM_INITRD
@@ -160,6 +165,7 @@ BAREBOX_MAGICVAR_NAMED(global_bootm_image_loadaddr, global.bootm.image.loadaddr,
BAREBOX_MAGICVAR_NAMED(global_bootm_initrd, global.bootm.initrd, "bootm default initrd");
BAREBOX_MAGICVAR_NAMED(global_bootm_initrd_loadaddr, global.bootm.initrd.loadaddr, "bootm default initrd loadaddr");
BAREBOX_MAGICVAR_NAMED(global_bootm_oftree, global.bootm.oftree, "bootm default oftree");
+BAREBOX_MAGICVAR_NAMED(global_bootm_verify, global.bootm.verify, "bootm default verify level");
static struct binfmt_hook binfmt_uimage_hook = {
.type = filetype_uimage,
diff --git a/common/bootm.c b/common/bootm.c
index 4409a8b..78a6bb5 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -56,8 +56,22 @@ void bootm_data_init_defaults(struct bootm_data *data)
getenv_ul("global.bootm.image.loadaddr", &data->os_address);
getenv_ul("global.bootm.initrd.loadaddr", &data->initrd_address);
data->initrd_file = getenv_nonempty("global.bootm.initrd");
+ data->verify = bootm_get_verify_mode();
}
+static enum bootm_verify bootm_verify_mode = BOOTM_VERIFY_HASH;
+
+enum bootm_verify bootm_get_verify_mode(void)
+{
+ return bootm_verify_mode;
+}
+
+static const char * const bootm_verify_names[] = {
+ [BOOTM_VERIFY_NONE] = "none",
+ [BOOTM_VERIFY_HASH] = "hash",
+ [BOOTM_VERIFY_SIGNATURE] = "signature",
+};
+
/*
* bootm_load_os() - load OS to RAM
*
@@ -122,7 +136,7 @@ static int bootm_open_initrd_uimage(struct image_data *data)
if (!data->initrd)
return -EINVAL;
- if (data->verify) {
+ if (bootm_get_verify_mode() > BOOTM_VERIFY_NONE) {
ret = uimage_verify(data->initrd);
if (ret) {
printf("Checking data crc failed with %s\n",
@@ -382,7 +396,7 @@ static int bootm_open_os_uimage(struct image_data *data)
if (!data->os)
return -EINVAL;
- if (data->verify) {
+ if (bootm_get_verify_mode() > BOOTM_VERIFY_NONE) {
ret = uimage_verify(data->os);
if (ret) {
printf("Checking data crc failed with %s\n",
@@ -550,6 +564,8 @@ static int bootm_init(void)
globalvar_add_simple("bootm.initrd", NULL);
globalvar_add_simple("bootm.initrd.loadaddr", NULL);
}
+ globalvar_add_simple_enum("bootm.verify", (unsigned int *)&bootm_verify_mode,
+ bootm_verify_names, ARRAY_SIZE(bootm_verify_names));
return 0;
}
diff --git a/include/boot.h b/include/boot.h
index 0c0febe..363a02a 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -7,12 +7,18 @@
#include <linux/list.h>
#include <environment.h>
+enum bootm_verify {
+ BOOTM_VERIFY_NONE,
+ BOOTM_VERIFY_HASH,
+ BOOTM_VERIFY_SIGNATURE,
+};
+
struct bootm_data {
const char *os_file;
const char *initrd_file;
const char *oftree_file;
int verbose;
- bool verify;
+ enum bootm_verify verify;
bool force;
bool dryrun;
unsigned long initrd_address;
@@ -63,7 +69,7 @@ struct image_data {
struct fdt_header *oftree;
struct resource *oftree_res;
- int verify;
+ enum bootm_verify verify;
int verbose;
int force;
int dryrun;
@@ -119,6 +125,8 @@ int bootm_load_initrd(struct image_data *data, unsigned long load_address);
int bootm_load_devicetree(struct image_data *data, unsigned long load_address);
int bootm_get_os_size(struct image_data *data);
+enum bootm_verify bootm_get_verify_mode(void);
+
#define UIMAGE_SOME_ADDRESS (UIMAGE_INVALID_ADDRESS - 1)
#endif /* __BOOT_H */
--
2.7.0.rc3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 13/14] bootm: add initial FIT support
2016-01-22 7:32 [PATCH v4] FIT support Sascha Hauer
` (11 preceding siblings ...)
2016-01-22 7:32 ` [PATCH 12/14] bootm: make verifying/hashing configurable Sascha Hauer
@ 2016-01-22 7:32 ` Sascha Hauer
2016-01-22 7:32 ` [PATCH 14/14] bootm: Add option to force booting signed images Sascha Hauer
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2016-01-22 7:32 UTC (permalink / raw)
To: Barebox List
From: Jan Luebbe <jlu@pengutronix.de>
This implementation is inspired by U-Boot's FIT support. Instead of
using libfdt (which does not exist in barebox), configuration signatures
are verified by using a simplified DT parser based on barebox's own
code.
Currently, only signed configurations with hashed images are supported,
as the other variants are less useful for verified boot. Compatible FIT
images can be created using U-Boot's mkimage tool.
Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/lib/bootm.c | 8 +
commands/Kconfig | 25 +++
common/Kconfig | 9 +
common/Makefile | 1 +
common/bootm.c | 53 ++++-
common/image-fit.c | 584 +++++++++++++++++++++++++++++++++++++++++++++++++++
include/boot.h | 4 +
include/image-fit.h | 45 ++++
8 files changed, 726 insertions(+), 3 deletions(-)
create mode 100644 common/image-fit.c
create mode 100644 include/image-fit.h
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 4dfe148..1913d5f 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -531,6 +531,12 @@ BAREBOX_MAGICVAR(aimage_noverwrite_bootargs, "Disable overwrite of the bootargs
BAREBOX_MAGICVAR(aimage_noverwrite_tags, "Disable overwrite of the tags addr with the one present in aimage");
#endif
+static struct image_handler arm_fit_handler = {
+ .name = "FIT image",
+ .bootm = do_bootm_linux,
+ .filetype = filetype_oftree,
+};
+
static struct binfmt_hook binfmt_aimage_hook = {
.type = filetype_aimage,
.exec = "bootm",
@@ -556,6 +562,8 @@ static int armlinux_register_image_handler(void)
register_image_handler(&aimage_handler);
binfmt_register(&binfmt_aimage_hook);
}
+ if (IS_BUILTIN(CONFIG_CMD_BOOTM_FITIMAGE))
+ register_image_handler(&arm_fit_handler);
binfmt_register(&binfmt_arm_zimage_hook);
binfmt_register(&binfmt_barebox_hook);
diff --git a/commands/Kconfig b/commands/Kconfig
index 1743670..b4fdc86 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -418,6 +418,31 @@ config CMD_BOOTM_AIMAGE
help
Support using Android Images.
+config CMD_BOOTM_FITIMAGE
+ bool
+ prompt "FIT image support"
+ select FITIMAGE
+ depends on CMD_BOOTM && ARM
+ help
+ Support using Flattened Image Tree (FIT) Images. FIT is an image
+ format introduced by U-Boot. A FIT image contains one or multiple
+ kernels, device trees and initrds. The FIT image itself is a flattened
+ device tree binary. Have a look at the u-boot source tree
+ in the "doc/uImage.FIT" folder for more information:
+ http://git.denx.de/?p=u-boot.git;a=tree;f=doc/uImage.FIT
+
+config CMD_BOOTM_FITIMAGE_SIGNATURE
+ bool
+ prompt "support verifying signed FIT images"
+ depends on CMD_BOOTM_FITIMAGE
+ select FITIMAGE_SIGNATURE
+ help
+ Support verifying signed FIT images. This requires FIT images
+ as described in:
+ http://git.denx.de/?p=u-boot.git;a=blob;f=doc/uImage.FIT/signature.txt
+ Additionally the barebox device tree needs a /signature node with the
+ public key with which the image has been signed.
+
config CMD_BOOTU
tristate
default y
diff --git a/common/Kconfig b/common/Kconfig
index 8e79509..345de50 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -66,6 +66,15 @@ config UIMAGE
select CRC32
bool
+config FITIMAGE
+ bool
+ select OFTREE
+ select DIGEST
+
+config FITIMAGE_SIGNATURE
+ select CRYPTO_RSA
+ bool
+
config LOGBUF
bool
diff --git a/common/Makefile b/common/Makefile
index 56e6bec..ffaf8e7 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_SHELL_HUSH) += hush.o
obj-$(CONFIG_SHELL_SIMPLE) += parser.o
obj-$(CONFIG_STATE) += state.o
obj-$(CONFIG_UIMAGE) += image.o uimage.o
+obj-$(CONFIG_FITIMAGE) += image-fit.o
obj-$(CONFIG_MENUTREE) += menutree.o
obj-$(CONFIG_EFI_GUID) += efi-guid.o
obj-$(CONFIG_EFI_DEVICEPATH) += efi-devicepath.o
diff --git a/common/bootm.c b/common/bootm.c
index 78a6bb5..d8acff8 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -17,6 +17,7 @@
#include <malloc.h>
#include <memory.h>
#include <libfile.h>
+#include <image-fit.h>
#include <globalvar.h>
#include <init.h>
#include <linux/stat.h>
@@ -92,6 +93,17 @@ int bootm_load_os(struct image_data *data, unsigned long load_address)
if (load_address == UIMAGE_INVALID_ADDRESS)
return -EINVAL;
+ if (data->os_fit) {
+ data->os_res = request_sdram_region("kernel",
+ load_address,
+ data->os_fit->kernel_size);
+ if (!data->os_res)
+ return -ENOMEM;
+ memcpy((void *)load_address, data->os_fit->kernel,
+ data->os_fit->kernel_size);
+ return 0;
+ }
+
if (data->os) {
int num;
@@ -121,6 +133,9 @@ bool bootm_has_initrd(struct image_data *data)
if (!IS_ENABLED(CONFIG_CMD_BOOTM_INITRD))
return false;
+ if (data->os_fit && data->os_fit->initrd)
+ return true;
+
if (data->initrd_file)
return true;
@@ -178,6 +193,18 @@ int bootm_load_initrd(struct image_data *data, unsigned long load_address)
if (data->initrd_res)
return 0;
+ if (data->os_fit && data->os_fit->initrd) {
+ data->initrd_res = request_sdram_region("initrd",
+ load_address,
+ data->os_fit->initrd_size);
+ if (!data->initrd_res)
+ return -ENOMEM;
+ memcpy((void *)load_address, data->os_fit->initrd,
+ data->os_fit->initrd_size);
+ printf("Loaded initrd from FIT image\n");
+ goto done1;
+ }
+
type = file_name_detect_type(data->initrd_file);
if ((int)type < 0) {
@@ -216,7 +243,7 @@ done:
if (type == filetype_uimage && data->initrd->header.ih_type == IH_TYPE_MULTI)
printf(", multifile image %s", data->initrd_part);
printf("\n");
-
+done1:
printf("initrd is at " PRINTF_CONVERSION_RESOURCE "-" PRINTF_CONVERSION_RESOURCE "\n",
data->initrd_res->start,
data->initrd_res->end);
@@ -289,7 +316,9 @@ int bootm_load_devicetree(struct image_data *data, unsigned long load_address)
if (!IS_ENABLED(CONFIG_OFTREE))
return 0;
- if (data->oftree_file) {
+ if (data->os_fit && data->os_fit->oftree) {
+ data->of_root_node = of_unflatten_dtb(data->os_fit->oftree);
+ } else if (data->oftree_file) {
size_t size;
type = file_name_detect_type(data->oftree_file);
@@ -376,6 +405,8 @@ int bootm_get_os_size(struct image_data *data)
if (data->os)
return uimage_get_size(data->os,
simple_strtoul(data->os_part, NULL, 0));
+ if (data->os_fit)
+ return data->os_fit->kernel_size;
if (data->os_file) {
struct stat s;
@@ -495,10 +526,24 @@ int bootm_boot(struct bootm_data *bootm_data)
goto err_out;
}
+ if (IS_ENABLED(CONFIG_FITIMAGE) && os_type == filetype_oftree) {
+ struct fit_handle *fit;
+
+ fit = fit_open(data->os_file, data->os_part, data->verbose, data->verify);
+ if (IS_ERR(fit)) {
+ printf("Loading FIT image %s failed with: %s\n", data->os_file,
+ strerrorp(fit));
+ ret = PTR_ERR(fit);
+ goto err_out;
+ }
+
+ data->os_fit = fit;
+ }
+
if (os_type == filetype_uimage) {
ret = bootm_open_os_uimage(data);
if (ret) {
- printf("Loading OS image failed with %s\n",
+ printf("Loading OS image failed with: %s\n",
strerror(-ret));
goto err_out;
}
@@ -544,6 +589,8 @@ err_out:
uimage_close(data->initrd);
if (data->os)
uimage_close(data->os);
+ if (IS_ENABLED(CONFIG_FITIMAGE) && data->os_fit)
+ fit_close(data->os_fit);
if (data->of_root_node && data->of_root_node != of_get_root_node())
of_delete_node(data->of_root_node);
diff --git a/common/image-fit.c b/common/image-fit.c
new file mode 100644
index 0000000..4f5c1f1
--- /dev/null
+++ b/common/image-fit.c
@@ -0,0 +1,584 @@
+/*
+ * Copyright (C) Jan Lübbe, 2014
+ *
+ * This code is inspired by the U-Boot FIT image code.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) "FIT: " fmt
+#include <common.h>
+#include <init.h>
+#include <boot.h>
+#include <libfile.h>
+#include <fdt.h>
+#include <digest.h>
+#include <of.h>
+#include <fs.h>
+#include <malloc.h>
+#include <linux/ctype.h>
+#include <asm/byteorder.h>
+#include <errno.h>
+#include <linux/err.h>
+#include <stringlist.h>
+#include <rsa.h>
+#include <image-fit.h>
+
+#define FDT_MAX_DEPTH 32
+#define FDT_MAX_PATH_LEN 200
+
+#define CHECK_LEVEL_NONE 0
+#define CHECK_LEVEL_HASH 1
+#define CHECK_LEVEL_SIG 2
+#define CHECK_LEVEL_MAX 3
+
+static uint32_t dt_struct_advance(struct fdt_header *f, uint32_t dt, int size)
+{
+ dt += size;
+ dt = ALIGN(dt, 4);
+
+ if (dt > f->off_dt_struct + f->size_dt_struct)
+ return 0;
+
+ return dt;
+}
+
+static char *dt_string(struct fdt_header *f, char *strstart, uint32_t ofs)
+{
+ if (ofs > f->size_dt_strings)
+ return NULL;
+ else
+ return strstart + ofs;
+}
+
+static int of_read_string_list(struct device_node *np, const char *name, struct string_list *sl)
+{
+ struct property *prop;
+ const char *s;
+
+ of_property_for_each_string(np, name, prop, s) {
+ string_list_add(sl, s);
+ }
+
+ return prop ? 0 : -EINVAL;
+}
+
+static int fit_digest(void *fit, struct digest *digest,
+ struct string_list *inc_nodes, struct string_list *exc_props,
+ uint32_t hashed_strings_start, uint32_t hashed_strings_size)
+{
+ struct fdt_header *fdt = fit;
+ uint32_t dt_struct;
+ void *dt_strings;
+ struct fdt_header f = {};
+ int stack[FDT_MAX_DEPTH];
+ char path[FDT_MAX_PATH_LEN];
+ char *end;
+ uint32_t tag;
+ int start = -1;
+ int depth = -1;
+ int want = 0;
+
+ f.totalsize = fdt32_to_cpu(fdt->totalsize);
+ f.off_dt_struct = fdt32_to_cpu(fdt->off_dt_struct);
+ f.size_dt_struct = fdt32_to_cpu(fdt->size_dt_struct);
+ f.off_dt_strings = fdt32_to_cpu(fdt->off_dt_strings);
+ f.size_dt_strings = fdt32_to_cpu(fdt->size_dt_strings);
+
+ if (hashed_strings_start > f.size_dt_strings ||
+ hashed_strings_size > f.size_dt_strings ||
+ hashed_strings_start + hashed_strings_size > f.size_dt_strings) {
+ pr_err("%s: hashed-strings too large\n", __func__);
+ return -EINVAL;
+ }
+
+ dt_struct = f.off_dt_struct;
+ dt_strings = (void *)fdt + f.off_dt_strings;
+
+ end = path;
+ *end = '\0';
+
+ do {
+ const struct fdt_property *fdt_prop;
+ const struct fdt_node_header *fnh;
+ const char *name;
+ int include = 0;
+ int stop_at = 0;
+ int offset = dt_struct;
+ int maxlen, len;
+
+ tag = be32_to_cpu(*(uint32_t *)(fit + dt_struct));
+
+ switch (tag) {
+ case FDT_BEGIN_NODE:
+ fnh = fit + dt_struct;
+ name = fnh->name;
+ maxlen = (unsigned long)fdt + f.off_dt_struct +
+ f.size_dt_struct - (unsigned long)name;
+
+ len = strnlen(name, maxlen + 1);
+ if (len > maxlen)
+ return -ESPIPE;
+
+ dt_struct = dt_struct_advance(&f, dt_struct,
+ sizeof(struct fdt_node_header) + len + 1);
+
+ depth++;
+ if (depth == FDT_MAX_DEPTH)
+ return -ESPIPE;
+ if (end - path + 2 + len >= FDT_MAX_PATH_LEN)
+ return -ESPIPE;
+ if (end != path + 1)
+ *end++ = '/';
+ strcpy(end, name);
+ end += len;
+ stack[depth] = want;
+ if (want == 1)
+ stop_at = offset;
+ if (string_list_contains(inc_nodes, path))
+ want = 2;
+ else if (want)
+ want--;
+ else
+ stop_at = offset;
+ include = want;
+
+ break;
+
+ case FDT_END_NODE:
+ dt_struct = dt_struct_advance(&f, dt_struct, FDT_TAGSIZE);
+
+ include = want;
+ want = stack[depth--];
+ while (end > path && *--end != '/')
+ ;
+ *end = '\0';
+
+ break;
+
+ case FDT_PROP:
+ fdt_prop = fit + dt_struct;
+ len = fdt32_to_cpu(fdt_prop->len);
+
+ name = dt_string(&f, dt_strings, fdt32_to_cpu(fdt_prop->nameoff));
+ if (!name)
+ return -ESPIPE;
+
+ dt_struct = dt_struct_advance(&f, dt_struct,
+ sizeof(struct fdt_property) + len);
+
+ include = want >= 2;
+ stop_at = offset;
+ if (string_list_contains(exc_props, name))
+ include = 0;
+
+ break;
+
+ case FDT_NOP:
+ dt_struct = dt_struct_advance(&f, dt_struct, FDT_TAGSIZE);
+
+ include = want >= 2;
+ stop_at = offset;
+
+ break;
+
+ case FDT_END:
+ dt_struct = dt_struct_advance(&f, dt_struct, FDT_TAGSIZE);
+
+ include = 1;
+
+ break;
+
+ default:
+ pr_err("%s: Unknown tag 0x%08X\n", __func__, tag);
+ return -EINVAL;
+ }
+
+ if (!dt_struct)
+ return -ESPIPE;
+
+ pr_debug("%s: include %d, want %d, offset 0x%x, len 0x%x\n",
+ path, include, want, offset, dt_struct-offset);
+
+ if (include && start == -1)
+ start = offset;
+
+ if (!include && start != -1) {
+ pr_debug("region: 0x%p+0x%x\n", fit + start, offset - start);
+ digest_update(digest, fit + start, offset - start);
+ start = -1;
+ }
+ } while (tag != FDT_END);
+
+ pr_debug("region: 0x%p+0x%x\n", fit + start, dt_struct - start);
+ digest_update(digest, fit + start, dt_struct - start);
+
+ pr_debug("strings: 0x%p+0x%x\n", dt_strings+hashed_strings_start, hashed_strings_size);
+ digest_update(digest, dt_strings + hashed_strings_start, hashed_strings_size);
+
+ return 0;
+}
+
+/*
+ * The consistency of the FTD structure was already checked by of_unflatten_dtb()
+ */
+static int fit_verify_signature(struct device_node *sig_node, void *fit)
+{
+ uint32_t hashed_strings_start, hashed_strings_size;
+ struct string_list inc_nodes, exc_props;
+ struct rsa_public_key key = {};
+ struct digest *digest;
+ int sig_len;
+ const char *algo_name, *key_name, *sig_value;
+ char *key_path;
+ struct device_node *key_node;
+ enum hash_algo algo;
+ void *hash;
+ int ret;
+
+ if (of_property_read_string(sig_node, "algo", &algo_name)) {
+ pr_err("algo not found\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ if (strcmp(algo_name, "sha1,rsa2048") == 0) {
+ algo = HASH_ALGO_SHA1;
+ } else if (strcmp(algo_name, "sha256,rsa4096") == 0) {
+ algo = HASH_ALGO_SHA256;
+ } else {
+ pr_err("unknown algo %s\n", algo_name);
+ ret = -EINVAL;
+ goto out;
+ }
+ digest = digest_alloc_by_algo(algo);
+ if (!digest) {
+ pr_err("unsupported algo %s\n", algo_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ sig_value = of_get_property(sig_node, "value", &sig_len);
+ if (!sig_value) {
+ pr_err("signature value not found in %s\n", sig_node->full_name);
+ ret = -EINVAL;
+ goto out_free_digest;
+ }
+
+ if (of_property_read_string(sig_node, "key-name-hint", &key_name)) {
+ pr_err("key name not found in %s\n", sig_node->full_name);
+ ret = -EINVAL;
+ goto out_free_digest;
+ }
+ key_path = xasprintf("/signature/key-%s", key_name);
+ key_node = of_find_node_by_path(key_path);
+ free(key_path);
+ if (!key_node) {
+ pr_info("failed to find key node\n");
+ ret = -ENOENT;
+ goto out_free_digest;
+ }
+
+ ret = rsa_of_read_key(key_node, &key);
+ if (ret) {
+ pr_info("failed to read key in %s\n", key_node->full_name);
+ ret = -ENOENT;
+ goto out_free_digest;
+ }
+
+ if (of_property_read_u32_index(sig_node, "hashed-strings", 0, &hashed_strings_start)) {
+ pr_err("hashed-strings start not found in %s\n", sig_node->full_name);
+ ret = -EINVAL;
+ goto out_free_digest;
+ }
+ if (of_property_read_u32_index(sig_node, "hashed-strings", 1, &hashed_strings_size)) {
+ pr_err("hashed-strings size not found in %s\n", sig_node->full_name);
+ ret = -EINVAL;
+ goto out_free_digest;
+ }
+
+ string_list_init(&inc_nodes);
+ string_list_init(&exc_props);
+
+ if (of_read_string_list(sig_node, "hashed-nodes", &inc_nodes)) {
+ pr_err("hashed-nodes property not found in %s\n", sig_node->full_name);
+ ret = -EINVAL;
+ goto out_sl;
+ }
+
+ string_list_add(&exc_props, "data");
+
+ digest_init(digest);
+ ret = fit_digest(fit, digest, &inc_nodes, &exc_props, hashed_strings_start, hashed_strings_size);
+ hash = xzalloc(digest_length(digest));
+ digest_final(digest, hash);
+
+ ret = rsa_verify(&key, sig_value, sig_len, hash, algo);
+ if (ret) {
+ pr_info("image signature BAD\n");
+ ret = -EBADMSG;
+ } else {
+ pr_info("image signature OK\n");
+ ret = 0;
+ }
+
+ free(hash);
+ out_sl:
+ string_list_free(&inc_nodes);
+ string_list_free(&exc_props);
+ out_free_digest:
+ digest_free(digest);
+ out:
+ return ret;
+}
+
+static int fit_verify_hash(struct device_node *hash, const void *data, int data_len)
+{
+ struct digest *d;
+ const char *algo;
+ const char *value_read;
+ char *value_calc;
+ int hash_len, ret;
+
+ value_read = of_get_property(hash, "value", &hash_len);
+ if (!value_read) {
+ pr_err("%s: \"value\" property not found\n", hash->full_name);
+ return -EINVAL;
+ }
+
+ if (of_property_read_string(hash, "algo", &algo)) {
+ pr_err("%s: \"algo\" property not found\n", hash->full_name);
+ return -EINVAL;
+ }
+
+ d = digest_alloc(algo);
+ if (!d) {
+ pr_err("%s: unsupported algo %s\n", hash->full_name, algo);
+ return -EINVAL;
+ }
+
+ if (hash_len != digest_length(d)) {
+ pr_err("%s: invalid hash length %d\n", hash->full_name, hash_len);
+ ret = -EINVAL;
+ goto err_digest_free;
+ }
+
+ value_calc = xmalloc(hash_len);
+
+ digest_init(d);
+ digest_update(d, data, data_len);
+ digest_final(d, value_calc);
+
+ if (memcmp(value_read, value_calc, hash_len)) {
+ pr_info("%s: hash BAD\n", hash->full_name);
+ ret = -EBADMSG;
+ } else {
+ pr_info("%s: hash OK\n", hash->full_name);
+ ret = 0;
+ }
+
+ free(value_calc);
+
+err_digest_free:
+ digest_free(d);
+
+ return ret;
+}
+
+static int fit_open_image(struct fit_handle *handle, const char *unit, const void **outdata,
+ unsigned long *outsize)
+{
+ struct device_node *image = NULL, *hash;
+ const char *type = NULL, *desc= "(no description)";
+ const void *data;
+ int data_len;
+ int ret = 0;
+
+ image = of_get_child_by_name(handle->root, "images");
+ if (!image)
+ return -ENOENT;
+
+ image = of_get_child_by_name(image, unit);
+ if (!image)
+ return -ENOENT;
+
+ of_property_read_string(image, "description", &desc);
+ pr_info("image '%s': '%s'\n", unit, desc);
+
+ of_property_read_string(image, "type", &type);
+ if (!type) {
+ pr_err("No \"type\" property found in %s\n", image->full_name);
+ return -EINVAL;
+ }
+
+ data = of_get_property(image, "data", &data_len);
+ if (!data) {
+ pr_err("data not found\n");
+ return -EINVAL;
+ }
+
+ if (handle->verify > BOOTM_VERIFY_NONE) {
+ ret = -EINVAL;
+ for_each_child_of_node(image, hash) {
+ if (handle->verbose)
+ of_print_nodes(hash, 0);
+ ret = fit_verify_hash(hash, data, data_len);
+ if (ret < 0)
+ return ret;
+ }
+ }
+ if (ret < 0)
+ return ret;
+
+ *outdata = data;
+ *outsize = data_len;
+
+ return 0;
+}
+
+static int fit_open_configuration(struct fit_handle *handle, const char *name)
+{
+ struct device_node *conf_node = NULL, *sig_node;
+ const char *unit, *desc = "(no description)";
+ int ret;
+
+ conf_node = of_get_child_by_name(handle->root, "configurations");
+ if (!conf_node)
+ return -ENOENT;
+
+ if (name) {
+ unit = name;
+ } else if (of_property_read_string(conf_node, "default", &unit)) {
+ unit = "conf@1";
+ }
+
+ conf_node = of_get_child_by_name(conf_node, unit);
+ if (!conf_node) {
+ pr_err("configuration '%s' not found\n", unit);
+ return -ENOENT;
+ }
+
+ of_property_read_string(conf_node, "description", &desc);
+ pr_info("configuration '%s': %s\n", unit, desc);
+
+ if (IS_ENABLED(CONFIG_FITIMAGE_SIGNATURE) &&
+ handle->verify == BOOTM_VERIFY_SIGNATURE) {
+ ret = -EINVAL;
+ for_each_child_of_node(conf_node, sig_node) {
+ if (handle->verbose)
+ of_print_nodes(sig_node, 0);
+ ret = fit_verify_signature(sig_node, handle->fit);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (ret < 0)
+ return ret;
+ }
+
+ if (of_property_read_string(conf_node, "kernel", &unit) == 0) {
+ ret = fit_open_image(handle, unit, &handle->kernel, &handle->kernel_size);
+ if (ret)
+ return ret;
+ } else {
+ return -ENOENT;
+ }
+
+ if (of_property_read_string(conf_node, "fdt", &unit) == 0) {
+ ret = fit_open_image(handle, unit, &handle->oftree, &handle->oftree_size);
+ if (ret)
+ return ret;
+ }
+
+ if (of_property_read_string(conf_node, "ramdisk", &unit) == 0) {
+ ret = fit_open_image(handle, unit, &handle->initrd, &handle->initrd_size);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+struct fit_handle *fit_open(const char *filename, const char *config, bool verbose,
+ enum bootm_verify verify)
+{
+ struct fit_handle *handle = NULL;
+ const char *desc = "(no description)";
+ int ret;
+
+ handle = xzalloc(sizeof(struct fit_handle));
+
+ handle->verbose = verbose;
+
+ ret = read_file_2(filename, &handle->size, &handle->fit, FILESIZE_MAX);
+ if (ret) {
+ pr_err("unable to read %s: %s\n", filename, strerror(-ret));
+ goto err;
+ }
+
+ handle->root = of_unflatten_dtb(handle->fit);
+ if (IS_ERR(handle->root)) {
+ ret = PTR_ERR(handle->root);
+ goto err;
+ }
+
+ handle->verify = verify;
+
+ of_property_read_string(handle->root, "description", &desc);
+ pr_info("'%s': %s\n", filename, desc);
+
+ ret = fit_open_configuration(handle, config);
+ if (ret)
+ goto err;
+
+ return handle;
+ err:
+ if (handle->root)
+ of_delete_node(handle->root);
+ free(handle->fit);
+ free(handle);
+
+ return ERR_PTR(ret);
+}
+
+void fit_close(struct fit_handle *handle)
+{
+ if (handle->root)
+ of_delete_node(handle->root);
+ if (handle->fit)
+ free(handle->fit);
+ free(handle);
+}
+
+#ifdef CONFIG_SANDBOX
+static int do_bootm_sandbox_fit(struct image_data *data)
+{
+ struct fit_handle *handle;
+ handle = fit_open(data->os_file, data->os_part, data->verbose);
+ if (handle)
+ fit_close(handle);
+ return 0;
+}
+
+static struct image_handler sandbox_fit_handler = {
+ .name = "FIT image",
+ .bootm = do_bootm_sandbox_fit,
+ .filetype = filetype_oftree,
+};
+
+static int sandbox_fit_register(void)
+{
+ return register_image_handler(&sandbox_fit_handler);
+}
+late_initcall(sandbox_fit_register);
+#endif
diff --git a/include/boot.h b/include/boot.h
index 363a02a..0198cc8 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -34,6 +34,10 @@ struct image_data {
/* if os is an uImage this will be provided */
struct uimage_handle *os;
+
+ /* if os is a FIT image this will be provided */
+ struct fit_handle *os_fit;
+
char *os_part;
/* otherwise only the filename will be provided */
diff --git a/include/image-fit.h b/include/image-fit.h
new file mode 100644
index 0000000..c9d6911
--- /dev/null
+++ b/include/image-fit.h
@@ -0,0 +1,45 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) Jan Lübbe, 2014
+ */
+
+#ifndef __IMAGE_FIT_H__
+#define __IMAGE_FIT_H__
+
+#include <linux/types.h>
+#include <boot.h>
+
+struct fit_handle {
+ void *fit;
+ size_t size;
+
+ bool verbose;
+ enum bootm_verify verify;
+
+ struct device_node *root;
+
+ const void *kernel;
+ unsigned long kernel_size;
+ const void *oftree;
+ unsigned long oftree_size;
+ const void *initrd;
+ unsigned long initrd_size;
+};
+
+struct fit_handle *fit_open(const char *filename, const char *config, bool verbose,
+ enum bootm_verify verify);
+void fit_close(struct fit_handle *handle);
+
+#endif /* __IMAGE_FIT_H__ */
--
2.7.0.rc3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 14/14] bootm: Add option to force booting signed images
2016-01-22 7:32 [PATCH v4] FIT support Sascha Hauer
` (12 preceding siblings ...)
2016-01-22 7:32 ` [PATCH 13/14] bootm: add initial FIT support Sascha Hauer
@ 2016-01-22 7:32 ` Sascha Hauer
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2016-01-22 7:32 UTC (permalink / raw)
To: Barebox List
With CONFIG_BOOTM_FORCE_SIGNED_IMAGES the bootm code will refuse to boot
unsigned images. Since currently FIT is the only image type which
supports signing, this means with this option we enforce using FIT
images. All additionally passed in device trees and initrds will be
ignored, so that only the ones from the FIT image can be used.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/bootm.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/common/bootm.c b/common/bootm.c
index d8acff8..3efc17e 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -68,8 +68,10 @@ enum bootm_verify bootm_get_verify_mode(void)
}
static const char * const bootm_verify_names[] = {
+#ifndef CONFIG_BOOTM_FORCE_SIGNED_IMAGES
[BOOTM_VERIFY_NONE] = "none",
[BOOTM_VERIFY_HASH] = "hash",
+#endif
[BOOTM_VERIFY_SIGNATURE] = "signature",
};
@@ -526,6 +528,23 @@ int bootm_boot(struct bootm_data *bootm_data)
goto err_out;
}
+ if (IS_ENABLED(CONFIG_BOOTM_FORCE_SIGNED_IMAGES))
+ data->verify = BOOTM_VERIFY_SIGNATURE;
+
+ /*
+ * When we only allow booting signed images make sure everything
+ * we boot is in the OS image and not given separately.
+ */
+ data->oftree = NULL;
+ data->oftree_file = NULL;
+ data->initrd_file = NULL;
+ if (os_type != filetype_oftree) {
+ printf("Signed boot and image is no FIT image, aborting\n");
+ ret = -EINVAL;
+ goto err_out;
+ }
+ }
+
if (IS_ENABLED(CONFIG_FITIMAGE) && os_type == filetype_oftree) {
struct fit_handle *fit;
--
2.7.0.rc3
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2016-01-22 7:33 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-22 7:32 [PATCH v4] FIT support Sascha Hauer
2016-01-22 7:32 ` [PATCH 01/14] ARM: zImage: add missing free() in appended device tree code Sascha Hauer
2016-01-22 7:32 ` [PATCH 02/14] bootm: Do not call uimage_close twice Sascha Hauer
2016-01-22 7:32 ` [PATCH 03/14] bootm: introduce bootm_get_os_size Sascha Hauer
2016-01-22 7:32 ` [PATCH 04/14] bootm: use names instead of numbers for image parts Sascha Hauer
2016-01-22 7:32 ` [PATCH 05/14] ARM: bootm: Use kernel handler to start barebox image Sascha Hauer
2016-01-22 7:32 ` [PATCH 06/14] bootm: Push dryrun to handlers Sascha Hauer
2016-01-22 7:32 ` [PATCH 07/14] bootm: move initrd code together Sascha Hauer
2016-01-22 7:32 ` [PATCH 08/14] bootm: move oftree " Sascha Hauer
2016-01-22 7:32 ` [PATCH 09/14] bootm: Initialize bootm_data defaults in single place Sascha Hauer
2016-01-22 7:32 ` [PATCH 10/14] crypto: add digest_alloc_by_algo() Sascha Hauer
2016-01-22 7:32 ` [PATCH 11/14] crypto: add RSA support Sascha Hauer
2016-01-22 7:32 ` [PATCH 12/14] bootm: make verifying/hashing configurable Sascha Hauer
2016-01-22 7:32 ` [PATCH 13/14] bootm: add initial FIT support Sascha Hauer
2016-01-22 7:32 ` [PATCH 14/14] bootm: Add option to force booting signed images Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox