Enhance fit_check_sign add beaglebone black vboot docs
cover Enhance fit_check_sign add beaglebone black vboot docs
The fit_check_sign tool checks that the configuration is correct, but does not check each image within that configuration. This series adds that feature, at least for uncompressed images.
In order to arrange this, cmd_bootm.c is split up into three files, one for the command processing, one for the OS booting and one for the general bootm processing. Apart from reducing the size of an over-large C file, this makes it easier to include what is needed for host compilation. As part of this, Android boot is enabled for sandbox in case someone wants to write a test for it.
Several people have had difficulty getting verified boot running on their board with the instructions available. Following on from the previous series which enabled verified boot on the Beaglebone Black, documentation is added with a step-by-step guide on how to get this running.
This series sits on top of the tools fixes:
http://patchwork.ozlabs.org/patch/354311/
http://patchwork.ozlabs.org/patch/354311/
This series is available at u-boot-x86.git branch 'bone'.
Simon Glass (11):
tools: Check arguments in fit_check_sign/fit_info Reverse the meaning of the fit_config_verify() return code
bootm: Split out code from cmd_bootm.c
image: Remove the fit_load_image() property parameter
bootm: Support android boot on sandbox
Fix small 'case' typo in image-fit.c
Avoid including config.h in command.h
Allow compiling common/bootm.c on with HOSTCC
bootm: Move decompression code into its own function Enhance fit_check_sign to check all images
Add documentation for verified boot on Beaglebone Black
common/Makefile | 2 +- common/bootm.c | 905 ++++++++++++++++++++++++ common/bootm_os.c | 480 +++++++++++++ common/cmd_bootm.c | 1337 +---------------------------------- common/cmd_fdt.c | 2 +- common/image-fdt.c | 1 - common/image-fit.c | 36 +- common/image-sig.c | 4 +- common/image.c | 2 +- doc/uImage.FIT/beaglebone_vboot.txt | 608 ++++++++++++++++ include/bootm.h | 57 ++ include/command.h | 1 - include/configs/sandbox.h | 1 + include/image.h | 10 +- tools/Makefile | 1 + tools/bootm.c | 1 + tools/fit_check_sign.c | 17 +- tools/fit_info.c | 12 + tools/image-host.c | 12 +- 19 files changed, 2140 insertions(+), 1349 deletions(-) create mode 100644 common/bootm.c create mode 100644 common/bootm_os.c create mode 100644 doc/uImage.FIT/beaglebone_vboot.txt create mode 100644 include/bootm.h create mode 100644 tools/bootm.c
Signature · 1 line
1.9.1.423.g4596e3a
PATCH 1/11 tools: Check arguments in fit_check_sign/fit_info
These tools crash if no arguments are provided. Add checks to avoid this.
---
tools/fit_check_sign.c | 9 +++++++++ tools/fit_info.c | 12 ++++++++++++ 2 files changed, 21 insertions(+)
tools/fit_check_sign.c +9 -0
@@ -62,6 +62,15 @@ int main(int argc, char **argv)break ; } +if (!fdtfile) { +fprintf (stderr,"%s: Missing fdt file\n" , *argv); +usage (*argv); + } +if (!keyfile) { +fprintf (stderr,"%s: Missing key file\n" , *argv); +usage (*argv); + } + ffd =mmap_fdt (cmdname, fdtfile,0 , &fit_blob, &fsbuf, false);if (ffd <0 )return EXIT_FAILURE ;
tools/fit_info.c +12 -0
@@ -68,6 +68,18 @@ int main(int argc, char **argv)break ; } +if (!fdtfile) { +fprintf (stderr,"%s: Missing fdt file\n" , *argv); +usage (*argv); + } +if (!nodename) { +fprintf (stderr,"%s: Missing node name\n" , *argv); +usage (*argv); + } +if (!propertyname) { +fprintf (stderr,"%s: Missing property name\n" , *argv); +usage (*argv); + } ffd =mmap_fdt (cmdname, fdtfile,0 , &fit_blob, &fsbuf, false);if (ffd <0 ) {
Signature · 1 line
1.9.1.423.g4596e3a
PATCH 1/11 tools: Check arguments in fit_check_sign/fit_info
Hello Simon,
Am 03.06.2014 06:39, schrieb Simon Glass:
Quoted 8 lines
These tools crash if no arguments are provided. Add checks to avoid this.
Signed-off-by Simon Glass<[email protected]>---
tools/fit_check_sign.c | 9 +++++++++ tools/fit_info.c | 12 ++++++++++++ 2 files changed, 21 insertions(+)
Good catch, thanks!
bye,
Heiko
Signature · 2 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
PATCH 2/11 Reverse the meaning of the fit_config_verify() return code
In reply to Simon GlassIt is more common to have 0 mean OK, and -ve mean error. Change this function to work the same way to avoid confusion.
---
common/cmd_fdt.c | 2 +- common/image-fit.c | 2 +- common/image-sig.c | 4 ++-- tools/fit_check_sign.c | 3 +-- 4 files changed, 5 insertions(+), 6 deletions(-)
common/cmd_fdt.c +1 -1
@@ -612,7 +612,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } ret =fit_config_verify (working_fdt, cfg_noffset); -if (ret ==1 ) +if (ret ==0 )return CMD_RET_SUCCESS ;else return CMD_RET_FAILURE ;
common/image-fit.c +1 -1
@@ -1534,7 +1534,7 @@ int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, images->fit_uname_cfg = fit_uname_config;if (IMAGE_ENABLE_VERIFY && images->verify) {puts (" Verifying Hash Integrity ... " ); -if (!fit_config_verify (fit, cfg_noffset)) { +if (fit_config_verify (fit, cfg_noffset)) {puts ("Bad Data Hash\n" );bootstage_error (bootstage_id +BOOTSTAGE_SUB_HASH );
common/image-sig.c +2 -2
@@ -467,6 +467,6 @@ int fit_config_verify_required_sigs(const void *fit, int conf_noffset,int fit_config_verify (const void *fit,int conf_noffset) { -return !fit_config_verify_required_sigs (fit, conf_noffset, -gd_fdt_blob ()); +return fit_config_verify_required_sigs (fit, conf_noffset, +gd_fdt_blob ()); }
tools/fit_check_sign.c +1 -2
@@ -80,8 +80,7 @@ int main(int argc, char **argv)image_set_host_blob (key_blob); ret =fit_check_sign (fit_blob, key_blob); - -if (ret) +if (!ret) ret =EXIT_SUCCESS ;else ret =EXIT_FAILURE ;
Signature · 1 line
1.9.1.423.g4596e3a
PATCH 3/11 bootm: Split out code from cmd_bootm.c
In reply to Simon GlassThis file has code in three different categories:
- Command processing
- OS-specific boot code
- Locating images and setting up to boot
Only the first category really belongs in a file called cmd_bootm.c.
Leave the command processing code where it is. Split out the OS-specific boot code into bootm_os.c. Split out the other code into bootm.c
Header files and extern declarations are tidied but otherwise no code changes are made, to make it easier to review.
---
common/Makefile | 2 +- common/bootm.c | 804 +++++++++++++++++++++++++++++++ common/bootm_os.c | 480 +++++++++++++++++++ common/cmd_bootm.c | 1337 +--------------------------------------------------- include/bootm.h | 55 +++ 5 files changed, 1348 insertions(+), 1330 deletions(-) create mode 100644 common/bootm.c create mode 100644 common/bootm_os.c create mode 100644 include/bootm.h
common/Makefile +1 -1
@@ -40,7 +40,7 @@ obj-$(CONFIG_SYS_GENERIC_BOARD) += board_r.o # core command obj-y += cmd_boot.o -obj-$(CONFIG_CMD_BOOTM) += cmd_bootm.o +obj-$(CONFIG_CMD_BOOTM) += cmd_bootm.o bootm.o bootm_os.o obj-y += cmd_help.o obj-y += cmd_version.o
common/bootm.c new file +804 -0
804 lines not on this page · raw message
common/bootm_os.c new file +480 -0
480 lines not on this page · raw message
common/cmd_bootm.c +8 -1329
1,395 lines not on this page · raw message
include/bootm.h new file +55 -0
55 lines not on this page · raw message
Signature · 1 line
1.9.1.423.g4596e3a
PATCH 3/11 bootm: Split out code from cmd_bootm.c
Quoted 7 lines · Simon Glass
This file has code in three different categories:
- Command processing
- OS-specific boot code
- Locating images and setting up to bootOnly the first category really belongs in a file called
cmd_bootm.c.
Quoted 7 lines
Leave the command processing code where it is. Split out the OS-specific boot code into
bootm_os.c. Split out the other code intobootm.cHeader files and extern declarations are tidied but otherwise no code changes are made, to make it easier to review.
Signed-off-by Simon Glass <[email protected]>
Non-trivial to re-apply on top of master, please rebase. Thanks!
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140611/b1901845/attachment.pgp>
PATCH 3/11 bootm: Split out code from cmd_bootm.c
Hi Tom,
Quoted 12 lines · Tom Rini
Quoted 10 lines · Simon Glass
This file has code in three different categories:
- Command processing
- OS-specific boot code
- Locating images and setting up to bootOnly the first category really belongs in a file called
cmd_bootm.c.Leave the command processing code where it is. Split out the OS-specific boot code into
bootm_os.c. Split out the other code intobootm.c
Quoted 6 lines
Quoted 4 lines
Header files and extern declarations are tidied but otherwise no code changes are made, to make it easier to review.
Signed-off-by Simon Glass <[email protected]>Non-trivial to re-apply on top of master, please rebase. Thanks!
Yes I have this locally, and will resend once I've retested.
Regards,
Simon
PATCH 4/11 image: Remove the fit_load_image() property parameter
In reply to Simon GlassThis can be obtained by looking up the image type, so is redundant. It is better to centralise this lookup to avoid errors.
---
common/bootm.c | 3 +-- common/image-fdt.c | 1 - common/image-fit.c | 29 ++++++++++++++++++++++++++++- common/image.c | 2 +- include/image.h | 5 +++-- 5 files changed, 33 insertions(+), 7 deletions(-)
common/bootm.c +1 -2
@@ -768,8 +768,7 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,break ;#if defined(CONFIG_FIT )case IMAGE_FORMAT_FIT : - os_noffset = fit_image_load(images, FIT_KERNEL_PROP, - img_addr, + os_noffset = fit_image_load(images, img_addr, &fit_uname_kernel, &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_KERNEL, BOOTSTAGE_ID_FIT_KERNEL_START,
common/image-fdt.c +0 -1
@@ -349,7 +349,6 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch,ulong load, len; fdt_noffset = fit_image_load(images, - FIT_FDT_PROP, fdt_addr, &fit_uname_fdt, &fit_uname_config, arch, IH_TYPE_FLATDT,
common/image-fit.c +28 -1
@@ -1477,7 +1477,32 @@ int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name,return noffset; } -int fit_image_load (bootm_headers_t *images,const char *prop_name,ulong addr, +/** +* fit_get_image_type_property() - get property name for IH_TYPE_... +* +* @return the properly name where we expect to find the image in the +* config node +*/ +static const char *fit_get_image_type_property (int type) +{ +/* +* This is sort-of available in the uimage_type[] table in image.c +* but we don't have access to the sohrt name, and "fdt" is different +* anyway. So let's just keep it here. +*/ +switch (type) { +case IH_TYPE_FLATDT : +return FIT_FDT_PROP ; +case IH_TYPE_KERNEL : +return FIT_KERNEL_PROP ; +case IH_TYPE_RAMDISK : +return FIT_RAMDISK_PROP ; + } + +return "unknown" ; +} + +int fit_image_load (bootm_headers_t *images,ulong addr,const char **fit_unamep,const char **fit_uname_configp,int arch,int image_type,int bootstage_id,enum fit_load_op load_op,ulong *datap,ulong *lenp)
@@ -1490,11 +1515,13 @@ int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr,size_t size;int type_ok, os_ok;ulong load, data, len; +const char *prop_name;int ret; fit =map_sysmem (addr,0 ); fit_uname = fit_unamep ? *fit_unamep :NULL ; fit_uname_config = fit_uname_configp ? *fit_uname_configp :NULL ; + prop_name =fit_get_image_type_property (image_type);printf ("## Loading %s from FIT Image at %08lx ...\n" , prop_name, addr);bootstage_mark (bootstage_id +BOOTSTAGE_SUB_FORMAT );
common/image.c +1 -1
@@ -892,7 +892,7 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,break ;#if defined(CONFIG_FIT )case IMAGE_FORMAT_FIT : - rd_noffset = fit_image_load(images, FIT_RAMDISK_PROP, + rd_noffset = fit_image_load(images, rd_addr, &fit_uname_ramdisk, &fit_uname_config, arch, IH_TYPE_RAMDISK,
include/image.h +3 -2
@@ -431,8 +431,9 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,* out progress messages, checking the type/arch/os and optionally copying it * to the right load address. * +* The property to look up is defined by image_type. +* * @param images Boot images structure -* @param prop_name Property name to look up (FIT_..._PROP) * @param addr Address of FIT in memory * @param fit_unamep On entry this is the requested image name * (e.g. "kernel at 1") or NULL to use the default. On exit
@@ -451,7 +452,7 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,* @param datap Returns address of loaded image * @param lenp Returns length of loaded image */ -int fit_image_load (bootm_headers_t *images,const char *prop_name,ulong addr, +int fit_image_load (bootm_headers_t *images,ulong addr,const char **fit_unamep,const char **fit_uname_configp,int arch,int image_type,int bootstage_id,enum fit_load_op load_op,ulong *datap,ulong *lenp);
Signature · 1 line
1.9.1.423.g4596e3a
PATCH 5/11 bootm: Support android boot on sandbox
In reply to Simon GlassA small change allows this to operate on sandbox.
---
common/bootm.c | 2 +- include/configs/sandbox.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-)
common/bootm.c +1 -1
@@ -785,7 +785,7 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,#ifdef CONFIG_ANDROID_BOOT_IMAGE case IMAGE_FORMAT_ANDROID :printf ("## Booting Android Image at 0x%08lx ...\n" , img_addr); -if (android_image_get_kernel ((void *)img_addr, images->verify, +if (android_image_get_kernel (buf, images->verify, os_data, os_len))return NULL ;break ;
include/configs/sandbox.h +1 -0
@@ -41,6 +41,7 @@#define CONFIG_RSA #define CONFIG_CMD_FDT #define CONFIG_DEFAULT_DEVICE_TREE sandbox +#define CONFIG_ANDROID_BOOT_IMAGE #define CONFIG_FS_FAT #define CONFIG_FS_EXT4
Signature · 1 line
1.9.1.423.g4596e3a
PATCH 6/11 Fix small 'case' typo in image-fit.c
In reply to Simon GlassThis typo makes the comment confusing. Fix it.
---
common/image-fit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
common/image-fit.c +1 -1
@@ -1637,7 +1637,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr,/* * Work-around for eldk-4.2 which gives this warning if we try to -* case in the unmap_sysmem() call: +* cast in the unmap_sysmem() call: * warning: initialization discards qualifiers from pointer target type */ {
Signature · 1 line
1.9.1.423.g4596e3a
PATCH 7/11 Avoid including config.h in command.h
In reply to Simon GlassThis is not necessary and prevents using this header when building tools.
---
include/command.h | 1 - 1 file changed, 1 deletion(-)
include/command.h +0 -1
@@ -11,7 +11,6 @@#ifndef __COMMAND_H#define __COMMAND_H -#include <config.h> #include <linker_lists.h> #ifndef NULL
Signature · 1 line
1.9.1.423.g4596e3a
PATCH 8/11 Allow compiling common/bootm.c on with HOSTCC
In reply to Simon GlassWe want to use some of the functionality in this file, so make it build on the host.
---
common/bootm.c | 18 ++++++++++++++---- tools/Makefile | 1 + tools/bootm.c | 1 + 3 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 tools/bootm.c
common/bootm.c +14 -4
@@ -5,10 +5,10 @@* SPDX-License-Identifier: GPL-2.0+ */ +#ifndef USE_HOSTCC #include <common.h> -#include <bootm.h> +#include <bootstage.h> #include <bzlib.h> -#include <image.h> #include <fdt_support.h> #include <lmb.h> #include <malloc.h>
@@ -17,12 +17,16 @@#include <lzma/LzmaTypes.h> #include <lzma/LzmaDec.h> #include <lzma/LzmaTools.h> -#if defined(CONFIG_CMD_USB )#include <usb.h> #endif +#else +#include "mkimage.h" +#endif -DECLARE_GLOBAL_DATA_PTR ; +#include <command.h> +#include <bootm.h> +#include <image.h> #ifndef CONFIG_SYS_BOOTM_LEN /* use 8MByte as default max gunzip size */
@@ -31,6 +35,10 @@ DECLARE_GLOBAL_DATA_PTR;#define IH_INITRD_ARCH IH_ARCH_DEFAULT +#ifndef USE_HOSTCC + +DECLARE_GLOBAL_DATA_PTR ; +static const void *boot_get_kernel (cmd_tbl_t *cmdtp,int flag,int argc,char *const argv[],bootm_headers_t *images,ulong *os_data,ulong *os_len);
@@ -801,3 +809,5 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, return buf; } + +#endif /* ndef USE_HOSTCC */
tools/Makefile +1 -0
@@ -73,6 +73,7 @@ RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := rsa-sign.o rsa-verify.o rsa-checksum.o dumpimage-mkimage-objs := aisimage.o \ atmelimage.o \ $(FIT_SIG_OBJS-y) \ + bootm.o \ crc32.o \ default_image.o \ fdtdec.o \
tools/bootm.c new file +1 -0
@@ -0,0 +1 @@ +#include "../common/bootm.c"
Signature · 1 line
1.9.1.423.g4596e3a
PATCH 9/11 bootm: Move decompression code into its own function
In reply to Simon GlassThis makes it possible to decompress an image without it being a kernel and without intending to boot it (as it needed for host tools, for example).
---
common/bootm.c | 75 +++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 27 deletions(-)
common/bootm.c +48 -27
@@ -243,32 +243,29 @@ static int bootm_find_other(cmd_tbl_t *cmdtp, int flag, int argc,return 0 ; } -static int bootm_load_os (bootm_headers_t *images,unsigned long *load_end, -int boot_progress) +/** +* decomp_image() - decompress the operating system +* +* @comp: Compression algorithm that is used (IH_COMP_...) +* @load: Destination load address in U-Boot memory +* @image_start Image start address (where we are decompressing from) +* @type: OS type (IH_OS_...) +* @load_bug: Place to decompress to +* @image_buf: Address to decompress from +* @return 0 if OK, -ve on error (BOOTM_ERR_...) +*/ +static int decomp_image (int comp,ulong load,ulong image_start,int type, +void *load_buf,void *image_buf,ulong image_len, +ulong *load_end) { -image_info_t os = images->os; -uint8_t comp = os.comp; -ulong load = os.load; -ulong blob_start = os.start; -ulong blob_end = os.end; -ulong image_start = os.image_start; -ulong image_len = os.image_len; -__maybe_unused uint unc_len =CONFIG_SYS_BOOTM_LEN ; -int no_overlap =0 ; -void *load_buf, *image_buf; -#if defined(CONFIG_LZMA ) || defined(CONFIG_LZO ) -int ret; -#endif /* defined(CONFIG_LZMA) || defined(CONFIG_LZO) */ - -const char *type_name =genimg_get_type_name (os.type); +const char *type_name =genimg_get_type_name (type); + __attribute__((unused))uint unc_len =CONFIG_SYS_BOOTM_LEN ; - load_buf =map_sysmem (load, unc_len); - image_buf =map_sysmem (image_start, image_len); + *load_end = load;switch (comp) {case IH_COMP_NONE :if (load == image_start) {printf (" XIP %s ... " , type_name); - no_overlap =1 ; }else {printf (" Loading %s ... " , type_name);memmove_wd (load_buf, image_buf, image_len,CHUNKSZ );
@@ -280,8 +277,6 @@ static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,printf (" Uncompressing %s ... " , type_name);if (gunzip (load_buf, unc_len, image_buf, &image_len) !=0 ) {puts ("GUNZIP: uncompress, out-of-mem or overwrite error - must RESET board to recover\n" ); -if (boot_progress) -bootstage_error (BOOTSTAGE_ID_DECOMP_IMAGE );return BOOTM_ERR_RESET ; }
@@ -302,8 +297,6 @@ static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,if (i !=BZ_OK ) {printf ("BUNZIP2: uncompress or overwrite error %d - must RESET board to recover\n" , i); -if (boot_progress) -bootstage_error (BOOTSTAGE_ID_DECOMP_IMAGE );return BOOTM_ERR_RESET ; }
@@ -313,6 +306,8 @@ static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,#ifdef CONFIG_LZMA case IH_COMP_LZMA : {SizeT lzma_len = unc_len; +int ret; +printf (" Uncompressing %s ... " , type_name); ret = lzmaBuffToBuffDecompress(load_buf, &lzma_len,
@@ -331,6 +326,7 @@ static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,#ifdef CONFIG_LZO case IH_COMP_LZO : {size_t size = unc_len; +int ret;printf (" Uncompressing %s ... " , type_name);
@@ -338,8 +334,6 @@ static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,if (ret !=LZO_E_OK ) {printf ("LZO: uncompress or overwrite error %d - must RESET board to recover\n" , ret); -if (boot_progress) -bootstage_error (BOOTSTAGE_ID_DECOMP_IMAGE );return BOOTM_ERR_RESET ; }
@@ -352,12 +346,39 @@ static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,return BOOTM_ERR_UNIMPLEMENTED ; } +puts ("OK\n" ); + +return 0 ; +} + +static int bootm_load_os (bootm_headers_t *images,unsigned long *load_end, +int boot_progress) +{ +image_info_t os = images->os; +ulong load = os.load; +ulong blob_start = os.start; +ulong blob_end = os.end; +ulong image_start = os.image_start; +ulong image_len = os.image_len; +bool no_overlap; +void *load_buf, *image_buf; +int err; + + load_buf =map_sysmem (load,0 ); + image_buf =map_sysmem (os.image_start, image_len); + err =decomp_image (os.comp, load, os.image_start, os.type, load_buf, + image_buf, image_len, load_end); +if (err) { +bootstage_error (BOOTSTAGE_ID_DECOMP_IMAGE ); +return err; + }flush_cache (load, (*load_end - load) *sizeof (ulong)); -puts ("OK\n" );debug (" kernel loaded at 0x%08lx, end = 0x%08lx\n" , load, *load_end);bootstage_mark (BOOTSTAGE_ID_KERNEL_LOADED ); + no_overlap = (os.comp ==IH_COMP_NONE && load == image_start); +if (!no_overlap && (load < blob_end) && (*load_end > blob_start)) {debug ("images.os.start = 0x%lX, images.os.end = 0x%lx\n" , blob_start, blob_end);
Signature · 1 line
1.9.1.423.g4596e3a
PATCH 10/11 Enhance fit_check_sign to check all images
In reply to Simon GlassAt present this tool only checks the configuration signing. Have it also look at each of the images in the configuration and confirm that they verify.
---
common/bootm.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ common/image-fit.c | 3 ++- include/bootm.h | 2 ++ include/image.h | 5 +++- tools/fit_check_sign.c | 7 +++-- tools/image-host.c | 12 ++++++--- 6 files changed, 93 insertions(+), 7 deletions(-)
common/bootm.c +71 -0
@@ -242,6 +242,7 @@ static int bootm_find_other(cmd_tbl_t *cmdtp, int flag, int argc, return 0; } +#endif /* USE_HOSTCC */ /** * decomp_image() - decompress the operating system
@@ -351,6 +352,7 @@ static int decomp_image(int comp, ulong load, ulong image_start, int type,return 0 ; } +#ifndef USE_HOSTCC static int bootm_load_os (bootm_headers_t *images,unsigned long *load_end,int boot_progress) {
@@ -830,5 +832,74 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,return buf; } +#else /* USE_HOSTCC */ + +void memmove_wd (void *to,void *from,size_t len,ulong chunksz) +{ +memmove (to, from, len); +} + +static int bootm_host_load_image (const void *fit,int req_image_type) +{ +const char *fit_uname_config =NULL ; +ulong data, len; +bootm_headers_t images; +int noffset; +ulong load_end; +uint8_t image_type; +uint8_t imape_comp; +void *load_buf; +int ret; + +memset (&images,'\0' ,sizeof (images)); + images.verify =1 ; + noffset =fit_image_load (&images, (ulong )fit, +NULL , &fit_uname_config, +IH_ARCH_DEFAULT , req_image_type,-1 , +FIT_LOAD_IGNORED , &data, &len); +if (noffset <0 ) +return noffset; +if (fit_image_get_type (fit, noffset, &image_type)) { +puts ("Can't get image type!\n" ); +return -EINVAL ; + } + +if (fit_image_get_comp (fit, noffset, &imape_comp)) { +puts ("Can't get image compression!\n" ); +return -EINVAL ; + } + +/* Allow the image to expand by a factor of 4, should be safe */ + load_buf =malloc ((1 <<20 ) + len *4 ); + ret =decomp_image (imape_comp,0 , data, image_type, load_buf, + (void *)data, len, &load_end); +free (load_buf); +if (ret && ret !=BOOTM_ERR_UNIMPLEMENTED ) +return ret; + +return 0 ; +} + +int bootm_host_load_images (const void *fit,int cfg_noffset) +{ +static uint8_t image_types[] = { +IH_TYPE_KERNEL , +IH_TYPE_FLATDT , +IH_TYPE_RAMDISK , + }; +int err =0 ; +int i; + +for (i =0 ; i <ARRAY_SIZE (image_types); i++) { +int ret; + + ret =bootm_host_load_image (fit, image_types[i]); +if (!err && ret && ret != -ENOENT ) + err = ret; + } + +/* Return the first error we found */ +return err; +}#endif /* ndef USE_HOSTCC */
common/image-fit.c +2 -1
@@ -1591,12 +1591,13 @@ int fit_image_load(bootm_headers_t *images, ulong addr, }bootstage_mark (bootstage_id +BOOTSTAGE_SUB_CHECK_ARCH ); +#ifndef USE_HOSTCC if (!fit_image_check_target_arch (fit, noffset)) {puts ("Unsupported Architecture\n" );bootstage_error (bootstage_id +BOOTSTAGE_SUB_CHECK_ARCH );return -ENOEXEC ; } - +#endif if (image_type ==IH_TYPE_FLATDT && !fit_image_check_comp (fit, noffset,IH_COMP_NONE )) {puts ("FDT image is compressed" );
include/bootm.h +2 -0
@@ -41,6 +41,8 @@ void lynxkdi_boot(image_header_t *hdr);boot_os_fn *bootm_os_get_boot_func (int os); +int bootm_host_load_images (const void *fit,int cfg_noffset); +int boot_selected_os (int argc,char *const argv[],int state,bootm_headers_t *images,boot_os_fn *boot_fn);
include/image.h +4 -1
@@ -422,6 +422,7 @@ ulong genimg_get_image(ulong img_addr);int boot_get_ramdisk (int argc,char *const argv[],bootm_headers_t *images,uint8_t arch,ulong *rd_start,ulong *rd_end); +#endif /** * fit_image_load() - load an image from a FIT
@@ -451,12 +452,14 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,* @param load_op Decribes what to do with the load address * @param datap Returns address of loaded image * @param lenp Returns length of loaded image +* @return node offset of image, or -ve error code on error */ int fit_image_load (bootm_headers_t *images,ulong addr,const char **fit_unamep,const char **fit_uname_configp,int arch,int image_type,int bootstage_id,enum fit_load_op load_op,ulong *datap,ulong *lenp); +#ifndef USE_HOSTCC /** * fit_get_node_from_config() - Look up an image a FIT by type *
@@ -601,8 +604,8 @@ int image_check_dcrc(const image_header_t *hdr);ulong getenv_bootm_low (void );phys_size_t getenv_bootm_size (void );phys_size_t getenv_bootm_mapsize (void ); -void memmove_wd (void *to,void *from,size_t len,ulong chunksz);#endif +void memmove_wd (void *to,void *from,size_t len,ulong chunksz);static inline int image_check_magic (const image_header_t *hdr) {
tools/fit_check_sign.c +5 -2
@@ -80,10 +80,13 @@ int main(int argc, char **argv)image_set_host_blob (key_blob); ret =fit_check_sign (fit_blob, key_blob); -if (!ret) +if (!ret) { ret =EXIT_SUCCESS ; -else +fprintf (stderr,"Signature check OK\n" ); + }else { ret =EXIT_FAILURE ; +fprintf (stderr,"Signature check Bad (error %d)\n" , ret); + } (void )munmap ((void *)fit_blob, fsbuf.st_size); (void )munmap ((void *)key_blob, ksbuf.st_size);
tools/image-host.c +9 -3
@@ -10,6 +10,7 @@*/ #include "mkimage.h" +#include <bootm.h> #include <image.h> #include <version.h>
@@ -705,16 +706,21 @@ int fit_add_verification_data(const char *keydir, void *keydest, void *fit, }#ifdef CONFIG_FIT_SIGNATURE -int fit_check_sign (const void *working_fdt,const void *key) +int fit_check_sign (const void *fit,const void *key) {int cfg_noffset;int ret; - cfg_noffset =fit_conf_get_node (working_fdt,NULL ); + cfg_noffset =fit_conf_get_node (fit,NULL );if (!cfg_noffset)return -1 ; - ret =fit_config_verify (working_fdt, cfg_noffset); +printf ("Verifying Hash Integrity ... " ); + ret =fit_config_verify (fit, cfg_noffset); +if (ret) +return ret; + ret =bootm_host_load_images (fit, cfg_noffset); +return ret; }#endif
Signature · 1 line
1.9.1.423.g4596e3a
PATCH 10/11 Enhance fit_check_sign to check all images
Hello Simon,
Am 03.06.2014 06:39, schrieb Simon Glass:
Quoted 7 lines
At present this tool only checks the configuration signing. Have it also look at each of the images in the configuration and confirm that they verify.
Signed-off-by Simon Glass<[email protected]>---
Quoted 7 lines
common/bootm.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ common/image-fit.c | 3 ++- include/bootm.h | 2 ++ include/image.h | 5 +++- tools/fit_check_sign.c | 7 +++-- tools/image-host.c | 12 ++++++--- 6 files changed, 93 insertions(+), 7 deletions(-)
Just a nitpick ... as this changes the output from fit_check_sign, could you please adapt the "doc/uImage.FIT/signature.txt" file in u-boot too, which shows a testing ouput for
"O=sandbox ./test/vboot/vboot_test.sh"
Thanks!
Beside of this, tested this series on the ids8313 board (fit_check_sign on the host and target rootfs without issues):
bye,
Heiko
Signature · 2 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
PATCH 11/11 Add documentation for verified boot on Beaglebone Black
In reply to Simon GlassAs an example of an end-to-end process for using verified boot in U-Boot, add a detailed description of the steps to be used for a Beaglebone Black.
---
doc/uImage.FIT/beaglebone_vboot.txt | 608 ++++++++++++++++++++++++++++++++++++ 1 file changed, 608 insertions(+) create mode 100644 doc/uImage.FIT/beaglebone_vboot.txt
doc/uImage.FIT/beaglebone_vboot.txt new file +608 -0
@@ -0,0 +1,608 @@ +Verified Boot on the Beaglebone Black +===================================== + +Introduction +------------ + +Before reading this, please read verified-boot.txt and signature.txt. These +instructions are for mainline U-Boot from v2014.07 onwards. + +There is quite a bit of documentation in this directory describing how +verified boot works in U-Boot. There is also a test which runs through the +entire process of signing an image and running U-Boot (sandbox) to check it. +However, it might be useful to also have an example on a real board. + +Beaglebone Black is a fairly common board so seems to be a reasonable choice +for an example of how to enable verified boot using U-Boot. + +First a note that may to help avoid confusion. U-Boot and Linux both use +device tree. They may use the same device tree source, but it is seldom useful +for them to use the exact same binary from the same place. More typically, +U-Boot has its device tree packaged wtih it, and the kernel's device tree is +packaged with the kernel. In particular this is important with verified boot, +since U-Boot's device tree must be immutable. If it can be changed then the +public keys can be changed and verified boot is useless. An attacker can +simply generate a new key and put his public key into U-Boot so that +everything verifies. On the other hand the kernel's device tree typically +changes when the kernel changes, so it is useful to package an updated device +tree with the kernel binary. U-Boot supports the latter with its flexible FIT +format (Flat Image Tree). + + +Overview +-------- + +The steps are roughly as follows: + +1. Build U-Boot for the board, with the verified boot options enabled. + +2. Obtain a suitable Linux kernel + +3. Create a Image Tree Source file (ITS) file describing how you want the +kernel to be packaged, compressed and signed. + +4. Create a key pair + +5. Sign the kernel + +6. Put the public key into U-Boot's image + +7. Put U-Boot and the kernel onto the board + +8. Try it + + +Step 1: Build U-Boot +-------------------- + +a. Set up the environment variable to point to your toolchain. You will need +this for U-Boot and also for the kernel if you build it. For example if you +installed a Linaro version manually it might be something like: + + export CROSS_COMPILE=/opt/linaro/gcc-linaro-arm-linux-gnueabihf-4.8-2013.08_linux/bin/arm-linux-gnueabihf- + +or if you just installed gcc-arm-linux-gnueabi then it might be + + export CROSS_COMPILE=arm-linux-gnueabi- + +b. Configure and build U-Boot with verified boot enabled: + + export ARCH=arm + export UBOOT=/path/to/u-boot + cd $UBOOT + # You can add -j10 if you have 10 CPUs to make it faster + make O=b/am335x_boneblack_vboot am335x_boneblack_vboot_config all + export UOUT=$UBOOT/b/am335x_boneblack_vboot + +c. You will now have a U-Boot image: + + file b/am335x_boneblack_vboot/u-boot-dtb.img +b/am335x_boneblack_vboot/u-boot-dtb.img: u-boot legacy uImage, U-Boot 2014.07-rc2-00065-g2f69f8, Firmware/ARM, Firmware Image (Not compressed), 395375 bytes, Sat May 31 16:19:04 2014, Load Address: 0x80800000, Entry Point: 0x00000000, Header CRC: 0x0ABD6ACA, Data CRC: 0x36DEF7E4 + + +Step 2: Build Linux +-------------------- + +a. Find the kernel image ('Image') and device tree (.dtb) file you plan to +use. In our case it is am335x-boneblack.dtb and it is built with the kernel. +At the time of writing an SD Boot image can be obtained from here: + + http://www.elinux.org/Beagleboard:Updating_The_Software#Image_For_Booting_From_microSD + +You can write this to an SD card and then mount it to extract the kernel and +device tree files. + +You can also build a kernel. Instructions for this are are here: + + http://elinux.org/Building_BBB_Kernel + +or you can use your favourite search engine. Following these instructions +produces a kernel Image and device tree files. For the record the steps were: + + export KERNEL=/path/to/kernel + cd $KERNEL + git clone git://github.com/beagleboard/kernel.git . + git checkout v3.14 + ./patch.sh + cp configs/beaglebone kernel/arch/arm/configs/beaglebone_defconfig + cd kernel + make beaglebone_defconfig + make uImage dtbs # -j10 if you have 10 CPUs + export OKERNEL=$KERNEL/kernel/arch/arm/boot + +c. You now have the 'Image' and 'am335x-boneblack.dtb' files needed to boot. + + +Step 3: Create the ITS +---------------------- + +Set up a directory for your work. + + export WORK=/path/to/dir + cd $WORK + +Put this into a file in that directory called sign.its: + +/dts-v1/; + +/ { + description = "Beaglebone black"; + #address-cells = <1>; + + images { + kernel at 1 { + data = /incbin/("Image.lzo"); + type = "kernel"; + arch = "arm"; + os = "linux"; + compression = "lzo"; + load = <0x80008000>; + entry = <0x80008000>; + hash at 1 { + algo = "sha1"; + }; + }; + fdt at 1 { + description = "beaglebone-black"; + data = /incbin/("am335x-boneblack.dtb"); + type = "flat_dt"; + arch = "arm"; + compression = "none"; + hash at 1 { + algo = "sha1"; + }; + }; + }; + configurations { + default = "conf at 1"; + conf at 1 { + kernel = "kernel at 1"; + fdt = "fdt at 1"; + signature at 1 { + algo = "sha1,rsa2048"; + key-name-hint = "dev"; + sign-images = "fdt", "kernel"; + }; + }; + }; +}; + + +The explanation for this is all in the documentation you have already read. +But briefly it packages a kernel and device tree, and provides a single +configuration to be signed with a key named 'dev'. The kernel is compressed +with LZO to make it smaller. + + +Step 4: Create a key pair +------------------------- + +See signature.txt for details on this step. + + cd $WORK + mkdir keys + openssl genrsa -F4 -out keys/dev.key 2048 + openssl req -batch -new -x509 -key keys/dev.key -out keys/dev.crt + +Note: keys/dev.key contains your private key and is very secret. If anyone +gets access to that file they can sign kernels with it. Keep it secure. + + +Step 5: Sign the kernel +----------------------- + +We need to use mkimage (which was built when you built U-Boot) to package the +Linux kernel into a FIT (Flat Image Tree, a flexible file format that U-Boot +can load) using the ITS file you just created. + +At the same time we must put the public key into U-Boot device tree, with the +'required' property, which tells U-Boot that this key must be verified for the +image to be valid. You will make this key available to U-Boot for booting in +step 6. + + ln -s $OKERNEL/dts/am335x-boneblack.dtb + ln -s $OKERNEL/Image + ln -s $UOUT/u-boot-dtb.img + cp $UOUT/arch/arm/dts/am335x-boneblack.dtb am335x-boneblack-pubkey.dtb + lzop Image + $UOUT/tools/mkimage -f sign.its -K am335x-boneblack-pubkey.dtb -k keys -r image.fit + +You should see something like this: + +FIT description: Beaglebone black +Created: Sun Jun 1 12:50:30 2014 + Image 0 (kernel at 1) + Description: unavailable + Created: Sun Jun 1 12:50:30 2014 + Type: Kernel Image + Compression: lzo compressed + Data Size: 7790938 Bytes = 7608.34 kB = 7.43 MB + Architecture: ARM + OS: Linux + Load Address: 0x80008000 + Entry Point: 0x80008000 + Hash algo: sha1 + Hash value: c94364646427e10f423837e559898ef02c97b988 + Image 1 (fdt at 1) + Description: beaglebone-black + Created: Sun Jun 1 12:50:30 2014 + Type: Flat Device Tree + Compression: uncompressed + Data Size: 31547 Bytes = 30.81 kB = 0.03 MB + Architecture: ARM + Hash algo: sha1 + Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d + Default Configuration: 'conf at 1' + Configuration 0 (conf at 1) + Description: unavailable + Kernel: kernel at 1 + FDT: fdt at 1 + + +Now am335x-boneblack-pubkey.dtb contains the public key and image.fit contains +the signed kernel. Jump to step 6 if you like, or continue reading to increase +your understanding. + +You can also run fit_check_sign to check it: + + $UOUT/tools/fit_check_sign -f image.fit -k am335x-boneblack-pubkey.dtb + +which results in: + +Verifying Hash Integrity ... sha1,rsa2048:dev+ +## Loading kernel from FIT Image at 7fc6ee469000 ... + Using 'conf at 1' configuration + Verifying Hash Integrity ... +sha1,rsa2048:dev+ +OK + + Trying 'kernel at 1' kernel subimage + Description: unavailable + Created: Sun Jun 1 12:50:30 2014 + Type: Kernel Image + Compression: lzo compressed + Data Size: 7790938 Bytes = 7608.34 kB = 7.43 MB + Architecture: ARM + OS: Linux + Load Address: 0x80008000 + Entry Point: 0x80008000 + Hash algo: sha1 + Hash value: c94364646427e10f423837e559898ef02c97b988 + Verifying Hash Integrity ... +sha1+ +OK + +Unimplemented compression type 4 +## Loading fdt from FIT Image at 7fc6ee469000 ... + Using 'conf at 1' configuration + Trying 'fdt at 1' fdt subimage + Description: beaglebone-black + Created: Sun Jun 1 12:50:30 2014 + Type: Flat Device Tree + Compression: uncompressed + Data Size: 31547 Bytes = 30.81 kB = 0.03 MB + Architecture: ARM + Hash algo: sha1 + Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d + Verifying Hash Integrity ... +sha1+ +OK + + Loading Flat Device Tree ... OK + +## Loading ramdisk from FIT Image at 7fc6ee469000 ... + Using 'conf at 1' configuration +Could not find subimage node + +Signature check OK + + +At the top, you see "sha1,rsa2048:dev+". This means that it checked an RSA key +of size 2048 bits using SHA1 as the hash algorithm. The key name checked was +'dev' and the '+' means that it verified. If it showed '-' that would be bad. + +Once the configuration is verified it is then possible to rely on the hashes +in each image referenced by that configuration. So fit_check_sign goes on to +load each of the images. We have a kernel and an FDT but no ramkdisk. In each +case fit_check_sign checks the hash and prints sha1+ meaning that the SHA1 +hash verified. This means that none of the images has been tampered with. + +There is a test in test/vboot which uses U-Boot's sandbox build to verify that +the above flow works. + +But it is fun to do this by hand, so you can load image.fit into a hex editor +like ghex, and change a byte in the kernel: + + $UOUT/tools/fit_info -f image.fit -n /images/kernel at 1 -p data +NAME: kernel at 1 +LEN: 7790938 +OFF: 168 + +This tells us that the kernel starts at byte offset 168 (decimal) in image.fit +and extends for about 7MB. Try changing a byte at 0x2000 (say) and run +fit_check_sign again. You should see something like: + +Verifying Hash Integrity ... sha1,rsa2048:dev+ +## Loading kernel from FIT Image at 7f5a39571000 ... + Using 'conf at 1' configuration + Verifying Hash Integrity ... +sha1,rsa2048:dev+ +OK + + Trying 'kernel at 1' kernel subimage + Description: unavailable + Created: Sun Jun 1 13:09:21 2014 + Type: Kernel Image + Compression: lzo compressed + Data Size: 7790938 Bytes = 7608.34 kB = 7.43 MB + Architecture: ARM + OS: Linux + Load Address: 0x80008000 + Entry Point: 0x80008000 + Hash algo: sha1 + Hash value: c94364646427e10f423837e559898ef02c97b988 + Verifying Hash Integrity ... +sha1 error +Bad hash value for 'hash at 1' hash node in 'kernel at 1' image node +Bad Data Hash + +## Loading fdt from FIT Image at 7f5a39571000 ... + Using 'conf at 1' configuration + Trying 'fdt at 1' fdt subimage + Description: beaglebone-black + Created: Sun Jun 1 13:09:21 2014 + Type: Flat Device Tree + Compression: uncompressed + Data Size: 31547 Bytes = 30.81 kB = 0.03 MB + Architecture: ARM + Hash algo: sha1 + Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d + Verifying Hash Integrity ... +sha1+ +OK + + Loading Flat Device Tree ... OK + +## Loading ramdisk from FIT Image at 7f5a39571000 ... + Using 'conf at 1' configuration +Could not find subimage node + +Signature check Bad (error 1) + + +It has detected the change in the kernel. + +You can also be sneaky and try to switch images, using the libfdt utilities +that come with dtc (package name is device-tree-compiler but you will need a +recent version like 1.4: + + dtc -v +Version: DTC 1.4.0 + +First we can check which nodes are actually hashed by the configuration: + + fdtget -l image.fit / +images +configurations + + fdtget -l image.fit /configurations +conf at 1 +fdtget -l image.fit /configurations/conf at 1 +signature at 1 + + fdtget -p image.fit /configurations/conf at 1/signature at 1 +hashed-strings +hashed-nodes +timestamp +signer-version +signer-name +value +algo +key-name-hint +sign-images + + fdtget image.fit /configurations/conf at 1/signature at 1 hashed-nodes +/ /configurations/conf at 1 /images/fdt at 1 /images/fdt at 1/hash at 1 /images/kernel at 1 /images/kernel at 1/hash at 1 + +This gives us a bit of a look into the signature that mkimage added. Note you +can also use fdtdump to list the entire device tree. + +Say we want to change the kernel that this configuration uses +(/images/kernel at 1). We could just put a new kernel in the image, but we will +need to change the hash to match. Let's simulate that by changing a byte of +the hash: + + fdtget -tx image.fit /images/kernel at 1/hash at 1 value +c9436464 6427e10f 423837e5 59898ef0 2c97b988 + fdtput -tx image.fit /images/kernel at 1/hash at 1 value c9436464 6427e10f 423837e5 59898ef0 2c97b981 + +Now check it again: + + $UOUT/tools/fit_check_sign -f image.fit -k am335x-boneblack-pubkey.dtb +Verifying Hash Integrity ... sha1,rsa2048:devrsa_verify_with_keynode: RSA failed to verify: -13 +rsa_verify_with_keynode: RSA failed to verify: -13 +- +Failed to verify required signature 'key-dev' +Signature check Bad (error 1) + +This time we don't even get as far as checking the images, since the +configuration signature doesn't match. We can't change any hashes without the +signature check noticing. The configuration is essentially locked. U-Boot has +a public key for which it requires a match, and will not permit the use of any +configuration that does not match that public key. The only way the +configuration will match is if it was signed by the matching private key. + +It would also be possible to add a new signature node that does match your new +configuration. But that won't work since you are not allowed to change the +configuration in any way. Try it with a fresh (valid) image if you like by +running the mkimage link again. Then: + + fdtput -p image.fit /configurations/conf at 1/signature at 2 value fred + $UOUT/tools/fit_check_sign -f image.fit -k am335x-boneblack-pubkey.dtb +Verifying Hash Integrity ... - +sha1,rsa2048:devrsa_verify_with_keynode: RSA failed to verify: -13 +rsa_verify_with_keynode: RSA failed to verify: -13 +- +Failed to verify required signature 'key-dev' +Signature check Bad (error 1) + + +Of course it would be possible to add an entirely new configuration and boot +with that, but it still needs to be signed, so it won't help. + + +6. Put the public key into U-Boot's image +----------------------------------------- + +Having confirmed that the signature is doing its job, let's try it out in +U-Boot on the board. U-Boot needs access to the public key corresponding to +the private key that you signed with so that it can verify any kernels that +you sign. + + cd $UBOOT + make O=b/am335x_boneblack_vboot DEV_TREE_BIN=${WORK}/am335x-boneblack-pubkey.dtb + +Here we are overrriding the normal device tree file with our one, which +contains the public key. + +Now you have a special U-Boot image with the public key. It can verify can +kernel that you sign with the private key as in step 5. + +If you like you can take a look at the public key information that mkimage +added to U-Boot's device tree: + + fdtget -p am335x-boneblack-pubkey.dtb /signature/key-dev +required +algo +rsa,r-squared +rsa,modulus +rsa,n0-inverse +rsa,num-bits +key-name-hint + +This has information about the key and some pre-processed values which U-Boot +can use to verify against it. These values are obtained from the public key +certificate by mkimage, but require quite a bit of code to generate. To save +code space in U-Boot, the information is extracted and written in raw form for +U-Boot to easily use. The same mechanism is used in Google's Chrome OS. + +Notice the 'required' property. This marks the key as required - U-Boot will +not boot any image that does not verify against this key. + + +7. Put U-Boot and the kernel onto the board +------------------------------------------- + +The method here varies depending on how you are booting. For this example we +are booting from an micro-SD card with two partitions, one for U-Boot and one +for Linux. Put it into your machine and write U-Boot and the kernel to it. +Here the card is /dev/sde: + + cd $WORK + export UDEV=/dev/sde1 # Change thes two lines to the correct device + export KDEV=/dev/sde2 + sudo mount $UDEV /mnt/tmp && sudo cp $UOUT/u-boot.img /mnt/tmp/u-boot.img && sleep 1 && sudo umount $UDEV + sudo mount $KDEV /mnt/tmp && sudo cp $WORK/image.fit /mnt/tmp/boot/image.fit && sleep 1 && sudo umount $KDEV + + +8. Try it +--------- + +Boot the board using the commands below: + + setenv bootargs console=ttyO0,115200n8 quiet root=/dev/mmcblk0p2 ro rootfstype=ext4 rootwait + ext2load mmc 0:2 82000000 /boot/image.fit + bootm 82000000 + +You should then see something like this: + +U-Boot# setenv bootargs console=ttyO0,115200n8 quiet root=/dev/mmcblk0p2 ro rootfstype=ext4 rootwait +U-Boot# ext2load mmc 0:2 82000000 /boot/image.fit +7824930 bytes read in 589 ms (12.7 MiB/s) +U-Boot# bootm 82000000 +## Loading kernel from FIT Image at 82000000 ... + Using 'conf at 1' configuration + Verifying Hash Integrity ... sha1,rsa2048:dev+ OK + Trying 'kernel at 1' kernel subimage + Description: unavailable + Created: 2014-06-01 19:32:54 UTC + Type: Kernel Image + Compression: lzo compressed + Data Start: 0x820000a8 + Data Size: 7790938 Bytes = 7.4 MiB + Architecture: ARM + OS: Linux + Load Address: 0x80008000 + Entry Point: 0x80008000 + Hash algo: sha1 + Hash value: c94364646427e10f423837e559898ef02c97b988 + Verifying Hash Integrity ... sha1+ OK +## Loading fdt from FIT Image at 82000000 ... + Using 'conf at 1' configuration + Trying 'fdt at 1' fdt subimage + Description: beaglebone-black + Created: 2014-06-01 19:32:54 UTC + Type: Flat Device Tree + Compression: uncompressed + Data Start: 0x8276e2ec + Data Size: 31547 Bytes = 30.8 KiB + Architecture: ARM + Hash algo: sha1 + Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d + Verifying Hash Integrity ... sha1+ OK + Booting using the fdt blob at 0x8276e2ec + Uncompressing Kernel Image ... OK + Loading Device Tree to 8fff5000, end 8ffffb3a ... OK + +Starting kernel ... + +[ 0.582377] omap_init_mbox: hwmod doesn't have valid attrs +[ 2.589651] musb-hdrc musb-hdrc.0.auto: Failed to request rx1. +[ 2.595830] musb-hdrc musb-hdrc.0.auto: musb_init_controller failed with status -517 +[ 2.606470] musb-hdrc musb-hdrc.1.auto: Failed to request rx1. +[ 2.612723] musb-hdrc musb-hdrc.1.auto: musb_init_controller failed with status -517 +[ 2.940808] drivers/rtc/hctosys.c: unable to open rtc device (rtc0) +[ 7.248889] libphy: PHY 4a101000.mdio:01 not found +[ 7.253995] net eth0: phy 4a101000.mdio:01 not found on slave 1 +systemd-fsck[83]: Angstrom: clean, 50607/218160 files, 306348/872448 blocks + +.---O---. +| | .-. o o +| | |-----.-----.-----.| | .----..-----.-----. +| | | __ | ---'| '--.| .-'| | | +| | | | | |--- || --'| | | ' | | | | +'---'---'--'--'--. |-----''----''--' '-----'-'-'-' + -' | + '---' + +The Angstrom Distribution beaglebone ttyO0 + +Angstrom v2012.12 - Kernel 3.14.1+ + +beaglebone login: + +At this point your kernel has been verified and you can be sure that it is one +that you signed. As an exercise, try changing image.fit as in step 5 and see +what happens. + + +Further Improvements +-------------------- + +Several of the steps here can be easily automated. In particular it would be +capital if signing and packaging a kernel were easy, perhaps a simple make +target in the kernel. + +Some mention of how to use multiple .dtb files in a FIT might be useful. + +U-Boot's verified boot mechanism has not had a robust and independent security +review. Such a review should look at the implementation and its resistance to +attacks. + +Perhaps the verified boot feature could could be integrated into the Amstrom +distribution. + + +Simon Glass +sjg at chromium.org +2-June-14
Signature · 1 line
1.9.1.423.g4596e3a