18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * caam - Freescale FSL CAAM support for ahash functions of crypto API 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2011 Freescale Semiconductor, Inc. 68c2ecf20Sopenharmony_ci * Copyright 2018-2019 NXP 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Based on caamalg.c crypto API driver. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * relationship of digest job descriptor or first job descriptor after init to 118c2ecf20Sopenharmony_ci * shared descriptors: 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * --------------- --------------- 148c2ecf20Sopenharmony_ci * | JobDesc #1 |-------------------->| ShareDesc | 158c2ecf20Sopenharmony_ci * | *(packet 1) | | (hashKey) | 168c2ecf20Sopenharmony_ci * --------------- | (operation) | 178c2ecf20Sopenharmony_ci * --------------- 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * relationship of subsequent job descriptors to shared descriptors: 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * --------------- --------------- 228c2ecf20Sopenharmony_ci * | JobDesc #2 |-------------------->| ShareDesc | 238c2ecf20Sopenharmony_ci * | *(packet 2) | |------------->| (hashKey) | 248c2ecf20Sopenharmony_ci * --------------- | |-------->| (operation) | 258c2ecf20Sopenharmony_ci * . | | | (load ctx2) | 268c2ecf20Sopenharmony_ci * . | | --------------- 278c2ecf20Sopenharmony_ci * --------------- | | 288c2ecf20Sopenharmony_ci * | JobDesc #3 |------| | 298c2ecf20Sopenharmony_ci * | *(packet 3) | | 308c2ecf20Sopenharmony_ci * --------------- | 318c2ecf20Sopenharmony_ci * . | 328c2ecf20Sopenharmony_ci * . | 338c2ecf20Sopenharmony_ci * --------------- | 348c2ecf20Sopenharmony_ci * | JobDesc #4 |------------ 358c2ecf20Sopenharmony_ci * | *(packet 4) | 368c2ecf20Sopenharmony_ci * --------------- 378c2ecf20Sopenharmony_ci * 388c2ecf20Sopenharmony_ci * The SharedDesc never changes for a connection unless rekeyed, but 398c2ecf20Sopenharmony_ci * each packet will likely be in a different place. So all we need 408c2ecf20Sopenharmony_ci * to know to process the packet is where the input is, where the 418c2ecf20Sopenharmony_ci * output goes, and what context we want to process with. Context is 428c2ecf20Sopenharmony_ci * in the SharedDesc, packet references in the JobDesc. 438c2ecf20Sopenharmony_ci * 448c2ecf20Sopenharmony_ci * So, a job desc looks like: 458c2ecf20Sopenharmony_ci * 468c2ecf20Sopenharmony_ci * --------------------- 478c2ecf20Sopenharmony_ci * | Header | 488c2ecf20Sopenharmony_ci * | ShareDesc Pointer | 498c2ecf20Sopenharmony_ci * | SEQ_OUT_PTR | 508c2ecf20Sopenharmony_ci * | (output buffer) | 518c2ecf20Sopenharmony_ci * | (output length) | 528c2ecf20Sopenharmony_ci * | SEQ_IN_PTR | 538c2ecf20Sopenharmony_ci * | (input buffer) | 548c2ecf20Sopenharmony_ci * | (input length) | 558c2ecf20Sopenharmony_ci * --------------------- 568c2ecf20Sopenharmony_ci */ 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci#include "compat.h" 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#include "regs.h" 618c2ecf20Sopenharmony_ci#include "intern.h" 628c2ecf20Sopenharmony_ci#include "desc_constr.h" 638c2ecf20Sopenharmony_ci#include "jr.h" 648c2ecf20Sopenharmony_ci#include "error.h" 658c2ecf20Sopenharmony_ci#include "sg_sw_sec4.h" 668c2ecf20Sopenharmony_ci#include "key_gen.h" 678c2ecf20Sopenharmony_ci#include "caamhash_desc.h" 688c2ecf20Sopenharmony_ci#include <crypto/engine.h> 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci#define CAAM_CRA_PRIORITY 3000 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci/* max hash key is max split key size */ 738c2ecf20Sopenharmony_ci#define CAAM_MAX_HASH_KEY_SIZE (SHA512_DIGEST_SIZE * 2) 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci#define CAAM_MAX_HASH_BLOCK_SIZE SHA512_BLOCK_SIZE 768c2ecf20Sopenharmony_ci#define CAAM_MAX_HASH_DIGEST_SIZE SHA512_DIGEST_SIZE 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci#define DESC_HASH_MAX_USED_BYTES (DESC_AHASH_FINAL_LEN + \ 798c2ecf20Sopenharmony_ci CAAM_MAX_HASH_KEY_SIZE) 808c2ecf20Sopenharmony_ci#define DESC_HASH_MAX_USED_LEN (DESC_HASH_MAX_USED_BYTES / CAAM_CMD_SZ) 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/* caam context sizes for hashes: running digest + 8 */ 838c2ecf20Sopenharmony_ci#define HASH_MSG_LEN 8 848c2ecf20Sopenharmony_ci#define MAX_CTX_LEN (HASH_MSG_LEN + SHA512_DIGEST_SIZE) 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic struct list_head hash_list; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci/* ahash per-session context */ 898c2ecf20Sopenharmony_cistruct caam_hash_ctx { 908c2ecf20Sopenharmony_ci struct crypto_engine_ctx enginectx; 918c2ecf20Sopenharmony_ci u32 sh_desc_update[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned; 928c2ecf20Sopenharmony_ci u32 sh_desc_update_first[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned; 938c2ecf20Sopenharmony_ci u32 sh_desc_fin[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned; 948c2ecf20Sopenharmony_ci u32 sh_desc_digest[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned; 958c2ecf20Sopenharmony_ci u8 key[CAAM_MAX_HASH_KEY_SIZE] ____cacheline_aligned; 968c2ecf20Sopenharmony_ci dma_addr_t sh_desc_update_dma ____cacheline_aligned; 978c2ecf20Sopenharmony_ci dma_addr_t sh_desc_update_first_dma; 988c2ecf20Sopenharmony_ci dma_addr_t sh_desc_fin_dma; 998c2ecf20Sopenharmony_ci dma_addr_t sh_desc_digest_dma; 1008c2ecf20Sopenharmony_ci enum dma_data_direction dir; 1018c2ecf20Sopenharmony_ci enum dma_data_direction key_dir; 1028c2ecf20Sopenharmony_ci struct device *jrdev; 1038c2ecf20Sopenharmony_ci int ctx_len; 1048c2ecf20Sopenharmony_ci struct alginfo adata; 1058c2ecf20Sopenharmony_ci}; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci/* ahash state */ 1088c2ecf20Sopenharmony_cistruct caam_hash_state { 1098c2ecf20Sopenharmony_ci dma_addr_t buf_dma; 1108c2ecf20Sopenharmony_ci dma_addr_t ctx_dma; 1118c2ecf20Sopenharmony_ci int ctx_dma_len; 1128c2ecf20Sopenharmony_ci u8 buf[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned; 1138c2ecf20Sopenharmony_ci int buflen; 1148c2ecf20Sopenharmony_ci int next_buflen; 1158c2ecf20Sopenharmony_ci u8 caam_ctx[MAX_CTX_LEN] ____cacheline_aligned; 1168c2ecf20Sopenharmony_ci int (*update)(struct ahash_request *req) ____cacheline_aligned; 1178c2ecf20Sopenharmony_ci int (*final)(struct ahash_request *req); 1188c2ecf20Sopenharmony_ci int (*finup)(struct ahash_request *req); 1198c2ecf20Sopenharmony_ci struct ahash_edesc *edesc; 1208c2ecf20Sopenharmony_ci void (*ahash_op_done)(struct device *jrdev, u32 *desc, u32 err, 1218c2ecf20Sopenharmony_ci void *context); 1228c2ecf20Sopenharmony_ci}; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistruct caam_export_state { 1258c2ecf20Sopenharmony_ci u8 buf[CAAM_MAX_HASH_BLOCK_SIZE]; 1268c2ecf20Sopenharmony_ci u8 caam_ctx[MAX_CTX_LEN]; 1278c2ecf20Sopenharmony_ci int buflen; 1288c2ecf20Sopenharmony_ci int (*update)(struct ahash_request *req); 1298c2ecf20Sopenharmony_ci int (*final)(struct ahash_request *req); 1308c2ecf20Sopenharmony_ci int (*finup)(struct ahash_request *req); 1318c2ecf20Sopenharmony_ci}; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic inline bool is_cmac_aes(u32 algtype) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci return (algtype & (OP_ALG_ALGSEL_MASK | OP_ALG_AAI_MASK)) == 1368c2ecf20Sopenharmony_ci (OP_ALG_ALGSEL_AES | OP_ALG_AAI_CMAC); 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci/* Common job descriptor seq in/out ptr routines */ 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci/* Map state->caam_ctx, and append seq_out_ptr command that points to it */ 1418c2ecf20Sopenharmony_cistatic inline int map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev, 1428c2ecf20Sopenharmony_ci struct caam_hash_state *state, 1438c2ecf20Sopenharmony_ci int ctx_len) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci state->ctx_dma_len = ctx_len; 1468c2ecf20Sopenharmony_ci state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, 1478c2ecf20Sopenharmony_ci ctx_len, DMA_FROM_DEVICE); 1488c2ecf20Sopenharmony_ci if (dma_mapping_error(jrdev, state->ctx_dma)) { 1498c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to map ctx\n"); 1508c2ecf20Sopenharmony_ci state->ctx_dma = 0; 1518c2ecf20Sopenharmony_ci return -ENOMEM; 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci append_seq_out_ptr(desc, state->ctx_dma, ctx_len, 0); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci return 0; 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci/* Map current buffer in state (if length > 0) and put it in link table */ 1608c2ecf20Sopenharmony_cistatic inline int buf_map_to_sec4_sg(struct device *jrdev, 1618c2ecf20Sopenharmony_ci struct sec4_sg_entry *sec4_sg, 1628c2ecf20Sopenharmony_ci struct caam_hash_state *state) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci int buflen = state->buflen; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci if (!buflen) 1678c2ecf20Sopenharmony_ci return 0; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci state->buf_dma = dma_map_single(jrdev, state->buf, buflen, 1708c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 1718c2ecf20Sopenharmony_ci if (dma_mapping_error(jrdev, state->buf_dma)) { 1728c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to map buf\n"); 1738c2ecf20Sopenharmony_ci state->buf_dma = 0; 1748c2ecf20Sopenharmony_ci return -ENOMEM; 1758c2ecf20Sopenharmony_ci } 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci dma_to_sec4_sg_one(sec4_sg, state->buf_dma, buflen, 0); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci return 0; 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci/* Map state->caam_ctx, and add it to link table */ 1838c2ecf20Sopenharmony_cistatic inline int ctx_map_to_sec4_sg(struct device *jrdev, 1848c2ecf20Sopenharmony_ci struct caam_hash_state *state, int ctx_len, 1858c2ecf20Sopenharmony_ci struct sec4_sg_entry *sec4_sg, u32 flag) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci state->ctx_dma_len = ctx_len; 1888c2ecf20Sopenharmony_ci state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, ctx_len, flag); 1898c2ecf20Sopenharmony_ci if (dma_mapping_error(jrdev, state->ctx_dma)) { 1908c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to map ctx\n"); 1918c2ecf20Sopenharmony_ci state->ctx_dma = 0; 1928c2ecf20Sopenharmony_ci return -ENOMEM; 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci dma_to_sec4_sg_one(sec4_sg, state->ctx_dma, ctx_len, 0); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci return 0; 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic int ahash_set_sh_desc(struct crypto_ahash *ahash) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 2038c2ecf20Sopenharmony_ci int digestsize = crypto_ahash_digestsize(ahash); 2048c2ecf20Sopenharmony_ci struct device *jrdev = ctx->jrdev; 2058c2ecf20Sopenharmony_ci struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent); 2068c2ecf20Sopenharmony_ci u32 *desc; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci ctx->adata.key_virt = ctx->key; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci /* ahash_update shared descriptor */ 2118c2ecf20Sopenharmony_ci desc = ctx->sh_desc_update; 2128c2ecf20Sopenharmony_ci cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_UPDATE, ctx->ctx_len, 2138c2ecf20Sopenharmony_ci ctx->ctx_len, true, ctrlpriv->era); 2148c2ecf20Sopenharmony_ci dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma, 2158c2ecf20Sopenharmony_ci desc_bytes(desc), ctx->dir); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci print_hex_dump_debug("ahash update shdesc@"__stringify(__LINE__)": ", 2188c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 2198c2ecf20Sopenharmony_ci 1); 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci /* ahash_update_first shared descriptor */ 2228c2ecf20Sopenharmony_ci desc = ctx->sh_desc_update_first; 2238c2ecf20Sopenharmony_ci cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len, 2248c2ecf20Sopenharmony_ci ctx->ctx_len, false, ctrlpriv->era); 2258c2ecf20Sopenharmony_ci dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma, 2268c2ecf20Sopenharmony_ci desc_bytes(desc), ctx->dir); 2278c2ecf20Sopenharmony_ci print_hex_dump_debug("ahash update first shdesc@"__stringify(__LINE__) 2288c2ecf20Sopenharmony_ci ": ", DUMP_PREFIX_ADDRESS, 16, 4, desc, 2298c2ecf20Sopenharmony_ci desc_bytes(desc), 1); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci /* ahash_final shared descriptor */ 2328c2ecf20Sopenharmony_ci desc = ctx->sh_desc_fin; 2338c2ecf20Sopenharmony_ci cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_FINALIZE, digestsize, 2348c2ecf20Sopenharmony_ci ctx->ctx_len, true, ctrlpriv->era); 2358c2ecf20Sopenharmony_ci dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma, 2368c2ecf20Sopenharmony_ci desc_bytes(desc), ctx->dir); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci print_hex_dump_debug("ahash final shdesc@"__stringify(__LINE__)": ", 2398c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, 2408c2ecf20Sopenharmony_ci desc_bytes(desc), 1); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci /* ahash_digest shared descriptor */ 2438c2ecf20Sopenharmony_ci desc = ctx->sh_desc_digest; 2448c2ecf20Sopenharmony_ci cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INITFINAL, digestsize, 2458c2ecf20Sopenharmony_ci ctx->ctx_len, false, ctrlpriv->era); 2468c2ecf20Sopenharmony_ci dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma, 2478c2ecf20Sopenharmony_ci desc_bytes(desc), ctx->dir); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci print_hex_dump_debug("ahash digest shdesc@"__stringify(__LINE__)": ", 2508c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, 2518c2ecf20Sopenharmony_ci desc_bytes(desc), 1); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci return 0; 2548c2ecf20Sopenharmony_ci} 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_cistatic int axcbc_set_sh_desc(struct crypto_ahash *ahash) 2578c2ecf20Sopenharmony_ci{ 2588c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 2598c2ecf20Sopenharmony_ci int digestsize = crypto_ahash_digestsize(ahash); 2608c2ecf20Sopenharmony_ci struct device *jrdev = ctx->jrdev; 2618c2ecf20Sopenharmony_ci u32 *desc; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci /* shared descriptor for ahash_update */ 2648c2ecf20Sopenharmony_ci desc = ctx->sh_desc_update; 2658c2ecf20Sopenharmony_ci cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_UPDATE, 2668c2ecf20Sopenharmony_ci ctx->ctx_len, ctx->ctx_len); 2678c2ecf20Sopenharmony_ci dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma, 2688c2ecf20Sopenharmony_ci desc_bytes(desc), ctx->dir); 2698c2ecf20Sopenharmony_ci print_hex_dump_debug("axcbc update shdesc@" __stringify(__LINE__)" : ", 2708c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 2718c2ecf20Sopenharmony_ci 1); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci /* shared descriptor for ahash_{final,finup} */ 2748c2ecf20Sopenharmony_ci desc = ctx->sh_desc_fin; 2758c2ecf20Sopenharmony_ci cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_FINALIZE, 2768c2ecf20Sopenharmony_ci digestsize, ctx->ctx_len); 2778c2ecf20Sopenharmony_ci dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma, 2788c2ecf20Sopenharmony_ci desc_bytes(desc), ctx->dir); 2798c2ecf20Sopenharmony_ci print_hex_dump_debug("axcbc finup shdesc@" __stringify(__LINE__)" : ", 2808c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 2818c2ecf20Sopenharmony_ci 1); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci /* key is immediate data for INIT and INITFINAL states */ 2848c2ecf20Sopenharmony_ci ctx->adata.key_virt = ctx->key; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci /* shared descriptor for first invocation of ahash_update */ 2878c2ecf20Sopenharmony_ci desc = ctx->sh_desc_update_first; 2888c2ecf20Sopenharmony_ci cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len, 2898c2ecf20Sopenharmony_ci ctx->ctx_len); 2908c2ecf20Sopenharmony_ci dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma, 2918c2ecf20Sopenharmony_ci desc_bytes(desc), ctx->dir); 2928c2ecf20Sopenharmony_ci print_hex_dump_debug("axcbc update first shdesc@" __stringify(__LINE__) 2938c2ecf20Sopenharmony_ci " : ", DUMP_PREFIX_ADDRESS, 16, 4, desc, 2948c2ecf20Sopenharmony_ci desc_bytes(desc), 1); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci /* shared descriptor for ahash_digest */ 2978c2ecf20Sopenharmony_ci desc = ctx->sh_desc_digest; 2988c2ecf20Sopenharmony_ci cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INITFINAL, 2998c2ecf20Sopenharmony_ci digestsize, ctx->ctx_len); 3008c2ecf20Sopenharmony_ci dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma, 3018c2ecf20Sopenharmony_ci desc_bytes(desc), ctx->dir); 3028c2ecf20Sopenharmony_ci print_hex_dump_debug("axcbc digest shdesc@" __stringify(__LINE__)" : ", 3038c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 3048c2ecf20Sopenharmony_ci 1); 3058c2ecf20Sopenharmony_ci return 0; 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cistatic int acmac_set_sh_desc(struct crypto_ahash *ahash) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 3118c2ecf20Sopenharmony_ci int digestsize = crypto_ahash_digestsize(ahash); 3128c2ecf20Sopenharmony_ci struct device *jrdev = ctx->jrdev; 3138c2ecf20Sopenharmony_ci u32 *desc; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci /* shared descriptor for ahash_update */ 3168c2ecf20Sopenharmony_ci desc = ctx->sh_desc_update; 3178c2ecf20Sopenharmony_ci cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_UPDATE, 3188c2ecf20Sopenharmony_ci ctx->ctx_len, ctx->ctx_len); 3198c2ecf20Sopenharmony_ci dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma, 3208c2ecf20Sopenharmony_ci desc_bytes(desc), ctx->dir); 3218c2ecf20Sopenharmony_ci print_hex_dump_debug("acmac update shdesc@" __stringify(__LINE__)" : ", 3228c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, 3238c2ecf20Sopenharmony_ci desc_bytes(desc), 1); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci /* shared descriptor for ahash_{final,finup} */ 3268c2ecf20Sopenharmony_ci desc = ctx->sh_desc_fin; 3278c2ecf20Sopenharmony_ci cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_FINALIZE, 3288c2ecf20Sopenharmony_ci digestsize, ctx->ctx_len); 3298c2ecf20Sopenharmony_ci dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma, 3308c2ecf20Sopenharmony_ci desc_bytes(desc), ctx->dir); 3318c2ecf20Sopenharmony_ci print_hex_dump_debug("acmac finup shdesc@" __stringify(__LINE__)" : ", 3328c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, 3338c2ecf20Sopenharmony_ci desc_bytes(desc), 1); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci /* shared descriptor for first invocation of ahash_update */ 3368c2ecf20Sopenharmony_ci desc = ctx->sh_desc_update_first; 3378c2ecf20Sopenharmony_ci cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len, 3388c2ecf20Sopenharmony_ci ctx->ctx_len); 3398c2ecf20Sopenharmony_ci dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma, 3408c2ecf20Sopenharmony_ci desc_bytes(desc), ctx->dir); 3418c2ecf20Sopenharmony_ci print_hex_dump_debug("acmac update first shdesc@" __stringify(__LINE__) 3428c2ecf20Sopenharmony_ci " : ", DUMP_PREFIX_ADDRESS, 16, 4, desc, 3438c2ecf20Sopenharmony_ci desc_bytes(desc), 1); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci /* shared descriptor for ahash_digest */ 3468c2ecf20Sopenharmony_ci desc = ctx->sh_desc_digest; 3478c2ecf20Sopenharmony_ci cnstr_shdsc_sk_hash(desc, &ctx->adata, OP_ALG_AS_INITFINAL, 3488c2ecf20Sopenharmony_ci digestsize, ctx->ctx_len); 3498c2ecf20Sopenharmony_ci dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma, 3508c2ecf20Sopenharmony_ci desc_bytes(desc), ctx->dir); 3518c2ecf20Sopenharmony_ci print_hex_dump_debug("acmac digest shdesc@" __stringify(__LINE__)" : ", 3528c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, 3538c2ecf20Sopenharmony_ci desc_bytes(desc), 1); 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci return 0; 3568c2ecf20Sopenharmony_ci} 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci/* Digest hash size if it is too large */ 3598c2ecf20Sopenharmony_cistatic int hash_digest_key(struct caam_hash_ctx *ctx, u32 *keylen, u8 *key, 3608c2ecf20Sopenharmony_ci u32 digestsize) 3618c2ecf20Sopenharmony_ci{ 3628c2ecf20Sopenharmony_ci struct device *jrdev = ctx->jrdev; 3638c2ecf20Sopenharmony_ci u32 *desc; 3648c2ecf20Sopenharmony_ci struct split_key_result result; 3658c2ecf20Sopenharmony_ci dma_addr_t key_dma; 3668c2ecf20Sopenharmony_ci int ret; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci desc = kmalloc(CAAM_CMD_SZ * 8 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA); 3698c2ecf20Sopenharmony_ci if (!desc) { 3708c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to allocate key input memory\n"); 3718c2ecf20Sopenharmony_ci return -ENOMEM; 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci init_job_desc(desc, 0); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci key_dma = dma_map_single(jrdev, key, *keylen, DMA_BIDIRECTIONAL); 3778c2ecf20Sopenharmony_ci if (dma_mapping_error(jrdev, key_dma)) { 3788c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to map key memory\n"); 3798c2ecf20Sopenharmony_ci kfree(desc); 3808c2ecf20Sopenharmony_ci return -ENOMEM; 3818c2ecf20Sopenharmony_ci } 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci /* Job descriptor to perform unkeyed hash on key_in */ 3848c2ecf20Sopenharmony_ci append_operation(desc, ctx->adata.algtype | OP_ALG_ENCRYPT | 3858c2ecf20Sopenharmony_ci OP_ALG_AS_INITFINAL); 3868c2ecf20Sopenharmony_ci append_seq_in_ptr(desc, key_dma, *keylen, 0); 3878c2ecf20Sopenharmony_ci append_seq_fifo_load(desc, *keylen, FIFOLD_CLASS_CLASS2 | 3888c2ecf20Sopenharmony_ci FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_MSG); 3898c2ecf20Sopenharmony_ci append_seq_out_ptr(desc, key_dma, digestsize, 0); 3908c2ecf20Sopenharmony_ci append_seq_store(desc, digestsize, LDST_CLASS_2_CCB | 3918c2ecf20Sopenharmony_ci LDST_SRCDST_BYTE_CONTEXT); 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci print_hex_dump_debug("key_in@"__stringify(__LINE__)": ", 3948c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, key, *keylen, 1); 3958c2ecf20Sopenharmony_ci print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ", 3968c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 3978c2ecf20Sopenharmony_ci 1); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci result.err = 0; 4008c2ecf20Sopenharmony_ci init_completion(&result.completion); 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result); 4038c2ecf20Sopenharmony_ci if (ret == -EINPROGRESS) { 4048c2ecf20Sopenharmony_ci /* in progress */ 4058c2ecf20Sopenharmony_ci wait_for_completion(&result.completion); 4068c2ecf20Sopenharmony_ci ret = result.err; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci print_hex_dump_debug("digested key@"__stringify(__LINE__)": ", 4098c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, key, 4108c2ecf20Sopenharmony_ci digestsize, 1); 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci dma_unmap_single(jrdev, key_dma, *keylen, DMA_BIDIRECTIONAL); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci *keylen = digestsize; 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci kfree(desc); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci return ret; 4198c2ecf20Sopenharmony_ci} 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_cistatic int ahash_setkey(struct crypto_ahash *ahash, 4228c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 4238c2ecf20Sopenharmony_ci{ 4248c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 4258c2ecf20Sopenharmony_ci struct device *jrdev = ctx->jrdev; 4268c2ecf20Sopenharmony_ci int blocksize = crypto_tfm_alg_blocksize(&ahash->base); 4278c2ecf20Sopenharmony_ci int digestsize = crypto_ahash_digestsize(ahash); 4288c2ecf20Sopenharmony_ci struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctx->jrdev->parent); 4298c2ecf20Sopenharmony_ci int ret; 4308c2ecf20Sopenharmony_ci u8 *hashed_key = NULL; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci dev_dbg(jrdev, "keylen %d\n", keylen); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci if (keylen > blocksize) { 4358c2ecf20Sopenharmony_ci hashed_key = kmemdup(key, keylen, GFP_KERNEL | GFP_DMA); 4368c2ecf20Sopenharmony_ci if (!hashed_key) 4378c2ecf20Sopenharmony_ci return -ENOMEM; 4388c2ecf20Sopenharmony_ci ret = hash_digest_key(ctx, &keylen, hashed_key, digestsize); 4398c2ecf20Sopenharmony_ci if (ret) 4408c2ecf20Sopenharmony_ci goto bad_free_key; 4418c2ecf20Sopenharmony_ci key = hashed_key; 4428c2ecf20Sopenharmony_ci } 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci /* 4458c2ecf20Sopenharmony_ci * If DKP is supported, use it in the shared descriptor to generate 4468c2ecf20Sopenharmony_ci * the split key. 4478c2ecf20Sopenharmony_ci */ 4488c2ecf20Sopenharmony_ci if (ctrlpriv->era >= 6) { 4498c2ecf20Sopenharmony_ci ctx->adata.key_inline = true; 4508c2ecf20Sopenharmony_ci ctx->adata.keylen = keylen; 4518c2ecf20Sopenharmony_ci ctx->adata.keylen_pad = split_key_len(ctx->adata.algtype & 4528c2ecf20Sopenharmony_ci OP_ALG_ALGSEL_MASK); 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci if (ctx->adata.keylen_pad > CAAM_MAX_HASH_KEY_SIZE) 4558c2ecf20Sopenharmony_ci goto bad_free_key; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci memcpy(ctx->key, key, keylen); 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci /* 4608c2ecf20Sopenharmony_ci * In case |user key| > |derived key|, using DKP<imm,imm> 4618c2ecf20Sopenharmony_ci * would result in invalid opcodes (last bytes of user key) in 4628c2ecf20Sopenharmony_ci * the resulting descriptor. Use DKP<ptr,imm> instead => both 4638c2ecf20Sopenharmony_ci * virtual and dma key addresses are needed. 4648c2ecf20Sopenharmony_ci */ 4658c2ecf20Sopenharmony_ci if (keylen > ctx->adata.keylen_pad) 4668c2ecf20Sopenharmony_ci dma_sync_single_for_device(ctx->jrdev, 4678c2ecf20Sopenharmony_ci ctx->adata.key_dma, 4688c2ecf20Sopenharmony_ci ctx->adata.keylen_pad, 4698c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 4708c2ecf20Sopenharmony_ci } else { 4718c2ecf20Sopenharmony_ci ret = gen_split_key(ctx->jrdev, ctx->key, &ctx->adata, key, 4728c2ecf20Sopenharmony_ci keylen, CAAM_MAX_HASH_KEY_SIZE); 4738c2ecf20Sopenharmony_ci if (ret) 4748c2ecf20Sopenharmony_ci goto bad_free_key; 4758c2ecf20Sopenharmony_ci } 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci kfree(hashed_key); 4788c2ecf20Sopenharmony_ci return ahash_set_sh_desc(ahash); 4798c2ecf20Sopenharmony_ci bad_free_key: 4808c2ecf20Sopenharmony_ci kfree(hashed_key); 4818c2ecf20Sopenharmony_ci return -EINVAL; 4828c2ecf20Sopenharmony_ci} 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_cistatic int axcbc_setkey(struct crypto_ahash *ahash, const u8 *key, 4858c2ecf20Sopenharmony_ci unsigned int keylen) 4868c2ecf20Sopenharmony_ci{ 4878c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 4888c2ecf20Sopenharmony_ci struct device *jrdev = ctx->jrdev; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci if (keylen != AES_KEYSIZE_128) 4918c2ecf20Sopenharmony_ci return -EINVAL; 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci memcpy(ctx->key, key, keylen); 4948c2ecf20Sopenharmony_ci dma_sync_single_for_device(jrdev, ctx->adata.key_dma, keylen, 4958c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 4968c2ecf20Sopenharmony_ci ctx->adata.keylen = keylen; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci print_hex_dump_debug("axcbc ctx.key@" __stringify(__LINE__)" : ", 4998c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, keylen, 1); 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci return axcbc_set_sh_desc(ahash); 5028c2ecf20Sopenharmony_ci} 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_cistatic int acmac_setkey(struct crypto_ahash *ahash, const u8 *key, 5058c2ecf20Sopenharmony_ci unsigned int keylen) 5068c2ecf20Sopenharmony_ci{ 5078c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 5088c2ecf20Sopenharmony_ci int err; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci err = aes_check_keylen(keylen); 5118c2ecf20Sopenharmony_ci if (err) 5128c2ecf20Sopenharmony_ci return err; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci /* key is immediate data for all cmac shared descriptors */ 5158c2ecf20Sopenharmony_ci ctx->adata.key_virt = key; 5168c2ecf20Sopenharmony_ci ctx->adata.keylen = keylen; 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci print_hex_dump_debug("acmac ctx.key@" __stringify(__LINE__)" : ", 5198c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci return acmac_set_sh_desc(ahash); 5228c2ecf20Sopenharmony_ci} 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci/* 5258c2ecf20Sopenharmony_ci * ahash_edesc - s/w-extended ahash descriptor 5268c2ecf20Sopenharmony_ci * @sec4_sg_dma: physical mapped address of h/w link table 5278c2ecf20Sopenharmony_ci * @src_nents: number of segments in input scatterlist 5288c2ecf20Sopenharmony_ci * @sec4_sg_bytes: length of dma mapped sec4_sg space 5298c2ecf20Sopenharmony_ci * @bklog: stored to determine if the request needs backlog 5308c2ecf20Sopenharmony_ci * @hw_desc: the h/w job descriptor followed by any referenced link tables 5318c2ecf20Sopenharmony_ci * @sec4_sg: h/w link table 5328c2ecf20Sopenharmony_ci */ 5338c2ecf20Sopenharmony_cistruct ahash_edesc { 5348c2ecf20Sopenharmony_ci dma_addr_t sec4_sg_dma; 5358c2ecf20Sopenharmony_ci int src_nents; 5368c2ecf20Sopenharmony_ci int sec4_sg_bytes; 5378c2ecf20Sopenharmony_ci bool bklog; 5388c2ecf20Sopenharmony_ci u32 hw_desc[DESC_JOB_IO_LEN_MAX / sizeof(u32)] ____cacheline_aligned; 5398c2ecf20Sopenharmony_ci struct sec4_sg_entry sec4_sg[]; 5408c2ecf20Sopenharmony_ci}; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_cistatic inline void ahash_unmap(struct device *dev, 5438c2ecf20Sopenharmony_ci struct ahash_edesc *edesc, 5448c2ecf20Sopenharmony_ci struct ahash_request *req, int dst_len) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci if (edesc->src_nents) 5498c2ecf20Sopenharmony_ci dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE); 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci if (edesc->sec4_sg_bytes) 5528c2ecf20Sopenharmony_ci dma_unmap_single(dev, edesc->sec4_sg_dma, 5538c2ecf20Sopenharmony_ci edesc->sec4_sg_bytes, DMA_TO_DEVICE); 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci if (state->buf_dma) { 5568c2ecf20Sopenharmony_ci dma_unmap_single(dev, state->buf_dma, state->buflen, 5578c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 5588c2ecf20Sopenharmony_ci state->buf_dma = 0; 5598c2ecf20Sopenharmony_ci } 5608c2ecf20Sopenharmony_ci} 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_cistatic inline void ahash_unmap_ctx(struct device *dev, 5638c2ecf20Sopenharmony_ci struct ahash_edesc *edesc, 5648c2ecf20Sopenharmony_ci struct ahash_request *req, int dst_len, u32 flag) 5658c2ecf20Sopenharmony_ci{ 5668c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci if (state->ctx_dma) { 5698c2ecf20Sopenharmony_ci dma_unmap_single(dev, state->ctx_dma, state->ctx_dma_len, flag); 5708c2ecf20Sopenharmony_ci state->ctx_dma = 0; 5718c2ecf20Sopenharmony_ci } 5728c2ecf20Sopenharmony_ci ahash_unmap(dev, edesc, req, dst_len); 5738c2ecf20Sopenharmony_ci} 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_cistatic inline void ahash_done_cpy(struct device *jrdev, u32 *desc, u32 err, 5768c2ecf20Sopenharmony_ci void *context, enum dma_data_direction dir) 5778c2ecf20Sopenharmony_ci{ 5788c2ecf20Sopenharmony_ci struct ahash_request *req = context; 5798c2ecf20Sopenharmony_ci struct caam_drv_private_jr *jrp = dev_get_drvdata(jrdev); 5808c2ecf20Sopenharmony_ci struct ahash_edesc *edesc; 5818c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 5828c2ecf20Sopenharmony_ci int digestsize = crypto_ahash_digestsize(ahash); 5838c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 5848c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 5858c2ecf20Sopenharmony_ci int ecode = 0; 5868c2ecf20Sopenharmony_ci bool has_bklog; 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci edesc = state->edesc; 5918c2ecf20Sopenharmony_ci has_bklog = edesc->bklog; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci if (err) 5948c2ecf20Sopenharmony_ci ecode = caam_jr_strstatus(jrdev, err); 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci ahash_unmap_ctx(jrdev, edesc, req, digestsize, dir); 5978c2ecf20Sopenharmony_ci memcpy(req->result, state->caam_ctx, digestsize); 5988c2ecf20Sopenharmony_ci kfree(edesc); 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci print_hex_dump_debug("ctx@"__stringify(__LINE__)": ", 6018c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx, 6028c2ecf20Sopenharmony_ci ctx->ctx_len, 1); 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci /* 6058c2ecf20Sopenharmony_ci * If no backlog flag, the completion of the request is done 6068c2ecf20Sopenharmony_ci * by CAAM, not crypto engine. 6078c2ecf20Sopenharmony_ci */ 6088c2ecf20Sopenharmony_ci if (!has_bklog) 6098c2ecf20Sopenharmony_ci req->base.complete(&req->base, ecode); 6108c2ecf20Sopenharmony_ci else 6118c2ecf20Sopenharmony_ci crypto_finalize_hash_request(jrp->engine, req, ecode); 6128c2ecf20Sopenharmony_ci} 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_cistatic void ahash_done(struct device *jrdev, u32 *desc, u32 err, 6158c2ecf20Sopenharmony_ci void *context) 6168c2ecf20Sopenharmony_ci{ 6178c2ecf20Sopenharmony_ci ahash_done_cpy(jrdev, desc, err, context, DMA_FROM_DEVICE); 6188c2ecf20Sopenharmony_ci} 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_cistatic void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err, 6218c2ecf20Sopenharmony_ci void *context) 6228c2ecf20Sopenharmony_ci{ 6238c2ecf20Sopenharmony_ci ahash_done_cpy(jrdev, desc, err, context, DMA_BIDIRECTIONAL); 6248c2ecf20Sopenharmony_ci} 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_cistatic inline void ahash_done_switch(struct device *jrdev, u32 *desc, u32 err, 6278c2ecf20Sopenharmony_ci void *context, enum dma_data_direction dir) 6288c2ecf20Sopenharmony_ci{ 6298c2ecf20Sopenharmony_ci struct ahash_request *req = context; 6308c2ecf20Sopenharmony_ci struct caam_drv_private_jr *jrp = dev_get_drvdata(jrdev); 6318c2ecf20Sopenharmony_ci struct ahash_edesc *edesc; 6328c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 6338c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 6348c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 6358c2ecf20Sopenharmony_ci int digestsize = crypto_ahash_digestsize(ahash); 6368c2ecf20Sopenharmony_ci int ecode = 0; 6378c2ecf20Sopenharmony_ci bool has_bklog; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci dev_dbg(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err); 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci edesc = state->edesc; 6428c2ecf20Sopenharmony_ci has_bklog = edesc->bklog; 6438c2ecf20Sopenharmony_ci if (err) 6448c2ecf20Sopenharmony_ci ecode = caam_jr_strstatus(jrdev, err); 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, dir); 6478c2ecf20Sopenharmony_ci kfree(edesc); 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(state->buf, req->src, 6508c2ecf20Sopenharmony_ci req->nbytes - state->next_buflen, 6518c2ecf20Sopenharmony_ci state->next_buflen, 0); 6528c2ecf20Sopenharmony_ci state->buflen = state->next_buflen; 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci print_hex_dump_debug("buf@" __stringify(__LINE__)": ", 6558c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, state->buf, 6568c2ecf20Sopenharmony_ci state->buflen, 1); 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci print_hex_dump_debug("ctx@"__stringify(__LINE__)": ", 6598c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx, 6608c2ecf20Sopenharmony_ci ctx->ctx_len, 1); 6618c2ecf20Sopenharmony_ci if (req->result) 6628c2ecf20Sopenharmony_ci print_hex_dump_debug("result@"__stringify(__LINE__)": ", 6638c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, req->result, 6648c2ecf20Sopenharmony_ci digestsize, 1); 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci /* 6678c2ecf20Sopenharmony_ci * If no backlog flag, the completion of the request is done 6688c2ecf20Sopenharmony_ci * by CAAM, not crypto engine. 6698c2ecf20Sopenharmony_ci */ 6708c2ecf20Sopenharmony_ci if (!has_bklog) 6718c2ecf20Sopenharmony_ci req->base.complete(&req->base, ecode); 6728c2ecf20Sopenharmony_ci else 6738c2ecf20Sopenharmony_ci crypto_finalize_hash_request(jrp->engine, req, ecode); 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci} 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_cistatic void ahash_done_bi(struct device *jrdev, u32 *desc, u32 err, 6788c2ecf20Sopenharmony_ci void *context) 6798c2ecf20Sopenharmony_ci{ 6808c2ecf20Sopenharmony_ci ahash_done_switch(jrdev, desc, err, context, DMA_BIDIRECTIONAL); 6818c2ecf20Sopenharmony_ci} 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_cistatic void ahash_done_ctx_dst(struct device *jrdev, u32 *desc, u32 err, 6848c2ecf20Sopenharmony_ci void *context) 6858c2ecf20Sopenharmony_ci{ 6868c2ecf20Sopenharmony_ci ahash_done_switch(jrdev, desc, err, context, DMA_FROM_DEVICE); 6878c2ecf20Sopenharmony_ci} 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci/* 6908c2ecf20Sopenharmony_ci * Allocate an enhanced descriptor, which contains the hardware descriptor 6918c2ecf20Sopenharmony_ci * and space for hardware scatter table containing sg_num entries. 6928c2ecf20Sopenharmony_ci */ 6938c2ecf20Sopenharmony_cistatic struct ahash_edesc *ahash_edesc_alloc(struct ahash_request *req, 6948c2ecf20Sopenharmony_ci int sg_num, u32 *sh_desc, 6958c2ecf20Sopenharmony_ci dma_addr_t sh_desc_dma) 6968c2ecf20Sopenharmony_ci{ 6978c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 6988c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 6998c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 7008c2ecf20Sopenharmony_ci gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? 7018c2ecf20Sopenharmony_ci GFP_KERNEL : GFP_ATOMIC; 7028c2ecf20Sopenharmony_ci struct ahash_edesc *edesc; 7038c2ecf20Sopenharmony_ci unsigned int sg_size = sg_num * sizeof(struct sec4_sg_entry); 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci edesc = kzalloc(sizeof(*edesc) + sg_size, GFP_DMA | flags); 7068c2ecf20Sopenharmony_ci if (!edesc) { 7078c2ecf20Sopenharmony_ci dev_err(ctx->jrdev, "could not allocate extended descriptor\n"); 7088c2ecf20Sopenharmony_ci return NULL; 7098c2ecf20Sopenharmony_ci } 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci state->edesc = edesc; 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci init_job_desc_shared(edesc->hw_desc, sh_desc_dma, desc_len(sh_desc), 7148c2ecf20Sopenharmony_ci HDR_SHARE_DEFER | HDR_REVERSE); 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci return edesc; 7178c2ecf20Sopenharmony_ci} 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_cistatic int ahash_edesc_add_src(struct caam_hash_ctx *ctx, 7208c2ecf20Sopenharmony_ci struct ahash_edesc *edesc, 7218c2ecf20Sopenharmony_ci struct ahash_request *req, int nents, 7228c2ecf20Sopenharmony_ci unsigned int first_sg, 7238c2ecf20Sopenharmony_ci unsigned int first_bytes, size_t to_hash) 7248c2ecf20Sopenharmony_ci{ 7258c2ecf20Sopenharmony_ci dma_addr_t src_dma; 7268c2ecf20Sopenharmony_ci u32 options; 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci if (nents > 1 || first_sg) { 7298c2ecf20Sopenharmony_ci struct sec4_sg_entry *sg = edesc->sec4_sg; 7308c2ecf20Sopenharmony_ci unsigned int sgsize = sizeof(*sg) * 7318c2ecf20Sopenharmony_ci pad_sg_nents(first_sg + nents); 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci sg_to_sec4_sg_last(req->src, to_hash, sg + first_sg, 0); 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci src_dma = dma_map_single(ctx->jrdev, sg, sgsize, DMA_TO_DEVICE); 7368c2ecf20Sopenharmony_ci if (dma_mapping_error(ctx->jrdev, src_dma)) { 7378c2ecf20Sopenharmony_ci dev_err(ctx->jrdev, "unable to map S/G table\n"); 7388c2ecf20Sopenharmony_ci return -ENOMEM; 7398c2ecf20Sopenharmony_ci } 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci edesc->sec4_sg_bytes = sgsize; 7428c2ecf20Sopenharmony_ci edesc->sec4_sg_dma = src_dma; 7438c2ecf20Sopenharmony_ci options = LDST_SGF; 7448c2ecf20Sopenharmony_ci } else { 7458c2ecf20Sopenharmony_ci src_dma = sg_dma_address(req->src); 7468c2ecf20Sopenharmony_ci options = 0; 7478c2ecf20Sopenharmony_ci } 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci append_seq_in_ptr(edesc->hw_desc, src_dma, first_bytes + to_hash, 7508c2ecf20Sopenharmony_ci options); 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci return 0; 7538c2ecf20Sopenharmony_ci} 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_cistatic int ahash_do_one_req(struct crypto_engine *engine, void *areq) 7568c2ecf20Sopenharmony_ci{ 7578c2ecf20Sopenharmony_ci struct ahash_request *req = ahash_request_cast(areq); 7588c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 7598c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 7608c2ecf20Sopenharmony_ci struct device *jrdev = ctx->jrdev; 7618c2ecf20Sopenharmony_ci u32 *desc = state->edesc->hw_desc; 7628c2ecf20Sopenharmony_ci int ret; 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci state->edesc->bklog = true; 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci ret = caam_jr_enqueue(jrdev, desc, state->ahash_op_done, req); 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci if (ret != -EINPROGRESS) { 7698c2ecf20Sopenharmony_ci ahash_unmap(jrdev, state->edesc, req, 0); 7708c2ecf20Sopenharmony_ci kfree(state->edesc); 7718c2ecf20Sopenharmony_ci } else { 7728c2ecf20Sopenharmony_ci ret = 0; 7738c2ecf20Sopenharmony_ci } 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci return ret; 7768c2ecf20Sopenharmony_ci} 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_cistatic int ahash_enqueue_req(struct device *jrdev, 7798c2ecf20Sopenharmony_ci void (*cbk)(struct device *jrdev, u32 *desc, 7808c2ecf20Sopenharmony_ci u32 err, void *context), 7818c2ecf20Sopenharmony_ci struct ahash_request *req, 7828c2ecf20Sopenharmony_ci int dst_len, enum dma_data_direction dir) 7838c2ecf20Sopenharmony_ci{ 7848c2ecf20Sopenharmony_ci struct caam_drv_private_jr *jrpriv = dev_get_drvdata(jrdev); 7858c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 7868c2ecf20Sopenharmony_ci struct ahash_edesc *edesc = state->edesc; 7878c2ecf20Sopenharmony_ci u32 *desc = edesc->hw_desc; 7888c2ecf20Sopenharmony_ci int ret; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci state->ahash_op_done = cbk; 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci /* 7938c2ecf20Sopenharmony_ci * Only the backlog request are sent to crypto-engine since the others 7948c2ecf20Sopenharmony_ci * can be handled by CAAM, if free, especially since JR has up to 1024 7958c2ecf20Sopenharmony_ci * entries (more than the 10 entries from crypto-engine). 7968c2ecf20Sopenharmony_ci */ 7978c2ecf20Sopenharmony_ci if (req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG) 7988c2ecf20Sopenharmony_ci ret = crypto_transfer_hash_request_to_engine(jrpriv->engine, 7998c2ecf20Sopenharmony_ci req); 8008c2ecf20Sopenharmony_ci else 8018c2ecf20Sopenharmony_ci ret = caam_jr_enqueue(jrdev, desc, cbk, req); 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci if ((ret != -EINPROGRESS) && (ret != -EBUSY)) { 8048c2ecf20Sopenharmony_ci ahash_unmap_ctx(jrdev, edesc, req, dst_len, dir); 8058c2ecf20Sopenharmony_ci kfree(edesc); 8068c2ecf20Sopenharmony_ci } 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci return ret; 8098c2ecf20Sopenharmony_ci} 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci/* submit update job descriptor */ 8128c2ecf20Sopenharmony_cistatic int ahash_update_ctx(struct ahash_request *req) 8138c2ecf20Sopenharmony_ci{ 8148c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 8158c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 8168c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 8178c2ecf20Sopenharmony_ci struct device *jrdev = ctx->jrdev; 8188c2ecf20Sopenharmony_ci u8 *buf = state->buf; 8198c2ecf20Sopenharmony_ci int *buflen = &state->buflen; 8208c2ecf20Sopenharmony_ci int *next_buflen = &state->next_buflen; 8218c2ecf20Sopenharmony_ci int blocksize = crypto_ahash_blocksize(ahash); 8228c2ecf20Sopenharmony_ci int in_len = *buflen + req->nbytes, to_hash; 8238c2ecf20Sopenharmony_ci u32 *desc; 8248c2ecf20Sopenharmony_ci int src_nents, mapped_nents, sec4_sg_bytes, sec4_sg_src_index; 8258c2ecf20Sopenharmony_ci struct ahash_edesc *edesc; 8268c2ecf20Sopenharmony_ci int ret = 0; 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci *next_buflen = in_len & (blocksize - 1); 8298c2ecf20Sopenharmony_ci to_hash = in_len - *next_buflen; 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci /* 8328c2ecf20Sopenharmony_ci * For XCBC and CMAC, if to_hash is multiple of block size, 8338c2ecf20Sopenharmony_ci * keep last block in internal buffer 8348c2ecf20Sopenharmony_ci */ 8358c2ecf20Sopenharmony_ci if ((is_xcbc_aes(ctx->adata.algtype) || 8368c2ecf20Sopenharmony_ci is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize && 8378c2ecf20Sopenharmony_ci (*next_buflen == 0)) { 8388c2ecf20Sopenharmony_ci *next_buflen = blocksize; 8398c2ecf20Sopenharmony_ci to_hash -= blocksize; 8408c2ecf20Sopenharmony_ci } 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci if (to_hash) { 8438c2ecf20Sopenharmony_ci int pad_nents; 8448c2ecf20Sopenharmony_ci int src_len = req->nbytes - *next_buflen; 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci src_nents = sg_nents_for_len(req->src, src_len); 8478c2ecf20Sopenharmony_ci if (src_nents < 0) { 8488c2ecf20Sopenharmony_ci dev_err(jrdev, "Invalid number of src SG.\n"); 8498c2ecf20Sopenharmony_ci return src_nents; 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci if (src_nents) { 8538c2ecf20Sopenharmony_ci mapped_nents = dma_map_sg(jrdev, req->src, src_nents, 8548c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 8558c2ecf20Sopenharmony_ci if (!mapped_nents) { 8568c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to DMA map source\n"); 8578c2ecf20Sopenharmony_ci return -ENOMEM; 8588c2ecf20Sopenharmony_ci } 8598c2ecf20Sopenharmony_ci } else { 8608c2ecf20Sopenharmony_ci mapped_nents = 0; 8618c2ecf20Sopenharmony_ci } 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci sec4_sg_src_index = 1 + (*buflen ? 1 : 0); 8648c2ecf20Sopenharmony_ci pad_nents = pad_sg_nents(sec4_sg_src_index + mapped_nents); 8658c2ecf20Sopenharmony_ci sec4_sg_bytes = pad_nents * sizeof(struct sec4_sg_entry); 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci /* 8688c2ecf20Sopenharmony_ci * allocate space for base edesc and hw desc commands, 8698c2ecf20Sopenharmony_ci * link tables 8708c2ecf20Sopenharmony_ci */ 8718c2ecf20Sopenharmony_ci edesc = ahash_edesc_alloc(req, pad_nents, ctx->sh_desc_update, 8728c2ecf20Sopenharmony_ci ctx->sh_desc_update_dma); 8738c2ecf20Sopenharmony_ci if (!edesc) { 8748c2ecf20Sopenharmony_ci dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE); 8758c2ecf20Sopenharmony_ci return -ENOMEM; 8768c2ecf20Sopenharmony_ci } 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci edesc->src_nents = src_nents; 8798c2ecf20Sopenharmony_ci edesc->sec4_sg_bytes = sec4_sg_bytes; 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len, 8828c2ecf20Sopenharmony_ci edesc->sec4_sg, DMA_BIDIRECTIONAL); 8838c2ecf20Sopenharmony_ci if (ret) 8848c2ecf20Sopenharmony_ci goto unmap_ctx; 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, state); 8878c2ecf20Sopenharmony_ci if (ret) 8888c2ecf20Sopenharmony_ci goto unmap_ctx; 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci if (mapped_nents) 8918c2ecf20Sopenharmony_ci sg_to_sec4_sg_last(req->src, src_len, 8928c2ecf20Sopenharmony_ci edesc->sec4_sg + sec4_sg_src_index, 8938c2ecf20Sopenharmony_ci 0); 8948c2ecf20Sopenharmony_ci else 8958c2ecf20Sopenharmony_ci sg_to_sec4_set_last(edesc->sec4_sg + sec4_sg_src_index - 8968c2ecf20Sopenharmony_ci 1); 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci desc = edesc->hw_desc; 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, 9018c2ecf20Sopenharmony_ci sec4_sg_bytes, 9028c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 9038c2ecf20Sopenharmony_ci if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) { 9048c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to map S/G table\n"); 9058c2ecf20Sopenharmony_ci ret = -ENOMEM; 9068c2ecf20Sopenharmony_ci goto unmap_ctx; 9078c2ecf20Sopenharmony_ci } 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + 9108c2ecf20Sopenharmony_ci to_hash, LDST_SGF); 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci append_seq_out_ptr(desc, state->ctx_dma, ctx->ctx_len, 0); 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ", 9158c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, 9168c2ecf20Sopenharmony_ci desc_bytes(desc), 1); 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci ret = ahash_enqueue_req(jrdev, ahash_done_bi, req, 9198c2ecf20Sopenharmony_ci ctx->ctx_len, DMA_BIDIRECTIONAL); 9208c2ecf20Sopenharmony_ci } else if (*next_buflen) { 9218c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(buf + *buflen, req->src, 0, 9228c2ecf20Sopenharmony_ci req->nbytes, 0); 9238c2ecf20Sopenharmony_ci *buflen = *next_buflen; 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci print_hex_dump_debug("buf@" __stringify(__LINE__)": ", 9268c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, buf, 9278c2ecf20Sopenharmony_ci *buflen, 1); 9288c2ecf20Sopenharmony_ci } 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci return ret; 9318c2ecf20Sopenharmony_ciunmap_ctx: 9328c2ecf20Sopenharmony_ci ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_BIDIRECTIONAL); 9338c2ecf20Sopenharmony_ci kfree(edesc); 9348c2ecf20Sopenharmony_ci return ret; 9358c2ecf20Sopenharmony_ci} 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_cistatic int ahash_final_ctx(struct ahash_request *req) 9388c2ecf20Sopenharmony_ci{ 9398c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 9408c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 9418c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 9428c2ecf20Sopenharmony_ci struct device *jrdev = ctx->jrdev; 9438c2ecf20Sopenharmony_ci int buflen = state->buflen; 9448c2ecf20Sopenharmony_ci u32 *desc; 9458c2ecf20Sopenharmony_ci int sec4_sg_bytes; 9468c2ecf20Sopenharmony_ci int digestsize = crypto_ahash_digestsize(ahash); 9478c2ecf20Sopenharmony_ci struct ahash_edesc *edesc; 9488c2ecf20Sopenharmony_ci int ret; 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci sec4_sg_bytes = pad_sg_nents(1 + (buflen ? 1 : 0)) * 9518c2ecf20Sopenharmony_ci sizeof(struct sec4_sg_entry); 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci /* allocate space for base edesc and hw desc commands, link tables */ 9548c2ecf20Sopenharmony_ci edesc = ahash_edesc_alloc(req, 4, ctx->sh_desc_fin, 9558c2ecf20Sopenharmony_ci ctx->sh_desc_fin_dma); 9568c2ecf20Sopenharmony_ci if (!edesc) 9578c2ecf20Sopenharmony_ci return -ENOMEM; 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci desc = edesc->hw_desc; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci edesc->sec4_sg_bytes = sec4_sg_bytes; 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len, 9648c2ecf20Sopenharmony_ci edesc->sec4_sg, DMA_BIDIRECTIONAL); 9658c2ecf20Sopenharmony_ci if (ret) 9668c2ecf20Sopenharmony_ci goto unmap_ctx; 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, state); 9698c2ecf20Sopenharmony_ci if (ret) 9708c2ecf20Sopenharmony_ci goto unmap_ctx; 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci sg_to_sec4_set_last(edesc->sec4_sg + (buflen ? 1 : 0)); 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, 9758c2ecf20Sopenharmony_ci sec4_sg_bytes, DMA_TO_DEVICE); 9768c2ecf20Sopenharmony_ci if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) { 9778c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to map S/G table\n"); 9788c2ecf20Sopenharmony_ci ret = -ENOMEM; 9798c2ecf20Sopenharmony_ci goto unmap_ctx; 9808c2ecf20Sopenharmony_ci } 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + buflen, 9838c2ecf20Sopenharmony_ci LDST_SGF); 9848c2ecf20Sopenharmony_ci append_seq_out_ptr(desc, state->ctx_dma, digestsize, 0); 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ", 9878c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 9888c2ecf20Sopenharmony_ci 1); 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci return ahash_enqueue_req(jrdev, ahash_done_ctx_src, req, 9918c2ecf20Sopenharmony_ci digestsize, DMA_BIDIRECTIONAL); 9928c2ecf20Sopenharmony_ci unmap_ctx: 9938c2ecf20Sopenharmony_ci ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL); 9948c2ecf20Sopenharmony_ci kfree(edesc); 9958c2ecf20Sopenharmony_ci return ret; 9968c2ecf20Sopenharmony_ci} 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_cistatic int ahash_finup_ctx(struct ahash_request *req) 9998c2ecf20Sopenharmony_ci{ 10008c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 10018c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 10028c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 10038c2ecf20Sopenharmony_ci struct device *jrdev = ctx->jrdev; 10048c2ecf20Sopenharmony_ci int buflen = state->buflen; 10058c2ecf20Sopenharmony_ci u32 *desc; 10068c2ecf20Sopenharmony_ci int sec4_sg_src_index; 10078c2ecf20Sopenharmony_ci int src_nents, mapped_nents; 10088c2ecf20Sopenharmony_ci int digestsize = crypto_ahash_digestsize(ahash); 10098c2ecf20Sopenharmony_ci struct ahash_edesc *edesc; 10108c2ecf20Sopenharmony_ci int ret; 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci src_nents = sg_nents_for_len(req->src, req->nbytes); 10138c2ecf20Sopenharmony_ci if (src_nents < 0) { 10148c2ecf20Sopenharmony_ci dev_err(jrdev, "Invalid number of src SG.\n"); 10158c2ecf20Sopenharmony_ci return src_nents; 10168c2ecf20Sopenharmony_ci } 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci if (src_nents) { 10198c2ecf20Sopenharmony_ci mapped_nents = dma_map_sg(jrdev, req->src, src_nents, 10208c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 10218c2ecf20Sopenharmony_ci if (!mapped_nents) { 10228c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to DMA map source\n"); 10238c2ecf20Sopenharmony_ci return -ENOMEM; 10248c2ecf20Sopenharmony_ci } 10258c2ecf20Sopenharmony_ci } else { 10268c2ecf20Sopenharmony_ci mapped_nents = 0; 10278c2ecf20Sopenharmony_ci } 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci sec4_sg_src_index = 1 + (buflen ? 1 : 0); 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci /* allocate space for base edesc and hw desc commands, link tables */ 10328c2ecf20Sopenharmony_ci edesc = ahash_edesc_alloc(req, sec4_sg_src_index + mapped_nents, 10338c2ecf20Sopenharmony_ci ctx->sh_desc_fin, ctx->sh_desc_fin_dma); 10348c2ecf20Sopenharmony_ci if (!edesc) { 10358c2ecf20Sopenharmony_ci dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE); 10368c2ecf20Sopenharmony_ci return -ENOMEM; 10378c2ecf20Sopenharmony_ci } 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci desc = edesc->hw_desc; 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci edesc->src_nents = src_nents; 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len, 10448c2ecf20Sopenharmony_ci edesc->sec4_sg, DMA_BIDIRECTIONAL); 10458c2ecf20Sopenharmony_ci if (ret) 10468c2ecf20Sopenharmony_ci goto unmap_ctx; 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, state); 10498c2ecf20Sopenharmony_ci if (ret) 10508c2ecf20Sopenharmony_ci goto unmap_ctx; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 10538c2ecf20Sopenharmony_ci sec4_sg_src_index, ctx->ctx_len + buflen, 10548c2ecf20Sopenharmony_ci req->nbytes); 10558c2ecf20Sopenharmony_ci if (ret) 10568c2ecf20Sopenharmony_ci goto unmap_ctx; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci append_seq_out_ptr(desc, state->ctx_dma, digestsize, 0); 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_ci print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ", 10618c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 10628c2ecf20Sopenharmony_ci 1); 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci return ahash_enqueue_req(jrdev, ahash_done_ctx_src, req, 10658c2ecf20Sopenharmony_ci digestsize, DMA_BIDIRECTIONAL); 10668c2ecf20Sopenharmony_ci unmap_ctx: 10678c2ecf20Sopenharmony_ci ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_BIDIRECTIONAL); 10688c2ecf20Sopenharmony_ci kfree(edesc); 10698c2ecf20Sopenharmony_ci return ret; 10708c2ecf20Sopenharmony_ci} 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_cistatic int ahash_digest(struct ahash_request *req) 10738c2ecf20Sopenharmony_ci{ 10748c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 10758c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 10768c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 10778c2ecf20Sopenharmony_ci struct device *jrdev = ctx->jrdev; 10788c2ecf20Sopenharmony_ci u32 *desc; 10798c2ecf20Sopenharmony_ci int digestsize = crypto_ahash_digestsize(ahash); 10808c2ecf20Sopenharmony_ci int src_nents, mapped_nents; 10818c2ecf20Sopenharmony_ci struct ahash_edesc *edesc; 10828c2ecf20Sopenharmony_ci int ret; 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci state->buf_dma = 0; 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci src_nents = sg_nents_for_len(req->src, req->nbytes); 10878c2ecf20Sopenharmony_ci if (src_nents < 0) { 10888c2ecf20Sopenharmony_ci dev_err(jrdev, "Invalid number of src SG.\n"); 10898c2ecf20Sopenharmony_ci return src_nents; 10908c2ecf20Sopenharmony_ci } 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci if (src_nents) { 10938c2ecf20Sopenharmony_ci mapped_nents = dma_map_sg(jrdev, req->src, src_nents, 10948c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 10958c2ecf20Sopenharmony_ci if (!mapped_nents) { 10968c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to map source for DMA\n"); 10978c2ecf20Sopenharmony_ci return -ENOMEM; 10988c2ecf20Sopenharmony_ci } 10998c2ecf20Sopenharmony_ci } else { 11008c2ecf20Sopenharmony_ci mapped_nents = 0; 11018c2ecf20Sopenharmony_ci } 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci /* allocate space for base edesc and hw desc commands, link tables */ 11048c2ecf20Sopenharmony_ci edesc = ahash_edesc_alloc(req, mapped_nents > 1 ? mapped_nents : 0, 11058c2ecf20Sopenharmony_ci ctx->sh_desc_digest, ctx->sh_desc_digest_dma); 11068c2ecf20Sopenharmony_ci if (!edesc) { 11078c2ecf20Sopenharmony_ci dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE); 11088c2ecf20Sopenharmony_ci return -ENOMEM; 11098c2ecf20Sopenharmony_ci } 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci edesc->src_nents = src_nents; 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_ci ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 0, 0, 11148c2ecf20Sopenharmony_ci req->nbytes); 11158c2ecf20Sopenharmony_ci if (ret) { 11168c2ecf20Sopenharmony_ci ahash_unmap(jrdev, edesc, req, digestsize); 11178c2ecf20Sopenharmony_ci kfree(edesc); 11188c2ecf20Sopenharmony_ci return ret; 11198c2ecf20Sopenharmony_ci } 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci desc = edesc->hw_desc; 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize); 11248c2ecf20Sopenharmony_ci if (ret) { 11258c2ecf20Sopenharmony_ci ahash_unmap(jrdev, edesc, req, digestsize); 11268c2ecf20Sopenharmony_ci kfree(edesc); 11278c2ecf20Sopenharmony_ci return -ENOMEM; 11288c2ecf20Sopenharmony_ci } 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ", 11318c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 11328c2ecf20Sopenharmony_ci 1); 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci return ahash_enqueue_req(jrdev, ahash_done, req, digestsize, 11358c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 11368c2ecf20Sopenharmony_ci} 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci/* submit ahash final if it the first job descriptor */ 11398c2ecf20Sopenharmony_cistatic int ahash_final_no_ctx(struct ahash_request *req) 11408c2ecf20Sopenharmony_ci{ 11418c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 11428c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 11438c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 11448c2ecf20Sopenharmony_ci struct device *jrdev = ctx->jrdev; 11458c2ecf20Sopenharmony_ci u8 *buf = state->buf; 11468c2ecf20Sopenharmony_ci int buflen = state->buflen; 11478c2ecf20Sopenharmony_ci u32 *desc; 11488c2ecf20Sopenharmony_ci int digestsize = crypto_ahash_digestsize(ahash); 11498c2ecf20Sopenharmony_ci struct ahash_edesc *edesc; 11508c2ecf20Sopenharmony_ci int ret; 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci /* allocate space for base edesc and hw desc commands, link tables */ 11538c2ecf20Sopenharmony_ci edesc = ahash_edesc_alloc(req, 0, ctx->sh_desc_digest, 11548c2ecf20Sopenharmony_ci ctx->sh_desc_digest_dma); 11558c2ecf20Sopenharmony_ci if (!edesc) 11568c2ecf20Sopenharmony_ci return -ENOMEM; 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci desc = edesc->hw_desc; 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci if (buflen) { 11618c2ecf20Sopenharmony_ci state->buf_dma = dma_map_single(jrdev, buf, buflen, 11628c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 11638c2ecf20Sopenharmony_ci if (dma_mapping_error(jrdev, state->buf_dma)) { 11648c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to map src\n"); 11658c2ecf20Sopenharmony_ci goto unmap; 11668c2ecf20Sopenharmony_ci } 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci append_seq_in_ptr(desc, state->buf_dma, buflen, 0); 11698c2ecf20Sopenharmony_ci } 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize); 11728c2ecf20Sopenharmony_ci if (ret) 11738c2ecf20Sopenharmony_ci goto unmap; 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ", 11768c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 11778c2ecf20Sopenharmony_ci 1); 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci return ahash_enqueue_req(jrdev, ahash_done, req, 11808c2ecf20Sopenharmony_ci digestsize, DMA_FROM_DEVICE); 11818c2ecf20Sopenharmony_ci unmap: 11828c2ecf20Sopenharmony_ci ahash_unmap(jrdev, edesc, req, digestsize); 11838c2ecf20Sopenharmony_ci kfree(edesc); 11848c2ecf20Sopenharmony_ci return -ENOMEM; 11858c2ecf20Sopenharmony_ci} 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci/* submit ahash update if it the first job descriptor after update */ 11888c2ecf20Sopenharmony_cistatic int ahash_update_no_ctx(struct ahash_request *req) 11898c2ecf20Sopenharmony_ci{ 11908c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 11918c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 11928c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 11938c2ecf20Sopenharmony_ci struct device *jrdev = ctx->jrdev; 11948c2ecf20Sopenharmony_ci u8 *buf = state->buf; 11958c2ecf20Sopenharmony_ci int *buflen = &state->buflen; 11968c2ecf20Sopenharmony_ci int *next_buflen = &state->next_buflen; 11978c2ecf20Sopenharmony_ci int blocksize = crypto_ahash_blocksize(ahash); 11988c2ecf20Sopenharmony_ci int in_len = *buflen + req->nbytes, to_hash; 11998c2ecf20Sopenharmony_ci int sec4_sg_bytes, src_nents, mapped_nents; 12008c2ecf20Sopenharmony_ci struct ahash_edesc *edesc; 12018c2ecf20Sopenharmony_ci u32 *desc; 12028c2ecf20Sopenharmony_ci int ret = 0; 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci *next_buflen = in_len & (blocksize - 1); 12058c2ecf20Sopenharmony_ci to_hash = in_len - *next_buflen; 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci /* 12088c2ecf20Sopenharmony_ci * For XCBC and CMAC, if to_hash is multiple of block size, 12098c2ecf20Sopenharmony_ci * keep last block in internal buffer 12108c2ecf20Sopenharmony_ci */ 12118c2ecf20Sopenharmony_ci if ((is_xcbc_aes(ctx->adata.algtype) || 12128c2ecf20Sopenharmony_ci is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize && 12138c2ecf20Sopenharmony_ci (*next_buflen == 0)) { 12148c2ecf20Sopenharmony_ci *next_buflen = blocksize; 12158c2ecf20Sopenharmony_ci to_hash -= blocksize; 12168c2ecf20Sopenharmony_ci } 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci if (to_hash) { 12198c2ecf20Sopenharmony_ci int pad_nents; 12208c2ecf20Sopenharmony_ci int src_len = req->nbytes - *next_buflen; 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci src_nents = sg_nents_for_len(req->src, src_len); 12238c2ecf20Sopenharmony_ci if (src_nents < 0) { 12248c2ecf20Sopenharmony_ci dev_err(jrdev, "Invalid number of src SG.\n"); 12258c2ecf20Sopenharmony_ci return src_nents; 12268c2ecf20Sopenharmony_ci } 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci if (src_nents) { 12298c2ecf20Sopenharmony_ci mapped_nents = dma_map_sg(jrdev, req->src, src_nents, 12308c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 12318c2ecf20Sopenharmony_ci if (!mapped_nents) { 12328c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to DMA map source\n"); 12338c2ecf20Sopenharmony_ci return -ENOMEM; 12348c2ecf20Sopenharmony_ci } 12358c2ecf20Sopenharmony_ci } else { 12368c2ecf20Sopenharmony_ci mapped_nents = 0; 12378c2ecf20Sopenharmony_ci } 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci pad_nents = pad_sg_nents(1 + mapped_nents); 12408c2ecf20Sopenharmony_ci sec4_sg_bytes = pad_nents * sizeof(struct sec4_sg_entry); 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci /* 12438c2ecf20Sopenharmony_ci * allocate space for base edesc and hw desc commands, 12448c2ecf20Sopenharmony_ci * link tables 12458c2ecf20Sopenharmony_ci */ 12468c2ecf20Sopenharmony_ci edesc = ahash_edesc_alloc(req, pad_nents, 12478c2ecf20Sopenharmony_ci ctx->sh_desc_update_first, 12488c2ecf20Sopenharmony_ci ctx->sh_desc_update_first_dma); 12498c2ecf20Sopenharmony_ci if (!edesc) { 12508c2ecf20Sopenharmony_ci dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE); 12518c2ecf20Sopenharmony_ci return -ENOMEM; 12528c2ecf20Sopenharmony_ci } 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_ci edesc->src_nents = src_nents; 12558c2ecf20Sopenharmony_ci edesc->sec4_sg_bytes = sec4_sg_bytes; 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, state); 12588c2ecf20Sopenharmony_ci if (ret) 12598c2ecf20Sopenharmony_ci goto unmap_ctx; 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci sg_to_sec4_sg_last(req->src, src_len, edesc->sec4_sg + 1, 0); 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci desc = edesc->hw_desc; 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_ci edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, 12668c2ecf20Sopenharmony_ci sec4_sg_bytes, 12678c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 12688c2ecf20Sopenharmony_ci if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) { 12698c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to map S/G table\n"); 12708c2ecf20Sopenharmony_ci ret = -ENOMEM; 12718c2ecf20Sopenharmony_ci goto unmap_ctx; 12728c2ecf20Sopenharmony_ci } 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci append_seq_in_ptr(desc, edesc->sec4_sg_dma, to_hash, LDST_SGF); 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_ci ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len); 12778c2ecf20Sopenharmony_ci if (ret) 12788c2ecf20Sopenharmony_ci goto unmap_ctx; 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ", 12818c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, 12828c2ecf20Sopenharmony_ci desc_bytes(desc), 1); 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ci ret = ahash_enqueue_req(jrdev, ahash_done_ctx_dst, req, 12858c2ecf20Sopenharmony_ci ctx->ctx_len, DMA_TO_DEVICE); 12868c2ecf20Sopenharmony_ci if ((ret != -EINPROGRESS) && (ret != -EBUSY)) 12878c2ecf20Sopenharmony_ci return ret; 12888c2ecf20Sopenharmony_ci state->update = ahash_update_ctx; 12898c2ecf20Sopenharmony_ci state->finup = ahash_finup_ctx; 12908c2ecf20Sopenharmony_ci state->final = ahash_final_ctx; 12918c2ecf20Sopenharmony_ci } else if (*next_buflen) { 12928c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(buf + *buflen, req->src, 0, 12938c2ecf20Sopenharmony_ci req->nbytes, 0); 12948c2ecf20Sopenharmony_ci *buflen = *next_buflen; 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci print_hex_dump_debug("buf@" __stringify(__LINE__)": ", 12978c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, buf, 12988c2ecf20Sopenharmony_ci *buflen, 1); 12998c2ecf20Sopenharmony_ci } 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci return ret; 13028c2ecf20Sopenharmony_ci unmap_ctx: 13038c2ecf20Sopenharmony_ci ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE); 13048c2ecf20Sopenharmony_ci kfree(edesc); 13058c2ecf20Sopenharmony_ci return ret; 13068c2ecf20Sopenharmony_ci} 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci/* submit ahash finup if it the first job descriptor after update */ 13098c2ecf20Sopenharmony_cistatic int ahash_finup_no_ctx(struct ahash_request *req) 13108c2ecf20Sopenharmony_ci{ 13118c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 13128c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 13138c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 13148c2ecf20Sopenharmony_ci struct device *jrdev = ctx->jrdev; 13158c2ecf20Sopenharmony_ci int buflen = state->buflen; 13168c2ecf20Sopenharmony_ci u32 *desc; 13178c2ecf20Sopenharmony_ci int sec4_sg_bytes, sec4_sg_src_index, src_nents, mapped_nents; 13188c2ecf20Sopenharmony_ci int digestsize = crypto_ahash_digestsize(ahash); 13198c2ecf20Sopenharmony_ci struct ahash_edesc *edesc; 13208c2ecf20Sopenharmony_ci int ret; 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci src_nents = sg_nents_for_len(req->src, req->nbytes); 13238c2ecf20Sopenharmony_ci if (src_nents < 0) { 13248c2ecf20Sopenharmony_ci dev_err(jrdev, "Invalid number of src SG.\n"); 13258c2ecf20Sopenharmony_ci return src_nents; 13268c2ecf20Sopenharmony_ci } 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_ci if (src_nents) { 13298c2ecf20Sopenharmony_ci mapped_nents = dma_map_sg(jrdev, req->src, src_nents, 13308c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 13318c2ecf20Sopenharmony_ci if (!mapped_nents) { 13328c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to DMA map source\n"); 13338c2ecf20Sopenharmony_ci return -ENOMEM; 13348c2ecf20Sopenharmony_ci } 13358c2ecf20Sopenharmony_ci } else { 13368c2ecf20Sopenharmony_ci mapped_nents = 0; 13378c2ecf20Sopenharmony_ci } 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci sec4_sg_src_index = 2; 13408c2ecf20Sopenharmony_ci sec4_sg_bytes = (sec4_sg_src_index + mapped_nents) * 13418c2ecf20Sopenharmony_ci sizeof(struct sec4_sg_entry); 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci /* allocate space for base edesc and hw desc commands, link tables */ 13448c2ecf20Sopenharmony_ci edesc = ahash_edesc_alloc(req, sec4_sg_src_index + mapped_nents, 13458c2ecf20Sopenharmony_ci ctx->sh_desc_digest, ctx->sh_desc_digest_dma); 13468c2ecf20Sopenharmony_ci if (!edesc) { 13478c2ecf20Sopenharmony_ci dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE); 13488c2ecf20Sopenharmony_ci return -ENOMEM; 13498c2ecf20Sopenharmony_ci } 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci desc = edesc->hw_desc; 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci edesc->src_nents = src_nents; 13548c2ecf20Sopenharmony_ci edesc->sec4_sg_bytes = sec4_sg_bytes; 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_ci ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, state); 13578c2ecf20Sopenharmony_ci if (ret) 13588c2ecf20Sopenharmony_ci goto unmap; 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 1, buflen, 13618c2ecf20Sopenharmony_ci req->nbytes); 13628c2ecf20Sopenharmony_ci if (ret) { 13638c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to map S/G table\n"); 13648c2ecf20Sopenharmony_ci goto unmap; 13658c2ecf20Sopenharmony_ci } 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci ret = map_seq_out_ptr_ctx(desc, jrdev, state, digestsize); 13688c2ecf20Sopenharmony_ci if (ret) 13698c2ecf20Sopenharmony_ci goto unmap; 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ", 13728c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 13738c2ecf20Sopenharmony_ci 1); 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci return ahash_enqueue_req(jrdev, ahash_done, req, 13768c2ecf20Sopenharmony_ci digestsize, DMA_FROM_DEVICE); 13778c2ecf20Sopenharmony_ci unmap: 13788c2ecf20Sopenharmony_ci ahash_unmap(jrdev, edesc, req, digestsize); 13798c2ecf20Sopenharmony_ci kfree(edesc); 13808c2ecf20Sopenharmony_ci return -ENOMEM; 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci} 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci/* submit first update job descriptor after init */ 13858c2ecf20Sopenharmony_cistatic int ahash_update_first(struct ahash_request *req) 13868c2ecf20Sopenharmony_ci{ 13878c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 13888c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); 13898c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 13908c2ecf20Sopenharmony_ci struct device *jrdev = ctx->jrdev; 13918c2ecf20Sopenharmony_ci u8 *buf = state->buf; 13928c2ecf20Sopenharmony_ci int *buflen = &state->buflen; 13938c2ecf20Sopenharmony_ci int *next_buflen = &state->next_buflen; 13948c2ecf20Sopenharmony_ci int to_hash; 13958c2ecf20Sopenharmony_ci int blocksize = crypto_ahash_blocksize(ahash); 13968c2ecf20Sopenharmony_ci u32 *desc; 13978c2ecf20Sopenharmony_ci int src_nents, mapped_nents; 13988c2ecf20Sopenharmony_ci struct ahash_edesc *edesc; 13998c2ecf20Sopenharmony_ci int ret = 0; 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci *next_buflen = req->nbytes & (blocksize - 1); 14028c2ecf20Sopenharmony_ci to_hash = req->nbytes - *next_buflen; 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci /* 14058c2ecf20Sopenharmony_ci * For XCBC and CMAC, if to_hash is multiple of block size, 14068c2ecf20Sopenharmony_ci * keep last block in internal buffer 14078c2ecf20Sopenharmony_ci */ 14088c2ecf20Sopenharmony_ci if ((is_xcbc_aes(ctx->adata.algtype) || 14098c2ecf20Sopenharmony_ci is_cmac_aes(ctx->adata.algtype)) && to_hash >= blocksize && 14108c2ecf20Sopenharmony_ci (*next_buflen == 0)) { 14118c2ecf20Sopenharmony_ci *next_buflen = blocksize; 14128c2ecf20Sopenharmony_ci to_hash -= blocksize; 14138c2ecf20Sopenharmony_ci } 14148c2ecf20Sopenharmony_ci 14158c2ecf20Sopenharmony_ci if (to_hash) { 14168c2ecf20Sopenharmony_ci src_nents = sg_nents_for_len(req->src, 14178c2ecf20Sopenharmony_ci req->nbytes - *next_buflen); 14188c2ecf20Sopenharmony_ci if (src_nents < 0) { 14198c2ecf20Sopenharmony_ci dev_err(jrdev, "Invalid number of src SG.\n"); 14208c2ecf20Sopenharmony_ci return src_nents; 14218c2ecf20Sopenharmony_ci } 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci if (src_nents) { 14248c2ecf20Sopenharmony_ci mapped_nents = dma_map_sg(jrdev, req->src, src_nents, 14258c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 14268c2ecf20Sopenharmony_ci if (!mapped_nents) { 14278c2ecf20Sopenharmony_ci dev_err(jrdev, "unable to map source for DMA\n"); 14288c2ecf20Sopenharmony_ci return -ENOMEM; 14298c2ecf20Sopenharmony_ci } 14308c2ecf20Sopenharmony_ci } else { 14318c2ecf20Sopenharmony_ci mapped_nents = 0; 14328c2ecf20Sopenharmony_ci } 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci /* 14358c2ecf20Sopenharmony_ci * allocate space for base edesc and hw desc commands, 14368c2ecf20Sopenharmony_ci * link tables 14378c2ecf20Sopenharmony_ci */ 14388c2ecf20Sopenharmony_ci edesc = ahash_edesc_alloc(req, mapped_nents > 1 ? 14398c2ecf20Sopenharmony_ci mapped_nents : 0, 14408c2ecf20Sopenharmony_ci ctx->sh_desc_update_first, 14418c2ecf20Sopenharmony_ci ctx->sh_desc_update_first_dma); 14428c2ecf20Sopenharmony_ci if (!edesc) { 14438c2ecf20Sopenharmony_ci dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE); 14448c2ecf20Sopenharmony_ci return -ENOMEM; 14458c2ecf20Sopenharmony_ci } 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci edesc->src_nents = src_nents; 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 0, 0, 14508c2ecf20Sopenharmony_ci to_hash); 14518c2ecf20Sopenharmony_ci if (ret) 14528c2ecf20Sopenharmony_ci goto unmap_ctx; 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci desc = edesc->hw_desc; 14558c2ecf20Sopenharmony_ci 14568c2ecf20Sopenharmony_ci ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len); 14578c2ecf20Sopenharmony_ci if (ret) 14588c2ecf20Sopenharmony_ci goto unmap_ctx; 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ", 14618c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, 14628c2ecf20Sopenharmony_ci desc_bytes(desc), 1); 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_ci ret = ahash_enqueue_req(jrdev, ahash_done_ctx_dst, req, 14658c2ecf20Sopenharmony_ci ctx->ctx_len, DMA_TO_DEVICE); 14668c2ecf20Sopenharmony_ci if ((ret != -EINPROGRESS) && (ret != -EBUSY)) 14678c2ecf20Sopenharmony_ci return ret; 14688c2ecf20Sopenharmony_ci state->update = ahash_update_ctx; 14698c2ecf20Sopenharmony_ci state->finup = ahash_finup_ctx; 14708c2ecf20Sopenharmony_ci state->final = ahash_final_ctx; 14718c2ecf20Sopenharmony_ci } else if (*next_buflen) { 14728c2ecf20Sopenharmony_ci state->update = ahash_update_no_ctx; 14738c2ecf20Sopenharmony_ci state->finup = ahash_finup_no_ctx; 14748c2ecf20Sopenharmony_ci state->final = ahash_final_no_ctx; 14758c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(buf, req->src, 0, 14768c2ecf20Sopenharmony_ci req->nbytes, 0); 14778c2ecf20Sopenharmony_ci *buflen = *next_buflen; 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci print_hex_dump_debug("buf@" __stringify(__LINE__)": ", 14808c2ecf20Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, buf, 14818c2ecf20Sopenharmony_ci *buflen, 1); 14828c2ecf20Sopenharmony_ci } 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci return ret; 14858c2ecf20Sopenharmony_ci unmap_ctx: 14868c2ecf20Sopenharmony_ci ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE); 14878c2ecf20Sopenharmony_ci kfree(edesc); 14888c2ecf20Sopenharmony_ci return ret; 14898c2ecf20Sopenharmony_ci} 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_cistatic int ahash_finup_first(struct ahash_request *req) 14928c2ecf20Sopenharmony_ci{ 14938c2ecf20Sopenharmony_ci return ahash_digest(req); 14948c2ecf20Sopenharmony_ci} 14958c2ecf20Sopenharmony_ci 14968c2ecf20Sopenharmony_cistatic int ahash_init(struct ahash_request *req) 14978c2ecf20Sopenharmony_ci{ 14988c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci state->update = ahash_update_first; 15018c2ecf20Sopenharmony_ci state->finup = ahash_finup_first; 15028c2ecf20Sopenharmony_ci state->final = ahash_final_no_ctx; 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci state->ctx_dma = 0; 15058c2ecf20Sopenharmony_ci state->ctx_dma_len = 0; 15068c2ecf20Sopenharmony_ci state->buf_dma = 0; 15078c2ecf20Sopenharmony_ci state->buflen = 0; 15088c2ecf20Sopenharmony_ci state->next_buflen = 0; 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci return 0; 15118c2ecf20Sopenharmony_ci} 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_cistatic int ahash_update(struct ahash_request *req) 15148c2ecf20Sopenharmony_ci{ 15158c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci return state->update(req); 15188c2ecf20Sopenharmony_ci} 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_cistatic int ahash_finup(struct ahash_request *req) 15218c2ecf20Sopenharmony_ci{ 15228c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci return state->finup(req); 15258c2ecf20Sopenharmony_ci} 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_cistatic int ahash_final(struct ahash_request *req) 15288c2ecf20Sopenharmony_ci{ 15298c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci return state->final(req); 15328c2ecf20Sopenharmony_ci} 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_cistatic int ahash_export(struct ahash_request *req, void *out) 15358c2ecf20Sopenharmony_ci{ 15368c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 15378c2ecf20Sopenharmony_ci struct caam_export_state *export = out; 15388c2ecf20Sopenharmony_ci u8 *buf = state->buf; 15398c2ecf20Sopenharmony_ci int len = state->buflen; 15408c2ecf20Sopenharmony_ci 15418c2ecf20Sopenharmony_ci memcpy(export->buf, buf, len); 15428c2ecf20Sopenharmony_ci memcpy(export->caam_ctx, state->caam_ctx, sizeof(export->caam_ctx)); 15438c2ecf20Sopenharmony_ci export->buflen = len; 15448c2ecf20Sopenharmony_ci export->update = state->update; 15458c2ecf20Sopenharmony_ci export->final = state->final; 15468c2ecf20Sopenharmony_ci export->finup = state->finup; 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci return 0; 15498c2ecf20Sopenharmony_ci} 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_cistatic int ahash_import(struct ahash_request *req, const void *in) 15528c2ecf20Sopenharmony_ci{ 15538c2ecf20Sopenharmony_ci struct caam_hash_state *state = ahash_request_ctx(req); 15548c2ecf20Sopenharmony_ci const struct caam_export_state *export = in; 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ci memset(state, 0, sizeof(*state)); 15578c2ecf20Sopenharmony_ci memcpy(state->buf, export->buf, export->buflen); 15588c2ecf20Sopenharmony_ci memcpy(state->caam_ctx, export->caam_ctx, sizeof(state->caam_ctx)); 15598c2ecf20Sopenharmony_ci state->buflen = export->buflen; 15608c2ecf20Sopenharmony_ci state->update = export->update; 15618c2ecf20Sopenharmony_ci state->final = export->final; 15628c2ecf20Sopenharmony_ci state->finup = export->finup; 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci return 0; 15658c2ecf20Sopenharmony_ci} 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_cistruct caam_hash_template { 15688c2ecf20Sopenharmony_ci char name[CRYPTO_MAX_ALG_NAME]; 15698c2ecf20Sopenharmony_ci char driver_name[CRYPTO_MAX_ALG_NAME]; 15708c2ecf20Sopenharmony_ci char hmac_name[CRYPTO_MAX_ALG_NAME]; 15718c2ecf20Sopenharmony_ci char hmac_driver_name[CRYPTO_MAX_ALG_NAME]; 15728c2ecf20Sopenharmony_ci unsigned int blocksize; 15738c2ecf20Sopenharmony_ci struct ahash_alg template_ahash; 15748c2ecf20Sopenharmony_ci u32 alg_type; 15758c2ecf20Sopenharmony_ci}; 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci/* ahash descriptors */ 15788c2ecf20Sopenharmony_cistatic struct caam_hash_template driver_hash[] = { 15798c2ecf20Sopenharmony_ci { 15808c2ecf20Sopenharmony_ci .name = "sha1", 15818c2ecf20Sopenharmony_ci .driver_name = "sha1-caam", 15828c2ecf20Sopenharmony_ci .hmac_name = "hmac(sha1)", 15838c2ecf20Sopenharmony_ci .hmac_driver_name = "hmac-sha1-caam", 15848c2ecf20Sopenharmony_ci .blocksize = SHA1_BLOCK_SIZE, 15858c2ecf20Sopenharmony_ci .template_ahash = { 15868c2ecf20Sopenharmony_ci .init = ahash_init, 15878c2ecf20Sopenharmony_ci .update = ahash_update, 15888c2ecf20Sopenharmony_ci .final = ahash_final, 15898c2ecf20Sopenharmony_ci .finup = ahash_finup, 15908c2ecf20Sopenharmony_ci .digest = ahash_digest, 15918c2ecf20Sopenharmony_ci .export = ahash_export, 15928c2ecf20Sopenharmony_ci .import = ahash_import, 15938c2ecf20Sopenharmony_ci .setkey = ahash_setkey, 15948c2ecf20Sopenharmony_ci .halg = { 15958c2ecf20Sopenharmony_ci .digestsize = SHA1_DIGEST_SIZE, 15968c2ecf20Sopenharmony_ci .statesize = sizeof(struct caam_export_state), 15978c2ecf20Sopenharmony_ci }, 15988c2ecf20Sopenharmony_ci }, 15998c2ecf20Sopenharmony_ci .alg_type = OP_ALG_ALGSEL_SHA1, 16008c2ecf20Sopenharmony_ci }, { 16018c2ecf20Sopenharmony_ci .name = "sha224", 16028c2ecf20Sopenharmony_ci .driver_name = "sha224-caam", 16038c2ecf20Sopenharmony_ci .hmac_name = "hmac(sha224)", 16048c2ecf20Sopenharmony_ci .hmac_driver_name = "hmac-sha224-caam", 16058c2ecf20Sopenharmony_ci .blocksize = SHA224_BLOCK_SIZE, 16068c2ecf20Sopenharmony_ci .template_ahash = { 16078c2ecf20Sopenharmony_ci .init = ahash_init, 16088c2ecf20Sopenharmony_ci .update = ahash_update, 16098c2ecf20Sopenharmony_ci .final = ahash_final, 16108c2ecf20Sopenharmony_ci .finup = ahash_finup, 16118c2ecf20Sopenharmony_ci .digest = ahash_digest, 16128c2ecf20Sopenharmony_ci .export = ahash_export, 16138c2ecf20Sopenharmony_ci .import = ahash_import, 16148c2ecf20Sopenharmony_ci .setkey = ahash_setkey, 16158c2ecf20Sopenharmony_ci .halg = { 16168c2ecf20Sopenharmony_ci .digestsize = SHA224_DIGEST_SIZE, 16178c2ecf20Sopenharmony_ci .statesize = sizeof(struct caam_export_state), 16188c2ecf20Sopenharmony_ci }, 16198c2ecf20Sopenharmony_ci }, 16208c2ecf20Sopenharmony_ci .alg_type = OP_ALG_ALGSEL_SHA224, 16218c2ecf20Sopenharmony_ci }, { 16228c2ecf20Sopenharmony_ci .name = "sha256", 16238c2ecf20Sopenharmony_ci .driver_name = "sha256-caam", 16248c2ecf20Sopenharmony_ci .hmac_name = "hmac(sha256)", 16258c2ecf20Sopenharmony_ci .hmac_driver_name = "hmac-sha256-caam", 16268c2ecf20Sopenharmony_ci .blocksize = SHA256_BLOCK_SIZE, 16278c2ecf20Sopenharmony_ci .template_ahash = { 16288c2ecf20Sopenharmony_ci .init = ahash_init, 16298c2ecf20Sopenharmony_ci .update = ahash_update, 16308c2ecf20Sopenharmony_ci .final = ahash_final, 16318c2ecf20Sopenharmony_ci .finup = ahash_finup, 16328c2ecf20Sopenharmony_ci .digest = ahash_digest, 16338c2ecf20Sopenharmony_ci .export = ahash_export, 16348c2ecf20Sopenharmony_ci .import = ahash_import, 16358c2ecf20Sopenharmony_ci .setkey = ahash_setkey, 16368c2ecf20Sopenharmony_ci .halg = { 16378c2ecf20Sopenharmony_ci .digestsize = SHA256_DIGEST_SIZE, 16388c2ecf20Sopenharmony_ci .statesize = sizeof(struct caam_export_state), 16398c2ecf20Sopenharmony_ci }, 16408c2ecf20Sopenharmony_ci }, 16418c2ecf20Sopenharmony_ci .alg_type = OP_ALG_ALGSEL_SHA256, 16428c2ecf20Sopenharmony_ci }, { 16438c2ecf20Sopenharmony_ci .name = "sha384", 16448c2ecf20Sopenharmony_ci .driver_name = "sha384-caam", 16458c2ecf20Sopenharmony_ci .hmac_name = "hmac(sha384)", 16468c2ecf20Sopenharmony_ci .hmac_driver_name = "hmac-sha384-caam", 16478c2ecf20Sopenharmony_ci .blocksize = SHA384_BLOCK_SIZE, 16488c2ecf20Sopenharmony_ci .template_ahash = { 16498c2ecf20Sopenharmony_ci .init = ahash_init, 16508c2ecf20Sopenharmony_ci .update = ahash_update, 16518c2ecf20Sopenharmony_ci .final = ahash_final, 16528c2ecf20Sopenharmony_ci .finup = ahash_finup, 16538c2ecf20Sopenharmony_ci .digest = ahash_digest, 16548c2ecf20Sopenharmony_ci .export = ahash_export, 16558c2ecf20Sopenharmony_ci .import = ahash_import, 16568c2ecf20Sopenharmony_ci .setkey = ahash_setkey, 16578c2ecf20Sopenharmony_ci .halg = { 16588c2ecf20Sopenharmony_ci .digestsize = SHA384_DIGEST_SIZE, 16598c2ecf20Sopenharmony_ci .statesize = sizeof(struct caam_export_state), 16608c2ecf20Sopenharmony_ci }, 16618c2ecf20Sopenharmony_ci }, 16628c2ecf20Sopenharmony_ci .alg_type = OP_ALG_ALGSEL_SHA384, 16638c2ecf20Sopenharmony_ci }, { 16648c2ecf20Sopenharmony_ci .name = "sha512", 16658c2ecf20Sopenharmony_ci .driver_name = "sha512-caam", 16668c2ecf20Sopenharmony_ci .hmac_name = "hmac(sha512)", 16678c2ecf20Sopenharmony_ci .hmac_driver_name = "hmac-sha512-caam", 16688c2ecf20Sopenharmony_ci .blocksize = SHA512_BLOCK_SIZE, 16698c2ecf20Sopenharmony_ci .template_ahash = { 16708c2ecf20Sopenharmony_ci .init = ahash_init, 16718c2ecf20Sopenharmony_ci .update = ahash_update, 16728c2ecf20Sopenharmony_ci .final = ahash_final, 16738c2ecf20Sopenharmony_ci .finup = ahash_finup, 16748c2ecf20Sopenharmony_ci .digest = ahash_digest, 16758c2ecf20Sopenharmony_ci .export = ahash_export, 16768c2ecf20Sopenharmony_ci .import = ahash_import, 16778c2ecf20Sopenharmony_ci .setkey = ahash_setkey, 16788c2ecf20Sopenharmony_ci .halg = { 16798c2ecf20Sopenharmony_ci .digestsize = SHA512_DIGEST_SIZE, 16808c2ecf20Sopenharmony_ci .statesize = sizeof(struct caam_export_state), 16818c2ecf20Sopenharmony_ci }, 16828c2ecf20Sopenharmony_ci }, 16838c2ecf20Sopenharmony_ci .alg_type = OP_ALG_ALGSEL_SHA512, 16848c2ecf20Sopenharmony_ci }, { 16858c2ecf20Sopenharmony_ci .name = "md5", 16868c2ecf20Sopenharmony_ci .driver_name = "md5-caam", 16878c2ecf20Sopenharmony_ci .hmac_name = "hmac(md5)", 16888c2ecf20Sopenharmony_ci .hmac_driver_name = "hmac-md5-caam", 16898c2ecf20Sopenharmony_ci .blocksize = MD5_BLOCK_WORDS * 4, 16908c2ecf20Sopenharmony_ci .template_ahash = { 16918c2ecf20Sopenharmony_ci .init = ahash_init, 16928c2ecf20Sopenharmony_ci .update = ahash_update, 16938c2ecf20Sopenharmony_ci .final = ahash_final, 16948c2ecf20Sopenharmony_ci .finup = ahash_finup, 16958c2ecf20Sopenharmony_ci .digest = ahash_digest, 16968c2ecf20Sopenharmony_ci .export = ahash_export, 16978c2ecf20Sopenharmony_ci .import = ahash_import, 16988c2ecf20Sopenharmony_ci .setkey = ahash_setkey, 16998c2ecf20Sopenharmony_ci .halg = { 17008c2ecf20Sopenharmony_ci .digestsize = MD5_DIGEST_SIZE, 17018c2ecf20Sopenharmony_ci .statesize = sizeof(struct caam_export_state), 17028c2ecf20Sopenharmony_ci }, 17038c2ecf20Sopenharmony_ci }, 17048c2ecf20Sopenharmony_ci .alg_type = OP_ALG_ALGSEL_MD5, 17058c2ecf20Sopenharmony_ci }, { 17068c2ecf20Sopenharmony_ci .hmac_name = "xcbc(aes)", 17078c2ecf20Sopenharmony_ci .hmac_driver_name = "xcbc-aes-caam", 17088c2ecf20Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 17098c2ecf20Sopenharmony_ci .template_ahash = { 17108c2ecf20Sopenharmony_ci .init = ahash_init, 17118c2ecf20Sopenharmony_ci .update = ahash_update, 17128c2ecf20Sopenharmony_ci .final = ahash_final, 17138c2ecf20Sopenharmony_ci .finup = ahash_finup, 17148c2ecf20Sopenharmony_ci .digest = ahash_digest, 17158c2ecf20Sopenharmony_ci .export = ahash_export, 17168c2ecf20Sopenharmony_ci .import = ahash_import, 17178c2ecf20Sopenharmony_ci .setkey = axcbc_setkey, 17188c2ecf20Sopenharmony_ci .halg = { 17198c2ecf20Sopenharmony_ci .digestsize = AES_BLOCK_SIZE, 17208c2ecf20Sopenharmony_ci .statesize = sizeof(struct caam_export_state), 17218c2ecf20Sopenharmony_ci }, 17228c2ecf20Sopenharmony_ci }, 17238c2ecf20Sopenharmony_ci .alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_XCBC_MAC, 17248c2ecf20Sopenharmony_ci }, { 17258c2ecf20Sopenharmony_ci .hmac_name = "cmac(aes)", 17268c2ecf20Sopenharmony_ci .hmac_driver_name = "cmac-aes-caam", 17278c2ecf20Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 17288c2ecf20Sopenharmony_ci .template_ahash = { 17298c2ecf20Sopenharmony_ci .init = ahash_init, 17308c2ecf20Sopenharmony_ci .update = ahash_update, 17318c2ecf20Sopenharmony_ci .final = ahash_final, 17328c2ecf20Sopenharmony_ci .finup = ahash_finup, 17338c2ecf20Sopenharmony_ci .digest = ahash_digest, 17348c2ecf20Sopenharmony_ci .export = ahash_export, 17358c2ecf20Sopenharmony_ci .import = ahash_import, 17368c2ecf20Sopenharmony_ci .setkey = acmac_setkey, 17378c2ecf20Sopenharmony_ci .halg = { 17388c2ecf20Sopenharmony_ci .digestsize = AES_BLOCK_SIZE, 17398c2ecf20Sopenharmony_ci .statesize = sizeof(struct caam_export_state), 17408c2ecf20Sopenharmony_ci }, 17418c2ecf20Sopenharmony_ci }, 17428c2ecf20Sopenharmony_ci .alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CMAC, 17438c2ecf20Sopenharmony_ci }, 17448c2ecf20Sopenharmony_ci}; 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_cistruct caam_hash_alg { 17478c2ecf20Sopenharmony_ci struct list_head entry; 17488c2ecf20Sopenharmony_ci int alg_type; 17498c2ecf20Sopenharmony_ci struct ahash_alg ahash_alg; 17508c2ecf20Sopenharmony_ci}; 17518c2ecf20Sopenharmony_ci 17528c2ecf20Sopenharmony_cistatic int caam_hash_cra_init(struct crypto_tfm *tfm) 17538c2ecf20Sopenharmony_ci{ 17548c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = __crypto_ahash_cast(tfm); 17558c2ecf20Sopenharmony_ci struct crypto_alg *base = tfm->__crt_alg; 17568c2ecf20Sopenharmony_ci struct hash_alg_common *halg = 17578c2ecf20Sopenharmony_ci container_of(base, struct hash_alg_common, base); 17588c2ecf20Sopenharmony_ci struct ahash_alg *alg = 17598c2ecf20Sopenharmony_ci container_of(halg, struct ahash_alg, halg); 17608c2ecf20Sopenharmony_ci struct caam_hash_alg *caam_hash = 17618c2ecf20Sopenharmony_ci container_of(alg, struct caam_hash_alg, ahash_alg); 17628c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm); 17638c2ecf20Sopenharmony_ci /* Sizes for MDHA running digests: MD5, SHA1, 224, 256, 384, 512 */ 17648c2ecf20Sopenharmony_ci static const u8 runninglen[] = { HASH_MSG_LEN + MD5_DIGEST_SIZE, 17658c2ecf20Sopenharmony_ci HASH_MSG_LEN + SHA1_DIGEST_SIZE, 17668c2ecf20Sopenharmony_ci HASH_MSG_LEN + 32, 17678c2ecf20Sopenharmony_ci HASH_MSG_LEN + SHA256_DIGEST_SIZE, 17688c2ecf20Sopenharmony_ci HASH_MSG_LEN + 64, 17698c2ecf20Sopenharmony_ci HASH_MSG_LEN + SHA512_DIGEST_SIZE }; 17708c2ecf20Sopenharmony_ci const size_t sh_desc_update_offset = offsetof(struct caam_hash_ctx, 17718c2ecf20Sopenharmony_ci sh_desc_update); 17728c2ecf20Sopenharmony_ci dma_addr_t dma_addr; 17738c2ecf20Sopenharmony_ci struct caam_drv_private *priv; 17748c2ecf20Sopenharmony_ci 17758c2ecf20Sopenharmony_ci /* 17768c2ecf20Sopenharmony_ci * Get a Job ring from Job Ring driver to ensure in-order 17778c2ecf20Sopenharmony_ci * crypto request processing per tfm 17788c2ecf20Sopenharmony_ci */ 17798c2ecf20Sopenharmony_ci ctx->jrdev = caam_jr_alloc(); 17808c2ecf20Sopenharmony_ci if (IS_ERR(ctx->jrdev)) { 17818c2ecf20Sopenharmony_ci pr_err("Job Ring Device allocation for transform failed\n"); 17828c2ecf20Sopenharmony_ci return PTR_ERR(ctx->jrdev); 17838c2ecf20Sopenharmony_ci } 17848c2ecf20Sopenharmony_ci 17858c2ecf20Sopenharmony_ci priv = dev_get_drvdata(ctx->jrdev->parent); 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_ci if (is_xcbc_aes(caam_hash->alg_type)) { 17888c2ecf20Sopenharmony_ci ctx->dir = DMA_TO_DEVICE; 17898c2ecf20Sopenharmony_ci ctx->key_dir = DMA_BIDIRECTIONAL; 17908c2ecf20Sopenharmony_ci ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type; 17918c2ecf20Sopenharmony_ci ctx->ctx_len = 48; 17928c2ecf20Sopenharmony_ci } else if (is_cmac_aes(caam_hash->alg_type)) { 17938c2ecf20Sopenharmony_ci ctx->dir = DMA_TO_DEVICE; 17948c2ecf20Sopenharmony_ci ctx->key_dir = DMA_NONE; 17958c2ecf20Sopenharmony_ci ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type; 17968c2ecf20Sopenharmony_ci ctx->ctx_len = 32; 17978c2ecf20Sopenharmony_ci } else { 17988c2ecf20Sopenharmony_ci if (priv->era >= 6) { 17998c2ecf20Sopenharmony_ci ctx->dir = DMA_BIDIRECTIONAL; 18008c2ecf20Sopenharmony_ci ctx->key_dir = alg->setkey ? DMA_TO_DEVICE : DMA_NONE; 18018c2ecf20Sopenharmony_ci } else { 18028c2ecf20Sopenharmony_ci ctx->dir = DMA_TO_DEVICE; 18038c2ecf20Sopenharmony_ci ctx->key_dir = DMA_NONE; 18048c2ecf20Sopenharmony_ci } 18058c2ecf20Sopenharmony_ci ctx->adata.algtype = OP_TYPE_CLASS2_ALG | caam_hash->alg_type; 18068c2ecf20Sopenharmony_ci ctx->ctx_len = runninglen[(ctx->adata.algtype & 18078c2ecf20Sopenharmony_ci OP_ALG_ALGSEL_SUBMASK) >> 18088c2ecf20Sopenharmony_ci OP_ALG_ALGSEL_SHIFT]; 18098c2ecf20Sopenharmony_ci } 18108c2ecf20Sopenharmony_ci 18118c2ecf20Sopenharmony_ci if (ctx->key_dir != DMA_NONE) { 18128c2ecf20Sopenharmony_ci ctx->adata.key_dma = dma_map_single_attrs(ctx->jrdev, ctx->key, 18138c2ecf20Sopenharmony_ci ARRAY_SIZE(ctx->key), 18148c2ecf20Sopenharmony_ci ctx->key_dir, 18158c2ecf20Sopenharmony_ci DMA_ATTR_SKIP_CPU_SYNC); 18168c2ecf20Sopenharmony_ci if (dma_mapping_error(ctx->jrdev, ctx->adata.key_dma)) { 18178c2ecf20Sopenharmony_ci dev_err(ctx->jrdev, "unable to map key\n"); 18188c2ecf20Sopenharmony_ci caam_jr_free(ctx->jrdev); 18198c2ecf20Sopenharmony_ci return -ENOMEM; 18208c2ecf20Sopenharmony_ci } 18218c2ecf20Sopenharmony_ci } 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci dma_addr = dma_map_single_attrs(ctx->jrdev, ctx->sh_desc_update, 18248c2ecf20Sopenharmony_ci offsetof(struct caam_hash_ctx, key) - 18258c2ecf20Sopenharmony_ci sh_desc_update_offset, 18268c2ecf20Sopenharmony_ci ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); 18278c2ecf20Sopenharmony_ci if (dma_mapping_error(ctx->jrdev, dma_addr)) { 18288c2ecf20Sopenharmony_ci dev_err(ctx->jrdev, "unable to map shared descriptors\n"); 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci if (ctx->key_dir != DMA_NONE) 18318c2ecf20Sopenharmony_ci dma_unmap_single_attrs(ctx->jrdev, ctx->adata.key_dma, 18328c2ecf20Sopenharmony_ci ARRAY_SIZE(ctx->key), 18338c2ecf20Sopenharmony_ci ctx->key_dir, 18348c2ecf20Sopenharmony_ci DMA_ATTR_SKIP_CPU_SYNC); 18358c2ecf20Sopenharmony_ci 18368c2ecf20Sopenharmony_ci caam_jr_free(ctx->jrdev); 18378c2ecf20Sopenharmony_ci return -ENOMEM; 18388c2ecf20Sopenharmony_ci } 18398c2ecf20Sopenharmony_ci 18408c2ecf20Sopenharmony_ci ctx->sh_desc_update_dma = dma_addr; 18418c2ecf20Sopenharmony_ci ctx->sh_desc_update_first_dma = dma_addr + 18428c2ecf20Sopenharmony_ci offsetof(struct caam_hash_ctx, 18438c2ecf20Sopenharmony_ci sh_desc_update_first) - 18448c2ecf20Sopenharmony_ci sh_desc_update_offset; 18458c2ecf20Sopenharmony_ci ctx->sh_desc_fin_dma = dma_addr + offsetof(struct caam_hash_ctx, 18468c2ecf20Sopenharmony_ci sh_desc_fin) - 18478c2ecf20Sopenharmony_ci sh_desc_update_offset; 18488c2ecf20Sopenharmony_ci ctx->sh_desc_digest_dma = dma_addr + offsetof(struct caam_hash_ctx, 18498c2ecf20Sopenharmony_ci sh_desc_digest) - 18508c2ecf20Sopenharmony_ci sh_desc_update_offset; 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci ctx->enginectx.op.do_one_request = ahash_do_one_req; 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_ci crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 18558c2ecf20Sopenharmony_ci sizeof(struct caam_hash_state)); 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci /* 18588c2ecf20Sopenharmony_ci * For keyed hash algorithms shared descriptors 18598c2ecf20Sopenharmony_ci * will be created later in setkey() callback 18608c2ecf20Sopenharmony_ci */ 18618c2ecf20Sopenharmony_ci return alg->setkey ? 0 : ahash_set_sh_desc(ahash); 18628c2ecf20Sopenharmony_ci} 18638c2ecf20Sopenharmony_ci 18648c2ecf20Sopenharmony_cistatic void caam_hash_cra_exit(struct crypto_tfm *tfm) 18658c2ecf20Sopenharmony_ci{ 18668c2ecf20Sopenharmony_ci struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm); 18678c2ecf20Sopenharmony_ci 18688c2ecf20Sopenharmony_ci dma_unmap_single_attrs(ctx->jrdev, ctx->sh_desc_update_dma, 18698c2ecf20Sopenharmony_ci offsetof(struct caam_hash_ctx, key) - 18708c2ecf20Sopenharmony_ci offsetof(struct caam_hash_ctx, sh_desc_update), 18718c2ecf20Sopenharmony_ci ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); 18728c2ecf20Sopenharmony_ci if (ctx->key_dir != DMA_NONE) 18738c2ecf20Sopenharmony_ci dma_unmap_single_attrs(ctx->jrdev, ctx->adata.key_dma, 18748c2ecf20Sopenharmony_ci ARRAY_SIZE(ctx->key), ctx->key_dir, 18758c2ecf20Sopenharmony_ci DMA_ATTR_SKIP_CPU_SYNC); 18768c2ecf20Sopenharmony_ci caam_jr_free(ctx->jrdev); 18778c2ecf20Sopenharmony_ci} 18788c2ecf20Sopenharmony_ci 18798c2ecf20Sopenharmony_civoid caam_algapi_hash_exit(void) 18808c2ecf20Sopenharmony_ci{ 18818c2ecf20Sopenharmony_ci struct caam_hash_alg *t_alg, *n; 18828c2ecf20Sopenharmony_ci 18838c2ecf20Sopenharmony_ci if (!hash_list.next) 18848c2ecf20Sopenharmony_ci return; 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci list_for_each_entry_safe(t_alg, n, &hash_list, entry) { 18878c2ecf20Sopenharmony_ci crypto_unregister_ahash(&t_alg->ahash_alg); 18888c2ecf20Sopenharmony_ci list_del(&t_alg->entry); 18898c2ecf20Sopenharmony_ci kfree(t_alg); 18908c2ecf20Sopenharmony_ci } 18918c2ecf20Sopenharmony_ci} 18928c2ecf20Sopenharmony_ci 18938c2ecf20Sopenharmony_cistatic struct caam_hash_alg * 18948c2ecf20Sopenharmony_cicaam_hash_alloc(struct caam_hash_template *template, 18958c2ecf20Sopenharmony_ci bool keyed) 18968c2ecf20Sopenharmony_ci{ 18978c2ecf20Sopenharmony_ci struct caam_hash_alg *t_alg; 18988c2ecf20Sopenharmony_ci struct ahash_alg *halg; 18998c2ecf20Sopenharmony_ci struct crypto_alg *alg; 19008c2ecf20Sopenharmony_ci 19018c2ecf20Sopenharmony_ci t_alg = kzalloc(sizeof(*t_alg), GFP_KERNEL); 19028c2ecf20Sopenharmony_ci if (!t_alg) { 19038c2ecf20Sopenharmony_ci pr_err("failed to allocate t_alg\n"); 19048c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 19058c2ecf20Sopenharmony_ci } 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci t_alg->ahash_alg = template->template_ahash; 19088c2ecf20Sopenharmony_ci halg = &t_alg->ahash_alg; 19098c2ecf20Sopenharmony_ci alg = &halg->halg.base; 19108c2ecf20Sopenharmony_ci 19118c2ecf20Sopenharmony_ci if (keyed) { 19128c2ecf20Sopenharmony_ci snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", 19138c2ecf20Sopenharmony_ci template->hmac_name); 19148c2ecf20Sopenharmony_ci snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", 19158c2ecf20Sopenharmony_ci template->hmac_driver_name); 19168c2ecf20Sopenharmony_ci } else { 19178c2ecf20Sopenharmony_ci snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", 19188c2ecf20Sopenharmony_ci template->name); 19198c2ecf20Sopenharmony_ci snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", 19208c2ecf20Sopenharmony_ci template->driver_name); 19218c2ecf20Sopenharmony_ci t_alg->ahash_alg.setkey = NULL; 19228c2ecf20Sopenharmony_ci } 19238c2ecf20Sopenharmony_ci alg->cra_module = THIS_MODULE; 19248c2ecf20Sopenharmony_ci alg->cra_init = caam_hash_cra_init; 19258c2ecf20Sopenharmony_ci alg->cra_exit = caam_hash_cra_exit; 19268c2ecf20Sopenharmony_ci alg->cra_ctxsize = sizeof(struct caam_hash_ctx); 19278c2ecf20Sopenharmony_ci alg->cra_priority = CAAM_CRA_PRIORITY; 19288c2ecf20Sopenharmony_ci alg->cra_blocksize = template->blocksize; 19298c2ecf20Sopenharmony_ci alg->cra_alignmask = 0; 19308c2ecf20Sopenharmony_ci alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY; 19318c2ecf20Sopenharmony_ci 19328c2ecf20Sopenharmony_ci t_alg->alg_type = template->alg_type; 19338c2ecf20Sopenharmony_ci 19348c2ecf20Sopenharmony_ci return t_alg; 19358c2ecf20Sopenharmony_ci} 19368c2ecf20Sopenharmony_ci 19378c2ecf20Sopenharmony_ciint caam_algapi_hash_init(struct device *ctrldev) 19388c2ecf20Sopenharmony_ci{ 19398c2ecf20Sopenharmony_ci int i = 0, err = 0; 19408c2ecf20Sopenharmony_ci struct caam_drv_private *priv = dev_get_drvdata(ctrldev); 19418c2ecf20Sopenharmony_ci unsigned int md_limit = SHA512_DIGEST_SIZE; 19428c2ecf20Sopenharmony_ci u32 md_inst, md_vid; 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci /* 19458c2ecf20Sopenharmony_ci * Register crypto algorithms the device supports. First, identify 19468c2ecf20Sopenharmony_ci * presence and attributes of MD block. 19478c2ecf20Sopenharmony_ci */ 19488c2ecf20Sopenharmony_ci if (priv->era < 10) { 19498c2ecf20Sopenharmony_ci md_vid = (rd_reg32(&priv->ctrl->perfmon.cha_id_ls) & 19508c2ecf20Sopenharmony_ci CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT; 19518c2ecf20Sopenharmony_ci md_inst = (rd_reg32(&priv->ctrl->perfmon.cha_num_ls) & 19528c2ecf20Sopenharmony_ci CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT; 19538c2ecf20Sopenharmony_ci } else { 19548c2ecf20Sopenharmony_ci u32 mdha = rd_reg32(&priv->ctrl->vreg.mdha); 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_ci md_vid = (mdha & CHA_VER_VID_MASK) >> CHA_VER_VID_SHIFT; 19578c2ecf20Sopenharmony_ci md_inst = mdha & CHA_VER_NUM_MASK; 19588c2ecf20Sopenharmony_ci } 19598c2ecf20Sopenharmony_ci 19608c2ecf20Sopenharmony_ci /* 19618c2ecf20Sopenharmony_ci * Skip registration of any hashing algorithms if MD block 19628c2ecf20Sopenharmony_ci * is not present. 19638c2ecf20Sopenharmony_ci */ 19648c2ecf20Sopenharmony_ci if (!md_inst) 19658c2ecf20Sopenharmony_ci return 0; 19668c2ecf20Sopenharmony_ci 19678c2ecf20Sopenharmony_ci /* Limit digest size based on LP256 */ 19688c2ecf20Sopenharmony_ci if (md_vid == CHA_VER_VID_MD_LP256) 19698c2ecf20Sopenharmony_ci md_limit = SHA256_DIGEST_SIZE; 19708c2ecf20Sopenharmony_ci 19718c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hash_list); 19728c2ecf20Sopenharmony_ci 19738c2ecf20Sopenharmony_ci /* register crypto algorithms the device supports */ 19748c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(driver_hash); i++) { 19758c2ecf20Sopenharmony_ci struct caam_hash_alg *t_alg; 19768c2ecf20Sopenharmony_ci struct caam_hash_template *alg = driver_hash + i; 19778c2ecf20Sopenharmony_ci 19788c2ecf20Sopenharmony_ci /* If MD size is not supported by device, skip registration */ 19798c2ecf20Sopenharmony_ci if (is_mdha(alg->alg_type) && 19808c2ecf20Sopenharmony_ci alg->template_ahash.halg.digestsize > md_limit) 19818c2ecf20Sopenharmony_ci continue; 19828c2ecf20Sopenharmony_ci 19838c2ecf20Sopenharmony_ci /* register hmac version */ 19848c2ecf20Sopenharmony_ci t_alg = caam_hash_alloc(alg, true); 19858c2ecf20Sopenharmony_ci if (IS_ERR(t_alg)) { 19868c2ecf20Sopenharmony_ci err = PTR_ERR(t_alg); 19878c2ecf20Sopenharmony_ci pr_warn("%s alg allocation failed\n", 19888c2ecf20Sopenharmony_ci alg->hmac_driver_name); 19898c2ecf20Sopenharmony_ci continue; 19908c2ecf20Sopenharmony_ci } 19918c2ecf20Sopenharmony_ci 19928c2ecf20Sopenharmony_ci err = crypto_register_ahash(&t_alg->ahash_alg); 19938c2ecf20Sopenharmony_ci if (err) { 19948c2ecf20Sopenharmony_ci pr_warn("%s alg registration failed: %d\n", 19958c2ecf20Sopenharmony_ci t_alg->ahash_alg.halg.base.cra_driver_name, 19968c2ecf20Sopenharmony_ci err); 19978c2ecf20Sopenharmony_ci kfree(t_alg); 19988c2ecf20Sopenharmony_ci } else 19998c2ecf20Sopenharmony_ci list_add_tail(&t_alg->entry, &hash_list); 20008c2ecf20Sopenharmony_ci 20018c2ecf20Sopenharmony_ci if ((alg->alg_type & OP_ALG_ALGSEL_MASK) == OP_ALG_ALGSEL_AES) 20028c2ecf20Sopenharmony_ci continue; 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_ci /* register unkeyed version */ 20058c2ecf20Sopenharmony_ci t_alg = caam_hash_alloc(alg, false); 20068c2ecf20Sopenharmony_ci if (IS_ERR(t_alg)) { 20078c2ecf20Sopenharmony_ci err = PTR_ERR(t_alg); 20088c2ecf20Sopenharmony_ci pr_warn("%s alg allocation failed\n", alg->driver_name); 20098c2ecf20Sopenharmony_ci continue; 20108c2ecf20Sopenharmony_ci } 20118c2ecf20Sopenharmony_ci 20128c2ecf20Sopenharmony_ci err = crypto_register_ahash(&t_alg->ahash_alg); 20138c2ecf20Sopenharmony_ci if (err) { 20148c2ecf20Sopenharmony_ci pr_warn("%s alg registration failed: %d\n", 20158c2ecf20Sopenharmony_ci t_alg->ahash_alg.halg.base.cra_driver_name, 20168c2ecf20Sopenharmony_ci err); 20178c2ecf20Sopenharmony_ci kfree(t_alg); 20188c2ecf20Sopenharmony_ci } else 20198c2ecf20Sopenharmony_ci list_add_tail(&t_alg->entry, &hash_list); 20208c2ecf20Sopenharmony_ci } 20218c2ecf20Sopenharmony_ci 20228c2ecf20Sopenharmony_ci return err; 20238c2ecf20Sopenharmony_ci} 2024