rsa: add sha256-rsa2048 algorithm
based on patch from andreas@oetken.name: http://patchwork.ozlabs.org/patch/294318/ commit message: I currently need support for rsa-sha256 signatures in u-boot and found out that the code for signatures is not very generic. Thus adding of different hash-algorithms for rsa-signatures is not easy to do without copy-pasting the rsa-code. I attached a patch for how I think it could be better and included support for rsa-sha256. This is a fast first shot. aditionally work: - removed checkpatch warnings - removed compiler warnings - rebased against current head Signed-off-by: Heiko Schocher <hs@denx.de> Cc: andreas@oetken.name Cc: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
2842c1c242
commit
646257d1f4
@ -14,15 +14,53 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
#endif /* !USE_HOSTCC*/
|
||||
#include <image.h>
|
||||
#include <rsa.h>
|
||||
#include <rsa-checksum.h>
|
||||
|
||||
#define IMAGE_MAX_HASHED_NODES 100
|
||||
|
||||
#ifdef USE_HOSTCC
|
||||
__attribute__((weak)) void *get_blob(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct checksum_algo checksum_algos[] = {
|
||||
{
|
||||
"sha1",
|
||||
SHA1_SUM_LEN,
|
||||
#if IMAGE_ENABLE_SIGN
|
||||
EVP_sha1,
|
||||
#else
|
||||
sha1_calculate,
|
||||
padding_sha1_rsa2048,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
"sha256",
|
||||
SHA256_SUM_LEN,
|
||||
#if IMAGE_ENABLE_SIGN
|
||||
EVP_sha256,
|
||||
#else
|
||||
sha256_calculate,
|
||||
padding_sha256_rsa2048,
|
||||
#endif
|
||||
}
|
||||
};
|
||||
struct image_sig_algo image_sig_algos[] = {
|
||||
{
|
||||
"sha1,rsa2048",
|
||||
rsa_sign,
|
||||
rsa_add_verify_data,
|
||||
rsa_verify,
|
||||
&checksum_algos[0],
|
||||
},
|
||||
{
|
||||
"sha256,rsa2048",
|
||||
rsa_sign,
|
||||
rsa_add_verify_data,
|
||||
rsa_verify,
|
||||
&checksum_algos[1],
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -346,7 +346,9 @@ Simple Verified Boot Test
|
||||
|
||||
Please see doc/uImage.FIT/verified-boot.txt for more information
|
||||
|
||||
/home/hs/ids/u-boot/sandbox/tools/mkimage -D -I dts -O dtb -p 2000
|
||||
Build keys
|
||||
do sha1 test
|
||||
Build FIT with signed images
|
||||
Test Verified Boot Run: unsigned signatures:: OK
|
||||
Sign images
|
||||
@ -355,10 +357,20 @@ Build FIT with signed configuration
|
||||
Test Verified Boot Run: unsigned config: OK
|
||||
Sign images
|
||||
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
|
||||
Test Verified Boot Run: unsigned signatures:: OK
|
||||
Sign images
|
||||
Test Verified Boot Run: signed images: OK
|
||||
Build FIT with signed configuration
|
||||
Test Verified Boot Run: unsigned config: OK
|
||||
Sign images
|
||||
Test Verified Boot Run: signed config: OK
|
||||
Test Verified Boot Run: signed config with bad hash: OK
|
||||
|
||||
Test passed
|
||||
|
||||
|
||||
Future Work
|
||||
-----------
|
||||
- Roll-back protection using a TPM is done using the tpm command. This can
|
||||
|
@ -833,6 +833,7 @@ int calculate_hash(const void *data, int data_len, const char *algo,
|
||||
# ifdef USE_HOSTCC
|
||||
# define IMAGE_ENABLE_SIGN 1
|
||||
# define IMAGE_ENABLE_VERIFY 0
|
||||
# include <openssl/evp.h>
|
||||
#else
|
||||
# define IMAGE_ENABLE_SIGN 0
|
||||
# define IMAGE_ENABLE_VERIFY 1
|
||||
@ -872,6 +873,23 @@ struct image_region {
|
||||
int size;
|
||||
};
|
||||
|
||||
#if IMAGE_ENABLE_VERIFY
|
||||
# include <rsa-checksum.h>
|
||||
#endif
|
||||
struct checksum_algo {
|
||||
const char *name;
|
||||
const int checksum_len;
|
||||
#if IMAGE_ENABLE_SIGN
|
||||
const EVP_MD *(*calculate)(void);
|
||||
#else
|
||||
#if IMAGE_ENABLE_VERIFY
|
||||
void (*calculate)(const struct image_region region[],
|
||||
int region_count, uint8_t *checksum);
|
||||
const uint8_t *rsa_padding;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
struct image_sig_algo {
|
||||
const char *name; /* Name of algorithm */
|
||||
|
||||
@ -922,6 +940,9 @@ struct image_sig_algo {
|
||||
int (*verify)(struct image_sign_info *info,
|
||||
const struct image_region region[], int region_count,
|
||||
uint8_t *sig, uint sig_len);
|
||||
|
||||
/* pointer to checksum algorithm */
|
||||
struct checksum_algo *checksum;
|
||||
};
|
||||
|
||||
/**
|
||||
|
23
include/rsa-checksum.h
Normal file
23
include/rsa-checksum.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Andreas Oetken.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _RSA_CHECKSUM_H
|
||||
#define _RSA_CHECKSUM_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <image.h>
|
||||
#include <sha1.h>
|
||||
#include <sha256.h>
|
||||
|
||||
extern const uint8_t padding_sha256_rsa2048[];
|
||||
extern const uint8_t padding_sha1_rsa2048[];
|
||||
|
||||
void sha256_calculate(const struct image_region region[], int region_count,
|
||||
uint8_t *checksum);
|
||||
void sha1_calculate(const struct image_region region[], int region_count,
|
||||
uint8_t *checksum);
|
||||
|
||||
#endif
|
@ -15,6 +15,20 @@
|
||||
#include <errno.h>
|
||||
#include <image.h>
|
||||
|
||||
/**
|
||||
* struct rsa_public_key - holder for a public key
|
||||
*
|
||||
* An RSA public key consists of a modulus (typically called N), the inverse
|
||||
* and R^2, where R is 2^(# key bits).
|
||||
*/
|
||||
|
||||
struct rsa_public_key {
|
||||
uint len; /* len of modulus[] in number of uint32_t */
|
||||
uint32_t n0inv; /* -1 / modulus[0] mod 2^32 */
|
||||
uint32_t *modulus; /* modulus as little endian array */
|
||||
uint32_t *rr; /* R^2 as little endian array */
|
||||
};
|
||||
|
||||
#if IMAGE_ENABLE_SIGN
|
||||
/**
|
||||
* sign() - calculate and return signature for given input data
|
||||
|
@ -7,4 +7,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-$(CONFIG_FIT_SIGNATURE) += rsa-verify.o
|
||||
obj-$(CONFIG_FIT_SIGNATURE) += rsa-verify.o rsa-checksum.o
|
||||
|
98
lib/rsa/rsa-checksum.c
Normal file
98
lib/rsa/rsa-checksum.c
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Andreas Oetken.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
#define RSA2048_BYTES 256
|
||||
|
||||
/* PKCS 1.5 paddings as described in the RSA PKCS#1 v2.1 standard. */
|
||||
|
||||
const uint8_t padding_sha256_rsa2048[RSA2048_BYTES - SHA256_SUM_LEN] = {
|
||||
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30,
|
||||
0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
|
||||
0x00, 0x04, 0x20
|
||||
};
|
||||
|
||||
const uint8_t padding_sha1_rsa2048[RSA2048_BYTES - SHA1_SUM_LEN] = {
|
||||
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30,
|
||||
0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
|
||||
0x05, 0x00, 0x04, 0x14
|
||||
};
|
||||
|
||||
void sha1_calculate(const struct image_region region[], int region_count,
|
||||
uint8_t *checksum)
|
||||
{
|
||||
sha1_context ctx;
|
||||
uint32_t i;
|
||||
i = 0;
|
||||
|
||||
sha1_starts(&ctx);
|
||||
for (i = 0; i < region_count; i++)
|
||||
sha1_update(&ctx, region[i].data, region[i].size);
|
||||
sha1_finish(&ctx, checksum);
|
||||
}
|
||||
|
||||
void sha256_calculate(const struct image_region region[], int region_count,
|
||||
uint8_t *checksum)
|
||||
{
|
||||
sha256_context ctx;
|
||||
uint32_t i;
|
||||
i = 0;
|
||||
|
||||
sha256_starts(&ctx);
|
||||
for (i = 0; i < region_count; i++)
|
||||
sha256_update(&ctx, region[i].data, region[i].size);
|
||||
sha256_finish(&ctx, checksum);
|
||||
}
|
@ -159,8 +159,9 @@ static void rsa_remove(void)
|
||||
EVP_cleanup();
|
||||
}
|
||||
|
||||
static int rsa_sign_with_key(RSA *rsa, const struct image_region region[],
|
||||
int region_count, uint8_t **sigp, uint *sig_size)
|
||||
static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
|
||||
const struct image_region region[], int region_count,
|
||||
uint8_t **sigp, uint *sig_size)
|
||||
{
|
||||
EVP_PKEY *key;
|
||||
EVP_MD_CTX *context;
|
||||
@ -192,7 +193,7 @@ static int rsa_sign_with_key(RSA *rsa, const struct image_region region[],
|
||||
goto err_create;
|
||||
}
|
||||
EVP_MD_CTX_init(context);
|
||||
if (!EVP_SignInit(context, EVP_sha1())) {
|
||||
if (!EVP_SignInit(context, checksum_algo->calculate())) {
|
||||
ret = rsa_err("Signer setup failed");
|
||||
goto err_sign;
|
||||
}
|
||||
@ -242,7 +243,8 @@ int rsa_sign(struct image_sign_info *info,
|
||||
ret = rsa_get_priv_key(info->keydir, info->keyname, &rsa);
|
||||
if (ret)
|
||||
goto err_priv;
|
||||
ret = rsa_sign_with_key(rsa, region, region_count, sigp, sig_len);
|
||||
ret = rsa_sign_with_key(rsa, info->algo->checksum, region,
|
||||
region_count, sigp, sig_len);
|
||||
if (ret)
|
||||
goto err_sign;
|
||||
|
||||
|
@ -8,23 +8,11 @@
|
||||
#include <fdtdec.h>
|
||||
#include <rsa.h>
|
||||
#include <sha1.h>
|
||||
#include <sha256.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
/**
|
||||
* struct rsa_public_key - holder for a public key
|
||||
*
|
||||
* An RSA public key consists of a modulus (typically called N), the inverse
|
||||
* and R^2, where R is 2^(# key bits).
|
||||
*/
|
||||
struct rsa_public_key {
|
||||
uint len; /* Length of modulus[] in number of uint32_t */
|
||||
uint32_t n0inv; /* -1 / modulus[0] mod 2^32 */
|
||||
uint32_t *modulus; /* modulus as little endian array */
|
||||
uint32_t *rr; /* R^2 as little endian array */
|
||||
};
|
||||
|
||||
#define UINT64_MULT32(v, multby) (((uint64_t)(v)) * ((uint32_t)(multby)))
|
||||
|
||||
#define RSA2048_BYTES (2048 / 8)
|
||||
@ -36,39 +24,6 @@ struct rsa_public_key {
|
||||
/* This is the maximum signature length that we support, in bits */
|
||||
#define RSA_MAX_SIG_BITS 2048
|
||||
|
||||
static const uint8_t padding_sha1_rsa2048[RSA2048_BYTES - SHA1_SUM_LEN] = {
|
||||
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30,
|
||||
0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
|
||||
0x05, 0x00, 0x04, 0x14
|
||||
};
|
||||
|
||||
/**
|
||||
* subtract_modulus() - subtract modulus from the given value
|
||||
*
|
||||
@ -209,13 +164,14 @@ static int pow_mod(const struct rsa_public_key *key, uint32_t *inout)
|
||||
}
|
||||
|
||||
static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig,
|
||||
const uint32_t sig_len, const uint8_t *hash)
|
||||
const uint32_t sig_len, const uint8_t *hash,
|
||||
struct checksum_algo *algo)
|
||||
{
|
||||
const uint8_t *padding;
|
||||
int pad_len;
|
||||
int ret;
|
||||
|
||||
if (!key || !sig || !hash)
|
||||
if (!key || !sig || !hash || !algo)
|
||||
return -EIO;
|
||||
|
||||
if (sig_len != (key->len * sizeof(uint32_t))) {
|
||||
@ -223,6 +179,8 @@ static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
debug("Checksum algorithm: %s", algo->name);
|
||||
|
||||
/* Sanity check for stack size */
|
||||
if (sig_len > RSA_MAX_SIG_BITS / 8) {
|
||||
debug("Signature length %u exceeds maximum %d\n", sig_len,
|
||||
@ -238,9 +196,8 @@ static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Determine padding to use depending on the signature type. */
|
||||
padding = padding_sha1_rsa2048;
|
||||
pad_len = RSA2048_BYTES - SHA1_SUM_LEN;
|
||||
padding = algo->rsa_padding;
|
||||
pad_len = RSA2048_BYTES - algo->checksum_len;
|
||||
|
||||
/* Check pkcs1.5 padding bytes. */
|
||||
if (memcmp(buf, padding, pad_len)) {
|
||||
@ -309,7 +266,7 @@ static int rsa_verify_with_keynode(struct image_sign_info *info,
|
||||
}
|
||||
|
||||
debug("key length %d\n", key.len);
|
||||
ret = rsa_verify_key(&key, sig, sig_len, hash);
|
||||
ret = rsa_verify_key(&key, sig, sig_len, hash, info->algo->checksum);
|
||||
if (ret) {
|
||||
printf("%s: RSA failed to verify: %d\n", __func__, ret);
|
||||
return ret;
|
||||
@ -323,12 +280,22 @@ int rsa_verify(struct image_sign_info *info,
|
||||
uint8_t *sig, uint sig_len)
|
||||
{
|
||||
const void *blob = info->fdt_blob;
|
||||
uint8_t hash[SHA1_SUM_LEN];
|
||||
/* Reserve memory for maximum checksum-length */
|
||||
uint8_t hash[RSA2048_BYTES];
|
||||
int ndepth, noffset;
|
||||
int sig_node, node;
|
||||
char name[100];
|
||||
sha1_context ctx;
|
||||
int ret, i;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Verify that the checksum-length does not exceed the
|
||||
* rsa-signature-length
|
||||
*/
|
||||
if (info->algo->checksum->checksum_len > RSA2048_BYTES) {
|
||||
debug("%s: invlaid checksum-algorithm %s for RSA2048\n",
|
||||
__func__, info->algo->checksum->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
|
||||
if (sig_node < 0) {
|
||||
@ -336,10 +303,8 @@ int rsa_verify(struct image_sign_info *info,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
sha1_starts(&ctx);
|
||||
for (i = 0; i < region_count; i++)
|
||||
sha1_update(&ctx, region[i].data, region[i].size);
|
||||
sha1_finish(&ctx, hash);
|
||||
/* Calculate checksum with checksum-algorithm */
|
||||
info->algo->checksum->calculate(region, region_count, hash);
|
||||
|
||||
/* See if we must use a particular key */
|
||||
if (info->required_keynode != -1) {
|
||||
|
45
test/vboot/sign-configs-sha256.its
Normal file
45
test/vboot/sign-configs-sha256.its
Normal file
@ -0,0 +1,45 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Chrome OS kernel image with one or more FDT blobs";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
kernel@1 {
|
||||
data = /incbin/("test-kernel.bin");
|
||||
type = "kernel_noload";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "none";
|
||||
load = <0x4>;
|
||||
entry = <0x8>;
|
||||
kernel-version = <1>;
|
||||
hash@1 {
|
||||
algo = "sha256";
|
||||
};
|
||||
};
|
||||
fdt@1 {
|
||||
description = "snow";
|
||||
data = /incbin/("sandbox-kernel.dtb");
|
||||
type = "flat_dt";
|
||||
arch = "sandbox";
|
||||
compression = "none";
|
||||
fdt-version = <1>;
|
||||
hash@1 {
|
||||
algo = "sha256";
|
||||
};
|
||||
};
|
||||
};
|
||||
configurations {
|
||||
default = "conf@1";
|
||||
conf@1 {
|
||||
kernel = "kernel@1";
|
||||
fdt = "fdt@1";
|
||||
signature@1 {
|
||||
algo = "sha256,rsa2048";
|
||||
key-name-hint = "dev";
|
||||
sign-images = "fdt", "kernel";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
42
test/vboot/sign-images-sha256.its
Normal file
42
test/vboot/sign-images-sha256.its
Normal file
@ -0,0 +1,42 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Chrome OS kernel image with one or more FDT blobs";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
kernel@1 {
|
||||
data = /incbin/("test-kernel.bin");
|
||||
type = "kernel_noload";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "none";
|
||||
load = <0x4>;
|
||||
entry = <0x8>;
|
||||
kernel-version = <1>;
|
||||
signature@1 {
|
||||
algo = "sha256,rsa2048";
|
||||
key-name-hint = "dev";
|
||||
};
|
||||
};
|
||||
fdt@1 {
|
||||
description = "snow";
|
||||
data = /incbin/("sandbox-kernel.dtb");
|
||||
type = "flat_dt";
|
||||
arch = "sandbox";
|
||||
compression = "none";
|
||||
fdt-version = <1>;
|
||||
signature@1 {
|
||||
algo = "sha256,rsa2048";
|
||||
key-name-hint = "dev";
|
||||
};
|
||||
};
|
||||
};
|
||||
configurations {
|
||||
default = "conf@1";
|
||||
conf@1 {
|
||||
kernel = "kernel@1";
|
||||
fdt = "fdt@1";
|
||||
};
|
||||
};
|
||||
};
|
@ -61,47 +61,57 @@ openssl req -batch -new -x509 -key ${keys}/dev.key -out ${keys}/dev.crt
|
||||
|
||||
pushd ${dir} >/dev/null
|
||||
|
||||
# Compile our device tree files for kernel and U-Boot (CONFIG_OF_CONTROL)
|
||||
dtc -p 0x1000 sandbox-kernel.dts -O dtb -o sandbox-kernel.dtb
|
||||
dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
|
||||
function do_test {
|
||||
echo do $sha test
|
||||
# Compile our device tree files for kernel and U-Boot
|
||||
dtc -p 0x1000 sandbox-kernel.dts -O dtb -o sandbox-kernel.dtb
|
||||
dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
|
||||
|
||||
# Create a number kernel image with zeroes
|
||||
head -c 5000 /dev/zero >test-kernel.bin
|
||||
# Create a number kernel image with zeroes
|
||||
head -c 5000 /dev/zero >test-kernel.bin
|
||||
|
||||
# Build the FIT, but don't sign anything yet
|
||||
echo Build FIT with signed images
|
||||
${mkimage} -D "${dtc}" -f sign-images.its test.fit >${tmp}
|
||||
# Build the FIT, but don't sign anything yet
|
||||
echo Build FIT with signed images
|
||||
${mkimage} -D "${dtc}" -f sign-images-$sha.its test.fit >${tmp}
|
||||
|
||||
run_uboot "unsigned signatures:" "dev-"
|
||||
run_uboot "unsigned signatures:" "dev-"
|
||||
|
||||
# Sign images with our dev keys
|
||||
echo Sign images
|
||||
${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb -r test.fit >${tmp}
|
||||
# Sign images with our dev keys
|
||||
echo Sign images
|
||||
${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb \
|
||||
-r test.fit >${tmp}
|
||||
|
||||
run_uboot "signed images" "dev+"
|
||||
run_uboot "signed images" "dev+"
|
||||
|
||||
|
||||
# Create a fresh .dtb without the public keys
|
||||
dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
|
||||
# Create a fresh .dtb without the public keys
|
||||
dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
|
||||
|
||||
echo Build FIT with signed configuration
|
||||
${mkimage} -D "${dtc}" -f sign-configs.its test.fit >${tmp}
|
||||
echo Build FIT with signed configuration
|
||||
${mkimage} -D "${dtc}" -f sign-configs-$sha.its test.fit >${tmp}
|
||||
|
||||
run_uboot "unsigned config" "sha1+ OK"
|
||||
run_uboot "unsigned config" $sha"+ OK"
|
||||
|
||||
# Sign images with our dev keys
|
||||
echo Sign images
|
||||
${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb -r test.fit >${tmp}
|
||||
# Sign images with our dev keys
|
||||
echo Sign images
|
||||
${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb \
|
||||
-r test.fit >${tmp}
|
||||
|
||||
run_uboot "signed config" "dev+"
|
||||
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)))
|
||||
sig="${newbyte} ${sig:2}"
|
||||
fdtput -t bx test.fit /configurations/conf@1/signature@1 value ${sig}
|
||||
# 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)))
|
||||
sig="${newbyte} ${sig:2}"
|
||||
fdtput -t bx test.fit /configurations/conf@1/signature@1 value ${sig}
|
||||
|
||||
run_uboot "signed config with bad hash" "Bad Data Hash"
|
||||
run_uboot "signed config with bad hash" "Bad Data Hash"
|
||||
}
|
||||
|
||||
sha=sha1
|
||||
do_test
|
||||
sha=sha256
|
||||
do_test
|
||||
|
||||
popd >/dev/null
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user