]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/hash.c
omap3: remove remnant macros GPMC_NAND_ECC_LP_x8_LAYOUT and GPMC_NAND_ECC_LP_x16_LAYOUT
[karo-tx-uboot.git] / common / hash.c
index ef6fe375d289edcfd313c0d65eaf10efe8e5cf0f..7627b84b451421a599f378511eccd71639e450fe 100644 (file)
  * (C) Copyright 2000
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
 #include <command.h>
+#include <malloc.h>
+#include <hw_sha.h>
 #include <hash.h>
 #include <sha1.h>
 #include <sha256.h>
+#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.
+ * crypto could perhaps add named version of these algorithms here. Note that
+ * algorithm names must be in lower case.
  */
 static struct hash_algo hash_algo[] = {
+       /*
+        * CONFIG_SHA_HW_ACCEL is defined if hardware acceleration is
+        * available.
+        */
+#ifdef CONFIG_SHA_HW_ACCEL
+       {
+               "sha1",
+               SHA1_SUM_LEN,
+               hw_sha1,
+               CHUNKSZ_SHA1,
+       }, {
+               "sha256",
+               SHA256_SUM_LEN,
+               hw_sha256,
+               CHUNKSZ_SHA256,
+       },
+#endif
        /*
         * This is CONFIG_CMD_SHA1SUM instead of CONFIG_SHA1 since otherwise
         * it bloats the code for boards which use SHA1 but not the 'hash'
@@ -41,27 +132,36 @@ static struct hash_algo hash_algo[] = {
         */
 #ifdef CONFIG_CMD_SHA1SUM
        {
-               "SHA1",
+               "sha1",
                SHA1_SUM_LEN,
                sha1_csum_wd,
                CHUNKSZ_SHA1,
+               hash_init_sha1,
+               hash_update_sha1,
+               hash_finish_sha1,
        },
 #define MULTI_HASH
 #endif
 #ifdef CONFIG_SHA256
        {
-               "SHA256",
+               "sha256",
                SHA256_SUM_LEN,
                sha256_csum_wd,
                CHUNKSZ_SHA256,
+               hash_init_sha256,
+               hash_update_sha256,
+               hash_finish_sha256,
        },
 #define MULTI_HASH
 #endif
        {
-               "CRC32",
+               "crc32",
                4,
                crc32_wd_buf,
                CHUNKSZ_CRC32,
+               hash_init_crc32,
+               hash_update_crc32,
+               hash_finish_crc32,
        },
 };
 
@@ -117,10 +217,13 @@ static void store_result(struct hash_algo *algo, const u8 *sum,
                str_ptr = '\0';
                setenv(dest, str_output);
        } else {
-               u8 *ptr;
+               ulong addr;
+               void *buf;
 
-               ptr = (u8 *)simple_strtoul(dest, NULL, 16);
-               memcpy(ptr, sum, algo->digest_size);
+               addr = simple_strtoul(dest, NULL, 16);
+               buf = map_sysmem(addr, algo->digest_size);
+               memcpy(buf, sum, algo->digest_size);
+               unmap_sysmem(buf);
        }
 }
 
@@ -154,10 +257,12 @@ static int parse_verify_sum(struct hash_algo *algo, char *verify_str, u8 *vsum,
        }
 
        if (env_var) {
-               u8 *ptr;
+               ulong addr;
+               void *buf;
 
-               ptr = (u8 *)simple_strtoul(verify_str, NULL, 16);
-               memcpy(vsum, ptr, algo->digest_size);
+               addr = simple_strtoul(verify_str, NULL, 16);
+               buf = map_sysmem(addr, algo->digest_size);
+               memcpy(vsum, buf, algo->digest_size);
        } else {
                unsigned int i;
                char *vsum_str;
@@ -191,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 (!strcasecmp(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,
@@ -213,6 +321,28 @@ static void show_hash(struct hash_algo *algo, ulong addr, ulong len,
                printf("%02x", output[i]);
 }
 
+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;
+
+       if (output_size && *output_size < algo->digest_size) {
+               debug("Output buffer size %d too small (need %d bytes)",
+                     *output_size, algo->digest_size);
+               return -ENOSPC;
+       }
+       if (output_size)
+               *output_size = algo->digest_size;
+       algo->hash_func_ws(data, len, output, algo->chunk_size);
+
+       return 0;
+}
+
 int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
                 int argc, char * const argv[])
 {
@@ -228,9 +358,9 @@ int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
                struct hash_algo *algo;
                u8 output[HASH_MAX_DIGEST_SIZE];
                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;
                }
@@ -241,8 +371,9 @@ int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
                        return 1;
                }
 
-               algo->hash_func_ws((const unsigned char *)addr, len, output,
-                                  algo->chunk_size);
+               buf = map_sysmem(addr, len);
+               algo->hash_func_ws(buf, len, output, algo->chunk_size);
+               unmap_sysmem(buf);
 
                /* Try to avoid code bloat when verify is not needed */
 #ifdef CONFIG_HASH_VERIFY
@@ -288,8 +419,8 @@ int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
                printf("CRC32 for %08lx ... %08lx ==> %08lx\n",
                                addr, addr + len - 1, crc);
 
-               if (argc > 3) {
-                       ptr = (ulong *)simple_strtoul(argv[3], NULL, 16);
+               if (argc >= 3) {
+                       ptr = (ulong *)simple_strtoul(argv[0], NULL, 16);
                        *ptr = crc;
                }
        }