[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