tools, fit_check_sign: verify a signed fit image
add host tool "fit_check_sign" which verifies, if a fit image is signed correct. Signed-off-by: Heiko Schocher <hs@denx.de> Cc: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
6bf4ca076f
commit
29a23f9d6c
@ -19,9 +19,14 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
#define IMAGE_MAX_HASHED_NODES 100
|
||||
|
||||
#ifdef USE_HOSTCC
|
||||
__attribute__((weak)) void *get_blob(void)
|
||||
void *host_blob;
|
||||
void image_set_host_blob(void *blob)
|
||||
{
|
||||
return NULL;
|
||||
host_blob = blob;
|
||||
}
|
||||
void *image_get_host_blob(void)
|
||||
{
|
||||
return host_blob;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -32,10 +37,9 @@ struct checksum_algo checksum_algos[] = {
|
||||
RSA2048_BYTES,
|
||||
#if IMAGE_ENABLE_SIGN
|
||||
EVP_sha1,
|
||||
#else
|
||||
#endif
|
||||
sha1_calculate,
|
||||
padding_sha1_rsa2048,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
"sha256",
|
||||
@ -43,10 +47,9 @@ struct checksum_algo checksum_algos[] = {
|
||||
RSA2048_BYTES,
|
||||
#if IMAGE_ENABLE_SIGN
|
||||
EVP_sha256,
|
||||
#else
|
||||
#endif
|
||||
sha256_calculate,
|
||||
padding_sha256_rsa2048,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
"sha256",
|
||||
@ -54,10 +57,9 @@ struct checksum_algo checksum_algos[] = {
|
||||
RSA4096_BYTES,
|
||||
#if IMAGE_ENABLE_SIGN
|
||||
EVP_sha256,
|
||||
#else
|
||||
#endif
|
||||
sha256_calculate,
|
||||
padding_sha256_rsa4096,
|
||||
#endif
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -357,6 +357,9 @@ Build FIT with signed configuration
|
||||
Test Verified Boot Run: unsigned config: OK
|
||||
Sign images
|
||||
Test Verified Boot Run: signed config: OK
|
||||
check signed config on the host
|
||||
OK
|
||||
Test Verified Boot Run: signed config: OK
|
||||
Test Verified Boot Run: signed config with bad hash: OK
|
||||
do sha256 test
|
||||
Build FIT with signed images
|
||||
@ -367,6 +370,9 @@ Build FIT with signed configuration
|
||||
Test Verified Boot Run: unsigned config: OK
|
||||
Sign images
|
||||
Test Verified Boot Run: signed config: OK
|
||||
check signed config on the host
|
||||
OK
|
||||
Test Verified Boot Run: signed config: OK
|
||||
Test Verified Boot Run: signed config with bad hash: OK
|
||||
|
||||
Test passed
|
||||
|
@ -115,4 +115,9 @@ static inline int fdt_status_disabled_by_alias(void *fdt, const char* alias)
|
||||
}
|
||||
|
||||
#endif /* ifdef CONFIG_OF_LIBFDT */
|
||||
|
||||
#ifdef USE_HOSTCC
|
||||
int fdtdec_get_int(const void *blob, int node, const char *prop_name,
|
||||
int default_val);
|
||||
#endif
|
||||
#endif /* ifndef __FDT_SUPPORT_H */
|
||||
|
@ -832,7 +832,7 @@ int calculate_hash(const void *data, int data_len, const char *algo,
|
||||
#if defined(CONFIG_FIT_SIGNATURE)
|
||||
# ifdef USE_HOSTCC
|
||||
# define IMAGE_ENABLE_SIGN 1
|
||||
# define IMAGE_ENABLE_VERIFY 0
|
||||
# define IMAGE_ENABLE_VERIFY 1
|
||||
# include <openssl/evp.h>
|
||||
#else
|
||||
# define IMAGE_ENABLE_SIGN 0
|
||||
@ -844,7 +844,9 @@ int calculate_hash(const void *data, int data_len, const char *algo,
|
||||
#endif
|
||||
|
||||
#ifdef USE_HOSTCC
|
||||
# define gd_fdt_blob() NULL
|
||||
void *image_get_host_blob(void);
|
||||
void image_set_host_blob(void *host_blob);
|
||||
# define gd_fdt_blob() image_get_host_blob()
|
||||
#else
|
||||
# define gd_fdt_blob() (gd->fdt_blob)
|
||||
#endif
|
||||
@ -881,14 +883,11 @@ struct checksum_algo {
|
||||
const int checksum_len;
|
||||
const int pad_len;
|
||||
#if IMAGE_ENABLE_SIGN
|
||||
const EVP_MD *(*calculate)(void);
|
||||
#else
|
||||
#if IMAGE_ENABLE_VERIFY
|
||||
const EVP_MD *(*calculate_sign)(void);
|
||||
#endif
|
||||
void (*calculate)(const struct image_region region[],
|
||||
int region_count, uint8_t *checksum);
|
||||
const uint8_t *rsa_padding;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
struct image_sig_algo {
|
||||
@ -1009,7 +1008,11 @@ struct image_region *fit_region_make_list(const void *fit,
|
||||
|
||||
static inline int fit_image_check_target_arch(const void *fdt, int node)
|
||||
{
|
||||
#ifndef USE_HOSTCC
|
||||
return fit_image_check_arch(fdt, node, IH_ARCH_DEFAULT);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FIT_VERBOSE
|
||||
|
20
lib/fdtdec.c
20
lib/fdtdec.c
@ -3,6 +3,7 @@
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
#include <common.h>
|
||||
#include <serial.h>
|
||||
#include <libfdt.h>
|
||||
@ -643,3 +644,22 @@ int fdtdec_read_fmap_entry(const void *blob, int node, const char *name,
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#include "libfdt.h"
|
||||
#include "fdt_support.h"
|
||||
|
||||
int fdtdec_get_int(const void *blob, int node, const char *prop_name,
|
||||
int default_val)
|
||||
{
|
||||
const int *cell;
|
||||
int len;
|
||||
|
||||
cell = fdt_getprop_w((void *)blob, node, prop_name, &len);
|
||||
if (cell && len >= sizeof(int)) {
|
||||
int val = fdt32_to_cpu(cell[0]);
|
||||
|
||||
return val;
|
||||
}
|
||||
return default_val;
|
||||
}
|
||||
#endif
|
||||
|
@ -4,14 +4,18 @@
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <rsa.h>
|
||||
#include <sha1.h>
|
||||
#include <sha256.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/unaligned.h>
|
||||
#else
|
||||
#include "fdt_host.h"
|
||||
#endif
|
||||
#include <rsa.h>
|
||||
#include <sha1.h>
|
||||
#include <sha256.h>
|
||||
|
||||
/* PKCS 1.5 paddings as described in the RSA PKCS#1 v2.1 standard. */
|
||||
|
||||
|
@ -193,7 +193,7 @@ static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
|
||||
goto err_create;
|
||||
}
|
||||
EVP_MD_CTX_init(context);
|
||||
if (!EVP_SignInit(context, checksum_algo->calculate())) {
|
||||
if (!EVP_SignInit(context, checksum_algo->calculate_sign())) {
|
||||
ret = rsa_err("Signer setup failed");
|
||||
goto err_sign;
|
||||
}
|
||||
|
@ -4,17 +4,28 @@
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/unaligned.h>
|
||||
#else
|
||||
#include "fdt_host.h"
|
||||
#include "mkimage.h"
|
||||
#include <fdt_support.h>
|
||||
#endif
|
||||
#include <rsa.h>
|
||||
#include <sha1.h>
|
||||
#include <sha256.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/errno.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))
|
||||
|
||||
/**
|
||||
* subtract_modulus() - subtract modulus from the given value
|
||||
*
|
||||
@ -150,7 +161,6 @@ static int pow_mod(const struct rsa_public_key *key, uint32_t *inout)
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@ O=$(readlink -f ${O})
|
||||
dtc="-I dts -O dtb -p 2000"
|
||||
uboot="${O}/u-boot"
|
||||
mkimage="${O}/tools/mkimage"
|
||||
fit_check_sign="${O}/tools/fit_check_sign"
|
||||
keys="${dir}/dev-keys"
|
||||
echo ${mkimage} -D "${dtc}"
|
||||
|
||||
@ -99,6 +100,25 @@ function do_test {
|
||||
|
||||
run_uboot "signed config" "dev+"
|
||||
|
||||
echo check signed config on the host
|
||||
if ! ${fit_check_sign} -f test.fit -k sandbox-u-boot.dtb >${tmp}; then
|
||||
echo
|
||||
echo "Verified boot key check on host failed, output follows:"
|
||||
cat ${tmp}
|
||||
false
|
||||
else
|
||||
if ! grep -q "dev+" ${tmp}; then
|
||||
echo
|
||||
echo "Verified boot key check failed, output follows:"
|
||||
cat ${tmp}
|
||||
false
|
||||
else
|
||||
echo "OK"
|
||||
fi
|
||||
fi
|
||||
|
||||
run_uboot "signed config" "dev+"
|
||||
|
||||
# Increment the first byte of the signature, which should cause failure
|
||||
sig=$(fdtget -t bx test.fit /configurations/conf@1/signature@1 value)
|
||||
newbyte=$(printf %x $((0x${sig:0:2} + 1)))
|
||||
|
1
tools/.gitignore
vendored
1
tools/.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
/bmp_logo
|
||||
/envcrc
|
||||
/fit_check_sign
|
||||
/fit_info
|
||||
/gen_eth_addr
|
||||
/img2srec
|
||||
|
@ -61,13 +61,13 @@ mkenvimage$(SFX)-objs := crc32.o mkenvimage.o os_support.o
|
||||
|
||||
hostprogs-y += dumpimage$(SFX) mkimage$(SFX)
|
||||
ifdef CONFIG_FIT_SIGNATURE
|
||||
hostprogs-y += fit_info$(SFX)
|
||||
hostprogs-y += fit_info$(SFX) fit_check_sign$(SFX)
|
||||
endif
|
||||
|
||||
FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := image-sig.o
|
||||
# Flattened device tree objects
|
||||
LIBFDT_OBJS := fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_wip.o
|
||||
RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := rsa-sign.o
|
||||
RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := rsa-sign.o rsa-verify.o rsa-checksum.o
|
||||
|
||||
# common objs for dumpimage and mkimage
|
||||
dumpimage-mkimage-objs := aisimage.o \
|
||||
@ -97,6 +97,7 @@ dumpimage-mkimage-objs := aisimage.o \
|
||||
dumpimage$(SFX)-objs := $(dumpimage-mkimage-objs) dumpimage.o
|
||||
mkimage$(SFX)-objs := $(dumpimage-mkimage-objs) mkimage.o
|
||||
fit_info$(SFX)-objs := $(dumpimage-mkimage-objs) fit_info.o
|
||||
fit_check_sign$(SFX)-objs := $(dumpimage-mkimage-objs) fit_check_sign.o
|
||||
|
||||
# TODO(sjg@chromium.org): Is this correct on Mac OS?
|
||||
|
||||
@ -105,6 +106,7 @@ ifneq ($(CONFIG_MX23)$(CONFIG_MX28),)
|
||||
HOSTLOADLIBES_dumpimage$(SFX) := -lssl -lcrypto
|
||||
HOSTLOADLIBES_mkimage$(SFX) := -lssl -lcrypto
|
||||
HOSTLOADLIBES_fit_info$(SFX) := -lssl -lcrypto
|
||||
HOSTLOADLIBES_fit_check_sign$(SFX) := -lssl -lcrypto
|
||||
# Add CONFIG_MXS into host CFLAGS, so we can check whether or not register
|
||||
# the mxsimage support within tools/mxsimage.c .
|
||||
HOSTCFLAGS_mxsimage.o += -DCONFIG_MXS
|
||||
@ -114,6 +116,7 @@ ifdef CONFIG_FIT_SIGNATURE
|
||||
HOSTLOADLIBES_dumpimage$(SFX) := -lssl -lcrypto
|
||||
HOSTLOADLIBES_mkimage$(SFX) := -lssl -lcrypto
|
||||
HOSTLOADLIBES_fit_info$(SFX) := -lssl -lcrypto
|
||||
HOSTLOADLIBES_fit_check_sign$(SFX) := -lssl -lcrypto
|
||||
|
||||
# This affects include/image.h, but including the board config file
|
||||
# is tricky, so manually define this options here.
|
||||
|
@ -11,4 +11,6 @@
|
||||
#include "../include/libfdt.h"
|
||||
#include "../include/fdt_support.h"
|
||||
|
||||
int fit_check_sign(const void *working_fdt, const void *key);
|
||||
|
||||
#endif /* __FDT_HOST_H__ */
|
||||
|
1
tools/fdtdec.c
Normal file
1
tools/fdtdec.c
Normal file
@ -0,0 +1 @@
|
||||
#include "../lib/fdtdec.c"
|
85
tools/fit_check_sign.c
Normal file
85
tools/fit_check_sign.c
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* (C) Copyright 2014
|
||||
* DENX Software Engineering
|
||||
* Heiko Schocher <hs@denx.de>
|
||||
*
|
||||
* Based on:
|
||||
* (C) Copyright 2008 Semihalf
|
||||
*
|
||||
* (C) Copyright 2000-2004
|
||||
* DENX Software Engineering
|
||||
* Wolfgang Denk, wd@denx.de
|
||||
*
|
||||
* Updated-by: Prafulla Wadaskar <prafulla@marvell.com>
|
||||
* FIT image specific code abstracted from mkimage.c
|
||||
* some functions added to address abstraction
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include "mkimage.h"
|
||||
#include "fit_common.h"
|
||||
#include <image.h>
|
||||
#include <u-boot/crc.h>
|
||||
|
||||
void usage(char *cmdname)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s -f fit file -k key file\n"
|
||||
" -f ==> set fit file which should be checked'\n"
|
||||
" -k ==> set key file which contains the key'\n",
|
||||
cmdname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ffd = -1;
|
||||
int kfd = -1;
|
||||
struct stat fsbuf;
|
||||
struct stat ksbuf;
|
||||
void *fit_blob;
|
||||
char *fdtfile = NULL;
|
||||
char *keyfile = NULL;
|
||||
char cmdname[50];
|
||||
int ret;
|
||||
void *key_blob;
|
||||
int c;
|
||||
|
||||
strcpy(cmdname, *argv);
|
||||
while ((c = getopt(argc, argv, "f:k:")) != -1)
|
||||
switch (c) {
|
||||
case 'f':
|
||||
fdtfile = optarg;
|
||||
break;
|
||||
case 'k':
|
||||
keyfile = optarg;
|
||||
break;
|
||||
default:
|
||||
usage(cmdname);
|
||||
break;
|
||||
}
|
||||
|
||||
ffd = mmap_fdt(cmdname, fdtfile, &fit_blob, &fsbuf, 0);
|
||||
if (ffd < 0)
|
||||
return EXIT_FAILURE;
|
||||
kfd = mmap_fdt(cmdname, keyfile, &key_blob, &ksbuf, 0);
|
||||
if (ffd < 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
image_set_host_blob(key_blob);
|
||||
ret = fit_check_sign(fit_blob, key_blob);
|
||||
|
||||
if (ret)
|
||||
ret = EXIT_SUCCESS;
|
||||
else
|
||||
ret = EXIT_FAILURE;
|
||||
|
||||
(void) munmap((void *)fit_blob, fsbuf.st_size);
|
||||
(void) munmap((void *)key_blob, ksbuf.st_size);
|
||||
|
||||
close(ffd);
|
||||
close(kfd);
|
||||
exit(ret);
|
||||
}
|
@ -695,3 +695,18 @@ int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FIT_SIGNATURE
|
||||
int fit_check_sign(const void *working_fdt, const void *key)
|
||||
{
|
||||
int cfg_noffset;
|
||||
int ret;
|
||||
|
||||
cfg_noffset = fit_conf_get_node(working_fdt, NULL);
|
||||
if (!cfg_noffset)
|
||||
return -1;
|
||||
|
||||
ret = fit_config_verify(working_fdt, cfg_noffset);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
1
tools/rsa-checksum.c
Normal file
1
tools/rsa-checksum.c
Normal file
@ -0,0 +1 @@
|
||||
#include "../lib/rsa/rsa-checksum.c"
|
1
tools/rsa-verify.c
Normal file
1
tools/rsa-verify.c
Normal file
@ -0,0 +1 @@
|
||||
#include "../lib/rsa/rsa-verify.c"
|
Loading…
Reference in New Issue
Block a user