Commit d7af2baa49c60c097d77986f49d7c2db06080c8e

Authored by Breno Lima
Committed by York Sun
1 parent 6d48d1c4b4

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

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