Commit d7af2baa49c60c097d77986f49d7c2db06080c8e
Committed by
York Sun
1 parent
6d48d1c4b4
Exists in
smarc_8mq_lf_v2020.04
and in
17 other branches
crypto/fsl: Fix HW accelerated hash commands
The hash command function were not flushing the dcache before passing data to CAAM/DMA and not invalidating the dcache when getting data back. Due the data cache incoherency, HW accelerated hash commands used to fail with CAAM errors like "Invalid KEY Command". Check if pbuf and pout buffers are properly aligned to the cache line size and flush/invalidate the memory regions to address this issue. This solution is based in a previous work from Clemens Gruber in commit 598e9dccc75d ("crypto/fsl: fix BLOB encapsulation and decapsulation") Reported-by: Anatolij Gustschin <agust@denx.de> Signed-off-by: Breno Lima <breno.lima@nxp.com> Reviewed-by: York Sun <york.sun@nxp.com>
Showing 2 changed files with 25 additions and 2 deletions Inline Diff
common/hash.c
1 | /* | 1 | /* |
2 | * Copyright (c) 2012 The Chromium OS Authors. | 2 | * Copyright (c) 2012 The Chromium OS Authors. |
3 | * | 3 | * |
4 | * (C) Copyright 2011 | 4 | * (C) Copyright 2011 |
5 | * Joe Hershberger, National Instruments, joe.hershberger@ni.com | 5 | * Joe Hershberger, National Instruments, joe.hershberger@ni.com |
6 | * | 6 | * |
7 | * (C) Copyright 2000 | 7 | * (C) Copyright 2000 |
8 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | 8 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
9 | * | 9 | * |
10 | * SPDX-License-Identifier: GPL-2.0+ | 10 | * SPDX-License-Identifier: GPL-2.0+ |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #ifndef USE_HOSTCC | 13 | #ifndef USE_HOSTCC |
14 | #include <common.h> | 14 | #include <common.h> |
15 | #include <command.h> | 15 | #include <command.h> |
16 | #include <malloc.h> | 16 | #include <malloc.h> |
17 | #include <mapmem.h> | 17 | #include <mapmem.h> |
18 | #include <hw_sha.h> | 18 | #include <hw_sha.h> |
19 | #include <asm/io.h> | 19 | #include <asm/io.h> |
20 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
21 | #else | 21 | #else |
22 | #include "mkimage.h" | 22 | #include "mkimage.h" |
23 | #include <time.h> | 23 | #include <time.h> |
24 | #include <image.h> | 24 | #include <image.h> |
25 | #endif /* !USE_HOSTCC*/ | 25 | #endif /* !USE_HOSTCC*/ |
26 | 26 | ||
27 | #include <hash.h> | 27 | #include <hash.h> |
28 | #include <u-boot/crc.h> | 28 | #include <u-boot/crc.h> |
29 | #include <u-boot/sha1.h> | 29 | #include <u-boot/sha1.h> |
30 | #include <u-boot/sha256.h> | 30 | #include <u-boot/sha256.h> |
31 | #include <u-boot/md5.h> | 31 | #include <u-boot/md5.h> |
32 | 32 | ||
33 | #if defined(CONFIG_SHA1) && !defined(CONFIG_SHA_PROG_HW_ACCEL) | 33 | #if defined(CONFIG_SHA1) && !defined(CONFIG_SHA_PROG_HW_ACCEL) |
34 | static int hash_init_sha1(struct hash_algo *algo, void **ctxp) | 34 | static int hash_init_sha1(struct hash_algo *algo, void **ctxp) |
35 | { | 35 | { |
36 | sha1_context *ctx = malloc(sizeof(sha1_context)); | 36 | sha1_context *ctx = malloc(sizeof(sha1_context)); |
37 | sha1_starts(ctx); | 37 | sha1_starts(ctx); |
38 | *ctxp = ctx; | 38 | *ctxp = ctx; |
39 | return 0; | 39 | return 0; |
40 | } | 40 | } |
41 | 41 | ||
42 | static int hash_update_sha1(struct hash_algo *algo, void *ctx, const void *buf, | 42 | static int hash_update_sha1(struct hash_algo *algo, void *ctx, const void *buf, |
43 | unsigned int size, int is_last) | 43 | unsigned int size, int is_last) |
44 | { | 44 | { |
45 | sha1_update((sha1_context *)ctx, buf, size); | 45 | sha1_update((sha1_context *)ctx, buf, size); |
46 | return 0; | 46 | return 0; |
47 | } | 47 | } |
48 | 48 | ||
49 | static int hash_finish_sha1(struct hash_algo *algo, void *ctx, void *dest_buf, | 49 | static int hash_finish_sha1(struct hash_algo *algo, void *ctx, void *dest_buf, |
50 | int size) | 50 | int size) |
51 | { | 51 | { |
52 | if (size < algo->digest_size) | 52 | if (size < algo->digest_size) |
53 | return -1; | 53 | return -1; |
54 | 54 | ||
55 | sha1_finish((sha1_context *)ctx, dest_buf); | 55 | sha1_finish((sha1_context *)ctx, dest_buf); |
56 | free(ctx); | 56 | free(ctx); |
57 | return 0; | 57 | return 0; |
58 | } | 58 | } |
59 | #endif | 59 | #endif |
60 | 60 | ||
61 | #if defined(CONFIG_SHA256) && !defined(CONFIG_SHA_PROG_HW_ACCEL) | 61 | #if defined(CONFIG_SHA256) && !defined(CONFIG_SHA_PROG_HW_ACCEL) |
62 | static int hash_init_sha256(struct hash_algo *algo, void **ctxp) | 62 | static int hash_init_sha256(struct hash_algo *algo, void **ctxp) |
63 | { | 63 | { |
64 | sha256_context *ctx = malloc(sizeof(sha256_context)); | 64 | sha256_context *ctx = malloc(sizeof(sha256_context)); |
65 | sha256_starts(ctx); | 65 | sha256_starts(ctx); |
66 | *ctxp = ctx; | 66 | *ctxp = ctx; |
67 | return 0; | 67 | return 0; |
68 | } | 68 | } |
69 | 69 | ||
70 | static int hash_update_sha256(struct hash_algo *algo, void *ctx, | 70 | static int hash_update_sha256(struct hash_algo *algo, void *ctx, |
71 | const void *buf, unsigned int size, int is_last) | 71 | const void *buf, unsigned int size, int is_last) |
72 | { | 72 | { |
73 | sha256_update((sha256_context *)ctx, buf, size); | 73 | sha256_update((sha256_context *)ctx, buf, size); |
74 | return 0; | 74 | return 0; |
75 | } | 75 | } |
76 | 76 | ||
77 | static int hash_finish_sha256(struct hash_algo *algo, void *ctx, void | 77 | static int hash_finish_sha256(struct hash_algo *algo, void *ctx, void |
78 | *dest_buf, int size) | 78 | *dest_buf, int size) |
79 | { | 79 | { |
80 | if (size < algo->digest_size) | 80 | if (size < algo->digest_size) |
81 | return -1; | 81 | return -1; |
82 | 82 | ||
83 | sha256_finish((sha256_context *)ctx, dest_buf); | 83 | sha256_finish((sha256_context *)ctx, dest_buf); |
84 | free(ctx); | 84 | free(ctx); |
85 | return 0; | 85 | return 0; |
86 | } | 86 | } |
87 | #endif | 87 | #endif |
88 | 88 | ||
89 | static int hash_init_crc32(struct hash_algo *algo, void **ctxp) | 89 | static int hash_init_crc32(struct hash_algo *algo, void **ctxp) |
90 | { | 90 | { |
91 | uint32_t *ctx = malloc(sizeof(uint32_t)); | 91 | uint32_t *ctx = malloc(sizeof(uint32_t)); |
92 | *ctx = 0; | 92 | *ctx = 0; |
93 | *ctxp = ctx; | 93 | *ctxp = ctx; |
94 | return 0; | 94 | return 0; |
95 | } | 95 | } |
96 | 96 | ||
97 | static int hash_update_crc32(struct hash_algo *algo, void *ctx, | 97 | static int hash_update_crc32(struct hash_algo *algo, void *ctx, |
98 | const void *buf, unsigned int size, int is_last) | 98 | const void *buf, unsigned int size, int is_last) |
99 | { | 99 | { |
100 | *((uint32_t *)ctx) = crc32(*((uint32_t *)ctx), buf, size); | 100 | *((uint32_t *)ctx) = crc32(*((uint32_t *)ctx), buf, size); |
101 | return 0; | 101 | return 0; |
102 | } | 102 | } |
103 | 103 | ||
104 | static int hash_finish_crc32(struct hash_algo *algo, void *ctx, void *dest_buf, | 104 | static int hash_finish_crc32(struct hash_algo *algo, void *ctx, void *dest_buf, |
105 | int size) | 105 | int size) |
106 | { | 106 | { |
107 | if (size < algo->digest_size) | 107 | if (size < algo->digest_size) |
108 | return -1; | 108 | return -1; |
109 | 109 | ||
110 | *((uint32_t *)dest_buf) = *((uint32_t *)ctx); | 110 | *((uint32_t *)dest_buf) = *((uint32_t *)ctx); |
111 | free(ctx); | 111 | free(ctx); |
112 | return 0; | 112 | return 0; |
113 | } | 113 | } |
114 | 114 | ||
115 | /* | 115 | /* |
116 | * These are the hash algorithms we support. If we have hardware acceleration | 116 | * These are the hash algorithms we support. If we have hardware acceleration |
117 | * is enable we will use that, otherwise a software version of the algorithm. | 117 | * is enable we will use that, otherwise a software version of the algorithm. |
118 | * Note that algorithm names must be in lower case. | 118 | * Note that algorithm names must be in lower case. |
119 | */ | 119 | */ |
120 | static struct hash_algo hash_algo[] = { | 120 | static struct hash_algo hash_algo[] = { |
121 | #ifdef CONFIG_SHA1 | 121 | #ifdef CONFIG_SHA1 |
122 | { | 122 | { |
123 | .name = "sha1", | 123 | .name = "sha1", |
124 | .digest_size = SHA1_SUM_LEN, | 124 | .digest_size = SHA1_SUM_LEN, |
125 | .chunk_size = CHUNKSZ_SHA1, | 125 | .chunk_size = CHUNKSZ_SHA1, |
126 | #ifdef CONFIG_SHA_HW_ACCEL | 126 | #ifdef CONFIG_SHA_HW_ACCEL |
127 | .hash_func_ws = hw_sha1, | 127 | .hash_func_ws = hw_sha1, |
128 | #else | 128 | #else |
129 | .hash_func_ws = sha1_csum_wd, | 129 | .hash_func_ws = sha1_csum_wd, |
130 | #endif | 130 | #endif |
131 | #ifdef CONFIG_SHA_PROG_HW_ACCEL | 131 | #ifdef CONFIG_SHA_PROG_HW_ACCEL |
132 | .hash_init = hw_sha_init, | 132 | .hash_init = hw_sha_init, |
133 | .hash_update = hw_sha_update, | 133 | .hash_update = hw_sha_update, |
134 | .hash_finish = hw_sha_finish, | 134 | .hash_finish = hw_sha_finish, |
135 | #else | 135 | #else |
136 | .hash_init = hash_init_sha1, | 136 | .hash_init = hash_init_sha1, |
137 | .hash_update = hash_update_sha1, | 137 | .hash_update = hash_update_sha1, |
138 | .hash_finish = hash_finish_sha1, | 138 | .hash_finish = hash_finish_sha1, |
139 | #endif | 139 | #endif |
140 | }, | 140 | }, |
141 | #endif | 141 | #endif |
142 | #ifdef CONFIG_SHA256 | 142 | #ifdef CONFIG_SHA256 |
143 | { | 143 | { |
144 | .name = "sha256", | 144 | .name = "sha256", |
145 | .digest_size = SHA256_SUM_LEN, | 145 | .digest_size = SHA256_SUM_LEN, |
146 | .chunk_size = CHUNKSZ_SHA256, | 146 | .chunk_size = CHUNKSZ_SHA256, |
147 | #ifdef CONFIG_SHA_HW_ACCEL | 147 | #ifdef CONFIG_SHA_HW_ACCEL |
148 | .hash_func_ws = hw_sha256, | 148 | .hash_func_ws = hw_sha256, |
149 | #else | 149 | #else |
150 | .hash_func_ws = sha256_csum_wd, | 150 | .hash_func_ws = sha256_csum_wd, |
151 | #endif | 151 | #endif |
152 | #ifdef CONFIG_SHA_PROG_HW_ACCEL | 152 | #ifdef CONFIG_SHA_PROG_HW_ACCEL |
153 | .hash_init = hw_sha_init, | 153 | .hash_init = hw_sha_init, |
154 | .hash_update = hw_sha_update, | 154 | .hash_update = hw_sha_update, |
155 | .hash_finish = hw_sha_finish, | 155 | .hash_finish = hw_sha_finish, |
156 | #else | 156 | #else |
157 | .hash_init = hash_init_sha256, | 157 | .hash_init = hash_init_sha256, |
158 | .hash_update = hash_update_sha256, | 158 | .hash_update = hash_update_sha256, |
159 | .hash_finish = hash_finish_sha256, | 159 | .hash_finish = hash_finish_sha256, |
160 | #endif | 160 | #endif |
161 | }, | 161 | }, |
162 | #endif | 162 | #endif |
163 | { | 163 | { |
164 | .name = "crc32", | 164 | .name = "crc32", |
165 | .digest_size = 4, | 165 | .digest_size = 4, |
166 | .chunk_size = CHUNKSZ_CRC32, | 166 | .chunk_size = CHUNKSZ_CRC32, |
167 | .hash_func_ws = crc32_wd_buf, | 167 | .hash_func_ws = crc32_wd_buf, |
168 | .hash_init = hash_init_crc32, | 168 | .hash_init = hash_init_crc32, |
169 | .hash_update = hash_update_crc32, | 169 | .hash_update = hash_update_crc32, |
170 | .hash_finish = hash_finish_crc32, | 170 | .hash_finish = hash_finish_crc32, |
171 | }, | 171 | }, |
172 | }; | 172 | }; |
173 | 173 | ||
174 | /* Try to minimize code size for boards that don't want much hashing */ | 174 | /* Try to minimize code size for boards that don't want much hashing */ |
175 | #if defined(CONFIG_SHA256) || defined(CONFIG_CMD_SHA1SUM) || \ | 175 | #if defined(CONFIG_SHA256) || defined(CONFIG_CMD_SHA1SUM) || \ |
176 | defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_CMD_HASH) | 176 | defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_CMD_HASH) |
177 | #define multi_hash() 1 | 177 | #define multi_hash() 1 |
178 | #else | 178 | #else |
179 | #define multi_hash() 0 | 179 | #define multi_hash() 0 |
180 | #endif | 180 | #endif |
181 | 181 | ||
182 | int hash_lookup_algo(const char *algo_name, struct hash_algo **algop) | 182 | int hash_lookup_algo(const char *algo_name, struct hash_algo **algop) |
183 | { | 183 | { |
184 | int i; | 184 | int i; |
185 | 185 | ||
186 | for (i = 0; i < ARRAY_SIZE(hash_algo); i++) { | 186 | for (i = 0; i < ARRAY_SIZE(hash_algo); i++) { |
187 | if (!strcmp(algo_name, hash_algo[i].name)) { | 187 | if (!strcmp(algo_name, hash_algo[i].name)) { |
188 | *algop = &hash_algo[i]; | 188 | *algop = &hash_algo[i]; |
189 | return 0; | 189 | return 0; |
190 | } | 190 | } |
191 | } | 191 | } |
192 | 192 | ||
193 | debug("Unknown hash algorithm '%s'\n", algo_name); | 193 | debug("Unknown hash algorithm '%s'\n", algo_name); |
194 | return -EPROTONOSUPPORT; | 194 | return -EPROTONOSUPPORT; |
195 | } | 195 | } |
196 | 196 | ||
197 | int hash_progressive_lookup_algo(const char *algo_name, | 197 | int hash_progressive_lookup_algo(const char *algo_name, |
198 | struct hash_algo **algop) | 198 | struct hash_algo **algop) |
199 | { | 199 | { |
200 | int i; | 200 | int i; |
201 | 201 | ||
202 | for (i = 0; i < ARRAY_SIZE(hash_algo); i++) { | 202 | for (i = 0; i < ARRAY_SIZE(hash_algo); i++) { |
203 | if (!strcmp(algo_name, hash_algo[i].name)) { | 203 | if (!strcmp(algo_name, hash_algo[i].name)) { |
204 | if (hash_algo[i].hash_init) { | 204 | if (hash_algo[i].hash_init) { |
205 | *algop = &hash_algo[i]; | 205 | *algop = &hash_algo[i]; |
206 | return 0; | 206 | return 0; |
207 | } | 207 | } |
208 | } | 208 | } |
209 | } | 209 | } |
210 | 210 | ||
211 | debug("Unknown hash algorithm '%s'\n", algo_name); | 211 | debug("Unknown hash algorithm '%s'\n", algo_name); |
212 | return -EPROTONOSUPPORT; | 212 | return -EPROTONOSUPPORT; |
213 | } | 213 | } |
214 | 214 | ||
215 | #ifndef USE_HOSTCC | 215 | #ifndef USE_HOSTCC |
216 | int hash_parse_string(const char *algo_name, const char *str, uint8_t *result) | 216 | int hash_parse_string(const char *algo_name, const char *str, uint8_t *result) |
217 | { | 217 | { |
218 | struct hash_algo *algo; | 218 | struct hash_algo *algo; |
219 | int ret; | 219 | int ret; |
220 | int i; | 220 | int i; |
221 | 221 | ||
222 | ret = hash_lookup_algo(algo_name, &algo); | 222 | ret = hash_lookup_algo(algo_name, &algo); |
223 | if (ret) | 223 | if (ret) |
224 | return ret; | 224 | return ret; |
225 | 225 | ||
226 | for (i = 0; i < algo->digest_size; i++) { | 226 | for (i = 0; i < algo->digest_size; i++) { |
227 | char chr[3]; | 227 | char chr[3]; |
228 | 228 | ||
229 | strncpy(chr, &str[i * 2], 2); | 229 | strncpy(chr, &str[i * 2], 2); |
230 | result[i] = simple_strtoul(chr, NULL, 16); | 230 | result[i] = simple_strtoul(chr, NULL, 16); |
231 | } | 231 | } |
232 | 232 | ||
233 | return 0; | 233 | return 0; |
234 | } | 234 | } |
235 | 235 | ||
236 | int hash_block(const char *algo_name, const void *data, unsigned int len, | 236 | int hash_block(const char *algo_name, const void *data, unsigned int len, |
237 | uint8_t *output, int *output_size) | 237 | uint8_t *output, int *output_size) |
238 | { | 238 | { |
239 | struct hash_algo *algo; | 239 | struct hash_algo *algo; |
240 | int ret; | 240 | int ret; |
241 | 241 | ||
242 | ret = hash_lookup_algo(algo_name, &algo); | 242 | ret = hash_lookup_algo(algo_name, &algo); |
243 | if (ret) | 243 | if (ret) |
244 | return ret; | 244 | return ret; |
245 | 245 | ||
246 | if (output_size && *output_size < algo->digest_size) { | 246 | if (output_size && *output_size < algo->digest_size) { |
247 | debug("Output buffer size %d too small (need %d bytes)", | 247 | debug("Output buffer size %d too small (need %d bytes)", |
248 | *output_size, algo->digest_size); | 248 | *output_size, algo->digest_size); |
249 | return -ENOSPC; | 249 | return -ENOSPC; |
250 | } | 250 | } |
251 | if (output_size) | 251 | if (output_size) |
252 | *output_size = algo->digest_size; | 252 | *output_size = algo->digest_size; |
253 | algo->hash_func_ws(data, len, output, algo->chunk_size); | 253 | algo->hash_func_ws(data, len, output, algo->chunk_size); |
254 | 254 | ||
255 | return 0; | 255 | return 0; |
256 | } | 256 | } |
257 | 257 | ||
258 | #if defined(CONFIG_CMD_HASH) || defined(CONFIG_CMD_SHA1SUM) || defined(CONFIG_CMD_CRC32) | 258 | #if defined(CONFIG_CMD_HASH) || defined(CONFIG_CMD_SHA1SUM) || defined(CONFIG_CMD_CRC32) |
259 | /** | 259 | /** |
260 | * store_result: Store the resulting sum to an address or variable | 260 | * store_result: Store the resulting sum to an address or variable |
261 | * | 261 | * |
262 | * @algo: Hash algorithm being used | 262 | * @algo: Hash algorithm being used |
263 | * @sum: Hash digest (algo->digest_size bytes) | 263 | * @sum: Hash digest (algo->digest_size bytes) |
264 | * @dest: Destination, interpreted as a hex address if it starts | 264 | * @dest: Destination, interpreted as a hex address if it starts |
265 | * with * (or allow_env_vars is 0) or otherwise as an | 265 | * with * (or allow_env_vars is 0) or otherwise as an |
266 | * environment variable. | 266 | * environment variable. |
267 | * @allow_env_vars: non-zero to permit storing the result to an | 267 | * @allow_env_vars: non-zero to permit storing the result to an |
268 | * variable environment | 268 | * variable environment |
269 | */ | 269 | */ |
270 | static void store_result(struct hash_algo *algo, const uint8_t *sum, | 270 | static void store_result(struct hash_algo *algo, const uint8_t *sum, |
271 | const char *dest, int allow_env_vars) | 271 | const char *dest, int allow_env_vars) |
272 | { | 272 | { |
273 | unsigned int i; | 273 | unsigned int i; |
274 | int env_var = 0; | 274 | int env_var = 0; |
275 | 275 | ||
276 | /* | 276 | /* |
277 | * If environment variables are allowed, then we assume that 'dest' | 277 | * If environment variables are allowed, then we assume that 'dest' |
278 | * is an environment variable, unless it starts with *, in which | 278 | * is an environment variable, unless it starts with *, in which |
279 | * case we assume it is an address. If not allowed, it is always an | 279 | * case we assume it is an address. If not allowed, it is always an |
280 | * address. This is to support the crc32 command. | 280 | * address. This is to support the crc32 command. |
281 | */ | 281 | */ |
282 | if (allow_env_vars) { | 282 | if (allow_env_vars) { |
283 | if (*dest == '*') | 283 | if (*dest == '*') |
284 | dest++; | 284 | dest++; |
285 | else | 285 | else |
286 | env_var = 1; | 286 | env_var = 1; |
287 | } | 287 | } |
288 | 288 | ||
289 | if (env_var) { | 289 | if (env_var) { |
290 | char str_output[HASH_MAX_DIGEST_SIZE * 2 + 1]; | 290 | char str_output[HASH_MAX_DIGEST_SIZE * 2 + 1]; |
291 | char *str_ptr = str_output; | 291 | char *str_ptr = str_output; |
292 | 292 | ||
293 | for (i = 0; i < algo->digest_size; i++) { | 293 | for (i = 0; i < algo->digest_size; i++) { |
294 | sprintf(str_ptr, "%02x", sum[i]); | 294 | sprintf(str_ptr, "%02x", sum[i]); |
295 | str_ptr += 2; | 295 | str_ptr += 2; |
296 | } | 296 | } |
297 | *str_ptr = '\0'; | 297 | *str_ptr = '\0'; |
298 | env_set(dest, str_output); | 298 | env_set(dest, str_output); |
299 | } else { | 299 | } else { |
300 | ulong addr; | 300 | ulong addr; |
301 | void *buf; | 301 | void *buf; |
302 | 302 | ||
303 | addr = simple_strtoul(dest, NULL, 16); | 303 | addr = simple_strtoul(dest, NULL, 16); |
304 | buf = map_sysmem(addr, algo->digest_size); | 304 | buf = map_sysmem(addr, algo->digest_size); |
305 | memcpy(buf, sum, algo->digest_size); | 305 | memcpy(buf, sum, algo->digest_size); |
306 | unmap_sysmem(buf); | 306 | unmap_sysmem(buf); |
307 | } | 307 | } |
308 | } | 308 | } |
309 | 309 | ||
310 | /** | 310 | /** |
311 | * parse_verify_sum: Parse a hash verification parameter | 311 | * parse_verify_sum: Parse a hash verification parameter |
312 | * | 312 | * |
313 | * @algo: Hash algorithm being used | 313 | * @algo: Hash algorithm being used |
314 | * @verify_str: Argument to parse. If it starts with * then it is | 314 | * @verify_str: Argument to parse. If it starts with * then it is |
315 | * interpreted as a hex address containing the hash. | 315 | * interpreted as a hex address containing the hash. |
316 | * If the length is exactly the right number of hex digits | 316 | * If the length is exactly the right number of hex digits |
317 | * for the digest size, then we assume it is a hex digest. | 317 | * for the digest size, then we assume it is a hex digest. |
318 | * Otherwise we assume it is an environment variable, and | 318 | * Otherwise we assume it is an environment variable, and |
319 | * look up its value (it must contain a hex digest). | 319 | * look up its value (it must contain a hex digest). |
320 | * @vsum: Returns binary digest value (algo->digest_size bytes) | 320 | * @vsum: Returns binary digest value (algo->digest_size bytes) |
321 | * @allow_env_vars: non-zero to permit storing the result to an environment | 321 | * @allow_env_vars: non-zero to permit storing the result to an environment |
322 | * variable. If 0 then verify_str is assumed to be an | 322 | * variable. If 0 then verify_str is assumed to be an |
323 | * address, and the * prefix is not expected. | 323 | * address, and the * prefix is not expected. |
324 | * @return 0 if ok, non-zero on error | 324 | * @return 0 if ok, non-zero on error |
325 | */ | 325 | */ |
326 | static int parse_verify_sum(struct hash_algo *algo, char *verify_str, | 326 | static int parse_verify_sum(struct hash_algo *algo, char *verify_str, |
327 | uint8_t *vsum, int allow_env_vars) | 327 | uint8_t *vsum, int allow_env_vars) |
328 | { | 328 | { |
329 | int env_var = 0; | 329 | int env_var = 0; |
330 | 330 | ||
331 | /* See comment above in store_result() */ | 331 | /* See comment above in store_result() */ |
332 | if (allow_env_vars) { | 332 | if (allow_env_vars) { |
333 | if (*verify_str == '*') | 333 | if (*verify_str == '*') |
334 | verify_str++; | 334 | verify_str++; |
335 | else | 335 | else |
336 | env_var = 1; | 336 | env_var = 1; |
337 | } | 337 | } |
338 | 338 | ||
339 | if (!env_var) { | 339 | if (!env_var) { |
340 | ulong addr; | 340 | ulong addr; |
341 | void *buf; | 341 | void *buf; |
342 | 342 | ||
343 | addr = simple_strtoul(verify_str, NULL, 16); | 343 | addr = simple_strtoul(verify_str, NULL, 16); |
344 | buf = map_sysmem(addr, algo->digest_size); | 344 | buf = map_sysmem(addr, algo->digest_size); |
345 | memcpy(vsum, buf, algo->digest_size); | 345 | memcpy(vsum, buf, algo->digest_size); |
346 | } else { | 346 | } else { |
347 | char *vsum_str; | 347 | char *vsum_str; |
348 | int digits = algo->digest_size * 2; | 348 | int digits = algo->digest_size * 2; |
349 | 349 | ||
350 | /* | 350 | /* |
351 | * As with the original code from sha1sum.c, we assume that a | 351 | * As with the original code from sha1sum.c, we assume that a |
352 | * string which matches the digest size exactly is a hex | 352 | * string which matches the digest size exactly is a hex |
353 | * string and not an environment variable. | 353 | * string and not an environment variable. |
354 | */ | 354 | */ |
355 | if (strlen(verify_str) == digits) | 355 | if (strlen(verify_str) == digits) |
356 | vsum_str = verify_str; | 356 | vsum_str = verify_str; |
357 | else { | 357 | else { |
358 | vsum_str = env_get(verify_str); | 358 | vsum_str = env_get(verify_str); |
359 | if (vsum_str == NULL || strlen(vsum_str) != digits) { | 359 | if (vsum_str == NULL || strlen(vsum_str) != digits) { |
360 | printf("Expected %d hex digits in env var\n", | 360 | printf("Expected %d hex digits in env var\n", |
361 | digits); | 361 | digits); |
362 | return 1; | 362 | return 1; |
363 | } | 363 | } |
364 | } | 364 | } |
365 | 365 | ||
366 | hash_parse_string(algo->name, vsum_str, vsum); | 366 | hash_parse_string(algo->name, vsum_str, vsum); |
367 | } | 367 | } |
368 | return 0; | 368 | return 0; |
369 | } | 369 | } |
370 | 370 | ||
371 | static void hash_show(struct hash_algo *algo, ulong addr, ulong len, uint8_t *output) | 371 | static void hash_show(struct hash_algo *algo, ulong addr, ulong len, uint8_t *output) |
372 | { | 372 | { |
373 | int i; | 373 | int i; |
374 | 374 | ||
375 | printf("%s for %08lx ... %08lx ==> ", algo->name, addr, addr + len - 1); | 375 | printf("%s for %08lx ... %08lx ==> ", algo->name, addr, addr + len - 1); |
376 | for (i = 0; i < algo->digest_size; i++) | 376 | for (i = 0; i < algo->digest_size; i++) |
377 | printf("%02x", output[i]); | 377 | printf("%02x", output[i]); |
378 | } | 378 | } |
379 | 379 | ||
380 | int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, | 380 | int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, |
381 | int argc, char * const argv[]) | 381 | int argc, char * const argv[]) |
382 | { | 382 | { |
383 | ulong addr, len; | 383 | ulong addr, len; |
384 | 384 | ||
385 | if ((argc < 2) || ((flags & HASH_FLAG_VERIFY) && (argc < 3))) | 385 | if ((argc < 2) || ((flags & HASH_FLAG_VERIFY) && (argc < 3))) |
386 | return CMD_RET_USAGE; | 386 | return CMD_RET_USAGE; |
387 | 387 | ||
388 | addr = simple_strtoul(*argv++, NULL, 16); | 388 | addr = simple_strtoul(*argv++, NULL, 16); |
389 | len = simple_strtoul(*argv++, NULL, 16); | 389 | len = simple_strtoul(*argv++, NULL, 16); |
390 | 390 | ||
391 | if (multi_hash()) { | 391 | if (multi_hash()) { |
392 | struct hash_algo *algo; | 392 | struct hash_algo *algo; |
393 | uint8_t output[HASH_MAX_DIGEST_SIZE]; | 393 | u8 *output; |
394 | uint8_t vsum[HASH_MAX_DIGEST_SIZE]; | 394 | uint8_t vsum[HASH_MAX_DIGEST_SIZE]; |
395 | void *buf; | 395 | void *buf; |
396 | 396 | ||
397 | if (hash_lookup_algo(algo_name, &algo)) { | 397 | if (hash_lookup_algo(algo_name, &algo)) { |
398 | printf("Unknown hash algorithm '%s'\n", algo_name); | 398 | printf("Unknown hash algorithm '%s'\n", algo_name); |
399 | return CMD_RET_USAGE; | 399 | return CMD_RET_USAGE; |
400 | } | 400 | } |
401 | argc -= 2; | 401 | argc -= 2; |
402 | 402 | ||
403 | if (algo->digest_size > HASH_MAX_DIGEST_SIZE) { | 403 | if (algo->digest_size > HASH_MAX_DIGEST_SIZE) { |
404 | puts("HASH_MAX_DIGEST_SIZE exceeded\n"); | 404 | puts("HASH_MAX_DIGEST_SIZE exceeded\n"); |
405 | return 1; | 405 | return 1; |
406 | } | 406 | } |
407 | 407 | ||
408 | output = memalign(ARCH_DMA_MINALIGN, | ||
409 | sizeof(uint32_t) * HASH_MAX_DIGEST_SIZE); | ||
410 | |||
408 | buf = map_sysmem(addr, len); | 411 | buf = map_sysmem(addr, len); |
409 | algo->hash_func_ws(buf, len, output, algo->chunk_size); | 412 | algo->hash_func_ws(buf, len, output, algo->chunk_size); |
410 | unmap_sysmem(buf); | 413 | unmap_sysmem(buf); |
411 | 414 | ||
412 | /* Try to avoid code bloat when verify is not needed */ | 415 | /* Try to avoid code bloat when verify is not needed */ |
413 | #if defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_SHA1SUM_VERIFY) || \ | 416 | #if defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_SHA1SUM_VERIFY) || \ |
414 | defined(CONFIG_HASH_VERIFY) | 417 | defined(CONFIG_HASH_VERIFY) |
415 | if (flags & HASH_FLAG_VERIFY) { | 418 | if (flags & HASH_FLAG_VERIFY) { |
416 | #else | 419 | #else |
417 | if (0) { | 420 | if (0) { |
418 | #endif | 421 | #endif |
419 | if (parse_verify_sum(algo, *argv, vsum, | 422 | if (parse_verify_sum(algo, *argv, vsum, |
420 | flags & HASH_FLAG_ENV)) { | 423 | flags & HASH_FLAG_ENV)) { |
421 | printf("ERROR: %s does not contain a valid " | 424 | printf("ERROR: %s does not contain a valid " |
422 | "%s sum\n", *argv, algo->name); | 425 | "%s sum\n", *argv, algo->name); |
423 | return 1; | 426 | return 1; |
424 | } | 427 | } |
425 | if (memcmp(output, vsum, algo->digest_size) != 0) { | 428 | if (memcmp(output, vsum, algo->digest_size) != 0) { |
426 | int i; | 429 | int i; |
427 | 430 | ||
428 | hash_show(algo, addr, len, output); | 431 | hash_show(algo, addr, len, output); |
429 | printf(" != "); | 432 | printf(" != "); |
430 | for (i = 0; i < algo->digest_size; i++) | 433 | for (i = 0; i < algo->digest_size; i++) |
431 | printf("%02x", vsum[i]); | 434 | printf("%02x", vsum[i]); |
432 | puts(" ** ERROR **\n"); | 435 | puts(" ** ERROR **\n"); |
433 | return 1; | 436 | return 1; |
434 | } | 437 | } |
435 | } else { | 438 | } else { |
436 | hash_show(algo, addr, len, output); | 439 | hash_show(algo, addr, len, output); |
437 | printf("\n"); | 440 | printf("\n"); |
438 | 441 | ||
439 | if (argc) { | 442 | if (argc) { |
440 | store_result(algo, output, *argv, | 443 | store_result(algo, output, *argv, |
441 | flags & HASH_FLAG_ENV); | 444 | flags & HASH_FLAG_ENV); |
442 | } | 445 | } |
446 | unmap_sysmem(output); | ||
447 | |||
443 | } | 448 | } |
444 | 449 | ||
445 | /* Horrible code size hack for boards that just want crc32 */ | 450 | /* Horrible code size hack for boards that just want crc32 */ |
446 | } else { | 451 | } else { |
447 | ulong crc; | 452 | ulong crc; |
448 | ulong *ptr; | 453 | ulong *ptr; |
449 | 454 | ||
450 | crc = crc32_wd(0, (const uchar *)addr, len, CHUNKSZ_CRC32); | 455 | crc = crc32_wd(0, (const uchar *)addr, len, CHUNKSZ_CRC32); |
451 | 456 | ||
452 | printf("CRC32 for %08lx ... %08lx ==> %08lx\n", | 457 | printf("CRC32 for %08lx ... %08lx ==> %08lx\n", |
453 | addr, addr + len - 1, crc); | 458 | addr, addr + len - 1, crc); |
454 | 459 | ||
455 | if (argc >= 3) { | 460 | if (argc >= 3) { |
456 | ptr = (ulong *)simple_strtoul(argv[0], NULL, 16); | 461 | ptr = (ulong *)simple_strtoul(argv[0], NULL, 16); |
457 | *ptr = crc; | 462 | *ptr = crc; |
458 | } | 463 | } |
459 | } | 464 | } |
460 | 465 | ||
461 | return 0; | 466 | return 0; |
462 | } | 467 | } |
463 | #endif /* CONFIG_CMD_HASH || CONFIG_CMD_SHA1SUM || CONFIG_CMD_CRC32) */ | 468 | #endif /* CONFIG_CMD_HASH || CONFIG_CMD_SHA1SUM || CONFIG_CMD_CRC32) */ |
464 | #endif /* !USE_HOSTCC */ | 469 | #endif /* !USE_HOSTCC */ |
465 | 470 |
drivers/crypto/fsl/fsl_hash.c
1 | /* | 1 | /* |
2 | * Copyright 2014 Freescale Semiconductor, Inc. | 2 | * Copyright 2014 Freescale Semiconductor, Inc. |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: GPL-2.0+ | 4 | * SPDX-License-Identifier: GPL-2.0+ |
5 | * | 5 | * |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <common.h> | 8 | #include <common.h> |
9 | #include <malloc.h> | 9 | #include <malloc.h> |
10 | #include <memalign.h> | ||
10 | #include "jobdesc.h" | 11 | #include "jobdesc.h" |
11 | #include "desc.h" | 12 | #include "desc.h" |
12 | #include "jr.h" | 13 | #include "jr.h" |
13 | #include "fsl_hash.h" | 14 | #include "fsl_hash.h" |
14 | #include <hw_sha.h> | 15 | #include <hw_sha.h> |
15 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
16 | 17 | ||
17 | #define CRYPTO_MAX_ALG_NAME 80 | 18 | #define CRYPTO_MAX_ALG_NAME 80 |
18 | #define SHA1_DIGEST_SIZE 20 | 19 | #define SHA1_DIGEST_SIZE 20 |
19 | #define SHA256_DIGEST_SIZE 32 | 20 | #define SHA256_DIGEST_SIZE 32 |
20 | 21 | ||
21 | struct caam_hash_template { | 22 | struct caam_hash_template { |
22 | char name[CRYPTO_MAX_ALG_NAME]; | 23 | char name[CRYPTO_MAX_ALG_NAME]; |
23 | unsigned int digestsize; | 24 | unsigned int digestsize; |
24 | u32 alg_type; | 25 | u32 alg_type; |
25 | }; | 26 | }; |
26 | 27 | ||
27 | enum caam_hash_algos { | 28 | enum caam_hash_algos { |
28 | SHA1 = 0, | 29 | SHA1 = 0, |
29 | SHA256 | 30 | SHA256 |
30 | }; | 31 | }; |
31 | 32 | ||
32 | static struct caam_hash_template driver_hash[] = { | 33 | static struct caam_hash_template driver_hash[] = { |
33 | { | 34 | { |
34 | .name = "sha1", | 35 | .name = "sha1", |
35 | .digestsize = SHA1_DIGEST_SIZE, | 36 | .digestsize = SHA1_DIGEST_SIZE, |
36 | .alg_type = OP_ALG_ALGSEL_SHA1, | 37 | .alg_type = OP_ALG_ALGSEL_SHA1, |
37 | }, | 38 | }, |
38 | { | 39 | { |
39 | .name = "sha256", | 40 | .name = "sha256", |
40 | .digestsize = SHA256_DIGEST_SIZE, | 41 | .digestsize = SHA256_DIGEST_SIZE, |
41 | .alg_type = OP_ALG_ALGSEL_SHA256, | 42 | .alg_type = OP_ALG_ALGSEL_SHA256, |
42 | }, | 43 | }, |
43 | }; | 44 | }; |
44 | 45 | ||
45 | static enum caam_hash_algos get_hash_type(struct hash_algo *algo) | 46 | static enum caam_hash_algos get_hash_type(struct hash_algo *algo) |
46 | { | 47 | { |
47 | if (!strcmp(algo->name, driver_hash[SHA1].name)) | 48 | if (!strcmp(algo->name, driver_hash[SHA1].name)) |
48 | return SHA1; | 49 | return SHA1; |
49 | else | 50 | else |
50 | return SHA256; | 51 | return SHA256; |
51 | } | 52 | } |
52 | 53 | ||
53 | /* Create the context for progressive hashing using h/w acceleration. | 54 | /* Create the context for progressive hashing using h/w acceleration. |
54 | * | 55 | * |
55 | * @ctxp: Pointer to the pointer of the context for hashing | 56 | * @ctxp: Pointer to the pointer of the context for hashing |
56 | * @caam_algo: Enum for SHA1 or SHA256 | 57 | * @caam_algo: Enum for SHA1 or SHA256 |
57 | * @return 0 if ok, -ENOMEM on error | 58 | * @return 0 if ok, -ENOMEM on error |
58 | */ | 59 | */ |
59 | static int caam_hash_init(void **ctxp, enum caam_hash_algos caam_algo) | 60 | static int caam_hash_init(void **ctxp, enum caam_hash_algos caam_algo) |
60 | { | 61 | { |
61 | *ctxp = calloc(1, sizeof(struct sha_ctx)); | 62 | *ctxp = calloc(1, sizeof(struct sha_ctx)); |
62 | if (*ctxp == NULL) { | 63 | if (*ctxp == NULL) { |
63 | debug("Cannot allocate memory for context\n"); | 64 | debug("Cannot allocate memory for context\n"); |
64 | return -ENOMEM; | 65 | return -ENOMEM; |
65 | } | 66 | } |
66 | return 0; | 67 | return 0; |
67 | } | 68 | } |
68 | 69 | ||
69 | /* | 70 | /* |
70 | * Update sg table for progressive hashing using h/w acceleration | 71 | * Update sg table for progressive hashing using h/w acceleration |
71 | * | 72 | * |
72 | * The context is freed by this function if an error occurs. | 73 | * The context is freed by this function if an error occurs. |
73 | * We support at most 32 Scatter/Gather Entries. | 74 | * We support at most 32 Scatter/Gather Entries. |
74 | * | 75 | * |
75 | * @hash_ctx: Pointer to the context for hashing | 76 | * @hash_ctx: Pointer to the context for hashing |
76 | * @buf: Pointer to the buffer being hashed | 77 | * @buf: Pointer to the buffer being hashed |
77 | * @size: Size of the buffer being hashed | 78 | * @size: Size of the buffer being hashed |
78 | * @is_last: 1 if this is the last update; 0 otherwise | 79 | * @is_last: 1 if this is the last update; 0 otherwise |
79 | * @caam_algo: Enum for SHA1 or SHA256 | 80 | * @caam_algo: Enum for SHA1 or SHA256 |
80 | * @return 0 if ok, -EINVAL on error | 81 | * @return 0 if ok, -EINVAL on error |
81 | */ | 82 | */ |
82 | static int caam_hash_update(void *hash_ctx, const void *buf, | 83 | static int caam_hash_update(void *hash_ctx, const void *buf, |
83 | unsigned int size, int is_last, | 84 | unsigned int size, int is_last, |
84 | enum caam_hash_algos caam_algo) | 85 | enum caam_hash_algos caam_algo) |
85 | { | 86 | { |
86 | uint32_t final = 0; | 87 | uint32_t final = 0; |
87 | phys_addr_t addr = virt_to_phys((void *)buf); | 88 | phys_addr_t addr = virt_to_phys((void *)buf); |
88 | struct sha_ctx *ctx = hash_ctx; | 89 | struct sha_ctx *ctx = hash_ctx; |
89 | 90 | ||
90 | if (ctx->sg_num >= MAX_SG_32) { | 91 | if (ctx->sg_num >= MAX_SG_32) { |
91 | free(ctx); | 92 | free(ctx); |
92 | return -EINVAL; | 93 | return -EINVAL; |
93 | } | 94 | } |
94 | 95 | ||
95 | #ifdef CONFIG_PHYS_64BIT | 96 | #ifdef CONFIG_PHYS_64BIT |
96 | sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, (uint32_t)(addr >> 32)); | 97 | sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, (uint32_t)(addr >> 32)); |
97 | #else | 98 | #else |
98 | sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, 0x0); | 99 | sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, 0x0); |
99 | #endif | 100 | #endif |
100 | sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_lo, (uint32_t)addr); | 101 | sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_lo, (uint32_t)addr); |
101 | 102 | ||
102 | sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag, | 103 | sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag, |
103 | (size & SG_ENTRY_LENGTH_MASK)); | 104 | (size & SG_ENTRY_LENGTH_MASK)); |
104 | 105 | ||
105 | ctx->sg_num++; | 106 | ctx->sg_num++; |
106 | 107 | ||
107 | if (is_last) { | 108 | if (is_last) { |
108 | final = sec_in32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag) | | 109 | final = sec_in32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag) | |
109 | SG_ENTRY_FINAL_BIT; | 110 | SG_ENTRY_FINAL_BIT; |
110 | sec_out32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag, final); | 111 | sec_out32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag, final); |
111 | } | 112 | } |
112 | 113 | ||
113 | return 0; | 114 | return 0; |
114 | } | 115 | } |
115 | 116 | ||
116 | /* | 117 | /* |
117 | * Perform progressive hashing on the given buffer and copy hash at | 118 | * Perform progressive hashing on the given buffer and copy hash at |
118 | * destination buffer | 119 | * destination buffer |
119 | * | 120 | * |
120 | * The context is freed after completion of hash operation. | 121 | * The context is freed after completion of hash operation. |
121 | * | 122 | * |
122 | * @hash_ctx: Pointer to the context for hashing | 123 | * @hash_ctx: Pointer to the context for hashing |
123 | * @dest_buf: Pointer to the destination buffer where hash is to be copied | 124 | * @dest_buf: Pointer to the destination buffer where hash is to be copied |
124 | * @size: Size of the buffer being hashed | 125 | * @size: Size of the buffer being hashed |
125 | * @caam_algo: Enum for SHA1 or SHA256 | 126 | * @caam_algo: Enum for SHA1 or SHA256 |
126 | * @return 0 if ok, -EINVAL on error | 127 | * @return 0 if ok, -EINVAL on error |
127 | */ | 128 | */ |
128 | static int caam_hash_finish(void *hash_ctx, void *dest_buf, | 129 | static int caam_hash_finish(void *hash_ctx, void *dest_buf, |
129 | int size, enum caam_hash_algos caam_algo) | 130 | int size, enum caam_hash_algos caam_algo) |
130 | { | 131 | { |
131 | uint32_t len = 0; | 132 | uint32_t len = 0; |
132 | struct sha_ctx *ctx = hash_ctx; | 133 | struct sha_ctx *ctx = hash_ctx; |
133 | int i = 0, ret = 0; | 134 | int i = 0, ret = 0; |
134 | 135 | ||
135 | if (size < driver_hash[caam_algo].digestsize) { | 136 | if (size < driver_hash[caam_algo].digestsize) { |
136 | free(ctx); | 137 | free(ctx); |
137 | return -EINVAL; | 138 | return -EINVAL; |
138 | } | 139 | } |
139 | 140 | ||
140 | for (i = 0; i < ctx->sg_num; i++) | 141 | for (i = 0; i < ctx->sg_num; i++) |
141 | len += (sec_in32(&ctx->sg_tbl[i].len_flag) & | 142 | len += (sec_in32(&ctx->sg_tbl[i].len_flag) & |
142 | SG_ENTRY_LENGTH_MASK); | 143 | SG_ENTRY_LENGTH_MASK); |
143 | 144 | ||
144 | inline_cnstr_jobdesc_hash(ctx->sha_desc, (uint8_t *)ctx->sg_tbl, len, | 145 | inline_cnstr_jobdesc_hash(ctx->sha_desc, (uint8_t *)ctx->sg_tbl, len, |
145 | ctx->hash, | 146 | ctx->hash, |
146 | driver_hash[caam_algo].alg_type, | 147 | driver_hash[caam_algo].alg_type, |
147 | driver_hash[caam_algo].digestsize, | 148 | driver_hash[caam_algo].digestsize, |
148 | 1); | 149 | 1); |
149 | 150 | ||
150 | ret = run_descriptor_jr(ctx->sha_desc); | 151 | ret = run_descriptor_jr(ctx->sha_desc); |
151 | 152 | ||
152 | if (ret) | 153 | if (ret) |
153 | debug("Error %x\n", ret); | 154 | debug("Error %x\n", ret); |
154 | else | 155 | else |
155 | memcpy(dest_buf, ctx->hash, sizeof(ctx->hash)); | 156 | memcpy(dest_buf, ctx->hash, sizeof(ctx->hash)); |
156 | 157 | ||
157 | free(ctx); | 158 | free(ctx); |
158 | return ret; | 159 | return ret; |
159 | } | 160 | } |
160 | 161 | ||
161 | int caam_hash(const unsigned char *pbuf, unsigned int buf_len, | 162 | int caam_hash(const unsigned char *pbuf, unsigned int buf_len, |
162 | unsigned char *pout, enum caam_hash_algos algo) | 163 | unsigned char *pout, enum caam_hash_algos algo) |
163 | { | 164 | { |
164 | int ret = 0; | 165 | int ret = 0; |
165 | uint32_t *desc; | 166 | uint32_t *desc; |
167 | unsigned int size; | ||
166 | 168 | ||
167 | desc = malloc(sizeof(int) * MAX_CAAM_DESCSIZE); | 169 | desc = malloc_cache_aligned(sizeof(int) * MAX_CAAM_DESCSIZE); |
168 | if (!desc) { | 170 | if (!desc) { |
169 | debug("Not enough memory for descriptor allocation\n"); | 171 | debug("Not enough memory for descriptor allocation\n"); |
170 | return -ENOMEM; | 172 | return -ENOMEM; |
171 | } | 173 | } |
172 | 174 | ||
175 | if (!IS_ALIGNED((uintptr_t)pbuf, ARCH_DMA_MINALIGN) || | ||
176 | !IS_ALIGNED((uintptr_t)pout, ARCH_DMA_MINALIGN)) { | ||
177 | puts("Error: Address arguments are not aligned\n"); | ||
178 | return -EINVAL; | ||
179 | } | ||
180 | |||
181 | size = ALIGN(buf_len, ARCH_DMA_MINALIGN); | ||
182 | flush_dcache_range((unsigned long)pbuf, (unsigned long)pbuf + size); | ||
183 | |||
173 | inline_cnstr_jobdesc_hash(desc, pbuf, buf_len, pout, | 184 | inline_cnstr_jobdesc_hash(desc, pbuf, buf_len, pout, |
174 | driver_hash[algo].alg_type, | 185 | driver_hash[algo].alg_type, |
175 | driver_hash[algo].digestsize, | 186 | driver_hash[algo].digestsize, |
176 | 0); | 187 | 0); |
177 | 188 | ||
189 | size = ALIGN(sizeof(int) * MAX_CAAM_DESCSIZE, ARCH_DMA_MINALIGN); | ||
190 | flush_dcache_range((unsigned long)desc, (unsigned long)desc + size); | ||
191 | |||
178 | ret = run_descriptor_jr(desc); | 192 | ret = run_descriptor_jr(desc); |
193 | |||
194 | size = ALIGN(driver_hash[algo].digestsize, ARCH_DMA_MINALIGN); | ||
195 | invalidate_dcache_range((unsigned long)pout, | ||
196 | (unsigned long)pout + size); | ||
179 | 197 | ||
180 | free(desc); | 198 | free(desc); |
181 | return ret; | 199 | return ret; |
182 | } | 200 | } |
183 | 201 | ||
184 | void hw_sha256(const unsigned char *pbuf, unsigned int buf_len, | 202 | void hw_sha256(const unsigned char *pbuf, unsigned int buf_len, |
185 | unsigned char *pout, unsigned int chunk_size) | 203 | unsigned char *pout, unsigned int chunk_size) |
186 | { | 204 | { |
187 | if (caam_hash(pbuf, buf_len, pout, SHA256)) | 205 | if (caam_hash(pbuf, buf_len, pout, SHA256)) |
188 | printf("CAAM was not setup properly or it is faulty\n"); | 206 | printf("CAAM was not setup properly or it is faulty\n"); |
189 | } | 207 | } |
190 | 208 | ||
191 | void hw_sha1(const unsigned char *pbuf, unsigned int buf_len, | 209 | void hw_sha1(const unsigned char *pbuf, unsigned int buf_len, |
192 | unsigned char *pout, unsigned int chunk_size) | 210 | unsigned char *pout, unsigned int chunk_size) |
193 | { | 211 | { |
194 | if (caam_hash(pbuf, buf_len, pout, SHA1)) | 212 | if (caam_hash(pbuf, buf_len, pout, SHA1)) |
195 | printf("CAAM was not setup properly or it is faulty\n"); | 213 | printf("CAAM was not setup properly or it is faulty\n"); |
196 | } | 214 | } |
197 | 215 | ||
198 | int hw_sha_init(struct hash_algo *algo, void **ctxp) | 216 | int hw_sha_init(struct hash_algo *algo, void **ctxp) |
199 | { | 217 | { |
200 | return caam_hash_init(ctxp, get_hash_type(algo)); | 218 | return caam_hash_init(ctxp, get_hash_type(algo)); |
201 | } | 219 | } |
202 | 220 | ||
203 | int hw_sha_update(struct hash_algo *algo, void *ctx, const void *buf, | 221 | int hw_sha_update(struct hash_algo *algo, void *ctx, const void *buf, |
204 | unsigned int size, int is_last) | 222 | unsigned int size, int is_last) |
205 | { | 223 | { |
206 | return caam_hash_update(ctx, buf, size, is_last, get_hash_type(algo)); | 224 | return caam_hash_update(ctx, buf, size, is_last, get_hash_type(algo)); |
207 | } | 225 | } |
208 | 226 | ||
209 | int hw_sha_finish(struct hash_algo *algo, void *ctx, void *dest_buf, | 227 | int hw_sha_finish(struct hash_algo *algo, void *ctx, void *dest_buf, |
210 | int size) | 228 | int size) |
211 | { | 229 | { |
212 | return caam_hash_finish(ctx, dest_buf, size, get_hash_type(algo)); | 230 | return caam_hash_finish(ctx, dest_buf, size, get_hash_type(algo)); |
213 | } | 231 | } |
214 | 232 |
-
mentioned in commit c67ddd