Skip to content

Commit

Permalink
lib: Add support for ECDSA image signing
Browse files Browse the repository at this point in the history
mkimage supports rsa2048, and rsa4096 signatures. With newer silicon
now supporting hardware-accelerated ECDSA, it makes sense to expand
signing support to elliptic curves.

Implement host-side ECDSA signing and verification with libcrypto.
Device-side implementation of signature verification is beyond the
scope of this patch.

Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
  • Loading branch information
mrnuke committed Feb 4, 2021
1 parent 5ab755d commit a2ae016
Show file tree
Hide file tree
Showing 5 changed files with 415 additions and 2 deletions.
11 changes: 9 additions & 2 deletions common/image-sig.c
Expand Up @@ -15,6 +15,7 @@
DECLARE_GLOBAL_DATA_PTR;
#endif /* !USE_HOSTCC*/
#include <image.h>
#include <u-boot/ecdsa.h>
#include <u-boot/rsa.h>
#include <u-boot/hash-checksum.h>

Expand Down Expand Up @@ -82,8 +83,14 @@ struct crypto_algo crypto_algos[] = {
.sign = rsa_sign,
.add_verify_data = rsa_add_verify_data,
.verify = rsa_verify,
}

},
{
.name = "ecdsa256",
.key_len = ECDSA256_BYTES,
.sign = ecdsa_sign,
.add_verify_data = ecdsa_add_verify_data,
.verify = ecdsa_verify,
},
};

struct padding_algo padding_algos[] = {
Expand Down
3 changes: 3 additions & 0 deletions include/image.h
Expand Up @@ -1200,16 +1200,19 @@ int calculate_hash(const void *data, int data_len, const char *algo,
# if defined(CONFIG_FIT_SIGNATURE)
# define IMAGE_ENABLE_SIGN 1
# define IMAGE_ENABLE_VERIFY 1
# define IMAGE_ENABLE_VERIFY_ECDSA 1
# define FIT_IMAGE_ENABLE_VERIFY 1
# include <openssl/evp.h>
# else
# define IMAGE_ENABLE_SIGN 0
# define IMAGE_ENABLE_VERIFY 0
# define IMAGE_ENABLE_VERIFY_ECDSA 0
# define FIT_IMAGE_ENABLE_VERIFY 0
# endif
#else
# define IMAGE_ENABLE_SIGN 0
# define IMAGE_ENABLE_VERIFY CONFIG_IS_ENABLED(RSA_VERIFY)
# define IMAGE_ENABLE_VERIFY_ECDSA 0
# define FIT_IMAGE_ENABLE_VERIFY CONFIG_IS_ENABLED(FIT_SIGNATURE)
#endif

Expand Down
94 changes: 94 additions & 0 deletions include/u-boot/ecdsa.h
@@ -0,0 +1,94 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 2020, Alexandru Gagniuc <mr.nuke.me@gmail.com>.
*/

#ifndef _ECDSA_H
#define _ECDSA_H

#include <errno.h>
#include <image.h>
#include <linux/kconfig.h>

/**
* crypto_algo API impementation for ECDSA;
* @see "struct crypto_algo"
* @{
*/
#if IMAGE_ENABLE_SIGN
/**
* sign() - calculate and return signature for given input data
*
* @info: Specifies key and FIT information
* @data: Pointer to the input data
* @data_len: Data length
* @sigp: Set to an allocated buffer holding the signature
* @sig_len: Set to length of the calculated hash
*
* This computes input data signature according to selected algorithm.
* Resulting signature value is placed in an allocated buffer, the
* pointer is returned as *sigp. The length of the calculated
* signature is returned via the sig_len pointer argument. The caller
* should free *sigp.
*
* @return: 0, on success, -ve on error
*/
int ecdsa_sign(struct image_sign_info *info, const struct image_region region[],
int region_count, uint8_t **sigp, uint *sig_len);

/**
* add_verify_data() - Add verification information to FDT
*
* Add public key information to the FDT node, suitable for
* verification at run-time. The information added depends on the
* algorithm being used. I just copypasted this from rsa.h.
*
* @info: Specifies key and FIT information
* @keydest: Destination FDT blob for public key data
* @return: 0, on success, -ENOSPC if the keydest FDT blob ran out of space,
* other -ve value on error
*/
int ecdsa_add_verify_data(struct image_sign_info *info, void *keydest);
#else
static inline
int ecdsa_sign(struct image_sign_info *info, const struct image_region region[],
int region_count, uint8_t **sigp, uint *sig_len)
{
return -ENXIO;
}

static inline
int ecdsa_add_verify_data(struct image_sign_info *info, void *keydest)
{
return -ENXIO;
}
#endif

#if IMAGE_ENABLE_VERIFY_ECDSA
/**
* verify() - Verify a signature against some data
*
* @info: Specifies key and FIT information
* @data: Pointer to the input data
* @data_len: Data length
* @sig: Signature
* @sig_len: Number of bytes in signature
* @return 0 if verified, -ve on error
*/
int ecdsa_verify(struct image_sign_info *info,
const struct image_region region[], int region_count,
uint8_t *sig, uint sig_len);
#else
static inline
int ecdsa_verify(struct image_sign_info *info,
const struct image_region region[], int region_count,
uint8_t *sig, uint sig_len)
{
return -ENXIO;
}
#endif
/** @} */

#define ECDSA256_BYTES (256 / 8)

#endif

0 comments on commit a2ae016

Please sign in to comment.