mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-18 10:54:37 +00:00
tools: Add preload_check_sign to authenticate images with a pre-load
preload_check_sign is added so that it can be used to authenticate images signed with the pre-load signature supported by binman and U-Boot. It could also be used to test the signature in binman tests signing images with the pre-load. Signed-off-by: Paul HENRYS <paul.henrys_ext@softathome.com>
This commit is contained in:
parent
6ce674c254
commit
7dd0bf5279
4 changed files with 172 additions and 0 deletions
1
tools/.gitignore
vendored
1
tools/.gitignore
vendored
|
@ -29,6 +29,7 @@
|
|||
/mxsboot
|
||||
/ncb
|
||||
/prelink-riscv
|
||||
/preload_check_sign
|
||||
/printinitialenv
|
||||
/proftool
|
||||
/relocate-rela
|
||||
|
|
|
@ -9,6 +9,11 @@ config MKIMAGE_DTC_PATH
|
|||
some cases the system dtc may not support all required features
|
||||
and the path to a different version should be given here.
|
||||
|
||||
config TOOLS_IMAGE_PRE_LOAD
|
||||
def_bool y
|
||||
help
|
||||
Enable pre-load signature support in the tools builds.
|
||||
|
||||
config TOOLS_CRC16
|
||||
def_bool y
|
||||
help
|
||||
|
|
|
@ -66,6 +66,7 @@ mkenvimage-objs := mkenvimage.o os_support.o generated/lib/crc32.o
|
|||
hostprogs-y += dumpimage mkimage
|
||||
hostprogs-$(CONFIG_TOOLS_LIBCRYPTO) += fit_info fit_check_sign
|
||||
hostprogs-$(CONFIG_TOOLS_LIBCRYPTO) += fdt_add_pubkey
|
||||
hostprogs-$(CONFIG_TOOLS_LIBCRYPTO) += preload_check_sign
|
||||
|
||||
ifneq ($(CONFIG_CMD_BOOTEFI_SELFTEST)$(CONFIG_FWU_MDATA_GPT_BLK),)
|
||||
hostprogs-y += file2include
|
||||
|
@ -89,6 +90,8 @@ ECDSA_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := $(addprefix generated/lib/ecdsa/, ecdsa-
|
|||
AES_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := $(addprefix generated/lib/aes/, \
|
||||
aes-encrypt.o aes-decrypt.o)
|
||||
|
||||
PRELOAD_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := generated/boot/image-pre-load.o
|
||||
|
||||
# Cryptographic helpers and image types that depend on openssl/libcrypto
|
||||
LIBCRYPTO_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := \
|
||||
generated/lib/fdt-libcrypto.o \
|
||||
|
@ -158,6 +161,7 @@ fit_info-objs := $(dumpimage-mkimage-objs) fit_info.o
|
|||
fit_check_sign-objs := $(dumpimage-mkimage-objs) fit_check_sign.o
|
||||
fdt_add_pubkey-objs := $(dumpimage-mkimage-objs) fdt_add_pubkey.o
|
||||
file2include-objs := file2include.o
|
||||
preload_check_sign-objs := $(dumpimage-mkimage-objs) $(PRELOAD_OBJS-y) preload_check_sign.o
|
||||
|
||||
ifneq ($(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_TOOLS_LIBCRYPTO),)
|
||||
# Add CFG_MXS into host CFLAGS, so we can check whether or not register
|
||||
|
@ -195,6 +199,7 @@ HOSTLDLIBS_dumpimage := $(HOSTLDLIBS_mkimage)
|
|||
HOSTLDLIBS_fit_info := $(HOSTLDLIBS_mkimage)
|
||||
HOSTLDLIBS_fit_check_sign := $(HOSTLDLIBS_mkimage)
|
||||
HOSTLDLIBS_fdt_add_pubkey := $(HOSTLDLIBS_mkimage)
|
||||
HOSTLDLIBS_preload_check_sign := $(HOSTLDLIBS_mkimage)
|
||||
|
||||
hostprogs-$(CONFIG_EXYNOS5250) += mkexynosspl
|
||||
hostprogs-$(CONFIG_EXYNOS5420) += mkexynosspl
|
||||
|
|
161
tools/preload_check_sign.c
Normal file
161
tools/preload_check_sign.c
Normal file
|
@ -0,0 +1,161 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Check a file including a preload header including a signature
|
||||
*
|
||||
* Copyright (c) 2025 Paul HENRYS <paul.henrys_ext@softathome.com>
|
||||
*
|
||||
* Binman makes it possible to generate a preload header signing part or the
|
||||
* complete file. The tool preload_check_sign allows to verify and authenticate
|
||||
* a file starting with a preload header.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/err.h>
|
||||
#include <image.h>
|
||||
|
||||
extern void image_pre_load_sig_set_info(struct image_sig_info *info);
|
||||
extern int image_pre_load_sig(ulong addr);
|
||||
|
||||
static void usage(char *cmdname)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s -f file -k PEM key file\n"
|
||||
" -f ==> set file which should be checked\n"
|
||||
" -k ==> PEM key file\n"
|
||||
" -a ==> algo (default: sha256,rsa2048)\n"
|
||||
" -p ==> padding (default: pkcs-1.5)\n"
|
||||
" -h ==> help\n",
|
||||
cmdname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret = 0;
|
||||
char cmdname[256];
|
||||
char *file = NULL;
|
||||
char *keyfile = NULL;
|
||||
int c;
|
||||
FILE *fp = NULL;
|
||||
FILE *fp_key = NULL;
|
||||
size_t bytes;
|
||||
long filesize;
|
||||
void *buffer = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
char *algo = "sha256,rsa2048";
|
||||
char *padding = "pkcs-1.5";
|
||||
struct image_sig_info info = {0};
|
||||
|
||||
strncpy(cmdname, *argv, sizeof(cmdname) - 1);
|
||||
cmdname[sizeof(cmdname) - 1] = '\0';
|
||||
while ((c = getopt(argc, argv, "f:k:a:p:h")) != -1)
|
||||
switch (c) {
|
||||
case 'f':
|
||||
file = optarg;
|
||||
break;
|
||||
case 'k':
|
||||
keyfile = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
algo = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
padding = optarg;
|
||||
break;
|
||||
default:
|
||||
usage(cmdname);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
fprintf(stderr, "%s: Missing file\n", *argv);
|
||||
usage(*argv);
|
||||
}
|
||||
|
||||
if (!keyfile) {
|
||||
fprintf(stderr, "%s: Missing key file\n", *argv);
|
||||
usage(*argv);
|
||||
}
|
||||
|
||||
fp = fopen(file, "r");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Error opening file: %s\n", file);
|
||||
ret = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
filesize = ftell(fp);
|
||||
rewind(fp);
|
||||
|
||||
buffer = malloc(filesize);
|
||||
if (!buffer) {
|
||||
fprintf(stderr, "Memory allocation failed");
|
||||
ret = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bytes = fread(buffer, 1, filesize, fp);
|
||||
if (bytes != filesize) {
|
||||
fprintf(stderr, "Error reading file\n");
|
||||
ret = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fp_key = fopen(keyfile, "r");
|
||||
if (!fp_key) {
|
||||
fprintf(stderr, "Error opening file: %s\n", keyfile);
|
||||
ret = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Attempt to read the private key */
|
||||
pkey = PEM_read_PrivateKey(fp_key, NULL, NULL, NULL);
|
||||
if (!pkey) {
|
||||
/* If private key reading fails, try reading as a public key */
|
||||
fseek(fp_key, 0, SEEK_SET);
|
||||
pkey = PEM_read_PUBKEY(fp_key, NULL, NULL, NULL);
|
||||
}
|
||||
if (!pkey) {
|
||||
fprintf(stderr, "Unable to retrieve the public key: %s\n",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
ret = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
info.algo_name = algo;
|
||||
info.padding_name = padding;
|
||||
info.key = (uint8_t *)pkey;
|
||||
info.mandatory = 1;
|
||||
info.sig_size = (EVP_PKEY_get_bits(pkey) + 7) / 8;
|
||||
if (info.sig_size < 0) {
|
||||
fprintf(stderr, "Fail to retrieve the signature size: %s\n",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
ret = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Compute signature information */
|
||||
info.sig_info.name = info.algo_name;
|
||||
info.sig_info.padding = image_get_padding_algo(info.padding_name);
|
||||
info.sig_info.checksum = image_get_checksum_algo(info.sig_info.name);
|
||||
info.sig_info.crypto = image_get_crypto_algo(info.sig_info.name);
|
||||
info.sig_info.key = info.key;
|
||||
info.sig_info.keylen = info.key_len;
|
||||
|
||||
/* Check the signature */
|
||||
image_pre_load_sig_set_info(&info);
|
||||
ret = image_pre_load_sig((ulong)buffer);
|
||||
out:
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
if (fp_key)
|
||||
fclose(fp_key);
|
||||
if (info.key)
|
||||
EVP_PKEY_free(pkey);
|
||||
free(buffer);
|
||||
|
||||
exit(ret);
|
||||
}
|
Loading…
Add table
Reference in a new issue