[U-Boot-Users] Secure Bootloader patch
Ladislav Michl
ladis at linux-mips.org
Thu Sep 14 19:56:10 CEST 2006
Dear Stephen,
On Wed, Sep 13, 2006 at 03:49:43PM -0400, Stephen Johnson wrote:
> This message contains a patch to add RSA signature validation to
> U-Boot. I previously sent a similar e-mail to the CELinux-dev mailing
> list for comments where I received the following:
>
> 1. I shouldn't be using OpenSSL (due to licensing concerns),
> 2. alternate RSA libraries are GNU TLS and MatrixSSL, and
> 3. the U-Boot mailing list might be a more appropriate place
>
> The patch modifies u-boot to verify an image signature created with a
> SHA1 digest and RSA encryption/decryption. Because I found the
> necessary information fairly easily about SHA1 and RSA from the
> OpenSSL package, that's what I used. Hence, the modified u-boot ran
> quite quickly, but was rather large.
Size is not surprising, surprising is that it was possible to do at all.
> The eventual goal is to release this patch to the community.
>
> I'm looking for additional comments, especially about other encryption
> libraries that would be better to use, and whether or not something
> like this is seen as useful.
>
> Notes:
> - I'm linking against openssl-0.9.8b.
> - I used crosstool based on gcc-3.4.5 and glibc-2.3.6 for the tool
> chain.
> - It all was built for an omap5912osk board.
> - The signature is added to the u-boot header by a modified mkimage
> (patch is included).
> - The signature is verified in cmd_bootm.c.
> - In u-boot/include/configs/omap5912osk.h there is a CONFIG_SIGNATURE
> that turns on/off the signature checking and creating.
>
> To compile the modified u-boot the following were needed:
>
> CPATH should be defined to point to where ever crosstool has it's
> generic include files, e.g.
> export CPATH="/opt/crosstool/gcc-3.4.5-glibc-2.3.6/arm-softfloat-linux-gnu/arm-softfloat-linux-gnu/include"
Why do you need this? Compiler knows where to find its includes.
> CRYPTO_INC needs to point at the openssl include files, e.g.
> export CRYPTO_INC="-I/home/steve/src/SecureBoot/openssl-0.9.8b/include"
>
> CRYPTO_LIBS needs to point the the openssl libraries, e.g.
> export CRYPTO_LIBS="-L /home/steve/src/SecureBoot/openssl-0.9.8b -lssl -lcrypto -lm -lc"
Oops, see below [*]
> If anyone has any problems or even better, suggestions, don't hesitate
> to let me know.
>
> Best regards,
> Steve
>
> =========================================
>
> diff -Naur u-boot.orig/common/cmd_bootm.c u-boot/common/cmd_bootm.c
> --- u-boot.orig/common/cmd_bootm.c 2006-05-10 11:43:20.000000000 -0400
> +++ u-boot/common/cmd_bootm.c 2006-06-12 10:35:57.000000000 -0400
> @@ -79,6 +79,12 @@
> # define CHUNKSZ (64 * 1024)
> #endif
>
> +#ifdef CONFIG_SIGNATURE
> +extern int verify_signature (const unsigned char *signature,
> + const unsigned char *buf,
> + unsigned int len);
> +#endif /* CONFIG_SIGNATURE */
> +
> int gunzip (void *, int, unsigned char *, unsigned long *);
>
> static void *zalloc(void *, unsigned, unsigned);
> @@ -238,6 +244,19 @@
> }
> puts ("OK\n");
> }
> +
> +#ifdef CONFIG_SIGNATURE
> + puts (" Verifying Signature ... ");
> + if (verify_signature(hdr->ih_sign,
> + (const unsigned char *)data,
> + len) == 0) {
> + puts("Invalid image signature\n");
> + SHOW_BOOT_PROGRESS(-3);
> + return 1;
> + }
> + puts ("OK\n");
> +#endif /* CONFIG_SIGNATURE */
> +
> SHOW_BOOT_PROGRESS (4);
>
> len_ptr = (ulong *)data;
> diff -Naur u-boot.orig/config.mk u-boot/config.mk
> --- u-boot.orig/config.mk 2006-05-10 11:43:20.000000000 -0400
> +++ u-boot/config.mk 2006-06-08 09:41:17.000000000 -0400
> @@ -126,7 +126,7 @@
> -D__KERNEL__ -DTEXT_BASE=$(TEXT_BASE) \
> -I$(TOPDIR)/include \
> -fno-builtin -ffreestanding -nostdinc -isystem \
> - $(gccincdir) -pipe $(PLATFORM_CPPFLAGS)
> + $(gccincdir) -pipe $(PLATFORM_CPPFLAGS) $(CRYPTO_INC)
[*] You are adding path to opessl includes to crosscompiler... Uh, I
have bad feelings...
> ifdef BUILD_TAG
> CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes \
> diff -Naur u-boot.orig/include/configs/omap5912osk.h u-boot/include/configs/omap5912osk.h
> --- u-boot.orig/include/configs/omap5912osk.h 2006-05-10 11:43:20.000000000 -0400
> +++ u-boot/include/configs/omap5912osk.h 2006-06-08 15:34:00.000000000 -0400
> @@ -38,6 +38,8 @@
> #define CONFIG_DISPLAY_CPUINFO 1 /* display cpu info (and speed) */
> #define CONFIG_DISPLAY_BOARDINFO 1 /* display board info */
>
> +#define CONFIG_SIGNATURE 1
> +
> /* input clock of PLL */
> /* the OMAP5912 OSK has 12MHz input clock */
> #define CONFIG_SYS_CLK_FREQ 12000000
> @@ -112,7 +122,11 @@
> */
> #define CFG_LONGHELP /* undef to save memory */
> #define CFG_PROMPT "OMAP5912 OSK # " /* Monitor Command Prompt */
> +#ifdef CONFIG_SIGNATURE
> +#define CFG_CBSIZE 512 /* Console I/O Buffer Size */
> +#else
> #define CFG_CBSIZE 256 /* Console I/O Buffer Size */
> +#endif
> /* Print Buffer Size */
> #define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16)
> #define CFG_MAXARGS 16 /* max number of command args */
> @@ -183,9 +197,9 @@
> */
> #define CFG_ENV_IS_IN_FLASH 1
> /* addr of environment */
> -#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x020000)
> +#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x0E0000)
>
> #define CFG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
> -#define CFG_ENV_OFFSET 0x20000 /* environment starts here */
> +#define CFG_ENV_OFFSET 0xE0000 /* environment starts here */
>
> #endif /* __CONFIG_H */
> diff -Naur u-boot.orig/include/image.h u-boot/include/image.h
> --- u-boot.orig/include/image.h 2006-05-10 11:43:20.000000000 -0400
> +++ u-boot/include/image.h 2006-06-08 09:09:09.000000000 -0400
> @@ -134,6 +134,9 @@
>
> #define IH_MAGIC 0x27051956 /* Image Magic Number */
> #define IH_NMLEN 32 /* Image Name Length */
> +#ifdef CONFIG_SIGNATURE
> +#define IH_SIGN 256 /* Image Signature Length */
> +#endif /* CONFIG_SIGNATURE */
>
> /*
> * all data in network byte order (aka natural aka bigendian)
> @@ -152,6 +155,9 @@
> uint8_t ih_type; /* Image Type */
> uint8_t ih_comp; /* Compression Type */
> uint8_t ih_name[IH_NMLEN]; /* Image Name */
> +#ifdef CONFIG_SIGNATURE
> + uint8_t ih_sign[IH_SIGN]; /* Image Signature */
> +#endif /* CONFIG_SIGNATURE */
> } image_header_t;
>
>
> diff -Naur u-boot.orig/lib_crypto/Makefile u-boot/lib_crypto/Makefile
> --- u-boot.orig/lib_crypto/Makefile 1969-12-31 19:00:00.000000000 -0500
> +++ u-boot/lib_crypto/Makefile 2006-06-08 10:17:56.000000000 -0400
> @@ -0,0 +1,40 @@
> +#
> +# (C) Copyright 2000-2002
> +# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
> +#
> +# See file CREDITS for list of people who contributed to this
> +# project.
> +#
> +# 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, write to the Free Software
> +# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> +# MA 02111-1307 USA
> +#
> +
> +include $(TOPDIR)/config.mk
> +
> +LIB = libcrypto.a
> +
> +OBJS = signature.o
> +
> +$(LIB): .depend $(OBJS)
> + $(AR) crv $@ $(OBJS)
> +
> +#########################################################################
> +
> +.depend: Makefile $(OBJS:.o=.c)
> + $(CC) -M $(CFLAGS) $(CRYPTO_INC) $(OBJS:.o=.c) > $@
> +
> +sinclude .depend
> +
> +#########################################################################
> diff -Naur u-boot.orig/lib_crypto/signature.c u-boot/lib_crypto/signature.c
> --- u-boot.orig/lib_crypto/signature.c 1969-12-31 19:00:00.000000000 -0500
> +++ u-boot/lib_crypto/signature.c 2006-06-12 10:41:51.000000000 -0400
> @@ -0,0 +1,121 @@
> +#include <stdio.h>
> +
> +#include <openssl/ssl.h>
> +#include <openssl/rsa.h>
> +#include <openssl/err.h>
> +#include <openssl/pem.h>
> +#include <openssl/sha.h>
> +#include <openssl/bio.h>
> +
> +#define IH_SIGN 256
> +
> +unsigned char key_string[] = "-----BEGIN PUBLIC KEY-----\n\
> +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6IgnrRN+ER3GG/ZNDQk/\n\
> +JByf09bYPgHfERJdHUb8p+6wM7cb7RvoxyVyaFQFA7RKErr6kvzjIKz/tyDnKKzK\n\
> +0kAE0vE5prSUDxhoExM9YBAAjc6TAQ0kKjerIwZx5iT9vYV7YSpG5U7Sycw2NrjP\n\
> +dMS2X8v1pHZSSgQAYPs3zGlC+oyMebd7vpsFKihc2vr2J0PXdD1Owh8gEIiZjm5o\n\
> +eXL93BGFUVMZa040YUvTn9627eEg6hJJqmRZ4Myx90585J/2Jmhztv2U2t2Rl2T9\n\
> +mentqOvFO0QhhadniRgDzhsLM6wbpwOqlRROcVGnkqmFckLKlLWqYbzoZOJs4xO3\n\
> +oQIDAQAB\n\
> +-----END PUBLIC KEY-----\n";
You want public key to be board specific, don't you?
> +void SSL_load_error_strings(void);
> +
> +static void err_msg(void);
> +static RSA *load_key(void) ;
> +static RSA *get_public_key(char *key_string);
> +
> +/*
> + =========================================================================
> +*/
> +
> +static void
> +err_msg(void)
> +{
> + char err_buff[1024];
> + unsigned long err;
> +
> + SSL_load_error_strings();
> +
> + while ((err = ERR_get_error())) {
> + ERR_error_string_n(err, err_buff, sizeof(err_buff));
> + fprintf(stderr, "%s\n", err_buff);
> + }
> +
> + ERR_free_strings();
> +}
> +
> +
> +int
> +verify_signature(const unsigned char *signature,
> + const unsigned char *buf,
> + unsigned int len)
> +{
> + RSA *public_key;
> + unsigned char digest[SHA_DIGEST_LENGTH];
> + int res;
> + int i;
> +
> + /* Do SHA1 encryption of buffer */
> + (void)SHA1(buf, len, digest);
Oh, here bad feeling came true. It seems you are indeed using SHA1
function from crypto/sha/sha1_one.c (openssl library).
> + /* Load public key */
> + if ((public_key = load_key()) == NULL) {
> + return 0;
> + }
> +
> + /* verify digest */
> + res = RSA_verify(NID_sha1,
> + digest, SHA_DIGEST_LENGTH,
> + signature, IH_SIGN,
> + public_key);
> +
> + /* Clean up */
> + RSA_free(public_key);
> +
> + return res;
> +}
[snip]
Well, I have admit it is a bit surprising that openssl can be compiled
as standalone library and linked with U-Boot :-)
Although I'd like to see support for something like this in U-Boot, this
is not way to go. Please see, how hush (busybox shell - common/hush.c)
or nand support (drivers/nand) were integrated. Just take all necesary
routines you need and make them fit into U-Boot tree. Remove all bloat,
but make future updates from original source easy.
Best regards,
ladis
More information about the U-Boot
mailing list