diff mbox

[U-Boot,v2,6/8] gen: Add progressive hash API

Message ID 1391924096-13253-7-git-send-email-hs@denx.de
State Deferred
Delegated to: Tom Rini
Headers show

Commit Message

Heiko Schocher Feb. 9, 2014, 5:34 a.m. UTC
From: Hung-ying Tyan <tyanh@chromium.org>

Add hash_init(), hash_update() and hash_finish() to the
hash_algo struct. Add hash_lookup_algo() to look up the
struct given an algorithm name.

Signed-off-by: Hung-ying Tyan <tyanh@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Heiko Schocher <hs@denx.de>

---
changes for v2:
- new in v2

 common/hash.c  | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++------
 include/hash.h |  48 ++++++++++++++++++++++++
 2 files changed, 153 insertions(+), 11 deletions(-)

Comments

Simon Glass Feb. 15, 2014, 11:14 p.m. UTC | #1
Hi Heiko,

On 8 February 2014 22:34, Heiko Schocher <hs@denx.de> wrote:
> From: Hung-ying Tyan <tyanh@chromium.org>
>
> Add hash_init(), hash_update() and hash_finish() to the
> hash_algo struct. Add hash_lookup_algo() to look up the
> struct given an algorithm name.
>
> Signed-off-by: Hung-ying Tyan <tyanh@chromium.org>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Heiko Schocher <hs@denx.de>

Acked-by: Simon Glass <sjg@chromium.org>

I think this is crying out for another patch - an integration to get
rid of lib/rsa/rsa-checksum.c. You should be able to look up the hash
algorithm name using the hash.h file and get the pad length, etc. from
that. Then you can call this progressive hashing API instead of adding
new code in lib/rsa/rsa-checksum.c.

There may be a catch, but I can't see one at present.

Regards,
Simon
diff mbox

Patch

diff --git a/common/hash.c b/common/hash.c
index 872cd85..7627b84 100644
--- a/common/hash.c
+++ b/common/hash.c
@@ -12,6 +12,7 @@ 
 
 #include <common.h>
 #include <command.h>
+#include <malloc.h>
 #include <hw_sha.h>
 #include <hash.h>
 #include <sha1.h>
@@ -19,6 +20,88 @@ 
 #include <asm/io.h>
 #include <asm/errno.h>
 
+#ifdef CONFIG_CMD_SHA1SUM
+static int hash_init_sha1(struct hash_algo *algo, void **ctxp)
+{
+	sha1_context *ctx = malloc(sizeof(sha1_context));
+	sha1_starts(ctx);
+	*ctxp = ctx;
+	return 0;
+}
+
+static int hash_update_sha1(struct hash_algo *algo, void *ctx, const void *buf,
+			    unsigned int size, int is_last)
+{
+	sha1_update((sha1_context *)ctx, buf, size);
+	return 0;
+}
+
+static int hash_finish_sha1(struct hash_algo *algo, void *ctx, void *dest_buf,
+			    int size)
+{
+	if (size < algo->digest_size)
+		return -1;
+
+	sha1_finish((sha1_context *)ctx, dest_buf);
+	free(ctx);
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_SHA256
+static int hash_init_sha256(struct hash_algo *algo, void **ctxp)
+{
+	sha256_context *ctx = malloc(sizeof(sha256_context));
+	sha256_starts(ctx);
+	*ctxp = ctx;
+	return 0;
+}
+
+static int hash_update_sha256(struct hash_algo *algo, void *ctx,
+			      const void *buf, unsigned int size, int is_last)
+{
+	sha256_update((sha256_context *)ctx, buf, size);
+	return 0;
+}
+
+static int hash_finish_sha256(struct hash_algo *algo, void *ctx, void
+			      *dest_buf, int size)
+{
+	if (size < algo->digest_size)
+		return -1;
+
+	sha256_finish((sha256_context *)ctx, dest_buf);
+	free(ctx);
+	return 0;
+}
+#endif
+
+static int hash_init_crc32(struct hash_algo *algo, void **ctxp)
+{
+	uint32_t *ctx = malloc(sizeof(uint32_t));
+	*ctx = 0;
+	*ctxp = ctx;
+	return 0;
+}
+
+static int hash_update_crc32(struct hash_algo *algo, void *ctx,
+			     const void *buf, unsigned int size, int is_last)
+{
+	*((uint32_t *)ctx) = crc32(*((uint32_t *)ctx), buf, size);
+	return 0;
+}
+
+static int hash_finish_crc32(struct hash_algo *algo, void *ctx, void *dest_buf,
+			     int size)
+{
+	if (size < algo->digest_size)
+		return -1;
+
+	*((uint32_t *)dest_buf) = *((uint32_t *)ctx);
+	free(ctx);
+	return 0;
+}
+
 /*
  * These are the hash algorithms we support. Chips which support accelerated
  * crypto could perhaps add named version of these algorithms here. Note that
@@ -53,6 +136,9 @@  static struct hash_algo hash_algo[] = {
 		SHA1_SUM_LEN,
 		sha1_csum_wd,
 		CHUNKSZ_SHA1,
+		hash_init_sha1,
+		hash_update_sha1,
+		hash_finish_sha1,
 	},
 #define MULTI_HASH
 #endif
@@ -62,6 +148,9 @@  static struct hash_algo hash_algo[] = {
 		SHA256_SUM_LEN,
 		sha256_csum_wd,
 		CHUNKSZ_SHA256,
+		hash_init_sha256,
+		hash_update_sha256,
+		hash_finish_sha256,
 	},
 #define MULTI_HASH
 #endif
@@ -70,6 +159,9 @@  static struct hash_algo hash_algo[] = {
 		4,
 		crc32_wd_buf,
 		CHUNKSZ_CRC32,
+		hash_init_crc32,
+		hash_update_crc32,
+		hash_finish_crc32,
 	},
 };
 
@@ -204,16 +296,19 @@  static int parse_verify_sum(struct hash_algo *algo, char *verify_str, u8 *vsum,
 	return 0;
 }
 
-static struct hash_algo *find_hash_algo(const char *name)
+int hash_lookup_algo(const char *algo_name, struct hash_algo **algop)
 {
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
-		if (!strcmp(name, hash_algo[i].name))
-			return &hash_algo[i];
+		if (!strcmp(algo_name, hash_algo[i].name)) {
+			*algop = &hash_algo[i];
+			return 0;
+		}
 	}
 
-	return NULL;
+	debug("Unknown hash algorithm '%s'\n", algo_name);
+	return -EPROTONOSUPPORT;
 }
 
 static void show_hash(struct hash_algo *algo, ulong addr, ulong len,
@@ -230,12 +325,12 @@  int hash_block(const char *algo_name, const void *data, unsigned int len,
 	       uint8_t *output, int *output_size)
 {
 	struct hash_algo *algo;
+	int ret;
+
+	ret = hash_lookup_algo(algo_name, &algo);
+	if (ret)
+		return ret;
 
-	algo = find_hash_algo(algo_name);
-	if (!algo) {
-		debug("Unknown hash algorithm '%s'\n", algo_name);
-		return -EPROTONOSUPPORT;
-	}
 	if (output_size && *output_size < algo->digest_size) {
 		debug("Output buffer size %d too small (need %d bytes)",
 		      *output_size, algo->digest_size);
@@ -265,8 +360,7 @@  int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
 		u8 vsum[HASH_MAX_DIGEST_SIZE];
 		void *buf;
 
-		algo = find_hash_algo(algo_name);
-		if (!algo) {
+		if (hash_lookup_algo(algo_name, &algo)) {
 			printf("Unknown hash algorithm '%s'\n", algo_name);
 			return CMD_RET_USAGE;
 		}
diff --git a/include/hash.h b/include/hash.h
index e92d272..dc21678 100644
--- a/include/hash.h
+++ b/include/hash.h
@@ -27,6 +27,42 @@  struct hash_algo {
 	void (*hash_func_ws)(const unsigned char *input, unsigned int ilen,
 		unsigned char *output, unsigned int chunk_sz);
 	int chunk_size;				/* Watchdog chunk size */
+	/*
+	 * hash_init: Create the context for progressive hashing
+	 *
+	 * @algo: Pointer to the hash_algo struct
+	 * @ctxp: Pointer to the pointer of the context for hashing
+	 * @return 0 if ok, -1 on error
+	 */
+	int (*hash_init)(struct hash_algo *algo, void **ctxp);
+	/*
+	 * hash_update: Perform hashing on the given buffer
+	 *
+	 * The context is freed by this function if an error occurs.
+	 *
+	 * @algo: Pointer to the hash_algo struct
+	 * @ctx: Pointer to the context for hashing
+	 * @buf: Pointer to the buffer being hashed
+	 * @size: Size of the buffer being hashed
+	 * @is_last: 1 if this is the last update; 0 otherwise
+	 * @return 0 if ok, -1 on error
+	 */
+	int (*hash_update)(struct hash_algo *algo, void *ctx, const void *buf,
+			   unsigned int size, int is_last);
+	/*
+	 * hash_finish: Write the hash result to the given buffer
+	 *
+	 * The context is freed by this function.
+	 *
+	 * @algo: Pointer to the hash_algo struct
+	 * @ctx: Pointer to the context for hashing
+	 * @dest_buf: Pointer to the buffer for the result
+	 * @size: Size of the buffer for the result
+	 * @return 0 if ok, -ENOSPC if size of the result buffer is too small
+	 *   or -1 on other errors
+	 */
+	int (*hash_finish)(struct hash_algo *algo, void *ctx, void *dest_buf,
+			   int size);
 };
 
 /*
@@ -77,4 +113,16 @@  int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
 int hash_block(const char *algo_name, const void *data, unsigned int len,
 	       uint8_t *output, int *output_size);
 
+/**
+ * hash_lookup_algo() - Look up the hash_algo struct for an algorithm
+ *
+ * The function returns the pointer to the struct or -EPROTONOSUPPORT if the
+ * algorithm is not available.
+ *
+ * @algo_name: Hash algorithm to look up
+ * @algop: Pointer to the hash_algo struct if found
+ *
+ * @return 0 if ok, -EPROTONOSUPPORT for an unknown algorithm.
+ */
+int hash_lookup_algo(const char *algo_name, struct hash_algo **algop);
 #endif