Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.2-rc6 1441 lines 35 kB view raw
1/* 2 * Hash algorithms supported by the CESA: MD5, SHA1 and SHA256. 3 * 4 * Author: Boris Brezillon <boris.brezillon@free-electrons.com> 5 * Author: Arnaud Ebalard <arno@natisbad.org> 6 * 7 * This work is based on an initial version written by 8 * Sebastian Andrzej Siewior < sebastian at breakpoint dot cc > 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License version 2 as published 12 * by the Free Software Foundation. 13 */ 14 15#include <crypto/md5.h> 16#include <crypto/sha.h> 17 18#include "cesa.h" 19 20struct mv_cesa_ahash_dma_iter { 21 struct mv_cesa_dma_iter base; 22 struct mv_cesa_sg_dma_iter src; 23}; 24 25static inline void 26mv_cesa_ahash_req_iter_init(struct mv_cesa_ahash_dma_iter *iter, 27 struct ahash_request *req) 28{ 29 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 30 unsigned int len = req->nbytes; 31 32 if (!creq->last_req) 33 len = (len + creq->cache_ptr) & ~CESA_HASH_BLOCK_SIZE_MSK; 34 35 mv_cesa_req_dma_iter_init(&iter->base, len); 36 mv_cesa_sg_dma_iter_init(&iter->src, req->src, DMA_TO_DEVICE); 37 iter->src.op_offset = creq->cache_ptr; 38} 39 40static inline bool 41mv_cesa_ahash_req_iter_next_op(struct mv_cesa_ahash_dma_iter *iter) 42{ 43 iter->src.op_offset = 0; 44 45 return mv_cesa_req_dma_iter_next_op(&iter->base); 46} 47 48static inline int mv_cesa_ahash_dma_alloc_cache(struct mv_cesa_ahash_req *creq, 49 gfp_t flags) 50{ 51 struct mv_cesa_ahash_dma_req *dreq = &creq->req.dma; 52 53 creq->cache = dma_pool_alloc(cesa_dev->dma->cache_pool, flags, 54 &dreq->cache_dma); 55 if (!creq->cache) 56 return -ENOMEM; 57 58 return 0; 59} 60 61static inline int mv_cesa_ahash_std_alloc_cache(struct mv_cesa_ahash_req *creq, 62 gfp_t flags) 63{ 64 creq->cache = kzalloc(CESA_MAX_HASH_BLOCK_SIZE, flags); 65 if (!creq->cache) 66 return -ENOMEM; 67 68 return 0; 69} 70 71static int mv_cesa_ahash_alloc_cache(struct ahash_request *req) 72{ 73 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 74 gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? 75 GFP_KERNEL : GFP_ATOMIC; 76 int ret; 77 78 if (creq->cache) 79 return 0; 80 81 if (creq->req.base.type == CESA_DMA_REQ) 82 ret = mv_cesa_ahash_dma_alloc_cache(creq, flags); 83 else 84 ret = mv_cesa_ahash_std_alloc_cache(creq, flags); 85 86 return ret; 87} 88 89static inline void mv_cesa_ahash_dma_free_cache(struct mv_cesa_ahash_req *creq) 90{ 91 dma_pool_free(cesa_dev->dma->cache_pool, creq->cache, 92 creq->req.dma.cache_dma); 93} 94 95static inline void mv_cesa_ahash_std_free_cache(struct mv_cesa_ahash_req *creq) 96{ 97 kfree(creq->cache); 98} 99 100static void mv_cesa_ahash_free_cache(struct mv_cesa_ahash_req *creq) 101{ 102 if (!creq->cache) 103 return; 104 105 if (creq->req.base.type == CESA_DMA_REQ) 106 mv_cesa_ahash_dma_free_cache(creq); 107 else 108 mv_cesa_ahash_std_free_cache(creq); 109 110 creq->cache = NULL; 111} 112 113static int mv_cesa_ahash_dma_alloc_padding(struct mv_cesa_ahash_dma_req *req, 114 gfp_t flags) 115{ 116 if (req->padding) 117 return 0; 118 119 req->padding = dma_pool_alloc(cesa_dev->dma->padding_pool, flags, 120 &req->padding_dma); 121 if (!req->padding) 122 return -ENOMEM; 123 124 return 0; 125} 126 127static void mv_cesa_ahash_dma_free_padding(struct mv_cesa_ahash_dma_req *req) 128{ 129 if (!req->padding) 130 return; 131 132 dma_pool_free(cesa_dev->dma->padding_pool, req->padding, 133 req->padding_dma); 134 req->padding = NULL; 135} 136 137static inline void mv_cesa_ahash_dma_last_cleanup(struct ahash_request *req) 138{ 139 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 140 141 mv_cesa_ahash_dma_free_padding(&creq->req.dma); 142} 143 144static inline void mv_cesa_ahash_dma_cleanup(struct ahash_request *req) 145{ 146 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 147 148 dma_unmap_sg(cesa_dev->dev, req->src, creq->src_nents, DMA_TO_DEVICE); 149 mv_cesa_dma_cleanup(&creq->req.dma.base); 150} 151 152static inline void mv_cesa_ahash_cleanup(struct ahash_request *req) 153{ 154 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 155 156 if (creq->req.base.type == CESA_DMA_REQ) 157 mv_cesa_ahash_dma_cleanup(req); 158} 159 160static void mv_cesa_ahash_last_cleanup(struct ahash_request *req) 161{ 162 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 163 164 mv_cesa_ahash_free_cache(creq); 165 166 if (creq->req.base.type == CESA_DMA_REQ) 167 mv_cesa_ahash_dma_last_cleanup(req); 168} 169 170static int mv_cesa_ahash_pad_len(struct mv_cesa_ahash_req *creq) 171{ 172 unsigned int index, padlen; 173 174 index = creq->len & CESA_HASH_BLOCK_SIZE_MSK; 175 padlen = (index < 56) ? (56 - index) : (64 + 56 - index); 176 177 return padlen; 178} 179 180static int mv_cesa_ahash_pad_req(struct mv_cesa_ahash_req *creq, u8 *buf) 181{ 182 __be64 bits = cpu_to_be64(creq->len << 3); 183 unsigned int index, padlen; 184 185 buf[0] = 0x80; 186 /* Pad out to 56 mod 64 */ 187 index = creq->len & CESA_HASH_BLOCK_SIZE_MSK; 188 padlen = mv_cesa_ahash_pad_len(creq); 189 memset(buf + 1, 0, padlen - 1); 190 memcpy(buf + padlen, &bits, sizeof(bits)); 191 192 return padlen + 8; 193} 194 195static void mv_cesa_ahash_std_step(struct ahash_request *req) 196{ 197 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 198 struct mv_cesa_ahash_std_req *sreq = &creq->req.std; 199 struct mv_cesa_engine *engine = sreq->base.engine; 200 struct mv_cesa_op_ctx *op; 201 unsigned int new_cache_ptr = 0; 202 u32 frag_mode; 203 size_t len; 204 205 if (creq->cache_ptr) 206 memcpy(engine->sram + CESA_SA_DATA_SRAM_OFFSET, creq->cache, 207 creq->cache_ptr); 208 209 len = min_t(size_t, req->nbytes + creq->cache_ptr - sreq->offset, 210 CESA_SA_SRAM_PAYLOAD_SIZE); 211 212 if (!creq->last_req) { 213 new_cache_ptr = len & CESA_HASH_BLOCK_SIZE_MSK; 214 len &= ~CESA_HASH_BLOCK_SIZE_MSK; 215 } 216 217 if (len - creq->cache_ptr) 218 sreq->offset += sg_pcopy_to_buffer(req->src, creq->src_nents, 219 engine->sram + 220 CESA_SA_DATA_SRAM_OFFSET + 221 creq->cache_ptr, 222 len - creq->cache_ptr, 223 sreq->offset); 224 225 op = &creq->op_tmpl; 226 227 frag_mode = mv_cesa_get_op_cfg(op) & CESA_SA_DESC_CFG_FRAG_MSK; 228 229 if (creq->last_req && sreq->offset == req->nbytes && 230 creq->len <= CESA_SA_DESC_MAC_SRC_TOTAL_LEN_MAX) { 231 if (frag_mode == CESA_SA_DESC_CFG_FIRST_FRAG) 232 frag_mode = CESA_SA_DESC_CFG_NOT_FRAG; 233 else if (frag_mode == CESA_SA_DESC_CFG_MID_FRAG) 234 frag_mode = CESA_SA_DESC_CFG_LAST_FRAG; 235 } 236 237 if (frag_mode == CESA_SA_DESC_CFG_NOT_FRAG || 238 frag_mode == CESA_SA_DESC_CFG_LAST_FRAG) { 239 if (len && 240 creq->len <= CESA_SA_DESC_MAC_SRC_TOTAL_LEN_MAX) { 241 mv_cesa_set_mac_op_total_len(op, creq->len); 242 } else { 243 int trailerlen = mv_cesa_ahash_pad_len(creq) + 8; 244 245 if (len + trailerlen > CESA_SA_SRAM_PAYLOAD_SIZE) { 246 len &= CESA_HASH_BLOCK_SIZE_MSK; 247 new_cache_ptr = 64 - trailerlen; 248 memcpy(creq->cache, 249 engine->sram + 250 CESA_SA_DATA_SRAM_OFFSET + len, 251 new_cache_ptr); 252 } else { 253 len += mv_cesa_ahash_pad_req(creq, 254 engine->sram + len + 255 CESA_SA_DATA_SRAM_OFFSET); 256 } 257 258 if (frag_mode == CESA_SA_DESC_CFG_LAST_FRAG) 259 frag_mode = CESA_SA_DESC_CFG_MID_FRAG; 260 else 261 frag_mode = CESA_SA_DESC_CFG_FIRST_FRAG; 262 } 263 } 264 265 mv_cesa_set_mac_op_frag_len(op, len); 266 mv_cesa_update_op_cfg(op, frag_mode, CESA_SA_DESC_CFG_FRAG_MSK); 267 268 /* FIXME: only update enc_len field */ 269 memcpy(engine->sram, op, sizeof(*op)); 270 271 if (frag_mode == CESA_SA_DESC_CFG_FIRST_FRAG) 272 mv_cesa_update_op_cfg(op, CESA_SA_DESC_CFG_MID_FRAG, 273 CESA_SA_DESC_CFG_FRAG_MSK); 274 275 creq->cache_ptr = new_cache_ptr; 276 277 mv_cesa_set_int_mask(engine, CESA_SA_INT_ACCEL0_DONE); 278 writel(CESA_SA_CFG_PARA_DIS, engine->regs + CESA_SA_CFG); 279 writel(CESA_SA_CMD_EN_CESA_SA_ACCL0, engine->regs + CESA_SA_CMD); 280} 281 282static int mv_cesa_ahash_std_process(struct ahash_request *req, u32 status) 283{ 284 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 285 struct mv_cesa_ahash_std_req *sreq = &creq->req.std; 286 287 if (sreq->offset < (req->nbytes - creq->cache_ptr)) 288 return -EINPROGRESS; 289 290 return 0; 291} 292 293static inline void mv_cesa_ahash_dma_prepare(struct ahash_request *req) 294{ 295 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 296 struct mv_cesa_tdma_req *dreq = &creq->req.dma.base; 297 298 mv_cesa_dma_prepare(dreq, dreq->base.engine); 299} 300 301static void mv_cesa_ahash_std_prepare(struct ahash_request *req) 302{ 303 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 304 struct mv_cesa_ahash_std_req *sreq = &creq->req.std; 305 struct mv_cesa_engine *engine = sreq->base.engine; 306 307 sreq->offset = 0; 308 mv_cesa_adjust_op(engine, &creq->op_tmpl); 309 memcpy(engine->sram, &creq->op_tmpl, sizeof(creq->op_tmpl)); 310} 311 312static void mv_cesa_ahash_step(struct crypto_async_request *req) 313{ 314 struct ahash_request *ahashreq = ahash_request_cast(req); 315 struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq); 316 317 if (creq->req.base.type == CESA_DMA_REQ) 318 mv_cesa_dma_step(&creq->req.dma.base); 319 else 320 mv_cesa_ahash_std_step(ahashreq); 321} 322 323static int mv_cesa_ahash_process(struct crypto_async_request *req, u32 status) 324{ 325 struct ahash_request *ahashreq = ahash_request_cast(req); 326 struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq); 327 struct mv_cesa_engine *engine = creq->req.base.engine; 328 unsigned int digsize; 329 int ret, i; 330 331 if (creq->req.base.type == CESA_DMA_REQ) 332 ret = mv_cesa_dma_process(&creq->req.dma.base, status); 333 else 334 ret = mv_cesa_ahash_std_process(ahashreq, status); 335 336 if (ret == -EINPROGRESS) 337 return ret; 338 339 digsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(ahashreq)); 340 for (i = 0; i < digsize / 4; i++) 341 creq->state[i] = readl(engine->regs + CESA_IVDIG(i)); 342 343 if (creq->cache_ptr) 344 sg_pcopy_to_buffer(ahashreq->src, creq->src_nents, 345 creq->cache, 346 creq->cache_ptr, 347 ahashreq->nbytes - creq->cache_ptr); 348 349 if (creq->last_req) { 350 for (i = 0; i < digsize / 4; i++) { 351 /* 352 * Hardware provides MD5 digest in a different 353 * endianness than SHA-1 and SHA-256 ones. 354 */ 355 if (digsize == MD5_DIGEST_SIZE) 356 creq->state[i] = cpu_to_le32(creq->state[i]); 357 else 358 creq->state[i] = cpu_to_be32(creq->state[i]); 359 } 360 361 memcpy(ahashreq->result, creq->state, digsize); 362 } 363 364 return ret; 365} 366 367static void mv_cesa_ahash_prepare(struct crypto_async_request *req, 368 struct mv_cesa_engine *engine) 369{ 370 struct ahash_request *ahashreq = ahash_request_cast(req); 371 struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq); 372 unsigned int digsize; 373 int i; 374 375 creq->req.base.engine = engine; 376 377 if (creq->req.base.type == CESA_DMA_REQ) 378 mv_cesa_ahash_dma_prepare(ahashreq); 379 else 380 mv_cesa_ahash_std_prepare(ahashreq); 381 382 digsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(ahashreq)); 383 for (i = 0; i < digsize / 4; i++) 384 writel(creq->state[i], 385 engine->regs + CESA_IVDIG(i)); 386} 387 388static void mv_cesa_ahash_req_cleanup(struct crypto_async_request *req) 389{ 390 struct ahash_request *ahashreq = ahash_request_cast(req); 391 struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq); 392 393 if (creq->last_req) 394 mv_cesa_ahash_last_cleanup(ahashreq); 395 396 mv_cesa_ahash_cleanup(ahashreq); 397} 398 399static const struct mv_cesa_req_ops mv_cesa_ahash_req_ops = { 400 .step = mv_cesa_ahash_step, 401 .process = mv_cesa_ahash_process, 402 .prepare = mv_cesa_ahash_prepare, 403 .cleanup = mv_cesa_ahash_req_cleanup, 404}; 405 406static int mv_cesa_ahash_init(struct ahash_request *req, 407 struct mv_cesa_op_ctx *tmpl) 408{ 409 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 410 411 memset(creq, 0, sizeof(*creq)); 412 mv_cesa_update_op_cfg(tmpl, 413 CESA_SA_DESC_CFG_OP_MAC_ONLY | 414 CESA_SA_DESC_CFG_FIRST_FRAG, 415 CESA_SA_DESC_CFG_OP_MSK | 416 CESA_SA_DESC_CFG_FRAG_MSK); 417 mv_cesa_set_mac_op_total_len(tmpl, 0); 418 mv_cesa_set_mac_op_frag_len(tmpl, 0); 419 creq->op_tmpl = *tmpl; 420 creq->len = 0; 421 422 return 0; 423} 424 425static inline int mv_cesa_ahash_cra_init(struct crypto_tfm *tfm) 426{ 427 struct mv_cesa_hash_ctx *ctx = crypto_tfm_ctx(tfm); 428 429 ctx->base.ops = &mv_cesa_ahash_req_ops; 430 431 crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 432 sizeof(struct mv_cesa_ahash_req)); 433 return 0; 434} 435 436static int mv_cesa_ahash_cache_req(struct ahash_request *req, bool *cached) 437{ 438 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 439 int ret; 440 441 if (((creq->cache_ptr + req->nbytes) & CESA_HASH_BLOCK_SIZE_MSK) && 442 !creq->last_req) { 443 ret = mv_cesa_ahash_alloc_cache(req); 444 if (ret) 445 return ret; 446 } 447 448 if (creq->cache_ptr + req->nbytes < 64 && !creq->last_req) { 449 *cached = true; 450 451 if (!req->nbytes) 452 return 0; 453 454 sg_pcopy_to_buffer(req->src, creq->src_nents, 455 creq->cache + creq->cache_ptr, 456 req->nbytes, 0); 457 458 creq->cache_ptr += req->nbytes; 459 } 460 461 return 0; 462} 463 464static struct mv_cesa_op_ctx * 465mv_cesa_ahash_dma_add_cache(struct mv_cesa_tdma_chain *chain, 466 struct mv_cesa_ahash_dma_iter *dma_iter, 467 struct mv_cesa_ahash_req *creq, 468 gfp_t flags) 469{ 470 struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma; 471 struct mv_cesa_op_ctx *op = NULL; 472 int ret; 473 474 if (!creq->cache_ptr) 475 return NULL; 476 477 ret = mv_cesa_dma_add_data_transfer(chain, 478 CESA_SA_DATA_SRAM_OFFSET, 479 ahashdreq->cache_dma, 480 creq->cache_ptr, 481 CESA_TDMA_DST_IN_SRAM, 482 flags); 483 if (ret) 484 return ERR_PTR(ret); 485 486 if (!dma_iter->base.op_len) { 487 op = mv_cesa_dma_add_op(chain, &creq->op_tmpl, false, flags); 488 if (IS_ERR(op)) 489 return op; 490 491 mv_cesa_set_mac_op_frag_len(op, creq->cache_ptr); 492 493 /* Add dummy desc to launch crypto operation */ 494 ret = mv_cesa_dma_add_dummy_launch(chain, flags); 495 if (ret) 496 return ERR_PTR(ret); 497 } 498 499 return op; 500} 501 502static struct mv_cesa_op_ctx * 503mv_cesa_ahash_dma_add_data(struct mv_cesa_tdma_chain *chain, 504 struct mv_cesa_ahash_dma_iter *dma_iter, 505 struct mv_cesa_ahash_req *creq, 506 gfp_t flags) 507{ 508 struct mv_cesa_op_ctx *op; 509 int ret; 510 511 op = mv_cesa_dma_add_op(chain, &creq->op_tmpl, false, flags); 512 if (IS_ERR(op)) 513 return op; 514 515 mv_cesa_set_mac_op_frag_len(op, dma_iter->base.op_len); 516 517 if ((mv_cesa_get_op_cfg(&creq->op_tmpl) & CESA_SA_DESC_CFG_FRAG_MSK) == 518 CESA_SA_DESC_CFG_FIRST_FRAG) 519 mv_cesa_update_op_cfg(&creq->op_tmpl, 520 CESA_SA_DESC_CFG_MID_FRAG, 521 CESA_SA_DESC_CFG_FRAG_MSK); 522 523 /* Add input transfers */ 524 ret = mv_cesa_dma_add_op_transfers(chain, &dma_iter->base, 525 &dma_iter->src, flags); 526 if (ret) 527 return ERR_PTR(ret); 528 529 /* Add dummy desc to launch crypto operation */ 530 ret = mv_cesa_dma_add_dummy_launch(chain, flags); 531 if (ret) 532 return ERR_PTR(ret); 533 534 return op; 535} 536 537static struct mv_cesa_op_ctx * 538mv_cesa_ahash_dma_last_req(struct mv_cesa_tdma_chain *chain, 539 struct mv_cesa_ahash_dma_iter *dma_iter, 540 struct mv_cesa_ahash_req *creq, 541 struct mv_cesa_op_ctx *op, 542 gfp_t flags) 543{ 544 struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma; 545 unsigned int len, trailerlen, padoff = 0; 546 int ret; 547 548 if (!creq->last_req) 549 return op; 550 551 if (op && creq->len <= CESA_SA_DESC_MAC_SRC_TOTAL_LEN_MAX) { 552 u32 frag = CESA_SA_DESC_CFG_NOT_FRAG; 553 554 if ((mv_cesa_get_op_cfg(op) & CESA_SA_DESC_CFG_FRAG_MSK) != 555 CESA_SA_DESC_CFG_FIRST_FRAG) 556 frag = CESA_SA_DESC_CFG_LAST_FRAG; 557 558 mv_cesa_update_op_cfg(op, frag, CESA_SA_DESC_CFG_FRAG_MSK); 559 560 return op; 561 } 562 563 ret = mv_cesa_ahash_dma_alloc_padding(ahashdreq, flags); 564 if (ret) 565 return ERR_PTR(ret); 566 567 trailerlen = mv_cesa_ahash_pad_req(creq, ahashdreq->padding); 568 569 if (op) { 570 len = min(CESA_SA_SRAM_PAYLOAD_SIZE - dma_iter->base.op_len, 571 trailerlen); 572 if (len) { 573 ret = mv_cesa_dma_add_data_transfer(chain, 574 CESA_SA_DATA_SRAM_OFFSET + 575 dma_iter->base.op_len, 576 ahashdreq->padding_dma, 577 len, CESA_TDMA_DST_IN_SRAM, 578 flags); 579 if (ret) 580 return ERR_PTR(ret); 581 582 mv_cesa_update_op_cfg(op, CESA_SA_DESC_CFG_MID_FRAG, 583 CESA_SA_DESC_CFG_FRAG_MSK); 584 mv_cesa_set_mac_op_frag_len(op, 585 dma_iter->base.op_len + len); 586 padoff += len; 587 } 588 } 589 590 if (padoff >= trailerlen) 591 return op; 592 593 if ((mv_cesa_get_op_cfg(&creq->op_tmpl) & CESA_SA_DESC_CFG_FRAG_MSK) != 594 CESA_SA_DESC_CFG_FIRST_FRAG) 595 mv_cesa_update_op_cfg(&creq->op_tmpl, 596 CESA_SA_DESC_CFG_MID_FRAG, 597 CESA_SA_DESC_CFG_FRAG_MSK); 598 599 op = mv_cesa_dma_add_op(chain, &creq->op_tmpl, false, flags); 600 if (IS_ERR(op)) 601 return op; 602 603 mv_cesa_set_mac_op_frag_len(op, trailerlen - padoff); 604 605 ret = mv_cesa_dma_add_data_transfer(chain, 606 CESA_SA_DATA_SRAM_OFFSET, 607 ahashdreq->padding_dma + 608 padoff, 609 trailerlen - padoff, 610 CESA_TDMA_DST_IN_SRAM, 611 flags); 612 if (ret) 613 return ERR_PTR(ret); 614 615 /* Add dummy desc to launch crypto operation */ 616 ret = mv_cesa_dma_add_dummy_launch(chain, flags); 617 if (ret) 618 return ERR_PTR(ret); 619 620 return op; 621} 622 623static int mv_cesa_ahash_dma_req_init(struct ahash_request *req) 624{ 625 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 626 gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? 627 GFP_KERNEL : GFP_ATOMIC; 628 struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma; 629 struct mv_cesa_tdma_req *dreq = &ahashdreq->base; 630 struct mv_cesa_tdma_chain chain; 631 struct mv_cesa_ahash_dma_iter iter; 632 struct mv_cesa_op_ctx *op = NULL; 633 int ret; 634 635 dreq->chain.first = NULL; 636 dreq->chain.last = NULL; 637 638 if (creq->src_nents) { 639 ret = dma_map_sg(cesa_dev->dev, req->src, creq->src_nents, 640 DMA_TO_DEVICE); 641 if (!ret) { 642 ret = -ENOMEM; 643 goto err; 644 } 645 } 646 647 mv_cesa_tdma_desc_iter_init(&chain); 648 mv_cesa_ahash_req_iter_init(&iter, req); 649 650 op = mv_cesa_ahash_dma_add_cache(&chain, &iter, 651 creq, flags); 652 if (IS_ERR(op)) { 653 ret = PTR_ERR(op); 654 goto err_free_tdma; 655 } 656 657 do { 658 if (!iter.base.op_len) 659 break; 660 661 op = mv_cesa_ahash_dma_add_data(&chain, &iter, 662 creq, flags); 663 if (IS_ERR(op)) { 664 ret = PTR_ERR(op); 665 goto err_free_tdma; 666 } 667 } while (mv_cesa_ahash_req_iter_next_op(&iter)); 668 669 op = mv_cesa_ahash_dma_last_req(&chain, &iter, creq, op, flags); 670 if (IS_ERR(op)) { 671 ret = PTR_ERR(op); 672 goto err_free_tdma; 673 } 674 675 if (op) { 676 /* Add dummy desc to wait for crypto operation end */ 677 ret = mv_cesa_dma_add_dummy_end(&chain, flags); 678 if (ret) 679 goto err_free_tdma; 680 } 681 682 if (!creq->last_req) 683 creq->cache_ptr = req->nbytes + creq->cache_ptr - 684 iter.base.len; 685 else 686 creq->cache_ptr = 0; 687 688 dreq->chain = chain; 689 690 return 0; 691 692err_free_tdma: 693 mv_cesa_dma_cleanup(dreq); 694 dma_unmap_sg(cesa_dev->dev, req->src, creq->src_nents, DMA_TO_DEVICE); 695 696err: 697 mv_cesa_ahash_last_cleanup(req); 698 699 return ret; 700} 701 702static int mv_cesa_ahash_req_init(struct ahash_request *req, bool *cached) 703{ 704 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 705 int ret; 706 707 if (cesa_dev->caps->has_tdma) 708 creq->req.base.type = CESA_DMA_REQ; 709 else 710 creq->req.base.type = CESA_STD_REQ; 711 712 creq->src_nents = sg_nents_for_len(req->src, req->nbytes); 713 714 ret = mv_cesa_ahash_cache_req(req, cached); 715 if (ret) 716 return ret; 717 718 if (*cached) 719 return 0; 720 721 if (creq->req.base.type == CESA_DMA_REQ) 722 ret = mv_cesa_ahash_dma_req_init(req); 723 724 return ret; 725} 726 727static int mv_cesa_ahash_update(struct ahash_request *req) 728{ 729 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 730 bool cached = false; 731 int ret; 732 733 creq->len += req->nbytes; 734 ret = mv_cesa_ahash_req_init(req, &cached); 735 if (ret) 736 return ret; 737 738 if (cached) 739 return 0; 740 741 ret = mv_cesa_queue_req(&req->base); 742 if (ret && ret != -EINPROGRESS) { 743 mv_cesa_ahash_cleanup(req); 744 return ret; 745 } 746 747 return ret; 748} 749 750static int mv_cesa_ahash_final(struct ahash_request *req) 751{ 752 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 753 struct mv_cesa_op_ctx *tmpl = &creq->op_tmpl; 754 bool cached = false; 755 int ret; 756 757 mv_cesa_set_mac_op_total_len(tmpl, creq->len); 758 creq->last_req = true; 759 req->nbytes = 0; 760 761 ret = mv_cesa_ahash_req_init(req, &cached); 762 if (ret) 763 return ret; 764 765 if (cached) 766 return 0; 767 768 ret = mv_cesa_queue_req(&req->base); 769 if (ret && ret != -EINPROGRESS) 770 mv_cesa_ahash_cleanup(req); 771 772 return ret; 773} 774 775static int mv_cesa_ahash_finup(struct ahash_request *req) 776{ 777 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 778 struct mv_cesa_op_ctx *tmpl = &creq->op_tmpl; 779 bool cached = false; 780 int ret; 781 782 creq->len += req->nbytes; 783 mv_cesa_set_mac_op_total_len(tmpl, creq->len); 784 creq->last_req = true; 785 786 ret = mv_cesa_ahash_req_init(req, &cached); 787 if (ret) 788 return ret; 789 790 if (cached) 791 return 0; 792 793 ret = mv_cesa_queue_req(&req->base); 794 if (ret && ret != -EINPROGRESS) 795 mv_cesa_ahash_cleanup(req); 796 797 return ret; 798} 799 800static int mv_cesa_md5_init(struct ahash_request *req) 801{ 802 struct mv_cesa_op_ctx tmpl; 803 804 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_MD5); 805 806 mv_cesa_ahash_init(req, &tmpl); 807 808 return 0; 809} 810 811static int mv_cesa_md5_export(struct ahash_request *req, void *out) 812{ 813 struct md5_state *out_state = out; 814 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 815 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 816 unsigned int digsize = crypto_ahash_digestsize(ahash); 817 818 out_state->byte_count = creq->len; 819 memcpy(out_state->hash, creq->state, digsize); 820 memset(out_state->block, 0, sizeof(out_state->block)); 821 if (creq->cache) 822 memcpy(out_state->block, creq->cache, creq->cache_ptr); 823 824 return 0; 825} 826 827static int mv_cesa_md5_import(struct ahash_request *req, const void *in) 828{ 829 const struct md5_state *in_state = in; 830 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 831 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 832 unsigned int digsize = crypto_ahash_digestsize(ahash); 833 unsigned int cache_ptr; 834 int ret; 835 836 creq->len = in_state->byte_count; 837 memcpy(creq->state, in_state->hash, digsize); 838 creq->cache_ptr = 0; 839 840 cache_ptr = creq->len % sizeof(in_state->block); 841 if (!cache_ptr) 842 return 0; 843 844 ret = mv_cesa_ahash_alloc_cache(req); 845 if (ret) 846 return ret; 847 848 memcpy(creq->cache, in_state->block, cache_ptr); 849 creq->cache_ptr = cache_ptr; 850 851 return 0; 852} 853 854static int mv_cesa_md5_digest(struct ahash_request *req) 855{ 856 int ret; 857 858 ret = mv_cesa_md5_init(req); 859 if (ret) 860 return ret; 861 862 return mv_cesa_ahash_finup(req); 863} 864 865struct ahash_alg mv_md5_alg = { 866 .init = mv_cesa_md5_init, 867 .update = mv_cesa_ahash_update, 868 .final = mv_cesa_ahash_final, 869 .finup = mv_cesa_ahash_finup, 870 .digest = mv_cesa_md5_digest, 871 .export = mv_cesa_md5_export, 872 .import = mv_cesa_md5_import, 873 .halg = { 874 .digestsize = MD5_DIGEST_SIZE, 875 .base = { 876 .cra_name = "md5", 877 .cra_driver_name = "mv-md5", 878 .cra_priority = 300, 879 .cra_flags = CRYPTO_ALG_ASYNC | 880 CRYPTO_ALG_KERN_DRIVER_ONLY, 881 .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 882 .cra_ctxsize = sizeof(struct mv_cesa_hash_ctx), 883 .cra_init = mv_cesa_ahash_cra_init, 884 .cra_module = THIS_MODULE, 885 } 886 } 887}; 888 889static int mv_cesa_sha1_init(struct ahash_request *req) 890{ 891 struct mv_cesa_op_ctx tmpl; 892 893 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_SHA1); 894 895 mv_cesa_ahash_init(req, &tmpl); 896 897 return 0; 898} 899 900static int mv_cesa_sha1_export(struct ahash_request *req, void *out) 901{ 902 struct sha1_state *out_state = out; 903 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 904 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 905 unsigned int digsize = crypto_ahash_digestsize(ahash); 906 907 out_state->count = creq->len; 908 memcpy(out_state->state, creq->state, digsize); 909 memset(out_state->buffer, 0, sizeof(out_state->buffer)); 910 if (creq->cache) 911 memcpy(out_state->buffer, creq->cache, creq->cache_ptr); 912 913 return 0; 914} 915 916static int mv_cesa_sha1_import(struct ahash_request *req, const void *in) 917{ 918 const struct sha1_state *in_state = in; 919 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 920 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 921 unsigned int digsize = crypto_ahash_digestsize(ahash); 922 unsigned int cache_ptr; 923 int ret; 924 925 creq->len = in_state->count; 926 memcpy(creq->state, in_state->state, digsize); 927 creq->cache_ptr = 0; 928 929 cache_ptr = creq->len % SHA1_BLOCK_SIZE; 930 if (!cache_ptr) 931 return 0; 932 933 ret = mv_cesa_ahash_alloc_cache(req); 934 if (ret) 935 return ret; 936 937 memcpy(creq->cache, in_state->buffer, cache_ptr); 938 creq->cache_ptr = cache_ptr; 939 940 return 0; 941} 942 943static int mv_cesa_sha1_digest(struct ahash_request *req) 944{ 945 int ret; 946 947 ret = mv_cesa_sha1_init(req); 948 if (ret) 949 return ret; 950 951 return mv_cesa_ahash_finup(req); 952} 953 954struct ahash_alg mv_sha1_alg = { 955 .init = mv_cesa_sha1_init, 956 .update = mv_cesa_ahash_update, 957 .final = mv_cesa_ahash_final, 958 .finup = mv_cesa_ahash_finup, 959 .digest = mv_cesa_sha1_digest, 960 .export = mv_cesa_sha1_export, 961 .import = mv_cesa_sha1_import, 962 .halg = { 963 .digestsize = SHA1_DIGEST_SIZE, 964 .base = { 965 .cra_name = "sha1", 966 .cra_driver_name = "mv-sha1", 967 .cra_priority = 300, 968 .cra_flags = CRYPTO_ALG_ASYNC | 969 CRYPTO_ALG_KERN_DRIVER_ONLY, 970 .cra_blocksize = SHA1_BLOCK_SIZE, 971 .cra_ctxsize = sizeof(struct mv_cesa_hash_ctx), 972 .cra_init = mv_cesa_ahash_cra_init, 973 .cra_module = THIS_MODULE, 974 } 975 } 976}; 977 978static int mv_cesa_sha256_init(struct ahash_request *req) 979{ 980 struct mv_cesa_op_ctx tmpl; 981 982 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_SHA256); 983 984 mv_cesa_ahash_init(req, &tmpl); 985 986 return 0; 987} 988 989static int mv_cesa_sha256_digest(struct ahash_request *req) 990{ 991 int ret; 992 993 ret = mv_cesa_sha256_init(req); 994 if (ret) 995 return ret; 996 997 return mv_cesa_ahash_finup(req); 998} 999 1000static int mv_cesa_sha256_export(struct ahash_request *req, void *out) 1001{ 1002 struct sha256_state *out_state = out; 1003 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 1004 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 1005 unsigned int ds = crypto_ahash_digestsize(ahash); 1006 1007 out_state->count = creq->len; 1008 memcpy(out_state->state, creq->state, ds); 1009 memset(out_state->buf, 0, sizeof(out_state->buf)); 1010 if (creq->cache) 1011 memcpy(out_state->buf, creq->cache, creq->cache_ptr); 1012 1013 return 0; 1014} 1015 1016static int mv_cesa_sha256_import(struct ahash_request *req, const void *in) 1017{ 1018 const struct sha256_state *in_state = in; 1019 struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 1020 struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); 1021 unsigned int digsize = crypto_ahash_digestsize(ahash); 1022 unsigned int cache_ptr; 1023 int ret; 1024 1025 creq->len = in_state->count; 1026 memcpy(creq->state, in_state->state, digsize); 1027 creq->cache_ptr = 0; 1028 1029 cache_ptr = creq->len % SHA256_BLOCK_SIZE; 1030 if (!cache_ptr) 1031 return 0; 1032 1033 ret = mv_cesa_ahash_alloc_cache(req); 1034 if (ret) 1035 return ret; 1036 1037 memcpy(creq->cache, in_state->buf, cache_ptr); 1038 creq->cache_ptr = cache_ptr; 1039 1040 return 0; 1041} 1042 1043struct ahash_alg mv_sha256_alg = { 1044 .init = mv_cesa_sha256_init, 1045 .update = mv_cesa_ahash_update, 1046 .final = mv_cesa_ahash_final, 1047 .finup = mv_cesa_ahash_finup, 1048 .digest = mv_cesa_sha256_digest, 1049 .export = mv_cesa_sha256_export, 1050 .import = mv_cesa_sha256_import, 1051 .halg = { 1052 .digestsize = SHA256_DIGEST_SIZE, 1053 .base = { 1054 .cra_name = "sha256", 1055 .cra_driver_name = "mv-sha256", 1056 .cra_priority = 300, 1057 .cra_flags = CRYPTO_ALG_ASYNC | 1058 CRYPTO_ALG_KERN_DRIVER_ONLY, 1059 .cra_blocksize = SHA256_BLOCK_SIZE, 1060 .cra_ctxsize = sizeof(struct mv_cesa_hash_ctx), 1061 .cra_init = mv_cesa_ahash_cra_init, 1062 .cra_module = THIS_MODULE, 1063 } 1064 } 1065}; 1066 1067struct mv_cesa_ahash_result { 1068 struct completion completion; 1069 int error; 1070}; 1071 1072static void mv_cesa_hmac_ahash_complete(struct crypto_async_request *req, 1073 int error) 1074{ 1075 struct mv_cesa_ahash_result *result = req->data; 1076 1077 if (error == -EINPROGRESS) 1078 return; 1079 1080 result->error = error; 1081 complete(&result->completion); 1082} 1083 1084static int mv_cesa_ahmac_iv_state_init(struct ahash_request *req, u8 *pad, 1085 void *state, unsigned int blocksize) 1086{ 1087 struct mv_cesa_ahash_result result; 1088 struct scatterlist sg; 1089 int ret; 1090 1091 ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 1092 mv_cesa_hmac_ahash_complete, &result); 1093 sg_init_one(&sg, pad, blocksize); 1094 ahash_request_set_crypt(req, &sg, pad, blocksize); 1095 init_completion(&result.completion); 1096 1097 ret = crypto_ahash_init(req); 1098 if (ret) 1099 return ret; 1100 1101 ret = crypto_ahash_update(req); 1102 if (ret && ret != -EINPROGRESS) 1103 return ret; 1104 1105 wait_for_completion_interruptible(&result.completion); 1106 if (result.error) 1107 return result.error; 1108 1109 ret = crypto_ahash_export(req, state); 1110 if (ret) 1111 return ret; 1112 1113 return 0; 1114} 1115 1116static int mv_cesa_ahmac_pad_init(struct ahash_request *req, 1117 const u8 *key, unsigned int keylen, 1118 u8 *ipad, u8 *opad, 1119 unsigned int blocksize) 1120{ 1121 struct mv_cesa_ahash_result result; 1122 struct scatterlist sg; 1123 int ret; 1124 int i; 1125 1126 if (keylen <= blocksize) { 1127 memcpy(ipad, key, keylen); 1128 } else { 1129 u8 *keydup = kmemdup(key, keylen, GFP_KERNEL); 1130 1131 if (!keydup) 1132 return -ENOMEM; 1133 1134 ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 1135 mv_cesa_hmac_ahash_complete, 1136 &result); 1137 sg_init_one(&sg, keydup, keylen); 1138 ahash_request_set_crypt(req, &sg, ipad, keylen); 1139 init_completion(&result.completion); 1140 1141 ret = crypto_ahash_digest(req); 1142 if (ret == -EINPROGRESS) { 1143 wait_for_completion_interruptible(&result.completion); 1144 ret = result.error; 1145 } 1146 1147 /* Set the memory region to 0 to avoid any leak. */ 1148 memset(keydup, 0, keylen); 1149 kfree(keydup); 1150 1151 if (ret) 1152 return ret; 1153 1154 keylen = crypto_ahash_digestsize(crypto_ahash_reqtfm(req)); 1155 } 1156 1157 memset(ipad + keylen, 0, blocksize - keylen); 1158 memcpy(opad, ipad, blocksize); 1159 1160 for (i = 0; i < blocksize; i++) { 1161 ipad[i] ^= 0x36; 1162 opad[i] ^= 0x5c; 1163 } 1164 1165 return 0; 1166} 1167 1168static int mv_cesa_ahmac_setkey(const char *hash_alg_name, 1169 const u8 *key, unsigned int keylen, 1170 void *istate, void *ostate) 1171{ 1172 struct ahash_request *req; 1173 struct crypto_ahash *tfm; 1174 unsigned int blocksize; 1175 u8 *ipad = NULL; 1176 u8 *opad; 1177 int ret; 1178 1179 tfm = crypto_alloc_ahash(hash_alg_name, CRYPTO_ALG_TYPE_AHASH, 1180 CRYPTO_ALG_TYPE_AHASH_MASK); 1181 if (IS_ERR(tfm)) 1182 return PTR_ERR(tfm); 1183 1184 req = ahash_request_alloc(tfm, GFP_KERNEL); 1185 if (!req) { 1186 ret = -ENOMEM; 1187 goto free_ahash; 1188 } 1189 1190 crypto_ahash_clear_flags(tfm, ~0); 1191 1192 blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); 1193 1194 ipad = kzalloc(2 * blocksize, GFP_KERNEL); 1195 if (!ipad) { 1196 ret = -ENOMEM; 1197 goto free_req; 1198 } 1199 1200 opad = ipad + blocksize; 1201 1202 ret = mv_cesa_ahmac_pad_init(req, key, keylen, ipad, opad, blocksize); 1203 if (ret) 1204 goto free_ipad; 1205 1206 ret = mv_cesa_ahmac_iv_state_init(req, ipad, istate, blocksize); 1207 if (ret) 1208 goto free_ipad; 1209 1210 ret = mv_cesa_ahmac_iv_state_init(req, opad, ostate, blocksize); 1211 1212free_ipad: 1213 kfree(ipad); 1214free_req: 1215 ahash_request_free(req); 1216free_ahash: 1217 crypto_free_ahash(tfm); 1218 1219 return ret; 1220} 1221 1222static int mv_cesa_ahmac_cra_init(struct crypto_tfm *tfm) 1223{ 1224 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(tfm); 1225 1226 ctx->base.ops = &mv_cesa_ahash_req_ops; 1227 1228 crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 1229 sizeof(struct mv_cesa_ahash_req)); 1230 return 0; 1231} 1232 1233static int mv_cesa_ahmac_md5_init(struct ahash_request *req) 1234{ 1235 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm); 1236 struct mv_cesa_op_ctx tmpl; 1237 1238 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_MD5); 1239 memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv)); 1240 1241 mv_cesa_ahash_init(req, &tmpl); 1242 1243 return 0; 1244} 1245 1246static int mv_cesa_ahmac_md5_setkey(struct crypto_ahash *tfm, const u8 *key, 1247 unsigned int keylen) 1248{ 1249 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 1250 struct md5_state istate, ostate; 1251 int ret, i; 1252 1253 ret = mv_cesa_ahmac_setkey("mv-md5", key, keylen, &istate, &ostate); 1254 if (ret) 1255 return ret; 1256 1257 for (i = 0; i < ARRAY_SIZE(istate.hash); i++) 1258 ctx->iv[i] = be32_to_cpu(istate.hash[i]); 1259 1260 for (i = 0; i < ARRAY_SIZE(ostate.hash); i++) 1261 ctx->iv[i + 8] = be32_to_cpu(ostate.hash[i]); 1262 1263 return 0; 1264} 1265 1266static int mv_cesa_ahmac_md5_digest(struct ahash_request *req) 1267{ 1268 int ret; 1269 1270 ret = mv_cesa_ahmac_md5_init(req); 1271 if (ret) 1272 return ret; 1273 1274 return mv_cesa_ahash_finup(req); 1275} 1276 1277struct ahash_alg mv_ahmac_md5_alg = { 1278 .init = mv_cesa_ahmac_md5_init, 1279 .update = mv_cesa_ahash_update, 1280 .final = mv_cesa_ahash_final, 1281 .finup = mv_cesa_ahash_finup, 1282 .digest = mv_cesa_ahmac_md5_digest, 1283 .setkey = mv_cesa_ahmac_md5_setkey, 1284 .export = mv_cesa_md5_export, 1285 .import = mv_cesa_md5_import, 1286 .halg = { 1287 .digestsize = MD5_DIGEST_SIZE, 1288 .statesize = sizeof(struct md5_state), 1289 .base = { 1290 .cra_name = "hmac(md5)", 1291 .cra_driver_name = "mv-hmac-md5", 1292 .cra_priority = 300, 1293 .cra_flags = CRYPTO_ALG_ASYNC | 1294 CRYPTO_ALG_KERN_DRIVER_ONLY, 1295 .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 1296 .cra_ctxsize = sizeof(struct mv_cesa_hmac_ctx), 1297 .cra_init = mv_cesa_ahmac_cra_init, 1298 .cra_module = THIS_MODULE, 1299 } 1300 } 1301}; 1302 1303static int mv_cesa_ahmac_sha1_init(struct ahash_request *req) 1304{ 1305 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm); 1306 struct mv_cesa_op_ctx tmpl; 1307 1308 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_SHA1); 1309 memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv)); 1310 1311 mv_cesa_ahash_init(req, &tmpl); 1312 1313 return 0; 1314} 1315 1316static int mv_cesa_ahmac_sha1_setkey(struct crypto_ahash *tfm, const u8 *key, 1317 unsigned int keylen) 1318{ 1319 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 1320 struct sha1_state istate, ostate; 1321 int ret, i; 1322 1323 ret = mv_cesa_ahmac_setkey("mv-sha1", key, keylen, &istate, &ostate); 1324 if (ret) 1325 return ret; 1326 1327 for (i = 0; i < ARRAY_SIZE(istate.state); i++) 1328 ctx->iv[i] = be32_to_cpu(istate.state[i]); 1329 1330 for (i = 0; i < ARRAY_SIZE(ostate.state); i++) 1331 ctx->iv[i + 8] = be32_to_cpu(ostate.state[i]); 1332 1333 return 0; 1334} 1335 1336static int mv_cesa_ahmac_sha1_digest(struct ahash_request *req) 1337{ 1338 int ret; 1339 1340 ret = mv_cesa_ahmac_sha1_init(req); 1341 if (ret) 1342 return ret; 1343 1344 return mv_cesa_ahash_finup(req); 1345} 1346 1347struct ahash_alg mv_ahmac_sha1_alg = { 1348 .init = mv_cesa_ahmac_sha1_init, 1349 .update = mv_cesa_ahash_update, 1350 .final = mv_cesa_ahash_final, 1351 .finup = mv_cesa_ahash_finup, 1352 .digest = mv_cesa_ahmac_sha1_digest, 1353 .setkey = mv_cesa_ahmac_sha1_setkey, 1354 .export = mv_cesa_sha1_export, 1355 .import = mv_cesa_sha1_import, 1356 .halg = { 1357 .digestsize = SHA1_DIGEST_SIZE, 1358 .statesize = sizeof(struct sha1_state), 1359 .base = { 1360 .cra_name = "hmac(sha1)", 1361 .cra_driver_name = "mv-hmac-sha1", 1362 .cra_priority = 300, 1363 .cra_flags = CRYPTO_ALG_ASYNC | 1364 CRYPTO_ALG_KERN_DRIVER_ONLY, 1365 .cra_blocksize = SHA1_BLOCK_SIZE, 1366 .cra_ctxsize = sizeof(struct mv_cesa_hmac_ctx), 1367 .cra_init = mv_cesa_ahmac_cra_init, 1368 .cra_module = THIS_MODULE, 1369 } 1370 } 1371}; 1372 1373static int mv_cesa_ahmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key, 1374 unsigned int keylen) 1375{ 1376 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); 1377 struct sha256_state istate, ostate; 1378 int ret, i; 1379 1380 ret = mv_cesa_ahmac_setkey("mv-sha256", key, keylen, &istate, &ostate); 1381 if (ret) 1382 return ret; 1383 1384 for (i = 0; i < ARRAY_SIZE(istate.state); i++) 1385 ctx->iv[i] = be32_to_cpu(istate.state[i]); 1386 1387 for (i = 0; i < ARRAY_SIZE(ostate.state); i++) 1388 ctx->iv[i + 8] = be32_to_cpu(ostate.state[i]); 1389 1390 return 0; 1391} 1392 1393static int mv_cesa_ahmac_sha256_init(struct ahash_request *req) 1394{ 1395 struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm); 1396 struct mv_cesa_op_ctx tmpl; 1397 1398 mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_SHA256); 1399 memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv)); 1400 1401 mv_cesa_ahash_init(req, &tmpl); 1402 1403 return 0; 1404} 1405 1406static int mv_cesa_ahmac_sha256_digest(struct ahash_request *req) 1407{ 1408 int ret; 1409 1410 ret = mv_cesa_ahmac_sha256_init(req); 1411 if (ret) 1412 return ret; 1413 1414 return mv_cesa_ahash_finup(req); 1415} 1416 1417struct ahash_alg mv_ahmac_sha256_alg = { 1418 .init = mv_cesa_ahmac_sha256_init, 1419 .update = mv_cesa_ahash_update, 1420 .final = mv_cesa_ahash_final, 1421 .finup = mv_cesa_ahash_finup, 1422 .digest = mv_cesa_ahmac_sha256_digest, 1423 .setkey = mv_cesa_ahmac_sha256_setkey, 1424 .export = mv_cesa_sha256_export, 1425 .import = mv_cesa_sha256_import, 1426 .halg = { 1427 .digestsize = SHA256_DIGEST_SIZE, 1428 .statesize = sizeof(struct sha256_state), 1429 .base = { 1430 .cra_name = "hmac(sha256)", 1431 .cra_driver_name = "mv-hmac-sha256", 1432 .cra_priority = 300, 1433 .cra_flags = CRYPTO_ALG_ASYNC | 1434 CRYPTO_ALG_KERN_DRIVER_ONLY, 1435 .cra_blocksize = SHA256_BLOCK_SIZE, 1436 .cra_ctxsize = sizeof(struct mv_cesa_hmac_ctx), 1437 .cra_init = mv_cesa_ahmac_cra_init, 1438 .cra_module = THIS_MODULE, 1439 } 1440 } 1441};