1 // SPDX-License-Identifier: GPL-2.0-only
2 // SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 /*
4 * Crypto driver to handle HASH algorithms using NVIDIA Security Engine.
5 */
6
7 #include <linux/clk.h>
8 #include <linux/dma-mapping.h>
9 #include <linux/module.h>
10 #include <linux/of_device.h>
11 #include <linux/platform_device.h>
12
13 #include <crypto/aes.h>
14 #include <crypto/sha1.h>
15 #include <crypto/sha2.h>
16 #include <crypto/sha3.h>
17 #include <crypto/internal/des.h>
18 #include <crypto/engine.h>
19 #include <crypto/scatterwalk.h>
20 #include <crypto/internal/hash.h>
21
22 #include "tegra-se.h"
23
24 struct tegra_sha_ctx {
25 struct tegra_se *se;
26 unsigned int alg;
27 bool fallback;
28 u32 key_id;
29 struct crypto_ahash *fallback_tfm;
30 };
31
32 struct tegra_sha_reqctx {
33 struct scatterlist *src_sg;
34 struct tegra_se_datbuf datbuf;
35 struct tegra_se_datbuf residue;
36 struct tegra_se_datbuf digest;
37 unsigned int alg;
38 unsigned int config;
39 unsigned int total_len;
40 unsigned int blk_size;
41 unsigned int task;
42 u32 key_id;
43 u32 result[HASH_RESULT_REG_COUNT];
44 struct ahash_request fallback_req;
45 };
46
tegra_sha_get_config(u32 alg)47 static int tegra_sha_get_config(u32 alg)
48 {
49 int cfg = 0;
50
51 switch (alg) {
52 case SE_ALG_SHA1:
53 cfg |= SE_SHA_ENC_ALG_SHA;
54 cfg |= SE_SHA_ENC_MODE_SHA1;
55 break;
56
57 case SE_ALG_HMAC_SHA224:
58 cfg |= SE_SHA_ENC_ALG_HMAC;
59 fallthrough;
60 case SE_ALG_SHA224:
61 cfg |= SE_SHA_ENC_ALG_SHA;
62 cfg |= SE_SHA_ENC_MODE_SHA224;
63 break;
64
65 case SE_ALG_HMAC_SHA256:
66 cfg |= SE_SHA_ENC_ALG_HMAC;
67 fallthrough;
68 case SE_ALG_SHA256:
69 cfg |= SE_SHA_ENC_ALG_SHA;
70 cfg |= SE_SHA_ENC_MODE_SHA256;
71 break;
72
73 case SE_ALG_HMAC_SHA384:
74 cfg |= SE_SHA_ENC_ALG_HMAC;
75 fallthrough;
76 case SE_ALG_SHA384:
77 cfg |= SE_SHA_ENC_ALG_SHA;
78 cfg |= SE_SHA_ENC_MODE_SHA384;
79 break;
80
81 case SE_ALG_HMAC_SHA512:
82 cfg |= SE_SHA_ENC_ALG_HMAC;
83 fallthrough;
84 case SE_ALG_SHA512:
85 cfg |= SE_SHA_ENC_ALG_SHA;
86 cfg |= SE_SHA_ENC_MODE_SHA512;
87 break;
88
89 case SE_ALG_SHA3_224:
90 cfg |= SE_SHA_ENC_ALG_SHA;
91 cfg |= SE_SHA_ENC_MODE_SHA3_224;
92 break;
93 case SE_ALG_SHA3_256:
94 cfg |= SE_SHA_ENC_ALG_SHA;
95 cfg |= SE_SHA_ENC_MODE_SHA3_256;
96 break;
97 case SE_ALG_SHA3_384:
98 cfg |= SE_SHA_ENC_ALG_SHA;
99 cfg |= SE_SHA_ENC_MODE_SHA3_384;
100 break;
101 case SE_ALG_SHA3_512:
102 cfg |= SE_SHA_ENC_ALG_SHA;
103 cfg |= SE_SHA_ENC_MODE_SHA3_512;
104 break;
105 default:
106 return -EINVAL;
107 }
108
109 return cfg;
110 }
111
tegra_sha_fallback_init(struct ahash_request * req)112 static int tegra_sha_fallback_init(struct ahash_request *req)
113 {
114 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
115 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
116 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
117
118 ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
119 rctx->fallback_req.base.flags = req->base.flags &
120 CRYPTO_TFM_REQ_MAY_SLEEP;
121
122 return crypto_ahash_init(&rctx->fallback_req);
123 }
124
tegra_sha_fallback_update(struct ahash_request * req)125 static int tegra_sha_fallback_update(struct ahash_request *req)
126 {
127 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
128 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
129 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
130
131 ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
132 rctx->fallback_req.base.flags = req->base.flags &
133 CRYPTO_TFM_REQ_MAY_SLEEP;
134 rctx->fallback_req.nbytes = req->nbytes;
135 rctx->fallback_req.src = req->src;
136
137 return crypto_ahash_update(&rctx->fallback_req);
138 }
139
tegra_sha_fallback_final(struct ahash_request * req)140 static int tegra_sha_fallback_final(struct ahash_request *req)
141 {
142 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
143 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
144 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
145
146 ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
147 rctx->fallback_req.base.flags = req->base.flags &
148 CRYPTO_TFM_REQ_MAY_SLEEP;
149 rctx->fallback_req.result = req->result;
150
151 return crypto_ahash_final(&rctx->fallback_req);
152 }
153
tegra_sha_fallback_finup(struct ahash_request * req)154 static int tegra_sha_fallback_finup(struct ahash_request *req)
155 {
156 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
157 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
158 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
159
160 ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
161 rctx->fallback_req.base.flags = req->base.flags &
162 CRYPTO_TFM_REQ_MAY_SLEEP;
163
164 rctx->fallback_req.nbytes = req->nbytes;
165 rctx->fallback_req.src = req->src;
166 rctx->fallback_req.result = req->result;
167
168 return crypto_ahash_finup(&rctx->fallback_req);
169 }
170
tegra_sha_fallback_digest(struct ahash_request * req)171 static int tegra_sha_fallback_digest(struct ahash_request *req)
172 {
173 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
174 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
175 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
176
177 ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
178 rctx->fallback_req.base.flags = req->base.flags &
179 CRYPTO_TFM_REQ_MAY_SLEEP;
180
181 rctx->fallback_req.nbytes = req->nbytes;
182 rctx->fallback_req.src = req->src;
183 rctx->fallback_req.result = req->result;
184
185 return crypto_ahash_digest(&rctx->fallback_req);
186 }
187
tegra_sha_fallback_import(struct ahash_request * req,const void * in)188 static int tegra_sha_fallback_import(struct ahash_request *req, const void *in)
189 {
190 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
191 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
192 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
193
194 ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
195 rctx->fallback_req.base.flags = req->base.flags &
196 CRYPTO_TFM_REQ_MAY_SLEEP;
197
198 return crypto_ahash_import(&rctx->fallback_req, in);
199 }
200
tegra_sha_fallback_export(struct ahash_request * req,void * out)201 static int tegra_sha_fallback_export(struct ahash_request *req, void *out)
202 {
203 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
204 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
205 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
206
207 ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
208 rctx->fallback_req.base.flags = req->base.flags &
209 CRYPTO_TFM_REQ_MAY_SLEEP;
210
211 return crypto_ahash_export(&rctx->fallback_req, out);
212 }
213
tegra_sha_prep_cmd(struct tegra_se * se,u32 * cpuvaddr,struct tegra_sha_reqctx * rctx)214 static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
215 struct tegra_sha_reqctx *rctx)
216 {
217 u64 msg_len, msg_left;
218 int i = 0;
219
220 msg_len = rctx->total_len * 8;
221 msg_left = rctx->datbuf.size * 8;
222
223 /*
224 * If IN_ADDR_HI_0.SZ > SHA_MSG_LEFT_[0-3] to the HASH engine,
225 * HW treats it as the last buffer and process the data.
226 * Therefore, add an extra byte to msg_left if it is not the
227 * last buffer.
228 */
229 if (rctx->task & SHA_UPDATE) {
230 msg_left += 8;
231 msg_len += 8;
232 }
233
234 cpuvaddr[i++] = host1x_opcode_setpayload(8);
235 cpuvaddr[i++] = se_host1x_opcode_incr_w(SE_SHA_MSG_LENGTH);
236 cpuvaddr[i++] = lower_32_bits(msg_len);
237 cpuvaddr[i++] = upper_32_bits(msg_len);
238 cpuvaddr[i++] = 0;
239 cpuvaddr[i++] = 0;
240 cpuvaddr[i++] = lower_32_bits(msg_left);
241 cpuvaddr[i++] = upper_32_bits(msg_left);
242 cpuvaddr[i++] = 0;
243 cpuvaddr[i++] = 0;
244 cpuvaddr[i++] = host1x_opcode_setpayload(6);
245 cpuvaddr[i++] = se_host1x_opcode_incr_w(SE_SHA_CFG);
246 cpuvaddr[i++] = rctx->config;
247
248 if (rctx->task & SHA_FIRST) {
249 cpuvaddr[i++] = SE_SHA_TASK_HASH_INIT;
250 rctx->task &= ~SHA_FIRST;
251 } else {
252 cpuvaddr[i++] = 0;
253 }
254
255 cpuvaddr[i++] = rctx->datbuf.addr;
256 cpuvaddr[i++] = (u32)(SE_ADDR_HI_MSB(upper_32_bits(rctx->datbuf.addr)) |
257 SE_ADDR_HI_SZ(rctx->datbuf.size));
258 cpuvaddr[i++] = rctx->digest.addr;
259 cpuvaddr[i++] = (u32)(SE_ADDR_HI_MSB(upper_32_bits(rctx->digest.addr)) |
260 SE_ADDR_HI_SZ(rctx->digest.size));
261 if (rctx->key_id) {
262 cpuvaddr[i++] = host1x_opcode_setpayload(1);
263 cpuvaddr[i++] = se_host1x_opcode_nonincr_w(SE_SHA_CRYPTO_CFG);
264 cpuvaddr[i++] = SE_AES_KEY_INDEX(rctx->key_id);
265 }
266
267 cpuvaddr[i++] = host1x_opcode_setpayload(1);
268 cpuvaddr[i++] = se_host1x_opcode_nonincr_w(SE_SHA_OPERATION);
269 cpuvaddr[i++] = SE_SHA_OP_WRSTALL |
270 SE_SHA_OP_START |
271 SE_SHA_OP_LASTBUF;
272 cpuvaddr[i++] = se_host1x_opcode_nonincr(host1x_uclass_incr_syncpt_r(), 1);
273 cpuvaddr[i++] = host1x_uclass_incr_syncpt_cond_f(1) |
274 host1x_uclass_incr_syncpt_indx_f(se->syncpt_id);
275
276 dev_dbg(se->dev, "msg len %llu msg left %llu cfg %#x",
277 msg_len, msg_left, rctx->config);
278
279 return i;
280 }
281
tegra_sha_copy_hash_result(struct tegra_se * se,struct tegra_sha_reqctx * rctx)282 static void tegra_sha_copy_hash_result(struct tegra_se *se, struct tegra_sha_reqctx *rctx)
283 {
284 int i;
285
286 for (i = 0; i < HASH_RESULT_REG_COUNT; i++)
287 rctx->result[i] = readl(se->base + se->hw->regs->result + (i * 4));
288 }
289
tegra_sha_paste_hash_result(struct tegra_se * se,struct tegra_sha_reqctx * rctx)290 static void tegra_sha_paste_hash_result(struct tegra_se *se, struct tegra_sha_reqctx *rctx)
291 {
292 int i;
293
294 for (i = 0; i < HASH_RESULT_REG_COUNT; i++)
295 writel(rctx->result[i],
296 se->base + se->hw->regs->result + (i * 4));
297 }
298
tegra_sha_do_update(struct ahash_request * req)299 static int tegra_sha_do_update(struct ahash_request *req)
300 {
301 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
302 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
303 unsigned int nblks, nresidue, size, ret;
304 u32 *cpuvaddr = ctx->se->cmdbuf->addr;
305
306 nresidue = (req->nbytes + rctx->residue.size) % rctx->blk_size;
307 nblks = (req->nbytes + rctx->residue.size) / rctx->blk_size;
308
309 /*
310 * If nbytes is a multiple of block size and there is no residue,
311 * then reserve the last block as residue during final() to process.
312 */
313 if (!nresidue && nblks) {
314 nresidue = rctx->blk_size;
315 nblks--;
316 }
317
318 rctx->src_sg = req->src;
319 rctx->datbuf.size = (req->nbytes + rctx->residue.size) - nresidue;
320 rctx->total_len += rctx->datbuf.size;
321
322 /*
323 * If nbytes are less than a block size, copy it residue and
324 * return. The bytes will be processed in final()
325 */
326 if (nblks < 1) {
327 scatterwalk_map_and_copy(rctx->residue.buf + rctx->residue.size,
328 rctx->src_sg, 0, req->nbytes, 0);
329
330 rctx->residue.size += req->nbytes;
331 return 0;
332 }
333
334 /* Copy the previous residue first */
335 if (rctx->residue.size)
336 memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
337
338 scatterwalk_map_and_copy(rctx->datbuf.buf + rctx->residue.size,
339 rctx->src_sg, 0, req->nbytes - nresidue, 0);
340
341 scatterwalk_map_and_copy(rctx->residue.buf, rctx->src_sg,
342 req->nbytes - nresidue, nresidue, 0);
343
344 /* Update residue value with the residue after current block */
345 rctx->residue.size = nresidue;
346
347 rctx->config = tegra_sha_get_config(rctx->alg) |
348 SE_SHA_DST_HASH_REG;
349
350 /*
351 * If this is not the first 'update' call, paste the previous copied
352 * intermediate results to the registers so that it gets picked up.
353 * This is to support the import/export functionality.
354 */
355 if (!(rctx->task & SHA_FIRST))
356 tegra_sha_paste_hash_result(ctx->se, rctx);
357
358 size = tegra_sha_prep_cmd(ctx->se, cpuvaddr, rctx);
359
360 ret = tegra_se_host1x_submit(ctx->se, size);
361
362 /*
363 * If this is not the final update, copy the intermediate results
364 * from the registers so that it can be used in the next 'update'
365 * call. This is to support the import/export functionality.
366 */
367 if (!(rctx->task & SHA_FINAL))
368 tegra_sha_copy_hash_result(ctx->se, rctx);
369
370 return ret;
371 }
372
tegra_sha_do_final(struct ahash_request * req)373 static int tegra_sha_do_final(struct ahash_request *req)
374 {
375 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
376 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
377 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
378 struct tegra_se *se = ctx->se;
379 u32 *cpuvaddr = se->cmdbuf->addr;
380 int size, ret = 0;
381
382 memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
383 rctx->datbuf.size = rctx->residue.size;
384 rctx->total_len += rctx->residue.size;
385
386 rctx->config = tegra_sha_get_config(rctx->alg) |
387 SE_SHA_DST_MEMORY;
388
389 size = tegra_sha_prep_cmd(se, cpuvaddr, rctx);
390
391 ret = tegra_se_host1x_submit(se, size);
392 if (ret)
393 goto out;
394
395 /* Copy result */
396 memcpy(req->result, rctx->digest.buf, rctx->digest.size);
397
398 out:
399 dma_free_coherent(se->dev, SE_SHA_BUFLEN,
400 rctx->datbuf.buf, rctx->datbuf.addr);
401 dma_free_coherent(se->dev, crypto_ahash_blocksize(tfm),
402 rctx->residue.buf, rctx->residue.addr);
403 dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
404 rctx->digest.addr);
405 return ret;
406 }
407
tegra_sha_do_one_req(struct crypto_engine * engine,void * areq)408 static int tegra_sha_do_one_req(struct crypto_engine *engine, void *areq)
409 {
410 struct ahash_request *req = ahash_request_cast(areq);
411 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
412 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
413 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
414 struct tegra_se *se = ctx->se;
415 int ret = 0;
416
417 if (rctx->task & SHA_UPDATE) {
418 ret = tegra_sha_do_update(req);
419 rctx->task &= ~SHA_UPDATE;
420 }
421
422 if (rctx->task & SHA_FINAL) {
423 ret = tegra_sha_do_final(req);
424 rctx->task &= ~SHA_FINAL;
425 }
426
427 crypto_finalize_hash_request(se->engine, req, ret);
428
429 return 0;
430 }
431
tegra_sha_init_fallback(struct crypto_ahash * tfm,struct tegra_sha_ctx * ctx,const char * algname)432 static void tegra_sha_init_fallback(struct crypto_ahash *tfm, struct tegra_sha_ctx *ctx,
433 const char *algname)
434 {
435 unsigned int statesize;
436
437 ctx->fallback_tfm = crypto_alloc_ahash(algname, 0, CRYPTO_ALG_ASYNC |
438 CRYPTO_ALG_NEED_FALLBACK);
439
440 if (IS_ERR(ctx->fallback_tfm)) {
441 dev_warn(ctx->se->dev,
442 "failed to allocate fallback for %s\n", algname);
443 ctx->fallback_tfm = NULL;
444 return;
445 }
446
447 statesize = crypto_ahash_statesize(ctx->fallback_tfm);
448
449 if (statesize > sizeof(struct tegra_sha_reqctx))
450 crypto_ahash_set_statesize(tfm, statesize);
451
452 /* Update reqsize if fallback is added */
453 crypto_ahash_set_reqsize(tfm,
454 sizeof(struct tegra_sha_reqctx) +
455 crypto_ahash_reqsize(ctx->fallback_tfm));
456 }
457
tegra_sha_cra_init(struct crypto_tfm * tfm)458 static int tegra_sha_cra_init(struct crypto_tfm *tfm)
459 {
460 struct tegra_sha_ctx *ctx = crypto_tfm_ctx(tfm);
461 struct crypto_ahash *ahash_tfm = __crypto_ahash_cast(tfm);
462 struct ahash_alg *alg = __crypto_ahash_alg(tfm->__crt_alg);
463 struct tegra_se_alg *se_alg;
464 const char *algname;
465 int ret;
466
467 algname = crypto_tfm_alg_name(tfm);
468 se_alg = container_of(alg, struct tegra_se_alg, alg.ahash.base);
469
470 crypto_ahash_set_reqsize(ahash_tfm, sizeof(struct tegra_sha_reqctx));
471
472 ctx->se = se_alg->se_dev;
473 ctx->fallback = false;
474 ctx->key_id = 0;
475
476 ret = se_algname_to_algid(algname);
477 if (ret < 0) {
478 dev_err(ctx->se->dev, "invalid algorithm\n");
479 return ret;
480 }
481
482 if (se_alg->alg_base)
483 tegra_sha_init_fallback(ahash_tfm, ctx, algname);
484
485 ctx->alg = ret;
486
487 return 0;
488 }
489
tegra_sha_cra_exit(struct crypto_tfm * tfm)490 static void tegra_sha_cra_exit(struct crypto_tfm *tfm)
491 {
492 struct tegra_sha_ctx *ctx = crypto_tfm_ctx(tfm);
493
494 if (ctx->fallback_tfm)
495 crypto_free_ahash(ctx->fallback_tfm);
496
497 tegra_key_invalidate(ctx->se, ctx->key_id, ctx->alg);
498 }
499
tegra_sha_init(struct ahash_request * req)500 static int tegra_sha_init(struct ahash_request *req)
501 {
502 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
503 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
504 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
505 struct tegra_se *se = ctx->se;
506
507 if (ctx->fallback)
508 return tegra_sha_fallback_init(req);
509
510 rctx->total_len = 0;
511 rctx->datbuf.size = 0;
512 rctx->residue.size = 0;
513 rctx->key_id = ctx->key_id;
514 rctx->task = SHA_FIRST;
515 rctx->alg = ctx->alg;
516 rctx->blk_size = crypto_ahash_blocksize(tfm);
517 rctx->digest.size = crypto_ahash_digestsize(tfm);
518
519 rctx->digest.buf = dma_alloc_coherent(se->dev, rctx->digest.size,
520 &rctx->digest.addr, GFP_KERNEL);
521 if (!rctx->digest.buf)
522 goto digbuf_fail;
523
524 rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size,
525 &rctx->residue.addr, GFP_KERNEL);
526 if (!rctx->residue.buf)
527 goto resbuf_fail;
528
529 rctx->datbuf.buf = dma_alloc_coherent(se->dev, SE_SHA_BUFLEN,
530 &rctx->datbuf.addr, GFP_KERNEL);
531 if (!rctx->datbuf.buf)
532 goto datbuf_fail;
533
534 return 0;
535
536 datbuf_fail:
537 dma_free_coherent(se->dev, rctx->blk_size, rctx->residue.buf,
538 rctx->residue.addr);
539 resbuf_fail:
540 dma_free_coherent(se->dev, SE_SHA_BUFLEN, rctx->datbuf.buf,
541 rctx->datbuf.addr);
542 digbuf_fail:
543 return -ENOMEM;
544 }
545
tegra_hmac_fallback_setkey(struct tegra_sha_ctx * ctx,const u8 * key,unsigned int keylen)546 static int tegra_hmac_fallback_setkey(struct tegra_sha_ctx *ctx, const u8 *key,
547 unsigned int keylen)
548 {
549 if (!ctx->fallback_tfm) {
550 dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen);
551 return -EINVAL;
552 }
553
554 ctx->fallback = true;
555 return crypto_ahash_setkey(ctx->fallback_tfm, key, keylen);
556 }
557
tegra_hmac_setkey(struct crypto_ahash * tfm,const u8 * key,unsigned int keylen)558 static int tegra_hmac_setkey(struct crypto_ahash *tfm, const u8 *key,
559 unsigned int keylen)
560 {
561 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
562
563 if (aes_check_keylen(keylen))
564 return tegra_hmac_fallback_setkey(ctx, key, keylen);
565
566 ctx->fallback = false;
567
568 return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
569 }
570
tegra_sha_update(struct ahash_request * req)571 static int tegra_sha_update(struct ahash_request *req)
572 {
573 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
574 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
575 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
576
577 if (ctx->fallback)
578 return tegra_sha_fallback_update(req);
579
580 rctx->task |= SHA_UPDATE;
581
582 return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
583 }
584
tegra_sha_final(struct ahash_request * req)585 static int tegra_sha_final(struct ahash_request *req)
586 {
587 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
588 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
589 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
590
591 if (ctx->fallback)
592 return tegra_sha_fallback_final(req);
593
594 rctx->task |= SHA_FINAL;
595
596 return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
597 }
598
tegra_sha_finup(struct ahash_request * req)599 static int tegra_sha_finup(struct ahash_request *req)
600 {
601 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
602 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
603 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
604
605 if (ctx->fallback)
606 return tegra_sha_fallback_finup(req);
607
608 rctx->task |= SHA_UPDATE | SHA_FINAL;
609
610 return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
611 }
612
tegra_sha_digest(struct ahash_request * req)613 static int tegra_sha_digest(struct ahash_request *req)
614 {
615 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
616 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
617 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
618
619 if (ctx->fallback)
620 return tegra_sha_fallback_digest(req);
621
622 tegra_sha_init(req);
623 rctx->task |= SHA_UPDATE | SHA_FINAL;
624
625 return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
626 }
627
tegra_sha_export(struct ahash_request * req,void * out)628 static int tegra_sha_export(struct ahash_request *req, void *out)
629 {
630 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
631 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
632 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
633
634 if (ctx->fallback)
635 return tegra_sha_fallback_export(req, out);
636
637 memcpy(out, rctx, sizeof(*rctx));
638
639 return 0;
640 }
641
tegra_sha_import(struct ahash_request * req,const void * in)642 static int tegra_sha_import(struct ahash_request *req, const void *in)
643 {
644 struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
645 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
646 struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
647
648 if (ctx->fallback)
649 return tegra_sha_fallback_import(req, in);
650
651 memcpy(rctx, in, sizeof(*rctx));
652
653 return 0;
654 }
655
656 static struct tegra_se_alg tegra_hash_algs[] = {
657 {
658 .alg.ahash.op.do_one_request = tegra_sha_do_one_req,
659 .alg.ahash.base = {
660 .init = tegra_sha_init,
661 .update = tegra_sha_update,
662 .final = tegra_sha_final,
663 .finup = tegra_sha_finup,
664 .digest = tegra_sha_digest,
665 .export = tegra_sha_export,
666 .import = tegra_sha_import,
667 .halg.digestsize = SHA1_DIGEST_SIZE,
668 .halg.statesize = sizeof(struct tegra_sha_reqctx),
669 .halg.base = {
670 .cra_name = "sha1",
671 .cra_driver_name = "tegra-se-sha1",
672 .cra_priority = 300,
673 .cra_flags = CRYPTO_ALG_TYPE_AHASH,
674 .cra_blocksize = SHA1_BLOCK_SIZE,
675 .cra_ctxsize = sizeof(struct tegra_sha_ctx),
676 .cra_alignmask = 0,
677 .cra_module = THIS_MODULE,
678 .cra_init = tegra_sha_cra_init,
679 .cra_exit = tegra_sha_cra_exit,
680 }
681 }
682 }, {
683 .alg.ahash.op.do_one_request = tegra_sha_do_one_req,
684 .alg.ahash.base = {
685 .init = tegra_sha_init,
686 .update = tegra_sha_update,
687 .final = tegra_sha_final,
688 .finup = tegra_sha_finup,
689 .digest = tegra_sha_digest,
690 .export = tegra_sha_export,
691 .import = tegra_sha_import,
692 .halg.digestsize = SHA224_DIGEST_SIZE,
693 .halg.statesize = sizeof(struct tegra_sha_reqctx),
694 .halg.base = {
695 .cra_name = "sha224",
696 .cra_driver_name = "tegra-se-sha224",
697 .cra_priority = 300,
698 .cra_flags = CRYPTO_ALG_TYPE_AHASH,
699 .cra_blocksize = SHA224_BLOCK_SIZE,
700 .cra_ctxsize = sizeof(struct tegra_sha_ctx),
701 .cra_alignmask = 0,
702 .cra_module = THIS_MODULE,
703 .cra_init = tegra_sha_cra_init,
704 .cra_exit = tegra_sha_cra_exit,
705 }
706 }
707 }, {
708 .alg.ahash.op.do_one_request = tegra_sha_do_one_req,
709 .alg.ahash.base = {
710 .init = tegra_sha_init,
711 .update = tegra_sha_update,
712 .final = tegra_sha_final,
713 .finup = tegra_sha_finup,
714 .digest = tegra_sha_digest,
715 .export = tegra_sha_export,
716 .import = tegra_sha_import,
717 .halg.digestsize = SHA256_DIGEST_SIZE,
718 .halg.statesize = sizeof(struct tegra_sha_reqctx),
719 .halg.base = {
720 .cra_name = "sha256",
721 .cra_driver_name = "tegra-se-sha256",
722 .cra_priority = 300,
723 .cra_flags = CRYPTO_ALG_TYPE_AHASH,
724 .cra_blocksize = SHA256_BLOCK_SIZE,
725 .cra_ctxsize = sizeof(struct tegra_sha_ctx),
726 .cra_alignmask = 0,
727 .cra_module = THIS_MODULE,
728 .cra_init = tegra_sha_cra_init,
729 .cra_exit = tegra_sha_cra_exit,
730 }
731 }
732 }, {
733 .alg.ahash.op.do_one_request = tegra_sha_do_one_req,
734 .alg.ahash.base = {
735 .init = tegra_sha_init,
736 .update = tegra_sha_update,
737 .final = tegra_sha_final,
738 .finup = tegra_sha_finup,
739 .digest = tegra_sha_digest,
740 .export = tegra_sha_export,
741 .import = tegra_sha_import,
742 .halg.digestsize = SHA384_DIGEST_SIZE,
743 .halg.statesize = sizeof(struct tegra_sha_reqctx),
744 .halg.base = {
745 .cra_name = "sha384",
746 .cra_driver_name = "tegra-se-sha384",
747 .cra_priority = 300,
748 .cra_flags = CRYPTO_ALG_TYPE_AHASH,
749 .cra_blocksize = SHA384_BLOCK_SIZE,
750 .cra_ctxsize = sizeof(struct tegra_sha_ctx),
751 .cra_alignmask = 0,
752 .cra_module = THIS_MODULE,
753 .cra_init = tegra_sha_cra_init,
754 .cra_exit = tegra_sha_cra_exit,
755 }
756 }
757 }, {
758 .alg.ahash.op.do_one_request = tegra_sha_do_one_req,
759 .alg.ahash.base = {
760 .init = tegra_sha_init,
761 .update = tegra_sha_update,
762 .final = tegra_sha_final,
763 .finup = tegra_sha_finup,
764 .digest = tegra_sha_digest,
765 .export = tegra_sha_export,
766 .import = tegra_sha_import,
767 .halg.digestsize = SHA512_DIGEST_SIZE,
768 .halg.statesize = sizeof(struct tegra_sha_reqctx),
769 .halg.base = {
770 .cra_name = "sha512",
771 .cra_driver_name = "tegra-se-sha512",
772 .cra_priority = 300,
773 .cra_flags = CRYPTO_ALG_TYPE_AHASH,
774 .cra_blocksize = SHA512_BLOCK_SIZE,
775 .cra_ctxsize = sizeof(struct tegra_sha_ctx),
776 .cra_alignmask = 0,
777 .cra_module = THIS_MODULE,
778 .cra_init = tegra_sha_cra_init,
779 .cra_exit = tegra_sha_cra_exit,
780 }
781 }
782 }, {
783 .alg.ahash.op.do_one_request = tegra_sha_do_one_req,
784 .alg.ahash.base = {
785 .init = tegra_sha_init,
786 .update = tegra_sha_update,
787 .final = tegra_sha_final,
788 .finup = tegra_sha_finup,
789 .digest = tegra_sha_digest,
790 .export = tegra_sha_export,
791 .import = tegra_sha_import,
792 .halg.digestsize = SHA3_224_DIGEST_SIZE,
793 .halg.statesize = sizeof(struct tegra_sha_reqctx),
794 .halg.base = {
795 .cra_name = "sha3-224",
796 .cra_driver_name = "tegra-se-sha3-224",
797 .cra_priority = 300,
798 .cra_flags = CRYPTO_ALG_TYPE_AHASH,
799 .cra_blocksize = SHA3_224_BLOCK_SIZE,
800 .cra_ctxsize = sizeof(struct tegra_sha_ctx),
801 .cra_alignmask = 0,
802 .cra_module = THIS_MODULE,
803 .cra_init = tegra_sha_cra_init,
804 .cra_exit = tegra_sha_cra_exit,
805 }
806 }
807 }, {
808 .alg.ahash.op.do_one_request = tegra_sha_do_one_req,
809 .alg.ahash.base = {
810 .init = tegra_sha_init,
811 .update = tegra_sha_update,
812 .final = tegra_sha_final,
813 .finup = tegra_sha_finup,
814 .digest = tegra_sha_digest,
815 .export = tegra_sha_export,
816 .import = tegra_sha_import,
817 .halg.digestsize = SHA3_256_DIGEST_SIZE,
818 .halg.statesize = sizeof(struct tegra_sha_reqctx),
819 .halg.base = {
820 .cra_name = "sha3-256",
821 .cra_driver_name = "tegra-se-sha3-256",
822 .cra_priority = 300,
823 .cra_flags = CRYPTO_ALG_TYPE_AHASH,
824 .cra_blocksize = SHA3_256_BLOCK_SIZE,
825 .cra_ctxsize = sizeof(struct tegra_sha_ctx),
826 .cra_alignmask = 0,
827 .cra_module = THIS_MODULE,
828 .cra_init = tegra_sha_cra_init,
829 .cra_exit = tegra_sha_cra_exit,
830 }
831 }
832 }, {
833 .alg.ahash.op.do_one_request = tegra_sha_do_one_req,
834 .alg.ahash.base = {
835 .init = tegra_sha_init,
836 .update = tegra_sha_update,
837 .final = tegra_sha_final,
838 .finup = tegra_sha_finup,
839 .digest = tegra_sha_digest,
840 .export = tegra_sha_export,
841 .import = tegra_sha_import,
842 .halg.digestsize = SHA3_384_DIGEST_SIZE,
843 .halg.statesize = sizeof(struct tegra_sha_reqctx),
844 .halg.base = {
845 .cra_name = "sha3-384",
846 .cra_driver_name = "tegra-se-sha3-384",
847 .cra_priority = 300,
848 .cra_flags = CRYPTO_ALG_TYPE_AHASH,
849 .cra_blocksize = SHA3_384_BLOCK_SIZE,
850 .cra_ctxsize = sizeof(struct tegra_sha_ctx),
851 .cra_alignmask = 0,
852 .cra_module = THIS_MODULE,
853 .cra_init = tegra_sha_cra_init,
854 .cra_exit = tegra_sha_cra_exit,
855 }
856 }
857 }, {
858 .alg.ahash.op.do_one_request = tegra_sha_do_one_req,
859 .alg.ahash.base = {
860 .init = tegra_sha_init,
861 .update = tegra_sha_update,
862 .final = tegra_sha_final,
863 .finup = tegra_sha_finup,
864 .digest = tegra_sha_digest,
865 .export = tegra_sha_export,
866 .import = tegra_sha_import,
867 .halg.digestsize = SHA3_512_DIGEST_SIZE,
868 .halg.statesize = sizeof(struct tegra_sha_reqctx),
869 .halg.base = {
870 .cra_name = "sha3-512",
871 .cra_driver_name = "tegra-se-sha3-512",
872 .cra_priority = 300,
873 .cra_flags = CRYPTO_ALG_TYPE_AHASH,
874 .cra_blocksize = SHA3_512_BLOCK_SIZE,
875 .cra_ctxsize = sizeof(struct tegra_sha_ctx),
876 .cra_alignmask = 0,
877 .cra_module = THIS_MODULE,
878 .cra_init = tegra_sha_cra_init,
879 .cra_exit = tegra_sha_cra_exit,
880 }
881 }
882 }, {
883 .alg_base = "sha224",
884 .alg.ahash.op.do_one_request = tegra_sha_do_one_req,
885 .alg.ahash.base = {
886 .init = tegra_sha_init,
887 .update = tegra_sha_update,
888 .final = tegra_sha_final,
889 .finup = tegra_sha_finup,
890 .digest = tegra_sha_digest,
891 .export = tegra_sha_export,
892 .import = tegra_sha_import,
893 .setkey = tegra_hmac_setkey,
894 .halg.digestsize = SHA224_DIGEST_SIZE,
895 .halg.statesize = sizeof(struct tegra_sha_reqctx),
896 .halg.base = {
897 .cra_name = "hmac(sha224)",
898 .cra_driver_name = "tegra-se-hmac-sha224",
899 .cra_priority = 300,
900 .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
901 .cra_blocksize = SHA224_BLOCK_SIZE,
902 .cra_ctxsize = sizeof(struct tegra_sha_ctx),
903 .cra_alignmask = 0,
904 .cra_module = THIS_MODULE,
905 .cra_init = tegra_sha_cra_init,
906 .cra_exit = tegra_sha_cra_exit,
907 }
908 }
909 }, {
910 .alg_base = "sha256",
911 .alg.ahash.op.do_one_request = tegra_sha_do_one_req,
912 .alg.ahash.base = {
913 .init = tegra_sha_init,
914 .update = tegra_sha_update,
915 .final = tegra_sha_final,
916 .finup = tegra_sha_finup,
917 .digest = tegra_sha_digest,
918 .export = tegra_sha_export,
919 .import = tegra_sha_import,
920 .setkey = tegra_hmac_setkey,
921 .halg.digestsize = SHA256_DIGEST_SIZE,
922 .halg.statesize = sizeof(struct tegra_sha_reqctx),
923 .halg.base = {
924 .cra_name = "hmac(sha256)",
925 .cra_driver_name = "tegra-se-hmac-sha256",
926 .cra_priority = 300,
927 .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
928 .cra_blocksize = SHA256_BLOCK_SIZE,
929 .cra_ctxsize = sizeof(struct tegra_sha_ctx),
930 .cra_alignmask = 0,
931 .cra_module = THIS_MODULE,
932 .cra_init = tegra_sha_cra_init,
933 .cra_exit = tegra_sha_cra_exit,
934 }
935 }
936 }, {
937 .alg_base = "sha384",
938 .alg.ahash.op.do_one_request = tegra_sha_do_one_req,
939 .alg.ahash.base = {
940 .init = tegra_sha_init,
941 .update = tegra_sha_update,
942 .final = tegra_sha_final,
943 .finup = tegra_sha_finup,
944 .digest = tegra_sha_digest,
945 .export = tegra_sha_export,
946 .import = tegra_sha_import,
947 .setkey = tegra_hmac_setkey,
948 .halg.digestsize = SHA384_DIGEST_SIZE,
949 .halg.statesize = sizeof(struct tegra_sha_reqctx),
950 .halg.base = {
951 .cra_name = "hmac(sha384)",
952 .cra_driver_name = "tegra-se-hmac-sha384",
953 .cra_priority = 300,
954 .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
955 .cra_blocksize = SHA384_BLOCK_SIZE,
956 .cra_ctxsize = sizeof(struct tegra_sha_ctx),
957 .cra_alignmask = 0,
958 .cra_module = THIS_MODULE,
959 .cra_init = tegra_sha_cra_init,
960 .cra_exit = tegra_sha_cra_exit,
961 }
962 }
963 }, {
964 .alg_base = "sha512",
965 .alg.ahash.op.do_one_request = tegra_sha_do_one_req,
966 .alg.ahash.base = {
967 .init = tegra_sha_init,
968 .update = tegra_sha_update,
969 .final = tegra_sha_final,
970 .finup = tegra_sha_finup,
971 .digest = tegra_sha_digest,
972 .export = tegra_sha_export,
973 .import = tegra_sha_import,
974 .setkey = tegra_hmac_setkey,
975 .halg.digestsize = SHA512_DIGEST_SIZE,
976 .halg.statesize = sizeof(struct tegra_sha_reqctx),
977 .halg.base = {
978 .cra_name = "hmac(sha512)",
979 .cra_driver_name = "tegra-se-hmac-sha512",
980 .cra_priority = 300,
981 .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
982 .cra_blocksize = SHA512_BLOCK_SIZE,
983 .cra_ctxsize = sizeof(struct tegra_sha_ctx),
984 .cra_alignmask = 0,
985 .cra_module = THIS_MODULE,
986 .cra_init = tegra_sha_cra_init,
987 .cra_exit = tegra_sha_cra_exit,
988 }
989 }
990 }
991 };
992
tegra_hash_kac_manifest(u32 user,u32 alg,u32 keylen)993 static int tegra_hash_kac_manifest(u32 user, u32 alg, u32 keylen)
994 {
995 int manifest;
996
997 manifest = SE_KAC_USER_NS;
998
999 switch (alg) {
1000 case SE_ALG_HMAC_SHA224:
1001 case SE_ALG_HMAC_SHA256:
1002 case SE_ALG_HMAC_SHA384:
1003 case SE_ALG_HMAC_SHA512:
1004 manifest |= SE_KAC_HMAC;
1005 break;
1006 default:
1007 return -EINVAL;
1008 }
1009
1010 switch (keylen) {
1011 case AES_KEYSIZE_128:
1012 manifest |= SE_KAC_SIZE_128;
1013 break;
1014 case AES_KEYSIZE_192:
1015 manifest |= SE_KAC_SIZE_192;
1016 break;
1017 case AES_KEYSIZE_256:
1018 default:
1019 manifest |= SE_KAC_SIZE_256;
1020 break;
1021 }
1022
1023 return manifest;
1024 }
1025
tegra_init_hash(struct tegra_se * se)1026 int tegra_init_hash(struct tegra_se *se)
1027 {
1028 struct ahash_engine_alg *alg;
1029 int i, ret;
1030
1031 se->manifest = tegra_hash_kac_manifest;
1032
1033 for (i = 0; i < ARRAY_SIZE(tegra_hash_algs); i++) {
1034 tegra_hash_algs[i].se_dev = se;
1035 alg = &tegra_hash_algs[i].alg.ahash;
1036
1037 ret = crypto_engine_register_ahash(alg);
1038 if (ret) {
1039 dev_err(se->dev, "failed to register %s\n",
1040 alg->base.halg.base.cra_name);
1041 goto sha_err;
1042 }
1043 }
1044
1045 return 0;
1046
1047 sha_err:
1048 while (i--)
1049 crypto_engine_unregister_ahash(&tegra_hash_algs[i].alg.ahash);
1050
1051 return ret;
1052 }
1053
tegra_deinit_hash(struct tegra_se * se)1054 void tegra_deinit_hash(struct tegra_se *se)
1055 {
1056 int i;
1057
1058 for (i = 0; i < ARRAY_SIZE(tegra_hash_algs); i++)
1059 crypto_engine_unregister_ahash(&tegra_hash_algs[i].alg.ahash);
1060 }
1061