Commit bf007ebb6f4b01af675782d23bacbddd17e1a627
Committed by
Tom Rini
1 parent
db1b5f3d20
Exists in
v2017.01-smarct4x
and in
40 other branches
gen: Add progressive hash API
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>
Showing 2 changed files with 153 additions and 11 deletions Side-by-side Diff
common/hash.c
... | ... | @@ -12,6 +12,7 @@ |
12 | 12 | |
13 | 13 | #include <common.h> |
14 | 14 | #include <command.h> |
15 | +#include <malloc.h> | |
15 | 16 | #include <hw_sha.h> |
16 | 17 | #include <hash.h> |
17 | 18 | #include <sha1.h> |
... | ... | @@ -19,6 +20,88 @@ |
19 | 20 | #include <asm/io.h> |
20 | 21 | #include <asm/errno.h> |
21 | 22 | |
23 | +#ifdef CONFIG_CMD_SHA1SUM | |
24 | +static int hash_init_sha1(struct hash_algo *algo, void **ctxp) | |
25 | +{ | |
26 | + sha1_context *ctx = malloc(sizeof(sha1_context)); | |
27 | + sha1_starts(ctx); | |
28 | + *ctxp = ctx; | |
29 | + return 0; | |
30 | +} | |
31 | + | |
32 | +static int hash_update_sha1(struct hash_algo *algo, void *ctx, const void *buf, | |
33 | + unsigned int size, int is_last) | |
34 | +{ | |
35 | + sha1_update((sha1_context *)ctx, buf, size); | |
36 | + return 0; | |
37 | +} | |
38 | + | |
39 | +static int hash_finish_sha1(struct hash_algo *algo, void *ctx, void *dest_buf, | |
40 | + int size) | |
41 | +{ | |
42 | + if (size < algo->digest_size) | |
43 | + return -1; | |
44 | + | |
45 | + sha1_finish((sha1_context *)ctx, dest_buf); | |
46 | + free(ctx); | |
47 | + return 0; | |
48 | +} | |
49 | +#endif | |
50 | + | |
51 | +#ifdef CONFIG_SHA256 | |
52 | +static int hash_init_sha256(struct hash_algo *algo, void **ctxp) | |
53 | +{ | |
54 | + sha256_context *ctx = malloc(sizeof(sha256_context)); | |
55 | + sha256_starts(ctx); | |
56 | + *ctxp = ctx; | |
57 | + return 0; | |
58 | +} | |
59 | + | |
60 | +static int hash_update_sha256(struct hash_algo *algo, void *ctx, | |
61 | + const void *buf, unsigned int size, int is_last) | |
62 | +{ | |
63 | + sha256_update((sha256_context *)ctx, buf, size); | |
64 | + return 0; | |
65 | +} | |
66 | + | |
67 | +static int hash_finish_sha256(struct hash_algo *algo, void *ctx, void | |
68 | + *dest_buf, int size) | |
69 | +{ | |
70 | + if (size < algo->digest_size) | |
71 | + return -1; | |
72 | + | |
73 | + sha256_finish((sha256_context *)ctx, dest_buf); | |
74 | + free(ctx); | |
75 | + return 0; | |
76 | +} | |
77 | +#endif | |
78 | + | |
79 | +static int hash_init_crc32(struct hash_algo *algo, void **ctxp) | |
80 | +{ | |
81 | + uint32_t *ctx = malloc(sizeof(uint32_t)); | |
82 | + *ctx = 0; | |
83 | + *ctxp = ctx; | |
84 | + return 0; | |
85 | +} | |
86 | + | |
87 | +static int hash_update_crc32(struct hash_algo *algo, void *ctx, | |
88 | + const void *buf, unsigned int size, int is_last) | |
89 | +{ | |
90 | + *((uint32_t *)ctx) = crc32(*((uint32_t *)ctx), buf, size); | |
91 | + return 0; | |
92 | +} | |
93 | + | |
94 | +static int hash_finish_crc32(struct hash_algo *algo, void *ctx, void *dest_buf, | |
95 | + int size) | |
96 | +{ | |
97 | + if (size < algo->digest_size) | |
98 | + return -1; | |
99 | + | |
100 | + *((uint32_t *)dest_buf) = *((uint32_t *)ctx); | |
101 | + free(ctx); | |
102 | + return 0; | |
103 | +} | |
104 | + | |
22 | 105 | /* |
23 | 106 | * These are the hash algorithms we support. Chips which support accelerated |
24 | 107 | * crypto could perhaps add named version of these algorithms here. Note that |
... | ... | @@ -53,6 +136,9 @@ |
53 | 136 | SHA1_SUM_LEN, |
54 | 137 | sha1_csum_wd, |
55 | 138 | CHUNKSZ_SHA1, |
139 | + hash_init_sha1, | |
140 | + hash_update_sha1, | |
141 | + hash_finish_sha1, | |
56 | 142 | }, |
57 | 143 | #define MULTI_HASH |
58 | 144 | #endif |
... | ... | @@ -62,6 +148,9 @@ |
62 | 148 | SHA256_SUM_LEN, |
63 | 149 | sha256_csum_wd, |
64 | 150 | CHUNKSZ_SHA256, |
151 | + hash_init_sha256, | |
152 | + hash_update_sha256, | |
153 | + hash_finish_sha256, | |
65 | 154 | }, |
66 | 155 | #define MULTI_HASH |
67 | 156 | #endif |
... | ... | @@ -70,6 +159,9 @@ |
70 | 159 | 4, |
71 | 160 | crc32_wd_buf, |
72 | 161 | CHUNKSZ_CRC32, |
162 | + hash_init_crc32, | |
163 | + hash_update_crc32, | |
164 | + hash_finish_crc32, | |
73 | 165 | }, |
74 | 166 | }; |
75 | 167 | |
76 | 168 | |
77 | 169 | |
... | ... | @@ -204,16 +296,19 @@ |
204 | 296 | return 0; |
205 | 297 | } |
206 | 298 | |
207 | -static struct hash_algo *find_hash_algo(const char *name) | |
299 | +int hash_lookup_algo(const char *algo_name, struct hash_algo **algop) | |
208 | 300 | { |
209 | 301 | int i; |
210 | 302 | |
211 | 303 | for (i = 0; i < ARRAY_SIZE(hash_algo); i++) { |
212 | - if (!strcmp(name, hash_algo[i].name)) | |
213 | - return &hash_algo[i]; | |
304 | + if (!strcmp(algo_name, hash_algo[i].name)) { | |
305 | + *algop = &hash_algo[i]; | |
306 | + return 0; | |
307 | + } | |
214 | 308 | } |
215 | 309 | |
216 | - return NULL; | |
310 | + debug("Unknown hash algorithm '%s'\n", algo_name); | |
311 | + return -EPROTONOSUPPORT; | |
217 | 312 | } |
218 | 313 | |
219 | 314 | static void show_hash(struct hash_algo *algo, ulong addr, ulong len, |
220 | 315 | |
... | ... | @@ -230,12 +325,12 @@ |
230 | 325 | uint8_t *output, int *output_size) |
231 | 326 | { |
232 | 327 | struct hash_algo *algo; |
328 | + int ret; | |
233 | 329 | |
234 | - algo = find_hash_algo(algo_name); | |
235 | - if (!algo) { | |
236 | - debug("Unknown hash algorithm '%s'\n", algo_name); | |
237 | - return -EPROTONOSUPPORT; | |
238 | - } | |
330 | + ret = hash_lookup_algo(algo_name, &algo); | |
331 | + if (ret) | |
332 | + return ret; | |
333 | + | |
239 | 334 | if (output_size && *output_size < algo->digest_size) { |
240 | 335 | debug("Output buffer size %d too small (need %d bytes)", |
241 | 336 | *output_size, algo->digest_size); |
... | ... | @@ -265,8 +360,7 @@ |
265 | 360 | u8 vsum[HASH_MAX_DIGEST_SIZE]; |
266 | 361 | void *buf; |
267 | 362 | |
268 | - algo = find_hash_algo(algo_name); | |
269 | - if (!algo) { | |
363 | + if (hash_lookup_algo(algo_name, &algo)) { | |
270 | 364 | printf("Unknown hash algorithm '%s'\n", algo_name); |
271 | 365 | return CMD_RET_USAGE; |
272 | 366 | } |
include/hash.h
... | ... | @@ -27,6 +27,42 @@ |
27 | 27 | void (*hash_func_ws)(const unsigned char *input, unsigned int ilen, |
28 | 28 | unsigned char *output, unsigned int chunk_sz); |
29 | 29 | int chunk_size; /* Watchdog chunk size */ |
30 | + /* | |
31 | + * hash_init: Create the context for progressive hashing | |
32 | + * | |
33 | + * @algo: Pointer to the hash_algo struct | |
34 | + * @ctxp: Pointer to the pointer of the context for hashing | |
35 | + * @return 0 if ok, -1 on error | |
36 | + */ | |
37 | + int (*hash_init)(struct hash_algo *algo, void **ctxp); | |
38 | + /* | |
39 | + * hash_update: Perform hashing on the given buffer | |
40 | + * | |
41 | + * The context is freed by this function if an error occurs. | |
42 | + * | |
43 | + * @algo: Pointer to the hash_algo struct | |
44 | + * @ctx: Pointer to the context for hashing | |
45 | + * @buf: Pointer to the buffer being hashed | |
46 | + * @size: Size of the buffer being hashed | |
47 | + * @is_last: 1 if this is the last update; 0 otherwise | |
48 | + * @return 0 if ok, -1 on error | |
49 | + */ | |
50 | + int (*hash_update)(struct hash_algo *algo, void *ctx, const void *buf, | |
51 | + unsigned int size, int is_last); | |
52 | + /* | |
53 | + * hash_finish: Write the hash result to the given buffer | |
54 | + * | |
55 | + * The context is freed by this function. | |
56 | + * | |
57 | + * @algo: Pointer to the hash_algo struct | |
58 | + * @ctx: Pointer to the context for hashing | |
59 | + * @dest_buf: Pointer to the buffer for the result | |
60 | + * @size: Size of the buffer for the result | |
61 | + * @return 0 if ok, -ENOSPC if size of the result buffer is too small | |
62 | + * or -1 on other errors | |
63 | + */ | |
64 | + int (*hash_finish)(struct hash_algo *algo, void *ctx, void *dest_buf, | |
65 | + int size); | |
30 | 66 | }; |
31 | 67 | |
32 | 68 | /* |
... | ... | @@ -77,5 +113,17 @@ |
77 | 113 | int hash_block(const char *algo_name, const void *data, unsigned int len, |
78 | 114 | uint8_t *output, int *output_size); |
79 | 115 | |
116 | +/** | |
117 | + * hash_lookup_algo() - Look up the hash_algo struct for an algorithm | |
118 | + * | |
119 | + * The function returns the pointer to the struct or -EPROTONOSUPPORT if the | |
120 | + * algorithm is not available. | |
121 | + * | |
122 | + * @algo_name: Hash algorithm to look up | |
123 | + * @algop: Pointer to the hash_algo struct if found | |
124 | + * | |
125 | + * @return 0 if ok, -EPROTONOSUPPORT for an unknown algorithm. | |
126 | + */ | |
127 | +int hash_lookup_algo(const char *algo_name, struct hash_algo **algop); | |
80 | 128 | #endif |