18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright (C) 2012-2019 ARM Limited (or its affiliates). */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <linux/kernel.h> 58c2ecf20Sopenharmony_ci#include <linux/module.h> 68c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 78c2ecf20Sopenharmony_ci#include <crypto/hash.h> 88c2ecf20Sopenharmony_ci#include <crypto/md5.h> 98c2ecf20Sopenharmony_ci#include <crypto/sm3.h> 108c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "cc_driver.h" 138c2ecf20Sopenharmony_ci#include "cc_request_mgr.h" 148c2ecf20Sopenharmony_ci#include "cc_buffer_mgr.h" 158c2ecf20Sopenharmony_ci#include "cc_hash.h" 168c2ecf20Sopenharmony_ci#include "cc_sram_mgr.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define CC_MAX_HASH_SEQ_LEN 12 198c2ecf20Sopenharmony_ci#define CC_MAX_OPAD_KEYS_SIZE CC_MAX_HASH_BLCK_SIZE 208c2ecf20Sopenharmony_ci#define CC_SM3_HASH_LEN_SIZE 8 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistruct cc_hash_handle { 238c2ecf20Sopenharmony_ci u32 digest_len_sram_addr; /* const value in SRAM*/ 248c2ecf20Sopenharmony_ci u32 larval_digest_sram_addr; /* const value in SRAM */ 258c2ecf20Sopenharmony_ci struct list_head hash_list; 268c2ecf20Sopenharmony_ci}; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic const u32 cc_digest_len_init[] = { 298c2ecf20Sopenharmony_ci 0x00000040, 0x00000000, 0x00000000, 0x00000000 }; 308c2ecf20Sopenharmony_cistatic const u32 cc_md5_init[] = { 318c2ecf20Sopenharmony_ci SHA1_H3, SHA1_H2, SHA1_H1, SHA1_H0 }; 328c2ecf20Sopenharmony_cistatic const u32 cc_sha1_init[] = { 338c2ecf20Sopenharmony_ci SHA1_H4, SHA1_H3, SHA1_H2, SHA1_H1, SHA1_H0 }; 348c2ecf20Sopenharmony_cistatic const u32 cc_sha224_init[] = { 358c2ecf20Sopenharmony_ci SHA224_H7, SHA224_H6, SHA224_H5, SHA224_H4, 368c2ecf20Sopenharmony_ci SHA224_H3, SHA224_H2, SHA224_H1, SHA224_H0 }; 378c2ecf20Sopenharmony_cistatic const u32 cc_sha256_init[] = { 388c2ecf20Sopenharmony_ci SHA256_H7, SHA256_H6, SHA256_H5, SHA256_H4, 398c2ecf20Sopenharmony_ci SHA256_H3, SHA256_H2, SHA256_H1, SHA256_H0 }; 408c2ecf20Sopenharmony_cistatic const u32 cc_digest_len_sha512_init[] = { 418c2ecf20Sopenharmony_ci 0x00000080, 0x00000000, 0x00000000, 0x00000000 }; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* 448c2ecf20Sopenharmony_ci * Due to the way the HW works, every double word in the SHA384 and SHA512 458c2ecf20Sopenharmony_ci * larval hashes must be stored in hi/lo order 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_ci#define hilo(x) upper_32_bits(x), lower_32_bits(x) 488c2ecf20Sopenharmony_cistatic const u32 cc_sha384_init[] = { 498c2ecf20Sopenharmony_ci hilo(SHA384_H7), hilo(SHA384_H6), hilo(SHA384_H5), hilo(SHA384_H4), 508c2ecf20Sopenharmony_ci hilo(SHA384_H3), hilo(SHA384_H2), hilo(SHA384_H1), hilo(SHA384_H0) }; 518c2ecf20Sopenharmony_cistatic const u32 cc_sha512_init[] = { 528c2ecf20Sopenharmony_ci hilo(SHA512_H7), hilo(SHA512_H6), hilo(SHA512_H5), hilo(SHA512_H4), 538c2ecf20Sopenharmony_ci hilo(SHA512_H3), hilo(SHA512_H2), hilo(SHA512_H1), hilo(SHA512_H0) }; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic const u32 cc_sm3_init[] = { 568c2ecf20Sopenharmony_ci SM3_IVH, SM3_IVG, SM3_IVF, SM3_IVE, 578c2ecf20Sopenharmony_ci SM3_IVD, SM3_IVC, SM3_IVB, SM3_IVA }; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic void cc_setup_xcbc(struct ahash_request *areq, struct cc_hw_desc desc[], 608c2ecf20Sopenharmony_ci unsigned int *seq_size); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic void cc_setup_cmac(struct ahash_request *areq, struct cc_hw_desc desc[], 638c2ecf20Sopenharmony_ci unsigned int *seq_size); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic const void *cc_larval_digest(struct device *dev, u32 mode); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistruct cc_hash_alg { 688c2ecf20Sopenharmony_ci struct list_head entry; 698c2ecf20Sopenharmony_ci int hash_mode; 708c2ecf20Sopenharmony_ci int hw_mode; 718c2ecf20Sopenharmony_ci int inter_digestsize; 728c2ecf20Sopenharmony_ci struct cc_drvdata *drvdata; 738c2ecf20Sopenharmony_ci struct ahash_alg ahash_alg; 748c2ecf20Sopenharmony_ci}; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistruct hash_key_req_ctx { 778c2ecf20Sopenharmony_ci u32 keylen; 788c2ecf20Sopenharmony_ci dma_addr_t key_dma_addr; 798c2ecf20Sopenharmony_ci u8 *key; 808c2ecf20Sopenharmony_ci}; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/* hash per-session context */ 838c2ecf20Sopenharmony_cistruct cc_hash_ctx { 848c2ecf20Sopenharmony_ci struct cc_drvdata *drvdata; 858c2ecf20Sopenharmony_ci /* holds the origin digest; the digest after "setkey" if HMAC,* 868c2ecf20Sopenharmony_ci * the initial digest if HASH. 878c2ecf20Sopenharmony_ci */ 888c2ecf20Sopenharmony_ci u8 digest_buff[CC_MAX_HASH_DIGEST_SIZE] ____cacheline_aligned; 898c2ecf20Sopenharmony_ci u8 opad_tmp_keys_buff[CC_MAX_OPAD_KEYS_SIZE] ____cacheline_aligned; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci dma_addr_t opad_tmp_keys_dma_addr ____cacheline_aligned; 928c2ecf20Sopenharmony_ci dma_addr_t digest_buff_dma_addr; 938c2ecf20Sopenharmony_ci /* use for hmac with key large then mode block size */ 948c2ecf20Sopenharmony_ci struct hash_key_req_ctx key_params; 958c2ecf20Sopenharmony_ci int hash_mode; 968c2ecf20Sopenharmony_ci int hw_mode; 978c2ecf20Sopenharmony_ci int inter_digestsize; 988c2ecf20Sopenharmony_ci unsigned int hash_len; 998c2ecf20Sopenharmony_ci struct completion setkey_comp; 1008c2ecf20Sopenharmony_ci bool is_hmac; 1018c2ecf20Sopenharmony_ci}; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic void cc_set_desc(struct ahash_req_ctx *areq_ctx, struct cc_hash_ctx *ctx, 1048c2ecf20Sopenharmony_ci unsigned int flow_mode, struct cc_hw_desc desc[], 1058c2ecf20Sopenharmony_ci bool is_not_last_data, unsigned int *seq_size); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic void cc_set_endianity(u32 mode, struct cc_hw_desc *desc) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci if (mode == DRV_HASH_MD5 || mode == DRV_HASH_SHA384 || 1108c2ecf20Sopenharmony_ci mode == DRV_HASH_SHA512) { 1118c2ecf20Sopenharmony_ci set_bytes_swap(desc, 1); 1128c2ecf20Sopenharmony_ci } else { 1138c2ecf20Sopenharmony_ci set_cipher_config0(desc, HASH_DIGEST_RESULT_LITTLE_ENDIAN); 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic int cc_map_result(struct device *dev, struct ahash_req_ctx *state, 1188c2ecf20Sopenharmony_ci unsigned int digestsize) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci state->digest_result_dma_addr = 1218c2ecf20Sopenharmony_ci dma_map_single(dev, state->digest_result_buff, 1228c2ecf20Sopenharmony_ci digestsize, DMA_BIDIRECTIONAL); 1238c2ecf20Sopenharmony_ci if (dma_mapping_error(dev, state->digest_result_dma_addr)) { 1248c2ecf20Sopenharmony_ci dev_err(dev, "Mapping digest result buffer %u B for DMA failed\n", 1258c2ecf20Sopenharmony_ci digestsize); 1268c2ecf20Sopenharmony_ci return -ENOMEM; 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci dev_dbg(dev, "Mapped digest result buffer %u B at va=%pK to dma=%pad\n", 1298c2ecf20Sopenharmony_ci digestsize, state->digest_result_buff, 1308c2ecf20Sopenharmony_ci &state->digest_result_dma_addr); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci return 0; 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic void cc_init_req(struct device *dev, struct ahash_req_ctx *state, 1368c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci bool is_hmac = ctx->is_hmac; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci memset(state, 0, sizeof(*state)); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci if (is_hmac) { 1438c2ecf20Sopenharmony_ci if (ctx->hw_mode != DRV_CIPHER_XCBC_MAC && 1448c2ecf20Sopenharmony_ci ctx->hw_mode != DRV_CIPHER_CMAC) { 1458c2ecf20Sopenharmony_ci dma_sync_single_for_cpu(dev, ctx->digest_buff_dma_addr, 1468c2ecf20Sopenharmony_ci ctx->inter_digestsize, 1478c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci memcpy(state->digest_buff, ctx->digest_buff, 1508c2ecf20Sopenharmony_ci ctx->inter_digestsize); 1518c2ecf20Sopenharmony_ci if (ctx->hash_mode == DRV_HASH_SHA512 || 1528c2ecf20Sopenharmony_ci ctx->hash_mode == DRV_HASH_SHA384) 1538c2ecf20Sopenharmony_ci memcpy(state->digest_bytes_len, 1548c2ecf20Sopenharmony_ci cc_digest_len_sha512_init, 1558c2ecf20Sopenharmony_ci ctx->hash_len); 1568c2ecf20Sopenharmony_ci else 1578c2ecf20Sopenharmony_ci memcpy(state->digest_bytes_len, 1588c2ecf20Sopenharmony_ci cc_digest_len_init, 1598c2ecf20Sopenharmony_ci ctx->hash_len); 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (ctx->hash_mode != DRV_HASH_NULL) { 1638c2ecf20Sopenharmony_ci dma_sync_single_for_cpu(dev, 1648c2ecf20Sopenharmony_ci ctx->opad_tmp_keys_dma_addr, 1658c2ecf20Sopenharmony_ci ctx->inter_digestsize, 1668c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 1678c2ecf20Sopenharmony_ci memcpy(state->opad_digest_buff, 1688c2ecf20Sopenharmony_ci ctx->opad_tmp_keys_buff, ctx->inter_digestsize); 1698c2ecf20Sopenharmony_ci } 1708c2ecf20Sopenharmony_ci } else { /*hash*/ 1718c2ecf20Sopenharmony_ci /* Copy the initial digests if hash flow. */ 1728c2ecf20Sopenharmony_ci const void *larval = cc_larval_digest(dev, ctx->hash_mode); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci memcpy(state->digest_buff, larval, ctx->inter_digestsize); 1758c2ecf20Sopenharmony_ci } 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic int cc_map_req(struct device *dev, struct ahash_req_ctx *state, 1798c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci bool is_hmac = ctx->is_hmac; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci state->digest_buff_dma_addr = 1848c2ecf20Sopenharmony_ci dma_map_single(dev, state->digest_buff, 1858c2ecf20Sopenharmony_ci ctx->inter_digestsize, DMA_BIDIRECTIONAL); 1868c2ecf20Sopenharmony_ci if (dma_mapping_error(dev, state->digest_buff_dma_addr)) { 1878c2ecf20Sopenharmony_ci dev_err(dev, "Mapping digest len %d B at va=%pK for DMA failed\n", 1888c2ecf20Sopenharmony_ci ctx->inter_digestsize, state->digest_buff); 1898c2ecf20Sopenharmony_ci return -EINVAL; 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci dev_dbg(dev, "Mapped digest %d B at va=%pK to dma=%pad\n", 1928c2ecf20Sopenharmony_ci ctx->inter_digestsize, state->digest_buff, 1938c2ecf20Sopenharmony_ci &state->digest_buff_dma_addr); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci if (ctx->hw_mode != DRV_CIPHER_XCBC_MAC) { 1968c2ecf20Sopenharmony_ci state->digest_bytes_len_dma_addr = 1978c2ecf20Sopenharmony_ci dma_map_single(dev, state->digest_bytes_len, 1988c2ecf20Sopenharmony_ci HASH_MAX_LEN_SIZE, DMA_BIDIRECTIONAL); 1998c2ecf20Sopenharmony_ci if (dma_mapping_error(dev, state->digest_bytes_len_dma_addr)) { 2008c2ecf20Sopenharmony_ci dev_err(dev, "Mapping digest len %u B at va=%pK for DMA failed\n", 2018c2ecf20Sopenharmony_ci HASH_MAX_LEN_SIZE, state->digest_bytes_len); 2028c2ecf20Sopenharmony_ci goto unmap_digest_buf; 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci dev_dbg(dev, "Mapped digest len %u B at va=%pK to dma=%pad\n", 2058c2ecf20Sopenharmony_ci HASH_MAX_LEN_SIZE, state->digest_bytes_len, 2068c2ecf20Sopenharmony_ci &state->digest_bytes_len_dma_addr); 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci if (is_hmac && ctx->hash_mode != DRV_HASH_NULL) { 2108c2ecf20Sopenharmony_ci state->opad_digest_dma_addr = 2118c2ecf20Sopenharmony_ci dma_map_single(dev, state->opad_digest_buff, 2128c2ecf20Sopenharmony_ci ctx->inter_digestsize, 2138c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 2148c2ecf20Sopenharmony_ci if (dma_mapping_error(dev, state->opad_digest_dma_addr)) { 2158c2ecf20Sopenharmony_ci dev_err(dev, "Mapping opad digest %d B at va=%pK for DMA failed\n", 2168c2ecf20Sopenharmony_ci ctx->inter_digestsize, 2178c2ecf20Sopenharmony_ci state->opad_digest_buff); 2188c2ecf20Sopenharmony_ci goto unmap_digest_len; 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci dev_dbg(dev, "Mapped opad digest %d B at va=%pK to dma=%pad\n", 2218c2ecf20Sopenharmony_ci ctx->inter_digestsize, state->opad_digest_buff, 2228c2ecf20Sopenharmony_ci &state->opad_digest_dma_addr); 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci return 0; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ciunmap_digest_len: 2288c2ecf20Sopenharmony_ci if (state->digest_bytes_len_dma_addr) { 2298c2ecf20Sopenharmony_ci dma_unmap_single(dev, state->digest_bytes_len_dma_addr, 2308c2ecf20Sopenharmony_ci HASH_MAX_LEN_SIZE, DMA_BIDIRECTIONAL); 2318c2ecf20Sopenharmony_ci state->digest_bytes_len_dma_addr = 0; 2328c2ecf20Sopenharmony_ci } 2338c2ecf20Sopenharmony_ciunmap_digest_buf: 2348c2ecf20Sopenharmony_ci if (state->digest_buff_dma_addr) { 2358c2ecf20Sopenharmony_ci dma_unmap_single(dev, state->digest_buff_dma_addr, 2368c2ecf20Sopenharmony_ci ctx->inter_digestsize, DMA_BIDIRECTIONAL); 2378c2ecf20Sopenharmony_ci state->digest_buff_dma_addr = 0; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci return -EINVAL; 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistatic void cc_unmap_req(struct device *dev, struct ahash_req_ctx *state, 2448c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci if (state->digest_buff_dma_addr) { 2478c2ecf20Sopenharmony_ci dma_unmap_single(dev, state->digest_buff_dma_addr, 2488c2ecf20Sopenharmony_ci ctx->inter_digestsize, DMA_BIDIRECTIONAL); 2498c2ecf20Sopenharmony_ci dev_dbg(dev, "Unmapped digest-buffer: digest_buff_dma_addr=%pad\n", 2508c2ecf20Sopenharmony_ci &state->digest_buff_dma_addr); 2518c2ecf20Sopenharmony_ci state->digest_buff_dma_addr = 0; 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci if (state->digest_bytes_len_dma_addr) { 2548c2ecf20Sopenharmony_ci dma_unmap_single(dev, state->digest_bytes_len_dma_addr, 2558c2ecf20Sopenharmony_ci HASH_MAX_LEN_SIZE, DMA_BIDIRECTIONAL); 2568c2ecf20Sopenharmony_ci dev_dbg(dev, "Unmapped digest-bytes-len buffer: digest_bytes_len_dma_addr=%pad\n", 2578c2ecf20Sopenharmony_ci &state->digest_bytes_len_dma_addr); 2588c2ecf20Sopenharmony_ci state->digest_bytes_len_dma_addr = 0; 2598c2ecf20Sopenharmony_ci } 2608c2ecf20Sopenharmony_ci if (state->opad_digest_dma_addr) { 2618c2ecf20Sopenharmony_ci dma_unmap_single(dev, state->opad_digest_dma_addr, 2628c2ecf20Sopenharmony_ci ctx->inter_digestsize, DMA_BIDIRECTIONAL); 2638c2ecf20Sopenharmony_ci dev_dbg(dev, "Unmapped opad-digest: opad_digest_dma_addr=%pad\n", 2648c2ecf20Sopenharmony_ci &state->opad_digest_dma_addr); 2658c2ecf20Sopenharmony_ci state->opad_digest_dma_addr = 0; 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci} 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_cistatic void cc_unmap_result(struct device *dev, struct ahash_req_ctx *state, 2708c2ecf20Sopenharmony_ci unsigned int digestsize, u8 *result) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci if (state->digest_result_dma_addr) { 2738c2ecf20Sopenharmony_ci dma_unmap_single(dev, state->digest_result_dma_addr, digestsize, 2748c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 2758c2ecf20Sopenharmony_ci dev_dbg(dev, "unmpa digest result buffer va (%pK) pa (%pad) len %u\n", 2768c2ecf20Sopenharmony_ci state->digest_result_buff, 2778c2ecf20Sopenharmony_ci &state->digest_result_dma_addr, digestsize); 2788c2ecf20Sopenharmony_ci memcpy(result, state->digest_result_buff, digestsize); 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci state->digest_result_dma_addr = 0; 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic void cc_update_complete(struct device *dev, void *cc_req, int err) 2848c2ecf20Sopenharmony_ci{ 2858c2ecf20Sopenharmony_ci struct ahash_request *req = (struct ahash_request *)cc_req; 2868c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(req); 2878c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 2888c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci dev_dbg(dev, "req=%pK\n", req); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci if (err != -EINPROGRESS) { 2938c2ecf20Sopenharmony_ci /* Not a BACKLOG notification */ 2948c2ecf20Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, false); 2958c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci ahash_request_complete(req, err); 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_cistatic void cc_digest_complete(struct device *dev, void *cc_req, int err) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci struct ahash_request *req = (struct ahash_request *)cc_req; 3048c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(req); 3058c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 3068c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm); 3078c2ecf20Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci dev_dbg(dev, "req=%pK\n", req); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci if (err != -EINPROGRESS) { 3128c2ecf20Sopenharmony_ci /* Not a BACKLOG notification */ 3138c2ecf20Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, false); 3148c2ecf20Sopenharmony_ci cc_unmap_result(dev, state, digestsize, req->result); 3158c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 3168c2ecf20Sopenharmony_ci } 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci ahash_request_complete(req, err); 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic void cc_hash_complete(struct device *dev, void *cc_req, int err) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci struct ahash_request *req = (struct ahash_request *)cc_req; 3248c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(req); 3258c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 3268c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm); 3278c2ecf20Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci dev_dbg(dev, "req=%pK\n", req); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci if (err != -EINPROGRESS) { 3328c2ecf20Sopenharmony_ci /* Not a BACKLOG notification */ 3338c2ecf20Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, false); 3348c2ecf20Sopenharmony_ci cc_unmap_result(dev, state, digestsize, req->result); 3358c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci ahash_request_complete(req, err); 3398c2ecf20Sopenharmony_ci} 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_cistatic int cc_fin_result(struct cc_hw_desc *desc, struct ahash_request *req, 3428c2ecf20Sopenharmony_ci int idx) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(req); 3458c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 3468c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm); 3478c2ecf20Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci /* Get final MAC result */ 3508c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 3518c2ecf20Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 3528c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_result_dma_addr, digestsize, 3538c2ecf20Sopenharmony_ci NS_BIT, 1); 3548c2ecf20Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 3558c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 3568c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 3578c2ecf20Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED); 3588c2ecf20Sopenharmony_ci cc_set_endianity(ctx->hash_mode, &desc[idx]); 3598c2ecf20Sopenharmony_ci idx++; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci return idx; 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cistatic int cc_fin_hmac(struct cc_hw_desc *desc, struct ahash_request *req, 3658c2ecf20Sopenharmony_ci int idx) 3668c2ecf20Sopenharmony_ci{ 3678c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(req); 3688c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 3698c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm); 3708c2ecf20Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci /* store the hash digest result in the context */ 3738c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 3748c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 3758c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_buff_dma_addr, digestsize, 3768c2ecf20Sopenharmony_ci NS_BIT, 0); 3778c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 3788c2ecf20Sopenharmony_ci cc_set_endianity(ctx->hash_mode, &desc[idx]); 3798c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 3808c2ecf20Sopenharmony_ci idx++; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci /* Loading hash opad xor key state */ 3838c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 3848c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 3858c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->opad_digest_dma_addr, 3868c2ecf20Sopenharmony_ci ctx->inter_digestsize, NS_BIT); 3878c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 3888c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 3898c2ecf20Sopenharmony_ci idx++; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci /* Load the hash current length */ 3928c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 3938c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 3948c2ecf20Sopenharmony_ci set_din_sram(&desc[idx], 3958c2ecf20Sopenharmony_ci cc_digest_len_addr(ctx->drvdata, ctx->hash_mode), 3968c2ecf20Sopenharmony_ci ctx->hash_len); 3978c2ecf20Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); 3988c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 3998c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 4008c2ecf20Sopenharmony_ci idx++; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci /* Memory Barrier: wait for IPAD/OPAD axi write to complete */ 4038c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 4048c2ecf20Sopenharmony_ci set_din_no_dma(&desc[idx], 0, 0xfffff0); 4058c2ecf20Sopenharmony_ci set_dout_no_dma(&desc[idx], 0, 0, 1); 4068c2ecf20Sopenharmony_ci idx++; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci /* Perform HASH update */ 4098c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 4108c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, 4118c2ecf20Sopenharmony_ci digestsize, NS_BIT); 4128c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], DIN_HASH); 4138c2ecf20Sopenharmony_ci idx++; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci return idx; 4168c2ecf20Sopenharmony_ci} 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_cistatic int cc_hash_digest(struct ahash_request *req) 4198c2ecf20Sopenharmony_ci{ 4208c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(req); 4218c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 4228c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm); 4238c2ecf20Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 4248c2ecf20Sopenharmony_ci struct scatterlist *src = req->src; 4258c2ecf20Sopenharmony_ci unsigned int nbytes = req->nbytes; 4268c2ecf20Sopenharmony_ci u8 *result = req->result; 4278c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 4288c2ecf20Sopenharmony_ci bool is_hmac = ctx->is_hmac; 4298c2ecf20Sopenharmony_ci struct cc_crypto_req cc_req = {}; 4308c2ecf20Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 4318c2ecf20Sopenharmony_ci u32 larval_digest_addr; 4328c2ecf20Sopenharmony_ci int idx = 0; 4338c2ecf20Sopenharmony_ci int rc = 0; 4348c2ecf20Sopenharmony_ci gfp_t flags = cc_gfp_flags(&req->base); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci dev_dbg(dev, "===== %s-digest (%d) ====\n", is_hmac ? "hmac" : "hash", 4378c2ecf20Sopenharmony_ci nbytes); 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci cc_init_req(dev, state, ctx); 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci if (cc_map_req(dev, state, ctx)) { 4428c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_source() failed\n"); 4438c2ecf20Sopenharmony_ci return -ENOMEM; 4448c2ecf20Sopenharmony_ci } 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci if (cc_map_result(dev, state, digestsize)) { 4478c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_digest() failed\n"); 4488c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 4498c2ecf20Sopenharmony_ci return -ENOMEM; 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci if (cc_map_hash_request_final(ctx->drvdata, state, src, nbytes, 1, 4538c2ecf20Sopenharmony_ci flags)) { 4548c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_request_final() failed\n"); 4558c2ecf20Sopenharmony_ci cc_unmap_result(dev, state, digestsize, result); 4568c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 4578c2ecf20Sopenharmony_ci return -ENOMEM; 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci /* Setup request structure */ 4618c2ecf20Sopenharmony_ci cc_req.user_cb = cc_digest_complete; 4628c2ecf20Sopenharmony_ci cc_req.user_arg = req; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci /* If HMAC then load hash IPAD xor key, if HASH then load initial 4658c2ecf20Sopenharmony_ci * digest 4668c2ecf20Sopenharmony_ci */ 4678c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 4688c2ecf20Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 4698c2ecf20Sopenharmony_ci if (is_hmac) { 4708c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, 4718c2ecf20Sopenharmony_ci ctx->inter_digestsize, NS_BIT); 4728c2ecf20Sopenharmony_ci } else { 4738c2ecf20Sopenharmony_ci larval_digest_addr = cc_larval_digest_addr(ctx->drvdata, 4748c2ecf20Sopenharmony_ci ctx->hash_mode); 4758c2ecf20Sopenharmony_ci set_din_sram(&desc[idx], larval_digest_addr, 4768c2ecf20Sopenharmony_ci ctx->inter_digestsize); 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 4798c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 4808c2ecf20Sopenharmony_ci idx++; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci /* Load the hash current length */ 4838c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 4848c2ecf20Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci if (is_hmac) { 4878c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 4888c2ecf20Sopenharmony_ci state->digest_bytes_len_dma_addr, 4898c2ecf20Sopenharmony_ci ctx->hash_len, NS_BIT); 4908c2ecf20Sopenharmony_ci } else { 4918c2ecf20Sopenharmony_ci set_din_const(&desc[idx], 0, ctx->hash_len); 4928c2ecf20Sopenharmony_ci if (nbytes) 4938c2ecf20Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); 4948c2ecf20Sopenharmony_ci else 4958c2ecf20Sopenharmony_ci set_cipher_do(&desc[idx], DO_PAD); 4968c2ecf20Sopenharmony_ci } 4978c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 4988c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 4998c2ecf20Sopenharmony_ci idx++; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci cc_set_desc(state, ctx, DIN_HASH, desc, false, &idx); 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci if (is_hmac) { 5048c2ecf20Sopenharmony_ci /* HW last hash block padding (aka. "DO_PAD") */ 5058c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 5068c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 5078c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_buff_dma_addr, 5088c2ecf20Sopenharmony_ci ctx->hash_len, NS_BIT, 0); 5098c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 5108c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE1); 5118c2ecf20Sopenharmony_ci set_cipher_do(&desc[idx], DO_PAD); 5128c2ecf20Sopenharmony_ci idx++; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci idx = cc_fin_hmac(desc, req, idx); 5158c2ecf20Sopenharmony_ci } 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci idx = cc_fin_result(desc, req, idx); 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base); 5208c2ecf20Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 5218c2ecf20Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 5228c2ecf20Sopenharmony_ci cc_unmap_hash_request(dev, state, src, true); 5238c2ecf20Sopenharmony_ci cc_unmap_result(dev, state, digestsize, result); 5248c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 5258c2ecf20Sopenharmony_ci } 5268c2ecf20Sopenharmony_ci return rc; 5278c2ecf20Sopenharmony_ci} 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_cistatic int cc_restore_hash(struct cc_hw_desc *desc, struct cc_hash_ctx *ctx, 5308c2ecf20Sopenharmony_ci struct ahash_req_ctx *state, unsigned int idx) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci /* Restore hash digest */ 5338c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 5348c2ecf20Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 5358c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, 5368c2ecf20Sopenharmony_ci ctx->inter_digestsize, NS_BIT); 5378c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 5388c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 5398c2ecf20Sopenharmony_ci idx++; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci /* Restore hash current length */ 5428c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 5438c2ecf20Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 5448c2ecf20Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED); 5458c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->digest_bytes_len_dma_addr, 5468c2ecf20Sopenharmony_ci ctx->hash_len, NS_BIT); 5478c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 5488c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 5498c2ecf20Sopenharmony_ci idx++; 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci cc_set_desc(state, ctx, DIN_HASH, desc, false, &idx); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci return idx; 5548c2ecf20Sopenharmony_ci} 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_cistatic int cc_hash_update(struct ahash_request *req) 5578c2ecf20Sopenharmony_ci{ 5588c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(req); 5598c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 5608c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm); 5618c2ecf20Sopenharmony_ci unsigned int block_size = crypto_tfm_alg_blocksize(&tfm->base); 5628c2ecf20Sopenharmony_ci struct scatterlist *src = req->src; 5638c2ecf20Sopenharmony_ci unsigned int nbytes = req->nbytes; 5648c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 5658c2ecf20Sopenharmony_ci struct cc_crypto_req cc_req = {}; 5668c2ecf20Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 5678c2ecf20Sopenharmony_ci u32 idx = 0; 5688c2ecf20Sopenharmony_ci int rc; 5698c2ecf20Sopenharmony_ci gfp_t flags = cc_gfp_flags(&req->base); 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci dev_dbg(dev, "===== %s-update (%d) ====\n", ctx->is_hmac ? 5728c2ecf20Sopenharmony_ci "hmac" : "hash", nbytes); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci if (nbytes == 0) { 5758c2ecf20Sopenharmony_ci /* no real updates required */ 5768c2ecf20Sopenharmony_ci return 0; 5778c2ecf20Sopenharmony_ci } 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci rc = cc_map_hash_request_update(ctx->drvdata, state, src, nbytes, 5808c2ecf20Sopenharmony_ci block_size, flags); 5818c2ecf20Sopenharmony_ci if (rc) { 5828c2ecf20Sopenharmony_ci if (rc == 1) { 5838c2ecf20Sopenharmony_ci dev_dbg(dev, " data size not require HW update %x\n", 5848c2ecf20Sopenharmony_ci nbytes); 5858c2ecf20Sopenharmony_ci /* No hardware updates are required */ 5868c2ecf20Sopenharmony_ci return 0; 5878c2ecf20Sopenharmony_ci } 5888c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_request_update() failed\n"); 5898c2ecf20Sopenharmony_ci return -ENOMEM; 5908c2ecf20Sopenharmony_ci } 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci if (cc_map_req(dev, state, ctx)) { 5938c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_source() failed\n"); 5948c2ecf20Sopenharmony_ci cc_unmap_hash_request(dev, state, src, true); 5958c2ecf20Sopenharmony_ci return -EINVAL; 5968c2ecf20Sopenharmony_ci } 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci /* Setup request structure */ 5998c2ecf20Sopenharmony_ci cc_req.user_cb = cc_update_complete; 6008c2ecf20Sopenharmony_ci cc_req.user_arg = req; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci idx = cc_restore_hash(desc, ctx, state, idx); 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci /* store the hash digest result in context */ 6058c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 6068c2ecf20Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 6078c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_buff_dma_addr, 6088c2ecf20Sopenharmony_ci ctx->inter_digestsize, NS_BIT, 0); 6098c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 6108c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 6118c2ecf20Sopenharmony_ci idx++; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci /* store current hash length in context */ 6148c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 6158c2ecf20Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 6168c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_bytes_len_dma_addr, 6178c2ecf20Sopenharmony_ci ctx->hash_len, NS_BIT, 1); 6188c2ecf20Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 6198c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 6208c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE1); 6218c2ecf20Sopenharmony_ci idx++; 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base); 6248c2ecf20Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 6258c2ecf20Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 6268c2ecf20Sopenharmony_ci cc_unmap_hash_request(dev, state, src, true); 6278c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 6288c2ecf20Sopenharmony_ci } 6298c2ecf20Sopenharmony_ci return rc; 6308c2ecf20Sopenharmony_ci} 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_cistatic int cc_do_finup(struct ahash_request *req, bool update) 6338c2ecf20Sopenharmony_ci{ 6348c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(req); 6358c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 6368c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm); 6378c2ecf20Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 6388c2ecf20Sopenharmony_ci struct scatterlist *src = req->src; 6398c2ecf20Sopenharmony_ci unsigned int nbytes = req->nbytes; 6408c2ecf20Sopenharmony_ci u8 *result = req->result; 6418c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 6428c2ecf20Sopenharmony_ci bool is_hmac = ctx->is_hmac; 6438c2ecf20Sopenharmony_ci struct cc_crypto_req cc_req = {}; 6448c2ecf20Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 6458c2ecf20Sopenharmony_ci unsigned int idx = 0; 6468c2ecf20Sopenharmony_ci int rc; 6478c2ecf20Sopenharmony_ci gfp_t flags = cc_gfp_flags(&req->base); 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci dev_dbg(dev, "===== %s-%s (%d) ====\n", is_hmac ? "hmac" : "hash", 6508c2ecf20Sopenharmony_ci update ? "finup" : "final", nbytes); 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci if (cc_map_req(dev, state, ctx)) { 6538c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_source() failed\n"); 6548c2ecf20Sopenharmony_ci return -EINVAL; 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci if (cc_map_hash_request_final(ctx->drvdata, state, src, nbytes, update, 6588c2ecf20Sopenharmony_ci flags)) { 6598c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_request_final() failed\n"); 6608c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 6618c2ecf20Sopenharmony_ci return -ENOMEM; 6628c2ecf20Sopenharmony_ci } 6638c2ecf20Sopenharmony_ci if (cc_map_result(dev, state, digestsize)) { 6648c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_digest() failed\n"); 6658c2ecf20Sopenharmony_ci cc_unmap_hash_request(dev, state, src, true); 6668c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 6678c2ecf20Sopenharmony_ci return -ENOMEM; 6688c2ecf20Sopenharmony_ci } 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci /* Setup request structure */ 6718c2ecf20Sopenharmony_ci cc_req.user_cb = cc_hash_complete; 6728c2ecf20Sopenharmony_ci cc_req.user_arg = req; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci idx = cc_restore_hash(desc, ctx, state, idx); 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci /* Pad the hash */ 6778c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 6788c2ecf20Sopenharmony_ci set_cipher_do(&desc[idx], DO_PAD); 6798c2ecf20Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 6808c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_bytes_len_dma_addr, 6818c2ecf20Sopenharmony_ci ctx->hash_len, NS_BIT, 0); 6828c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE1); 6838c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 6848c2ecf20Sopenharmony_ci idx++; 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci if (is_hmac) 6878c2ecf20Sopenharmony_ci idx = cc_fin_hmac(desc, req, idx); 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci idx = cc_fin_result(desc, req, idx); 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base); 6928c2ecf20Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 6938c2ecf20Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 6948c2ecf20Sopenharmony_ci cc_unmap_hash_request(dev, state, src, true); 6958c2ecf20Sopenharmony_ci cc_unmap_result(dev, state, digestsize, result); 6968c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 6978c2ecf20Sopenharmony_ci } 6988c2ecf20Sopenharmony_ci return rc; 6998c2ecf20Sopenharmony_ci} 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_cistatic int cc_hash_finup(struct ahash_request *req) 7028c2ecf20Sopenharmony_ci{ 7038c2ecf20Sopenharmony_ci return cc_do_finup(req, true); 7048c2ecf20Sopenharmony_ci} 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_cistatic int cc_hash_final(struct ahash_request *req) 7088c2ecf20Sopenharmony_ci{ 7098c2ecf20Sopenharmony_ci return cc_do_finup(req, false); 7108c2ecf20Sopenharmony_ci} 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_cistatic int cc_hash_init(struct ahash_request *req) 7138c2ecf20Sopenharmony_ci{ 7148c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(req); 7158c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 7168c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm); 7178c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci dev_dbg(dev, "===== init (%d) ====\n", req->nbytes); 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci cc_init_req(dev, state, ctx); 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci return 0; 7248c2ecf20Sopenharmony_ci} 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_cistatic int cc_hash_setkey(struct crypto_ahash *ahash, const u8 *key, 7278c2ecf20Sopenharmony_ci unsigned int keylen) 7288c2ecf20Sopenharmony_ci{ 7298c2ecf20Sopenharmony_ci unsigned int hmac_pad_const[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST }; 7308c2ecf20Sopenharmony_ci struct cc_crypto_req cc_req = {}; 7318c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = NULL; 7328c2ecf20Sopenharmony_ci int blocksize = 0; 7338c2ecf20Sopenharmony_ci int digestsize = 0; 7348c2ecf20Sopenharmony_ci int i, idx = 0, rc = 0; 7358c2ecf20Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 7368c2ecf20Sopenharmony_ci u32 larval_addr; 7378c2ecf20Sopenharmony_ci struct device *dev; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci ctx = crypto_ahash_ctx(ahash); 7408c2ecf20Sopenharmony_ci dev = drvdata_to_dev(ctx->drvdata); 7418c2ecf20Sopenharmony_ci dev_dbg(dev, "start keylen: %d", keylen); 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci blocksize = crypto_tfm_alg_blocksize(&ahash->base); 7448c2ecf20Sopenharmony_ci digestsize = crypto_ahash_digestsize(ahash); 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci larval_addr = cc_larval_digest_addr(ctx->drvdata, ctx->hash_mode); 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci /* The keylen value distinguishes HASH in case keylen is ZERO bytes, 7498c2ecf20Sopenharmony_ci * any NON-ZERO value utilizes HMAC flow 7508c2ecf20Sopenharmony_ci */ 7518c2ecf20Sopenharmony_ci ctx->key_params.keylen = keylen; 7528c2ecf20Sopenharmony_ci ctx->key_params.key_dma_addr = 0; 7538c2ecf20Sopenharmony_ci ctx->is_hmac = true; 7548c2ecf20Sopenharmony_ci ctx->key_params.key = NULL; 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci if (keylen) { 7578c2ecf20Sopenharmony_ci ctx->key_params.key = kmemdup(key, keylen, GFP_KERNEL); 7588c2ecf20Sopenharmony_ci if (!ctx->key_params.key) 7598c2ecf20Sopenharmony_ci return -ENOMEM; 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci ctx->key_params.key_dma_addr = 7628c2ecf20Sopenharmony_ci dma_map_single(dev, ctx->key_params.key, keylen, 7638c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 7648c2ecf20Sopenharmony_ci if (dma_mapping_error(dev, ctx->key_params.key_dma_addr)) { 7658c2ecf20Sopenharmony_ci dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n", 7668c2ecf20Sopenharmony_ci ctx->key_params.key, keylen); 7678c2ecf20Sopenharmony_ci kfree_sensitive(ctx->key_params.key); 7688c2ecf20Sopenharmony_ci return -ENOMEM; 7698c2ecf20Sopenharmony_ci } 7708c2ecf20Sopenharmony_ci dev_dbg(dev, "mapping key-buffer: key_dma_addr=%pad keylen=%u\n", 7718c2ecf20Sopenharmony_ci &ctx->key_params.key_dma_addr, ctx->key_params.keylen); 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci if (keylen > blocksize) { 7748c2ecf20Sopenharmony_ci /* Load hash initial state */ 7758c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 7768c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 7778c2ecf20Sopenharmony_ci set_din_sram(&desc[idx], larval_addr, 7788c2ecf20Sopenharmony_ci ctx->inter_digestsize); 7798c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 7808c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 7818c2ecf20Sopenharmony_ci idx++; 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci /* Load the hash current length*/ 7848c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 7858c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 7868c2ecf20Sopenharmony_ci set_din_const(&desc[idx], 0, ctx->hash_len); 7878c2ecf20Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); 7888c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 7898c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 7908c2ecf20Sopenharmony_ci idx++; 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 7938c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 7948c2ecf20Sopenharmony_ci ctx->key_params.key_dma_addr, keylen, 7958c2ecf20Sopenharmony_ci NS_BIT); 7968c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], DIN_HASH); 7978c2ecf20Sopenharmony_ci idx++; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci /* Get hashed key */ 8008c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 8018c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 8028c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr, 8038c2ecf20Sopenharmony_ci digestsize, NS_BIT, 0); 8048c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 8058c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 8068c2ecf20Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED); 8078c2ecf20Sopenharmony_ci cc_set_endianity(ctx->hash_mode, &desc[idx]); 8088c2ecf20Sopenharmony_ci idx++; 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 8118c2ecf20Sopenharmony_ci set_din_const(&desc[idx], 0, (blocksize - digestsize)); 8128c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], BYPASS); 8138c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], 8148c2ecf20Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + 8158c2ecf20Sopenharmony_ci digestsize), 8168c2ecf20Sopenharmony_ci (blocksize - digestsize), NS_BIT, 0); 8178c2ecf20Sopenharmony_ci idx++; 8188c2ecf20Sopenharmony_ci } else { 8198c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 8208c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 8218c2ecf20Sopenharmony_ci ctx->key_params.key_dma_addr, keylen, 8228c2ecf20Sopenharmony_ci NS_BIT); 8238c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], BYPASS); 8248c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr, 8258c2ecf20Sopenharmony_ci keylen, NS_BIT, 0); 8268c2ecf20Sopenharmony_ci idx++; 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci if ((blocksize - keylen)) { 8298c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 8308c2ecf20Sopenharmony_ci set_din_const(&desc[idx], 0, 8318c2ecf20Sopenharmony_ci (blocksize - keylen)); 8328c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], BYPASS); 8338c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], 8348c2ecf20Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + 8358c2ecf20Sopenharmony_ci keylen), (blocksize - keylen), 8368c2ecf20Sopenharmony_ci NS_BIT, 0); 8378c2ecf20Sopenharmony_ci idx++; 8388c2ecf20Sopenharmony_ci } 8398c2ecf20Sopenharmony_ci } 8408c2ecf20Sopenharmony_ci } else { 8418c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 8428c2ecf20Sopenharmony_ci set_din_const(&desc[idx], 0, blocksize); 8438c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], BYPASS); 8448c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr), 8458c2ecf20Sopenharmony_ci blocksize, NS_BIT, 0); 8468c2ecf20Sopenharmony_ci idx++; 8478c2ecf20Sopenharmony_ci } 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, idx); 8508c2ecf20Sopenharmony_ci if (rc) { 8518c2ecf20Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 8528c2ecf20Sopenharmony_ci goto out; 8538c2ecf20Sopenharmony_ci } 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci /* calc derived HMAC key */ 8568c2ecf20Sopenharmony_ci for (idx = 0, i = 0; i < 2; i++) { 8578c2ecf20Sopenharmony_ci /* Load hash initial state */ 8588c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 8598c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 8608c2ecf20Sopenharmony_ci set_din_sram(&desc[idx], larval_addr, ctx->inter_digestsize); 8618c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 8628c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 8638c2ecf20Sopenharmony_ci idx++; 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci /* Load the hash current length*/ 8668c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 8678c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 8688c2ecf20Sopenharmony_ci set_din_const(&desc[idx], 0, ctx->hash_len); 8698c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 8708c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 8718c2ecf20Sopenharmony_ci idx++; 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci /* Prepare ipad key */ 8748c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 8758c2ecf20Sopenharmony_ci set_xor_val(&desc[idx], hmac_pad_const[i]); 8768c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 8778c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 8788c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); 8798c2ecf20Sopenharmony_ci idx++; 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci /* Perform HASH update */ 8828c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 8838c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, ctx->opad_tmp_keys_dma_addr, 8848c2ecf20Sopenharmony_ci blocksize, NS_BIT); 8858c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 8868c2ecf20Sopenharmony_ci set_xor_active(&desc[idx]); 8878c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], DIN_HASH); 8888c2ecf20Sopenharmony_ci idx++; 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci /* Get the IPAD/OPAD xor key (Note, IPAD is the initial digest 8918c2ecf20Sopenharmony_ci * of the first HASH "update" state) 8928c2ecf20Sopenharmony_ci */ 8938c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 8948c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 8958c2ecf20Sopenharmony_ci if (i > 0) /* Not first iteration */ 8968c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr, 8978c2ecf20Sopenharmony_ci ctx->inter_digestsize, NS_BIT, 0); 8988c2ecf20Sopenharmony_ci else /* First iteration */ 8998c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], ctx->digest_buff_dma_addr, 9008c2ecf20Sopenharmony_ci ctx->inter_digestsize, NS_BIT, 0); 9018c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 9028c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 9038c2ecf20Sopenharmony_ci idx++; 9048c2ecf20Sopenharmony_ci } 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, idx); 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ciout: 9098c2ecf20Sopenharmony_ci if (ctx->key_params.key_dma_addr) { 9108c2ecf20Sopenharmony_ci dma_unmap_single(dev, ctx->key_params.key_dma_addr, 9118c2ecf20Sopenharmony_ci ctx->key_params.keylen, DMA_TO_DEVICE); 9128c2ecf20Sopenharmony_ci dev_dbg(dev, "Unmapped key-buffer: key_dma_addr=%pad keylen=%u\n", 9138c2ecf20Sopenharmony_ci &ctx->key_params.key_dma_addr, ctx->key_params.keylen); 9148c2ecf20Sopenharmony_ci } 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci kfree_sensitive(ctx->key_params.key); 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci return rc; 9198c2ecf20Sopenharmony_ci} 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_cistatic int cc_xcbc_setkey(struct crypto_ahash *ahash, 9228c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 9238c2ecf20Sopenharmony_ci{ 9248c2ecf20Sopenharmony_ci struct cc_crypto_req cc_req = {}; 9258c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(ahash); 9268c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 9278c2ecf20Sopenharmony_ci int rc = 0; 9288c2ecf20Sopenharmony_ci unsigned int idx = 0; 9298c2ecf20Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci dev_dbg(dev, "===== setkey (%d) ====\n", keylen); 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci switch (keylen) { 9348c2ecf20Sopenharmony_ci case AES_KEYSIZE_128: 9358c2ecf20Sopenharmony_ci case AES_KEYSIZE_192: 9368c2ecf20Sopenharmony_ci case AES_KEYSIZE_256: 9378c2ecf20Sopenharmony_ci break; 9388c2ecf20Sopenharmony_ci default: 9398c2ecf20Sopenharmony_ci return -EINVAL; 9408c2ecf20Sopenharmony_ci } 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci ctx->key_params.keylen = keylen; 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci ctx->key_params.key = kmemdup(key, keylen, GFP_KERNEL); 9458c2ecf20Sopenharmony_ci if (!ctx->key_params.key) 9468c2ecf20Sopenharmony_ci return -ENOMEM; 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci ctx->key_params.key_dma_addr = 9498c2ecf20Sopenharmony_ci dma_map_single(dev, ctx->key_params.key, keylen, DMA_TO_DEVICE); 9508c2ecf20Sopenharmony_ci if (dma_mapping_error(dev, ctx->key_params.key_dma_addr)) { 9518c2ecf20Sopenharmony_ci dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n", 9528c2ecf20Sopenharmony_ci key, keylen); 9538c2ecf20Sopenharmony_ci kfree_sensitive(ctx->key_params.key); 9548c2ecf20Sopenharmony_ci return -ENOMEM; 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci dev_dbg(dev, "mapping key-buffer: key_dma_addr=%pad keylen=%u\n", 9578c2ecf20Sopenharmony_ci &ctx->key_params.key_dma_addr, ctx->key_params.keylen); 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci ctx->is_hmac = true; 9608c2ecf20Sopenharmony_ci /* 1. Load the AES key */ 9618c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 9628c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, ctx->key_params.key_dma_addr, 9638c2ecf20Sopenharmony_ci keylen, NS_BIT); 9648c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_ECB); 9658c2ecf20Sopenharmony_ci set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT); 9668c2ecf20Sopenharmony_ci set_key_size_aes(&desc[idx], keylen); 9678c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 9688c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 9698c2ecf20Sopenharmony_ci idx++; 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 9728c2ecf20Sopenharmony_ci set_din_const(&desc[idx], 0x01010101, CC_AES_128_BIT_KEY_SIZE); 9738c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], DIN_AES_DOUT); 9748c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], 9758c2ecf20Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K1_OFFSET), 9768c2ecf20Sopenharmony_ci CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0); 9778c2ecf20Sopenharmony_ci idx++; 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 9808c2ecf20Sopenharmony_ci set_din_const(&desc[idx], 0x02020202, CC_AES_128_BIT_KEY_SIZE); 9818c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], DIN_AES_DOUT); 9828c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], 9838c2ecf20Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K2_OFFSET), 9848c2ecf20Sopenharmony_ci CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0); 9858c2ecf20Sopenharmony_ci idx++; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 9888c2ecf20Sopenharmony_ci set_din_const(&desc[idx], 0x03030303, CC_AES_128_BIT_KEY_SIZE); 9898c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], DIN_AES_DOUT); 9908c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], 9918c2ecf20Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K3_OFFSET), 9928c2ecf20Sopenharmony_ci CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0); 9938c2ecf20Sopenharmony_ci idx++; 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, idx); 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci dma_unmap_single(dev, ctx->key_params.key_dma_addr, 9988c2ecf20Sopenharmony_ci ctx->key_params.keylen, DMA_TO_DEVICE); 9998c2ecf20Sopenharmony_ci dev_dbg(dev, "Unmapped key-buffer: key_dma_addr=%pad keylen=%u\n", 10008c2ecf20Sopenharmony_ci &ctx->key_params.key_dma_addr, ctx->key_params.keylen); 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci kfree_sensitive(ctx->key_params.key); 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci return rc; 10058c2ecf20Sopenharmony_ci} 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_cistatic int cc_cmac_setkey(struct crypto_ahash *ahash, 10088c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 10098c2ecf20Sopenharmony_ci{ 10108c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(ahash); 10118c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci dev_dbg(dev, "===== setkey (%d) ====\n", keylen); 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci ctx->is_hmac = true; 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci switch (keylen) { 10188c2ecf20Sopenharmony_ci case AES_KEYSIZE_128: 10198c2ecf20Sopenharmony_ci case AES_KEYSIZE_192: 10208c2ecf20Sopenharmony_ci case AES_KEYSIZE_256: 10218c2ecf20Sopenharmony_ci break; 10228c2ecf20Sopenharmony_ci default: 10238c2ecf20Sopenharmony_ci return -EINVAL; 10248c2ecf20Sopenharmony_ci } 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci ctx->key_params.keylen = keylen; 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci /* STAT_PHASE_1: Copy key to ctx */ 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci dma_sync_single_for_cpu(dev, ctx->opad_tmp_keys_dma_addr, 10318c2ecf20Sopenharmony_ci keylen, DMA_TO_DEVICE); 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci memcpy(ctx->opad_tmp_keys_buff, key, keylen); 10348c2ecf20Sopenharmony_ci if (keylen == 24) { 10358c2ecf20Sopenharmony_ci memset(ctx->opad_tmp_keys_buff + 24, 0, 10368c2ecf20Sopenharmony_ci CC_AES_KEY_SIZE_MAX - 24); 10378c2ecf20Sopenharmony_ci } 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci dma_sync_single_for_device(dev, ctx->opad_tmp_keys_dma_addr, 10408c2ecf20Sopenharmony_ci keylen, DMA_TO_DEVICE); 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci ctx->key_params.keylen = keylen; 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci return 0; 10458c2ecf20Sopenharmony_ci} 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_cistatic void cc_free_ctx(struct cc_hash_ctx *ctx) 10488c2ecf20Sopenharmony_ci{ 10498c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci if (ctx->digest_buff_dma_addr) { 10528c2ecf20Sopenharmony_ci dma_unmap_single(dev, ctx->digest_buff_dma_addr, 10538c2ecf20Sopenharmony_ci sizeof(ctx->digest_buff), DMA_BIDIRECTIONAL); 10548c2ecf20Sopenharmony_ci dev_dbg(dev, "Unmapped digest-buffer: digest_buff_dma_addr=%pad\n", 10558c2ecf20Sopenharmony_ci &ctx->digest_buff_dma_addr); 10568c2ecf20Sopenharmony_ci ctx->digest_buff_dma_addr = 0; 10578c2ecf20Sopenharmony_ci } 10588c2ecf20Sopenharmony_ci if (ctx->opad_tmp_keys_dma_addr) { 10598c2ecf20Sopenharmony_ci dma_unmap_single(dev, ctx->opad_tmp_keys_dma_addr, 10608c2ecf20Sopenharmony_ci sizeof(ctx->opad_tmp_keys_buff), 10618c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 10628c2ecf20Sopenharmony_ci dev_dbg(dev, "Unmapped opad-digest: opad_tmp_keys_dma_addr=%pad\n", 10638c2ecf20Sopenharmony_ci &ctx->opad_tmp_keys_dma_addr); 10648c2ecf20Sopenharmony_ci ctx->opad_tmp_keys_dma_addr = 0; 10658c2ecf20Sopenharmony_ci } 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci ctx->key_params.keylen = 0; 10688c2ecf20Sopenharmony_ci} 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_cistatic int cc_alloc_ctx(struct cc_hash_ctx *ctx) 10718c2ecf20Sopenharmony_ci{ 10728c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci ctx->key_params.keylen = 0; 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci ctx->digest_buff_dma_addr = 10778c2ecf20Sopenharmony_ci dma_map_single(dev, ctx->digest_buff, sizeof(ctx->digest_buff), 10788c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 10798c2ecf20Sopenharmony_ci if (dma_mapping_error(dev, ctx->digest_buff_dma_addr)) { 10808c2ecf20Sopenharmony_ci dev_err(dev, "Mapping digest len %zu B at va=%pK for DMA failed\n", 10818c2ecf20Sopenharmony_ci sizeof(ctx->digest_buff), ctx->digest_buff); 10828c2ecf20Sopenharmony_ci goto fail; 10838c2ecf20Sopenharmony_ci } 10848c2ecf20Sopenharmony_ci dev_dbg(dev, "Mapped digest %zu B at va=%pK to dma=%pad\n", 10858c2ecf20Sopenharmony_ci sizeof(ctx->digest_buff), ctx->digest_buff, 10868c2ecf20Sopenharmony_ci &ctx->digest_buff_dma_addr); 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci ctx->opad_tmp_keys_dma_addr = 10898c2ecf20Sopenharmony_ci dma_map_single(dev, ctx->opad_tmp_keys_buff, 10908c2ecf20Sopenharmony_ci sizeof(ctx->opad_tmp_keys_buff), 10918c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 10928c2ecf20Sopenharmony_ci if (dma_mapping_error(dev, ctx->opad_tmp_keys_dma_addr)) { 10938c2ecf20Sopenharmony_ci dev_err(dev, "Mapping opad digest %zu B at va=%pK for DMA failed\n", 10948c2ecf20Sopenharmony_ci sizeof(ctx->opad_tmp_keys_buff), 10958c2ecf20Sopenharmony_ci ctx->opad_tmp_keys_buff); 10968c2ecf20Sopenharmony_ci goto fail; 10978c2ecf20Sopenharmony_ci } 10988c2ecf20Sopenharmony_ci dev_dbg(dev, "Mapped opad_tmp_keys %zu B at va=%pK to dma=%pad\n", 10998c2ecf20Sopenharmony_ci sizeof(ctx->opad_tmp_keys_buff), ctx->opad_tmp_keys_buff, 11008c2ecf20Sopenharmony_ci &ctx->opad_tmp_keys_dma_addr); 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci ctx->is_hmac = false; 11038c2ecf20Sopenharmony_ci return 0; 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_cifail: 11068c2ecf20Sopenharmony_ci cc_free_ctx(ctx); 11078c2ecf20Sopenharmony_ci return -ENOMEM; 11088c2ecf20Sopenharmony_ci} 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_cistatic int cc_get_hash_len(struct crypto_tfm *tfm) 11118c2ecf20Sopenharmony_ci{ 11128c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_tfm_ctx(tfm); 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci if (ctx->hash_mode == DRV_HASH_SM3) 11158c2ecf20Sopenharmony_ci return CC_SM3_HASH_LEN_SIZE; 11168c2ecf20Sopenharmony_ci else 11178c2ecf20Sopenharmony_ci return cc_get_default_hash_len(ctx->drvdata); 11188c2ecf20Sopenharmony_ci} 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_cistatic int cc_cra_init(struct crypto_tfm *tfm) 11218c2ecf20Sopenharmony_ci{ 11228c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_tfm_ctx(tfm); 11238c2ecf20Sopenharmony_ci struct hash_alg_common *hash_alg_common = 11248c2ecf20Sopenharmony_ci container_of(tfm->__crt_alg, struct hash_alg_common, base); 11258c2ecf20Sopenharmony_ci struct ahash_alg *ahash_alg = 11268c2ecf20Sopenharmony_ci container_of(hash_alg_common, struct ahash_alg, halg); 11278c2ecf20Sopenharmony_ci struct cc_hash_alg *cc_alg = 11288c2ecf20Sopenharmony_ci container_of(ahash_alg, struct cc_hash_alg, ahash_alg); 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 11318c2ecf20Sopenharmony_ci sizeof(struct ahash_req_ctx)); 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci ctx->hash_mode = cc_alg->hash_mode; 11348c2ecf20Sopenharmony_ci ctx->hw_mode = cc_alg->hw_mode; 11358c2ecf20Sopenharmony_ci ctx->inter_digestsize = cc_alg->inter_digestsize; 11368c2ecf20Sopenharmony_ci ctx->drvdata = cc_alg->drvdata; 11378c2ecf20Sopenharmony_ci ctx->hash_len = cc_get_hash_len(tfm); 11388c2ecf20Sopenharmony_ci return cc_alloc_ctx(ctx); 11398c2ecf20Sopenharmony_ci} 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_cistatic void cc_cra_exit(struct crypto_tfm *tfm) 11428c2ecf20Sopenharmony_ci{ 11438c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_tfm_ctx(tfm); 11448c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci dev_dbg(dev, "cc_cra_exit"); 11478c2ecf20Sopenharmony_ci cc_free_ctx(ctx); 11488c2ecf20Sopenharmony_ci} 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_cistatic int cc_mac_update(struct ahash_request *req) 11518c2ecf20Sopenharmony_ci{ 11528c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(req); 11538c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 11548c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm); 11558c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 11568c2ecf20Sopenharmony_ci unsigned int block_size = crypto_tfm_alg_blocksize(&tfm->base); 11578c2ecf20Sopenharmony_ci struct cc_crypto_req cc_req = {}; 11588c2ecf20Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 11598c2ecf20Sopenharmony_ci int rc; 11608c2ecf20Sopenharmony_ci u32 idx = 0; 11618c2ecf20Sopenharmony_ci gfp_t flags = cc_gfp_flags(&req->base); 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci if (req->nbytes == 0) { 11648c2ecf20Sopenharmony_ci /* no real updates required */ 11658c2ecf20Sopenharmony_ci return 0; 11668c2ecf20Sopenharmony_ci } 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci state->xcbc_count++; 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci rc = cc_map_hash_request_update(ctx->drvdata, state, req->src, 11718c2ecf20Sopenharmony_ci req->nbytes, block_size, flags); 11728c2ecf20Sopenharmony_ci if (rc) { 11738c2ecf20Sopenharmony_ci if (rc == 1) { 11748c2ecf20Sopenharmony_ci dev_dbg(dev, " data size not require HW update %x\n", 11758c2ecf20Sopenharmony_ci req->nbytes); 11768c2ecf20Sopenharmony_ci /* No hardware updates are required */ 11778c2ecf20Sopenharmony_ci return 0; 11788c2ecf20Sopenharmony_ci } 11798c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_request_update() failed\n"); 11808c2ecf20Sopenharmony_ci return -ENOMEM; 11818c2ecf20Sopenharmony_ci } 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci if (cc_map_req(dev, state, ctx)) { 11848c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_source() failed\n"); 11858c2ecf20Sopenharmony_ci return -EINVAL; 11868c2ecf20Sopenharmony_ci } 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) 11898c2ecf20Sopenharmony_ci cc_setup_xcbc(req, desc, &idx); 11908c2ecf20Sopenharmony_ci else 11918c2ecf20Sopenharmony_ci cc_setup_cmac(req, desc, &idx); 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci cc_set_desc(state, ctx, DIN_AES_DOUT, desc, true, &idx); 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci /* store the hash digest result in context */ 11968c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 11978c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 11988c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_buff_dma_addr, 11998c2ecf20Sopenharmony_ci ctx->inter_digestsize, NS_BIT, 1); 12008c2ecf20Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 12018c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_AES_to_DOUT); 12028c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 12038c2ecf20Sopenharmony_ci idx++; 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci /* Setup request structure */ 12068c2ecf20Sopenharmony_ci cc_req.user_cb = cc_update_complete; 12078c2ecf20Sopenharmony_ci cc_req.user_arg = req; 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base); 12108c2ecf20Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 12118c2ecf20Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 12128c2ecf20Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, true); 12138c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 12148c2ecf20Sopenharmony_ci } 12158c2ecf20Sopenharmony_ci return rc; 12168c2ecf20Sopenharmony_ci} 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_cistatic int cc_mac_final(struct ahash_request *req) 12198c2ecf20Sopenharmony_ci{ 12208c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(req); 12218c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 12228c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm); 12238c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 12248c2ecf20Sopenharmony_ci struct cc_crypto_req cc_req = {}; 12258c2ecf20Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 12268c2ecf20Sopenharmony_ci int idx = 0; 12278c2ecf20Sopenharmony_ci int rc = 0; 12288c2ecf20Sopenharmony_ci u32 key_size, key_len; 12298c2ecf20Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 12308c2ecf20Sopenharmony_ci gfp_t flags = cc_gfp_flags(&req->base); 12318c2ecf20Sopenharmony_ci u32 rem_cnt = *cc_hash_buf_cnt(state); 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) { 12348c2ecf20Sopenharmony_ci key_size = CC_AES_128_BIT_KEY_SIZE; 12358c2ecf20Sopenharmony_ci key_len = CC_AES_128_BIT_KEY_SIZE; 12368c2ecf20Sopenharmony_ci } else { 12378c2ecf20Sopenharmony_ci key_size = (ctx->key_params.keylen == 24) ? AES_MAX_KEY_SIZE : 12388c2ecf20Sopenharmony_ci ctx->key_params.keylen; 12398c2ecf20Sopenharmony_ci key_len = ctx->key_params.keylen; 12408c2ecf20Sopenharmony_ci } 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci dev_dbg(dev, "===== final xcbc reminder (%d) ====\n", rem_cnt); 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci if (cc_map_req(dev, state, ctx)) { 12458c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_source() failed\n"); 12468c2ecf20Sopenharmony_ci return -EINVAL; 12478c2ecf20Sopenharmony_ci } 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci if (cc_map_hash_request_final(ctx->drvdata, state, req->src, 12508c2ecf20Sopenharmony_ci req->nbytes, 0, flags)) { 12518c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_request_final() failed\n"); 12528c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 12538c2ecf20Sopenharmony_ci return -ENOMEM; 12548c2ecf20Sopenharmony_ci } 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci if (cc_map_result(dev, state, digestsize)) { 12578c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_digest() failed\n"); 12588c2ecf20Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, true); 12598c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 12608c2ecf20Sopenharmony_ci return -ENOMEM; 12618c2ecf20Sopenharmony_ci } 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci /* Setup request structure */ 12648c2ecf20Sopenharmony_ci cc_req.user_cb = cc_hash_complete; 12658c2ecf20Sopenharmony_ci cc_req.user_arg = req; 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci if (state->xcbc_count && rem_cnt == 0) { 12688c2ecf20Sopenharmony_ci /* Load key for ECB decryption */ 12698c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 12708c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_ECB); 12718c2ecf20Sopenharmony_ci set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_DECRYPT); 12728c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 12738c2ecf20Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K1_OFFSET), 12748c2ecf20Sopenharmony_ci key_size, NS_BIT); 12758c2ecf20Sopenharmony_ci set_key_size_aes(&desc[idx], key_len); 12768c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 12778c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 12788c2ecf20Sopenharmony_ci idx++; 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci /* Initiate decryption of block state to previous 12818c2ecf20Sopenharmony_ci * block_state-XOR-M[n] 12828c2ecf20Sopenharmony_ci */ 12838c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 12848c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, 12858c2ecf20Sopenharmony_ci CC_AES_BLOCK_SIZE, NS_BIT); 12868c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_buff_dma_addr, 12878c2ecf20Sopenharmony_ci CC_AES_BLOCK_SIZE, NS_BIT, 0); 12888c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], DIN_AES_DOUT); 12898c2ecf20Sopenharmony_ci idx++; 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci /* Memory Barrier: wait for axi write to complete */ 12928c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 12938c2ecf20Sopenharmony_ci set_din_no_dma(&desc[idx], 0, 0xfffff0); 12948c2ecf20Sopenharmony_ci set_dout_no_dma(&desc[idx], 0, 0, 1); 12958c2ecf20Sopenharmony_ci idx++; 12968c2ecf20Sopenharmony_ci } 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) 12998c2ecf20Sopenharmony_ci cc_setup_xcbc(req, desc, &idx); 13008c2ecf20Sopenharmony_ci else 13018c2ecf20Sopenharmony_ci cc_setup_cmac(req, desc, &idx); 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ci if (state->xcbc_count == 0) { 13048c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 13058c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 13068c2ecf20Sopenharmony_ci set_key_size_aes(&desc[idx], key_len); 13078c2ecf20Sopenharmony_ci set_cmac_size0_mode(&desc[idx]); 13088c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 13098c2ecf20Sopenharmony_ci idx++; 13108c2ecf20Sopenharmony_ci } else if (rem_cnt > 0) { 13118c2ecf20Sopenharmony_ci cc_set_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx); 13128c2ecf20Sopenharmony_ci } else { 13138c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 13148c2ecf20Sopenharmony_ci set_din_const(&desc[idx], 0x00, CC_AES_BLOCK_SIZE); 13158c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], DIN_AES_DOUT); 13168c2ecf20Sopenharmony_ci idx++; 13178c2ecf20Sopenharmony_ci } 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_ci /* Get final MAC result */ 13208c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 13218c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_result_dma_addr, 13228c2ecf20Sopenharmony_ci digestsize, NS_BIT, 1); 13238c2ecf20Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 13248c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_AES_to_DOUT); 13258c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 13268c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 13278c2ecf20Sopenharmony_ci idx++; 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_ci rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base); 13308c2ecf20Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 13318c2ecf20Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 13328c2ecf20Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, true); 13338c2ecf20Sopenharmony_ci cc_unmap_result(dev, state, digestsize, req->result); 13348c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 13358c2ecf20Sopenharmony_ci } 13368c2ecf20Sopenharmony_ci return rc; 13378c2ecf20Sopenharmony_ci} 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_cistatic int cc_mac_finup(struct ahash_request *req) 13408c2ecf20Sopenharmony_ci{ 13418c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(req); 13428c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 13438c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm); 13448c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 13458c2ecf20Sopenharmony_ci struct cc_crypto_req cc_req = {}; 13468c2ecf20Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 13478c2ecf20Sopenharmony_ci int idx = 0; 13488c2ecf20Sopenharmony_ci int rc = 0; 13498c2ecf20Sopenharmony_ci u32 key_len = 0; 13508c2ecf20Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 13518c2ecf20Sopenharmony_ci gfp_t flags = cc_gfp_flags(&req->base); 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci dev_dbg(dev, "===== finup xcbc(%d) ====\n", req->nbytes); 13548c2ecf20Sopenharmony_ci if (state->xcbc_count > 0 && req->nbytes == 0) { 13558c2ecf20Sopenharmony_ci dev_dbg(dev, "No data to update. Call to fdx_mac_final\n"); 13568c2ecf20Sopenharmony_ci return cc_mac_final(req); 13578c2ecf20Sopenharmony_ci } 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci if (cc_map_req(dev, state, ctx)) { 13608c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_source() failed\n"); 13618c2ecf20Sopenharmony_ci return -EINVAL; 13628c2ecf20Sopenharmony_ci } 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci if (cc_map_hash_request_final(ctx->drvdata, state, req->src, 13658c2ecf20Sopenharmony_ci req->nbytes, 1, flags)) { 13668c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_request_final() failed\n"); 13678c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 13688c2ecf20Sopenharmony_ci return -ENOMEM; 13698c2ecf20Sopenharmony_ci } 13708c2ecf20Sopenharmony_ci if (cc_map_result(dev, state, digestsize)) { 13718c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_digest() failed\n"); 13728c2ecf20Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, true); 13738c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 13748c2ecf20Sopenharmony_ci return -ENOMEM; 13758c2ecf20Sopenharmony_ci } 13768c2ecf20Sopenharmony_ci 13778c2ecf20Sopenharmony_ci /* Setup request structure */ 13788c2ecf20Sopenharmony_ci cc_req.user_cb = cc_hash_complete; 13798c2ecf20Sopenharmony_ci cc_req.user_arg = req; 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) { 13828c2ecf20Sopenharmony_ci key_len = CC_AES_128_BIT_KEY_SIZE; 13838c2ecf20Sopenharmony_ci cc_setup_xcbc(req, desc, &idx); 13848c2ecf20Sopenharmony_ci } else { 13858c2ecf20Sopenharmony_ci key_len = ctx->key_params.keylen; 13868c2ecf20Sopenharmony_ci cc_setup_cmac(req, desc, &idx); 13878c2ecf20Sopenharmony_ci } 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci if (req->nbytes == 0) { 13908c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 13918c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 13928c2ecf20Sopenharmony_ci set_key_size_aes(&desc[idx], key_len); 13938c2ecf20Sopenharmony_ci set_cmac_size0_mode(&desc[idx]); 13948c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 13958c2ecf20Sopenharmony_ci idx++; 13968c2ecf20Sopenharmony_ci } else { 13978c2ecf20Sopenharmony_ci cc_set_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx); 13988c2ecf20Sopenharmony_ci } 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_ci /* Get final MAC result */ 14018c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 14028c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_result_dma_addr, 14038c2ecf20Sopenharmony_ci digestsize, NS_BIT, 1); 14048c2ecf20Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 14058c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_AES_to_DOUT); 14068c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 14078c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 14088c2ecf20Sopenharmony_ci idx++; 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base); 14118c2ecf20Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 14128c2ecf20Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 14138c2ecf20Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, true); 14148c2ecf20Sopenharmony_ci cc_unmap_result(dev, state, digestsize, req->result); 14158c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 14168c2ecf20Sopenharmony_ci } 14178c2ecf20Sopenharmony_ci return rc; 14188c2ecf20Sopenharmony_ci} 14198c2ecf20Sopenharmony_ci 14208c2ecf20Sopenharmony_cistatic int cc_mac_digest(struct ahash_request *req) 14218c2ecf20Sopenharmony_ci{ 14228c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(req); 14238c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 14248c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm); 14258c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 14268c2ecf20Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 14278c2ecf20Sopenharmony_ci struct cc_crypto_req cc_req = {}; 14288c2ecf20Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 14298c2ecf20Sopenharmony_ci u32 key_len; 14308c2ecf20Sopenharmony_ci unsigned int idx = 0; 14318c2ecf20Sopenharmony_ci int rc; 14328c2ecf20Sopenharmony_ci gfp_t flags = cc_gfp_flags(&req->base); 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci dev_dbg(dev, "===== -digest mac (%d) ====\n", req->nbytes); 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci cc_init_req(dev, state, ctx); 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci if (cc_map_req(dev, state, ctx)) { 14398c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_source() failed\n"); 14408c2ecf20Sopenharmony_ci return -ENOMEM; 14418c2ecf20Sopenharmony_ci } 14428c2ecf20Sopenharmony_ci if (cc_map_result(dev, state, digestsize)) { 14438c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_digest() failed\n"); 14448c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 14458c2ecf20Sopenharmony_ci return -ENOMEM; 14468c2ecf20Sopenharmony_ci } 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci if (cc_map_hash_request_final(ctx->drvdata, state, req->src, 14498c2ecf20Sopenharmony_ci req->nbytes, 1, flags)) { 14508c2ecf20Sopenharmony_ci dev_err(dev, "map_ahash_request_final() failed\n"); 14518c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 14528c2ecf20Sopenharmony_ci return -ENOMEM; 14538c2ecf20Sopenharmony_ci } 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci /* Setup request structure */ 14568c2ecf20Sopenharmony_ci cc_req.user_cb = cc_digest_complete; 14578c2ecf20Sopenharmony_ci cc_req.user_arg = req; 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) { 14608c2ecf20Sopenharmony_ci key_len = CC_AES_128_BIT_KEY_SIZE; 14618c2ecf20Sopenharmony_ci cc_setup_xcbc(req, desc, &idx); 14628c2ecf20Sopenharmony_ci } else { 14638c2ecf20Sopenharmony_ci key_len = ctx->key_params.keylen; 14648c2ecf20Sopenharmony_ci cc_setup_cmac(req, desc, &idx); 14658c2ecf20Sopenharmony_ci } 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci if (req->nbytes == 0) { 14688c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 14698c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 14708c2ecf20Sopenharmony_ci set_key_size_aes(&desc[idx], key_len); 14718c2ecf20Sopenharmony_ci set_cmac_size0_mode(&desc[idx]); 14728c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 14738c2ecf20Sopenharmony_ci idx++; 14748c2ecf20Sopenharmony_ci } else { 14758c2ecf20Sopenharmony_ci cc_set_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx); 14768c2ecf20Sopenharmony_ci } 14778c2ecf20Sopenharmony_ci 14788c2ecf20Sopenharmony_ci /* Get final MAC result */ 14798c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 14808c2ecf20Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_result_dma_addr, 14818c2ecf20Sopenharmony_ci CC_AES_BLOCK_SIZE, NS_BIT, 1); 14828c2ecf20Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 14838c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_AES_to_DOUT); 14848c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 14858c2ecf20Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 14868c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 14878c2ecf20Sopenharmony_ci idx++; 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base); 14908c2ecf20Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 14918c2ecf20Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 14928c2ecf20Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, true); 14938c2ecf20Sopenharmony_ci cc_unmap_result(dev, state, digestsize, req->result); 14948c2ecf20Sopenharmony_ci cc_unmap_req(dev, state, ctx); 14958c2ecf20Sopenharmony_ci } 14968c2ecf20Sopenharmony_ci return rc; 14978c2ecf20Sopenharmony_ci} 14988c2ecf20Sopenharmony_ci 14998c2ecf20Sopenharmony_cistatic int cc_hash_export(struct ahash_request *req, void *out) 15008c2ecf20Sopenharmony_ci{ 15018c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 15028c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(ahash); 15038c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(req); 15048c2ecf20Sopenharmony_ci u8 *curr_buff = cc_hash_buf(state); 15058c2ecf20Sopenharmony_ci u32 curr_buff_cnt = *cc_hash_buf_cnt(state); 15068c2ecf20Sopenharmony_ci const u32 tmp = CC_EXPORT_MAGIC; 15078c2ecf20Sopenharmony_ci 15088c2ecf20Sopenharmony_ci memcpy(out, &tmp, sizeof(u32)); 15098c2ecf20Sopenharmony_ci out += sizeof(u32); 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_ci memcpy(out, state->digest_buff, ctx->inter_digestsize); 15128c2ecf20Sopenharmony_ci out += ctx->inter_digestsize; 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci memcpy(out, state->digest_bytes_len, ctx->hash_len); 15158c2ecf20Sopenharmony_ci out += ctx->hash_len; 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci memcpy(out, &curr_buff_cnt, sizeof(u32)); 15188c2ecf20Sopenharmony_ci out += sizeof(u32); 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_ci memcpy(out, curr_buff, curr_buff_cnt); 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_ci return 0; 15238c2ecf20Sopenharmony_ci} 15248c2ecf20Sopenharmony_ci 15258c2ecf20Sopenharmony_cistatic int cc_hash_import(struct ahash_request *req, const void *in) 15268c2ecf20Sopenharmony_ci{ 15278c2ecf20Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 15288c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(ahash); 15298c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 15308c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(req); 15318c2ecf20Sopenharmony_ci u32 tmp; 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_ci memcpy(&tmp, in, sizeof(u32)); 15348c2ecf20Sopenharmony_ci if (tmp != CC_EXPORT_MAGIC) 15358c2ecf20Sopenharmony_ci return -EINVAL; 15368c2ecf20Sopenharmony_ci in += sizeof(u32); 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_ci cc_init_req(dev, state, ctx); 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci memcpy(state->digest_buff, in, ctx->inter_digestsize); 15418c2ecf20Sopenharmony_ci in += ctx->inter_digestsize; 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci memcpy(state->digest_bytes_len, in, ctx->hash_len); 15448c2ecf20Sopenharmony_ci in += ctx->hash_len; 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci /* Sanity check the data as much as possible */ 15478c2ecf20Sopenharmony_ci memcpy(&tmp, in, sizeof(u32)); 15488c2ecf20Sopenharmony_ci if (tmp > CC_MAX_HASH_BLCK_SIZE) 15498c2ecf20Sopenharmony_ci return -EINVAL; 15508c2ecf20Sopenharmony_ci in += sizeof(u32); 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_ci state->buf_cnt[0] = tmp; 15538c2ecf20Sopenharmony_ci memcpy(state->buffers[0], in, tmp); 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ci return 0; 15568c2ecf20Sopenharmony_ci} 15578c2ecf20Sopenharmony_ci 15588c2ecf20Sopenharmony_cistruct cc_hash_template { 15598c2ecf20Sopenharmony_ci char name[CRYPTO_MAX_ALG_NAME]; 15608c2ecf20Sopenharmony_ci char driver_name[CRYPTO_MAX_ALG_NAME]; 15618c2ecf20Sopenharmony_ci char mac_name[CRYPTO_MAX_ALG_NAME]; 15628c2ecf20Sopenharmony_ci char mac_driver_name[CRYPTO_MAX_ALG_NAME]; 15638c2ecf20Sopenharmony_ci unsigned int blocksize; 15648c2ecf20Sopenharmony_ci bool is_mac; 15658c2ecf20Sopenharmony_ci bool synchronize; 15668c2ecf20Sopenharmony_ci struct ahash_alg template_ahash; 15678c2ecf20Sopenharmony_ci int hash_mode; 15688c2ecf20Sopenharmony_ci int hw_mode; 15698c2ecf20Sopenharmony_ci int inter_digestsize; 15708c2ecf20Sopenharmony_ci struct cc_drvdata *drvdata; 15718c2ecf20Sopenharmony_ci u32 min_hw_rev; 15728c2ecf20Sopenharmony_ci enum cc_std_body std_body; 15738c2ecf20Sopenharmony_ci}; 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_ci#define CC_STATE_SIZE(_x) \ 15768c2ecf20Sopenharmony_ci ((_x) + HASH_MAX_LEN_SIZE + CC_MAX_HASH_BLCK_SIZE + (2 * sizeof(u32))) 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci/* hash descriptors */ 15798c2ecf20Sopenharmony_cistatic struct cc_hash_template driver_hash[] = { 15808c2ecf20Sopenharmony_ci //Asynchronize hash template 15818c2ecf20Sopenharmony_ci { 15828c2ecf20Sopenharmony_ci .name = "sha1", 15838c2ecf20Sopenharmony_ci .driver_name = "sha1-ccree", 15848c2ecf20Sopenharmony_ci .mac_name = "hmac(sha1)", 15858c2ecf20Sopenharmony_ci .mac_driver_name = "hmac-sha1-ccree", 15868c2ecf20Sopenharmony_ci .blocksize = SHA1_BLOCK_SIZE, 15878c2ecf20Sopenharmony_ci .is_mac = true, 15888c2ecf20Sopenharmony_ci .synchronize = false, 15898c2ecf20Sopenharmony_ci .template_ahash = { 15908c2ecf20Sopenharmony_ci .init = cc_hash_init, 15918c2ecf20Sopenharmony_ci .update = cc_hash_update, 15928c2ecf20Sopenharmony_ci .final = cc_hash_final, 15938c2ecf20Sopenharmony_ci .finup = cc_hash_finup, 15948c2ecf20Sopenharmony_ci .digest = cc_hash_digest, 15958c2ecf20Sopenharmony_ci .export = cc_hash_export, 15968c2ecf20Sopenharmony_ci .import = cc_hash_import, 15978c2ecf20Sopenharmony_ci .setkey = cc_hash_setkey, 15988c2ecf20Sopenharmony_ci .halg = { 15998c2ecf20Sopenharmony_ci .digestsize = SHA1_DIGEST_SIZE, 16008c2ecf20Sopenharmony_ci .statesize = CC_STATE_SIZE(SHA1_DIGEST_SIZE), 16018c2ecf20Sopenharmony_ci }, 16028c2ecf20Sopenharmony_ci }, 16038c2ecf20Sopenharmony_ci .hash_mode = DRV_HASH_SHA1, 16048c2ecf20Sopenharmony_ci .hw_mode = DRV_HASH_HW_SHA1, 16058c2ecf20Sopenharmony_ci .inter_digestsize = SHA1_DIGEST_SIZE, 16068c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 16078c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 16088c2ecf20Sopenharmony_ci }, 16098c2ecf20Sopenharmony_ci { 16108c2ecf20Sopenharmony_ci .name = "sha256", 16118c2ecf20Sopenharmony_ci .driver_name = "sha256-ccree", 16128c2ecf20Sopenharmony_ci .mac_name = "hmac(sha256)", 16138c2ecf20Sopenharmony_ci .mac_driver_name = "hmac-sha256-ccree", 16148c2ecf20Sopenharmony_ci .blocksize = SHA256_BLOCK_SIZE, 16158c2ecf20Sopenharmony_ci .is_mac = true, 16168c2ecf20Sopenharmony_ci .template_ahash = { 16178c2ecf20Sopenharmony_ci .init = cc_hash_init, 16188c2ecf20Sopenharmony_ci .update = cc_hash_update, 16198c2ecf20Sopenharmony_ci .final = cc_hash_final, 16208c2ecf20Sopenharmony_ci .finup = cc_hash_finup, 16218c2ecf20Sopenharmony_ci .digest = cc_hash_digest, 16228c2ecf20Sopenharmony_ci .export = cc_hash_export, 16238c2ecf20Sopenharmony_ci .import = cc_hash_import, 16248c2ecf20Sopenharmony_ci .setkey = cc_hash_setkey, 16258c2ecf20Sopenharmony_ci .halg = { 16268c2ecf20Sopenharmony_ci .digestsize = SHA256_DIGEST_SIZE, 16278c2ecf20Sopenharmony_ci .statesize = CC_STATE_SIZE(SHA256_DIGEST_SIZE) 16288c2ecf20Sopenharmony_ci }, 16298c2ecf20Sopenharmony_ci }, 16308c2ecf20Sopenharmony_ci .hash_mode = DRV_HASH_SHA256, 16318c2ecf20Sopenharmony_ci .hw_mode = DRV_HASH_HW_SHA256, 16328c2ecf20Sopenharmony_ci .inter_digestsize = SHA256_DIGEST_SIZE, 16338c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 16348c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 16358c2ecf20Sopenharmony_ci }, 16368c2ecf20Sopenharmony_ci { 16378c2ecf20Sopenharmony_ci .name = "sha224", 16388c2ecf20Sopenharmony_ci .driver_name = "sha224-ccree", 16398c2ecf20Sopenharmony_ci .mac_name = "hmac(sha224)", 16408c2ecf20Sopenharmony_ci .mac_driver_name = "hmac-sha224-ccree", 16418c2ecf20Sopenharmony_ci .blocksize = SHA224_BLOCK_SIZE, 16428c2ecf20Sopenharmony_ci .is_mac = true, 16438c2ecf20Sopenharmony_ci .template_ahash = { 16448c2ecf20Sopenharmony_ci .init = cc_hash_init, 16458c2ecf20Sopenharmony_ci .update = cc_hash_update, 16468c2ecf20Sopenharmony_ci .final = cc_hash_final, 16478c2ecf20Sopenharmony_ci .finup = cc_hash_finup, 16488c2ecf20Sopenharmony_ci .digest = cc_hash_digest, 16498c2ecf20Sopenharmony_ci .export = cc_hash_export, 16508c2ecf20Sopenharmony_ci .import = cc_hash_import, 16518c2ecf20Sopenharmony_ci .setkey = cc_hash_setkey, 16528c2ecf20Sopenharmony_ci .halg = { 16538c2ecf20Sopenharmony_ci .digestsize = SHA224_DIGEST_SIZE, 16548c2ecf20Sopenharmony_ci .statesize = CC_STATE_SIZE(SHA256_DIGEST_SIZE), 16558c2ecf20Sopenharmony_ci }, 16568c2ecf20Sopenharmony_ci }, 16578c2ecf20Sopenharmony_ci .hash_mode = DRV_HASH_SHA224, 16588c2ecf20Sopenharmony_ci .hw_mode = DRV_HASH_HW_SHA256, 16598c2ecf20Sopenharmony_ci .inter_digestsize = SHA256_DIGEST_SIZE, 16608c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 16618c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 16628c2ecf20Sopenharmony_ci }, 16638c2ecf20Sopenharmony_ci { 16648c2ecf20Sopenharmony_ci .name = "sha384", 16658c2ecf20Sopenharmony_ci .driver_name = "sha384-ccree", 16668c2ecf20Sopenharmony_ci .mac_name = "hmac(sha384)", 16678c2ecf20Sopenharmony_ci .mac_driver_name = "hmac-sha384-ccree", 16688c2ecf20Sopenharmony_ci .blocksize = SHA384_BLOCK_SIZE, 16698c2ecf20Sopenharmony_ci .is_mac = true, 16708c2ecf20Sopenharmony_ci .template_ahash = { 16718c2ecf20Sopenharmony_ci .init = cc_hash_init, 16728c2ecf20Sopenharmony_ci .update = cc_hash_update, 16738c2ecf20Sopenharmony_ci .final = cc_hash_final, 16748c2ecf20Sopenharmony_ci .finup = cc_hash_finup, 16758c2ecf20Sopenharmony_ci .digest = cc_hash_digest, 16768c2ecf20Sopenharmony_ci .export = cc_hash_export, 16778c2ecf20Sopenharmony_ci .import = cc_hash_import, 16788c2ecf20Sopenharmony_ci .setkey = cc_hash_setkey, 16798c2ecf20Sopenharmony_ci .halg = { 16808c2ecf20Sopenharmony_ci .digestsize = SHA384_DIGEST_SIZE, 16818c2ecf20Sopenharmony_ci .statesize = CC_STATE_SIZE(SHA512_DIGEST_SIZE), 16828c2ecf20Sopenharmony_ci }, 16838c2ecf20Sopenharmony_ci }, 16848c2ecf20Sopenharmony_ci .hash_mode = DRV_HASH_SHA384, 16858c2ecf20Sopenharmony_ci .hw_mode = DRV_HASH_HW_SHA512, 16868c2ecf20Sopenharmony_ci .inter_digestsize = SHA512_DIGEST_SIZE, 16878c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_712, 16888c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 16898c2ecf20Sopenharmony_ci }, 16908c2ecf20Sopenharmony_ci { 16918c2ecf20Sopenharmony_ci .name = "sha512", 16928c2ecf20Sopenharmony_ci .driver_name = "sha512-ccree", 16938c2ecf20Sopenharmony_ci .mac_name = "hmac(sha512)", 16948c2ecf20Sopenharmony_ci .mac_driver_name = "hmac-sha512-ccree", 16958c2ecf20Sopenharmony_ci .blocksize = SHA512_BLOCK_SIZE, 16968c2ecf20Sopenharmony_ci .is_mac = true, 16978c2ecf20Sopenharmony_ci .template_ahash = { 16988c2ecf20Sopenharmony_ci .init = cc_hash_init, 16998c2ecf20Sopenharmony_ci .update = cc_hash_update, 17008c2ecf20Sopenharmony_ci .final = cc_hash_final, 17018c2ecf20Sopenharmony_ci .finup = cc_hash_finup, 17028c2ecf20Sopenharmony_ci .digest = cc_hash_digest, 17038c2ecf20Sopenharmony_ci .export = cc_hash_export, 17048c2ecf20Sopenharmony_ci .import = cc_hash_import, 17058c2ecf20Sopenharmony_ci .setkey = cc_hash_setkey, 17068c2ecf20Sopenharmony_ci .halg = { 17078c2ecf20Sopenharmony_ci .digestsize = SHA512_DIGEST_SIZE, 17088c2ecf20Sopenharmony_ci .statesize = CC_STATE_SIZE(SHA512_DIGEST_SIZE), 17098c2ecf20Sopenharmony_ci }, 17108c2ecf20Sopenharmony_ci }, 17118c2ecf20Sopenharmony_ci .hash_mode = DRV_HASH_SHA512, 17128c2ecf20Sopenharmony_ci .hw_mode = DRV_HASH_HW_SHA512, 17138c2ecf20Sopenharmony_ci .inter_digestsize = SHA512_DIGEST_SIZE, 17148c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_712, 17158c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 17168c2ecf20Sopenharmony_ci }, 17178c2ecf20Sopenharmony_ci { 17188c2ecf20Sopenharmony_ci .name = "md5", 17198c2ecf20Sopenharmony_ci .driver_name = "md5-ccree", 17208c2ecf20Sopenharmony_ci .mac_name = "hmac(md5)", 17218c2ecf20Sopenharmony_ci .mac_driver_name = "hmac-md5-ccree", 17228c2ecf20Sopenharmony_ci .blocksize = MD5_HMAC_BLOCK_SIZE, 17238c2ecf20Sopenharmony_ci .is_mac = true, 17248c2ecf20Sopenharmony_ci .template_ahash = { 17258c2ecf20Sopenharmony_ci .init = cc_hash_init, 17268c2ecf20Sopenharmony_ci .update = cc_hash_update, 17278c2ecf20Sopenharmony_ci .final = cc_hash_final, 17288c2ecf20Sopenharmony_ci .finup = cc_hash_finup, 17298c2ecf20Sopenharmony_ci .digest = cc_hash_digest, 17308c2ecf20Sopenharmony_ci .export = cc_hash_export, 17318c2ecf20Sopenharmony_ci .import = cc_hash_import, 17328c2ecf20Sopenharmony_ci .setkey = cc_hash_setkey, 17338c2ecf20Sopenharmony_ci .halg = { 17348c2ecf20Sopenharmony_ci .digestsize = MD5_DIGEST_SIZE, 17358c2ecf20Sopenharmony_ci .statesize = CC_STATE_SIZE(MD5_DIGEST_SIZE), 17368c2ecf20Sopenharmony_ci }, 17378c2ecf20Sopenharmony_ci }, 17388c2ecf20Sopenharmony_ci .hash_mode = DRV_HASH_MD5, 17398c2ecf20Sopenharmony_ci .hw_mode = DRV_HASH_HW_MD5, 17408c2ecf20Sopenharmony_ci .inter_digestsize = MD5_DIGEST_SIZE, 17418c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 17428c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 17438c2ecf20Sopenharmony_ci }, 17448c2ecf20Sopenharmony_ci { 17458c2ecf20Sopenharmony_ci .name = "sm3", 17468c2ecf20Sopenharmony_ci .driver_name = "sm3-ccree", 17478c2ecf20Sopenharmony_ci .blocksize = SM3_BLOCK_SIZE, 17488c2ecf20Sopenharmony_ci .is_mac = false, 17498c2ecf20Sopenharmony_ci .template_ahash = { 17508c2ecf20Sopenharmony_ci .init = cc_hash_init, 17518c2ecf20Sopenharmony_ci .update = cc_hash_update, 17528c2ecf20Sopenharmony_ci .final = cc_hash_final, 17538c2ecf20Sopenharmony_ci .finup = cc_hash_finup, 17548c2ecf20Sopenharmony_ci .digest = cc_hash_digest, 17558c2ecf20Sopenharmony_ci .export = cc_hash_export, 17568c2ecf20Sopenharmony_ci .import = cc_hash_import, 17578c2ecf20Sopenharmony_ci .setkey = cc_hash_setkey, 17588c2ecf20Sopenharmony_ci .halg = { 17598c2ecf20Sopenharmony_ci .digestsize = SM3_DIGEST_SIZE, 17608c2ecf20Sopenharmony_ci .statesize = CC_STATE_SIZE(SM3_DIGEST_SIZE), 17618c2ecf20Sopenharmony_ci }, 17628c2ecf20Sopenharmony_ci }, 17638c2ecf20Sopenharmony_ci .hash_mode = DRV_HASH_SM3, 17648c2ecf20Sopenharmony_ci .hw_mode = DRV_HASH_HW_SM3, 17658c2ecf20Sopenharmony_ci .inter_digestsize = SM3_DIGEST_SIZE, 17668c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_713, 17678c2ecf20Sopenharmony_ci .std_body = CC_STD_OSCCA, 17688c2ecf20Sopenharmony_ci }, 17698c2ecf20Sopenharmony_ci { 17708c2ecf20Sopenharmony_ci .mac_name = "xcbc(aes)", 17718c2ecf20Sopenharmony_ci .mac_driver_name = "xcbc-aes-ccree", 17728c2ecf20Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 17738c2ecf20Sopenharmony_ci .is_mac = true, 17748c2ecf20Sopenharmony_ci .template_ahash = { 17758c2ecf20Sopenharmony_ci .init = cc_hash_init, 17768c2ecf20Sopenharmony_ci .update = cc_mac_update, 17778c2ecf20Sopenharmony_ci .final = cc_mac_final, 17788c2ecf20Sopenharmony_ci .finup = cc_mac_finup, 17798c2ecf20Sopenharmony_ci .digest = cc_mac_digest, 17808c2ecf20Sopenharmony_ci .setkey = cc_xcbc_setkey, 17818c2ecf20Sopenharmony_ci .export = cc_hash_export, 17828c2ecf20Sopenharmony_ci .import = cc_hash_import, 17838c2ecf20Sopenharmony_ci .halg = { 17848c2ecf20Sopenharmony_ci .digestsize = AES_BLOCK_SIZE, 17858c2ecf20Sopenharmony_ci .statesize = CC_STATE_SIZE(AES_BLOCK_SIZE), 17868c2ecf20Sopenharmony_ci }, 17878c2ecf20Sopenharmony_ci }, 17888c2ecf20Sopenharmony_ci .hash_mode = DRV_HASH_NULL, 17898c2ecf20Sopenharmony_ci .hw_mode = DRV_CIPHER_XCBC_MAC, 17908c2ecf20Sopenharmony_ci .inter_digestsize = AES_BLOCK_SIZE, 17918c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 17928c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 17938c2ecf20Sopenharmony_ci }, 17948c2ecf20Sopenharmony_ci { 17958c2ecf20Sopenharmony_ci .mac_name = "cmac(aes)", 17968c2ecf20Sopenharmony_ci .mac_driver_name = "cmac-aes-ccree", 17978c2ecf20Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 17988c2ecf20Sopenharmony_ci .is_mac = true, 17998c2ecf20Sopenharmony_ci .template_ahash = { 18008c2ecf20Sopenharmony_ci .init = cc_hash_init, 18018c2ecf20Sopenharmony_ci .update = cc_mac_update, 18028c2ecf20Sopenharmony_ci .final = cc_mac_final, 18038c2ecf20Sopenharmony_ci .finup = cc_mac_finup, 18048c2ecf20Sopenharmony_ci .digest = cc_mac_digest, 18058c2ecf20Sopenharmony_ci .setkey = cc_cmac_setkey, 18068c2ecf20Sopenharmony_ci .export = cc_hash_export, 18078c2ecf20Sopenharmony_ci .import = cc_hash_import, 18088c2ecf20Sopenharmony_ci .halg = { 18098c2ecf20Sopenharmony_ci .digestsize = AES_BLOCK_SIZE, 18108c2ecf20Sopenharmony_ci .statesize = CC_STATE_SIZE(AES_BLOCK_SIZE), 18118c2ecf20Sopenharmony_ci }, 18128c2ecf20Sopenharmony_ci }, 18138c2ecf20Sopenharmony_ci .hash_mode = DRV_HASH_NULL, 18148c2ecf20Sopenharmony_ci .hw_mode = DRV_CIPHER_CMAC, 18158c2ecf20Sopenharmony_ci .inter_digestsize = AES_BLOCK_SIZE, 18168c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 18178c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 18188c2ecf20Sopenharmony_ci }, 18198c2ecf20Sopenharmony_ci}; 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_cistatic struct cc_hash_alg *cc_alloc_hash_alg(struct cc_hash_template *template, 18228c2ecf20Sopenharmony_ci struct device *dev, bool keyed) 18238c2ecf20Sopenharmony_ci{ 18248c2ecf20Sopenharmony_ci struct cc_hash_alg *t_crypto_alg; 18258c2ecf20Sopenharmony_ci struct crypto_alg *alg; 18268c2ecf20Sopenharmony_ci struct ahash_alg *halg; 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_ci t_crypto_alg = devm_kzalloc(dev, sizeof(*t_crypto_alg), GFP_KERNEL); 18298c2ecf20Sopenharmony_ci if (!t_crypto_alg) 18308c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 18318c2ecf20Sopenharmony_ci 18328c2ecf20Sopenharmony_ci t_crypto_alg->ahash_alg = template->template_ahash; 18338c2ecf20Sopenharmony_ci halg = &t_crypto_alg->ahash_alg; 18348c2ecf20Sopenharmony_ci alg = &halg->halg.base; 18358c2ecf20Sopenharmony_ci 18368c2ecf20Sopenharmony_ci if (keyed) { 18378c2ecf20Sopenharmony_ci snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", 18388c2ecf20Sopenharmony_ci template->mac_name); 18398c2ecf20Sopenharmony_ci snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", 18408c2ecf20Sopenharmony_ci template->mac_driver_name); 18418c2ecf20Sopenharmony_ci } else { 18428c2ecf20Sopenharmony_ci halg->setkey = NULL; 18438c2ecf20Sopenharmony_ci snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", 18448c2ecf20Sopenharmony_ci template->name); 18458c2ecf20Sopenharmony_ci snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", 18468c2ecf20Sopenharmony_ci template->driver_name); 18478c2ecf20Sopenharmony_ci } 18488c2ecf20Sopenharmony_ci alg->cra_module = THIS_MODULE; 18498c2ecf20Sopenharmony_ci alg->cra_ctxsize = sizeof(struct cc_hash_ctx); 18508c2ecf20Sopenharmony_ci alg->cra_priority = CC_CRA_PRIO; 18518c2ecf20Sopenharmony_ci alg->cra_blocksize = template->blocksize; 18528c2ecf20Sopenharmony_ci alg->cra_alignmask = 0; 18538c2ecf20Sopenharmony_ci alg->cra_exit = cc_cra_exit; 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_ci alg->cra_init = cc_cra_init; 18568c2ecf20Sopenharmony_ci alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY; 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_ci t_crypto_alg->hash_mode = template->hash_mode; 18598c2ecf20Sopenharmony_ci t_crypto_alg->hw_mode = template->hw_mode; 18608c2ecf20Sopenharmony_ci t_crypto_alg->inter_digestsize = template->inter_digestsize; 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_ci return t_crypto_alg; 18638c2ecf20Sopenharmony_ci} 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_cistatic int cc_init_copy_sram(struct cc_drvdata *drvdata, const u32 *data, 18668c2ecf20Sopenharmony_ci unsigned int size, u32 *sram_buff_ofs) 18678c2ecf20Sopenharmony_ci{ 18688c2ecf20Sopenharmony_ci struct cc_hw_desc larval_seq[CC_DIGEST_SIZE_MAX / sizeof(u32)]; 18698c2ecf20Sopenharmony_ci unsigned int larval_seq_len = 0; 18708c2ecf20Sopenharmony_ci int rc; 18718c2ecf20Sopenharmony_ci 18728c2ecf20Sopenharmony_ci cc_set_sram_desc(data, *sram_buff_ofs, size / sizeof(*data), 18738c2ecf20Sopenharmony_ci larval_seq, &larval_seq_len); 18748c2ecf20Sopenharmony_ci rc = send_request_init(drvdata, larval_seq, larval_seq_len); 18758c2ecf20Sopenharmony_ci if (rc) 18768c2ecf20Sopenharmony_ci return rc; 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_ci *sram_buff_ofs += size; 18798c2ecf20Sopenharmony_ci return 0; 18808c2ecf20Sopenharmony_ci} 18818c2ecf20Sopenharmony_ci 18828c2ecf20Sopenharmony_ciint cc_init_hash_sram(struct cc_drvdata *drvdata) 18838c2ecf20Sopenharmony_ci{ 18848c2ecf20Sopenharmony_ci struct cc_hash_handle *hash_handle = drvdata->hash_handle; 18858c2ecf20Sopenharmony_ci u32 sram_buff_ofs = hash_handle->digest_len_sram_addr; 18868c2ecf20Sopenharmony_ci bool large_sha_supported = (drvdata->hw_rev >= CC_HW_REV_712); 18878c2ecf20Sopenharmony_ci bool sm3_supported = (drvdata->hw_rev >= CC_HW_REV_713); 18888c2ecf20Sopenharmony_ci int rc = 0; 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci /* Copy-to-sram digest-len */ 18918c2ecf20Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_digest_len_init, 18928c2ecf20Sopenharmony_ci sizeof(cc_digest_len_init), &sram_buff_ofs); 18938c2ecf20Sopenharmony_ci if (rc) 18948c2ecf20Sopenharmony_ci goto init_digest_const_err; 18958c2ecf20Sopenharmony_ci 18968c2ecf20Sopenharmony_ci if (large_sha_supported) { 18978c2ecf20Sopenharmony_ci /* Copy-to-sram digest-len for sha384/512 */ 18988c2ecf20Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_digest_len_sha512_init, 18998c2ecf20Sopenharmony_ci sizeof(cc_digest_len_sha512_init), 19008c2ecf20Sopenharmony_ci &sram_buff_ofs); 19018c2ecf20Sopenharmony_ci if (rc) 19028c2ecf20Sopenharmony_ci goto init_digest_const_err; 19038c2ecf20Sopenharmony_ci } 19048c2ecf20Sopenharmony_ci 19058c2ecf20Sopenharmony_ci /* The initial digests offset */ 19068c2ecf20Sopenharmony_ci hash_handle->larval_digest_sram_addr = sram_buff_ofs; 19078c2ecf20Sopenharmony_ci 19088c2ecf20Sopenharmony_ci /* Copy-to-sram initial SHA* digests */ 19098c2ecf20Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_md5_init, sizeof(cc_md5_init), 19108c2ecf20Sopenharmony_ci &sram_buff_ofs); 19118c2ecf20Sopenharmony_ci if (rc) 19128c2ecf20Sopenharmony_ci goto init_digest_const_err; 19138c2ecf20Sopenharmony_ci 19148c2ecf20Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_sha1_init, sizeof(cc_sha1_init), 19158c2ecf20Sopenharmony_ci &sram_buff_ofs); 19168c2ecf20Sopenharmony_ci if (rc) 19178c2ecf20Sopenharmony_ci goto init_digest_const_err; 19188c2ecf20Sopenharmony_ci 19198c2ecf20Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_sha224_init, sizeof(cc_sha224_init), 19208c2ecf20Sopenharmony_ci &sram_buff_ofs); 19218c2ecf20Sopenharmony_ci if (rc) 19228c2ecf20Sopenharmony_ci goto init_digest_const_err; 19238c2ecf20Sopenharmony_ci 19248c2ecf20Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_sha256_init, sizeof(cc_sha256_init), 19258c2ecf20Sopenharmony_ci &sram_buff_ofs); 19268c2ecf20Sopenharmony_ci if (rc) 19278c2ecf20Sopenharmony_ci goto init_digest_const_err; 19288c2ecf20Sopenharmony_ci 19298c2ecf20Sopenharmony_ci if (sm3_supported) { 19308c2ecf20Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_sm3_init, 19318c2ecf20Sopenharmony_ci sizeof(cc_sm3_init), &sram_buff_ofs); 19328c2ecf20Sopenharmony_ci if (rc) 19338c2ecf20Sopenharmony_ci goto init_digest_const_err; 19348c2ecf20Sopenharmony_ci } 19358c2ecf20Sopenharmony_ci 19368c2ecf20Sopenharmony_ci if (large_sha_supported) { 19378c2ecf20Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_sha384_init, 19388c2ecf20Sopenharmony_ci sizeof(cc_sha384_init), &sram_buff_ofs); 19398c2ecf20Sopenharmony_ci if (rc) 19408c2ecf20Sopenharmony_ci goto init_digest_const_err; 19418c2ecf20Sopenharmony_ci 19428c2ecf20Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_sha512_init, 19438c2ecf20Sopenharmony_ci sizeof(cc_sha512_init), &sram_buff_ofs); 19448c2ecf20Sopenharmony_ci if (rc) 19458c2ecf20Sopenharmony_ci goto init_digest_const_err; 19468c2ecf20Sopenharmony_ci } 19478c2ecf20Sopenharmony_ci 19488c2ecf20Sopenharmony_ciinit_digest_const_err: 19498c2ecf20Sopenharmony_ci return rc; 19508c2ecf20Sopenharmony_ci} 19518c2ecf20Sopenharmony_ci 19528c2ecf20Sopenharmony_ciint cc_hash_alloc(struct cc_drvdata *drvdata) 19538c2ecf20Sopenharmony_ci{ 19548c2ecf20Sopenharmony_ci struct cc_hash_handle *hash_handle; 19558c2ecf20Sopenharmony_ci u32 sram_buff; 19568c2ecf20Sopenharmony_ci u32 sram_size_to_alloc; 19578c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(drvdata); 19588c2ecf20Sopenharmony_ci int rc = 0; 19598c2ecf20Sopenharmony_ci int alg; 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_ci hash_handle = devm_kzalloc(dev, sizeof(*hash_handle), GFP_KERNEL); 19628c2ecf20Sopenharmony_ci if (!hash_handle) 19638c2ecf20Sopenharmony_ci return -ENOMEM; 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hash_handle->hash_list); 19668c2ecf20Sopenharmony_ci drvdata->hash_handle = hash_handle; 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_ci sram_size_to_alloc = sizeof(cc_digest_len_init) + 19698c2ecf20Sopenharmony_ci sizeof(cc_md5_init) + 19708c2ecf20Sopenharmony_ci sizeof(cc_sha1_init) + 19718c2ecf20Sopenharmony_ci sizeof(cc_sha224_init) + 19728c2ecf20Sopenharmony_ci sizeof(cc_sha256_init); 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci if (drvdata->hw_rev >= CC_HW_REV_713) 19758c2ecf20Sopenharmony_ci sram_size_to_alloc += sizeof(cc_sm3_init); 19768c2ecf20Sopenharmony_ci 19778c2ecf20Sopenharmony_ci if (drvdata->hw_rev >= CC_HW_REV_712) 19788c2ecf20Sopenharmony_ci sram_size_to_alloc += sizeof(cc_digest_len_sha512_init) + 19798c2ecf20Sopenharmony_ci sizeof(cc_sha384_init) + sizeof(cc_sha512_init); 19808c2ecf20Sopenharmony_ci 19818c2ecf20Sopenharmony_ci sram_buff = cc_sram_alloc(drvdata, sram_size_to_alloc); 19828c2ecf20Sopenharmony_ci if (sram_buff == NULL_SRAM_ADDR) { 19838c2ecf20Sopenharmony_ci rc = -ENOMEM; 19848c2ecf20Sopenharmony_ci goto fail; 19858c2ecf20Sopenharmony_ci } 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_ci /* The initial digest-len offset */ 19888c2ecf20Sopenharmony_ci hash_handle->digest_len_sram_addr = sram_buff; 19898c2ecf20Sopenharmony_ci 19908c2ecf20Sopenharmony_ci /*must be set before the alg registration as it is being used there*/ 19918c2ecf20Sopenharmony_ci rc = cc_init_hash_sram(drvdata); 19928c2ecf20Sopenharmony_ci if (rc) { 19938c2ecf20Sopenharmony_ci dev_err(dev, "Init digest CONST failed (rc=%d)\n", rc); 19948c2ecf20Sopenharmony_ci goto fail; 19958c2ecf20Sopenharmony_ci } 19968c2ecf20Sopenharmony_ci 19978c2ecf20Sopenharmony_ci /* ahash registration */ 19988c2ecf20Sopenharmony_ci for (alg = 0; alg < ARRAY_SIZE(driver_hash); alg++) { 19998c2ecf20Sopenharmony_ci struct cc_hash_alg *t_alg; 20008c2ecf20Sopenharmony_ci int hw_mode = driver_hash[alg].hw_mode; 20018c2ecf20Sopenharmony_ci 20028c2ecf20Sopenharmony_ci /* Check that the HW revision and variants are suitable */ 20038c2ecf20Sopenharmony_ci if ((driver_hash[alg].min_hw_rev > drvdata->hw_rev) || 20048c2ecf20Sopenharmony_ci !(drvdata->std_bodies & driver_hash[alg].std_body)) 20058c2ecf20Sopenharmony_ci continue; 20068c2ecf20Sopenharmony_ci 20078c2ecf20Sopenharmony_ci if (driver_hash[alg].is_mac) { 20088c2ecf20Sopenharmony_ci /* register hmac version */ 20098c2ecf20Sopenharmony_ci t_alg = cc_alloc_hash_alg(&driver_hash[alg], dev, true); 20108c2ecf20Sopenharmony_ci if (IS_ERR(t_alg)) { 20118c2ecf20Sopenharmony_ci rc = PTR_ERR(t_alg); 20128c2ecf20Sopenharmony_ci dev_err(dev, "%s alg allocation failed\n", 20138c2ecf20Sopenharmony_ci driver_hash[alg].driver_name); 20148c2ecf20Sopenharmony_ci goto fail; 20158c2ecf20Sopenharmony_ci } 20168c2ecf20Sopenharmony_ci t_alg->drvdata = drvdata; 20178c2ecf20Sopenharmony_ci 20188c2ecf20Sopenharmony_ci rc = crypto_register_ahash(&t_alg->ahash_alg); 20198c2ecf20Sopenharmony_ci if (rc) { 20208c2ecf20Sopenharmony_ci dev_err(dev, "%s alg registration failed\n", 20218c2ecf20Sopenharmony_ci driver_hash[alg].driver_name); 20228c2ecf20Sopenharmony_ci goto fail; 20238c2ecf20Sopenharmony_ci } 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_ci list_add_tail(&t_alg->entry, &hash_handle->hash_list); 20268c2ecf20Sopenharmony_ci } 20278c2ecf20Sopenharmony_ci if (hw_mode == DRV_CIPHER_XCBC_MAC || 20288c2ecf20Sopenharmony_ci hw_mode == DRV_CIPHER_CMAC) 20298c2ecf20Sopenharmony_ci continue; 20308c2ecf20Sopenharmony_ci 20318c2ecf20Sopenharmony_ci /* register hash version */ 20328c2ecf20Sopenharmony_ci t_alg = cc_alloc_hash_alg(&driver_hash[alg], dev, false); 20338c2ecf20Sopenharmony_ci if (IS_ERR(t_alg)) { 20348c2ecf20Sopenharmony_ci rc = PTR_ERR(t_alg); 20358c2ecf20Sopenharmony_ci dev_err(dev, "%s alg allocation failed\n", 20368c2ecf20Sopenharmony_ci driver_hash[alg].driver_name); 20378c2ecf20Sopenharmony_ci goto fail; 20388c2ecf20Sopenharmony_ci } 20398c2ecf20Sopenharmony_ci t_alg->drvdata = drvdata; 20408c2ecf20Sopenharmony_ci 20418c2ecf20Sopenharmony_ci rc = crypto_register_ahash(&t_alg->ahash_alg); 20428c2ecf20Sopenharmony_ci if (rc) { 20438c2ecf20Sopenharmony_ci dev_err(dev, "%s alg registration failed\n", 20448c2ecf20Sopenharmony_ci driver_hash[alg].driver_name); 20458c2ecf20Sopenharmony_ci goto fail; 20468c2ecf20Sopenharmony_ci } 20478c2ecf20Sopenharmony_ci 20488c2ecf20Sopenharmony_ci list_add_tail(&t_alg->entry, &hash_handle->hash_list); 20498c2ecf20Sopenharmony_ci } 20508c2ecf20Sopenharmony_ci 20518c2ecf20Sopenharmony_ci return 0; 20528c2ecf20Sopenharmony_ci 20538c2ecf20Sopenharmony_cifail: 20548c2ecf20Sopenharmony_ci cc_hash_free(drvdata); 20558c2ecf20Sopenharmony_ci return rc; 20568c2ecf20Sopenharmony_ci} 20578c2ecf20Sopenharmony_ci 20588c2ecf20Sopenharmony_ciint cc_hash_free(struct cc_drvdata *drvdata) 20598c2ecf20Sopenharmony_ci{ 20608c2ecf20Sopenharmony_ci struct cc_hash_alg *t_hash_alg, *hash_n; 20618c2ecf20Sopenharmony_ci struct cc_hash_handle *hash_handle = drvdata->hash_handle; 20628c2ecf20Sopenharmony_ci 20638c2ecf20Sopenharmony_ci list_for_each_entry_safe(t_hash_alg, hash_n, &hash_handle->hash_list, 20648c2ecf20Sopenharmony_ci entry) { 20658c2ecf20Sopenharmony_ci crypto_unregister_ahash(&t_hash_alg->ahash_alg); 20668c2ecf20Sopenharmony_ci list_del(&t_hash_alg->entry); 20678c2ecf20Sopenharmony_ci } 20688c2ecf20Sopenharmony_ci 20698c2ecf20Sopenharmony_ci return 0; 20708c2ecf20Sopenharmony_ci} 20718c2ecf20Sopenharmony_ci 20728c2ecf20Sopenharmony_cistatic void cc_setup_xcbc(struct ahash_request *areq, struct cc_hw_desc desc[], 20738c2ecf20Sopenharmony_ci unsigned int *seq_size) 20748c2ecf20Sopenharmony_ci{ 20758c2ecf20Sopenharmony_ci unsigned int idx = *seq_size; 20768c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(areq); 20778c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 20788c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm); 20798c2ecf20Sopenharmony_ci 20808c2ecf20Sopenharmony_ci /* Setup XCBC MAC K1 */ 20818c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 20828c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, (ctx->opad_tmp_keys_dma_addr + 20838c2ecf20Sopenharmony_ci XCBC_MAC_K1_OFFSET), 20848c2ecf20Sopenharmony_ci CC_AES_128_BIT_KEY_SIZE, NS_BIT); 20858c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 20868c2ecf20Sopenharmony_ci set_hash_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC, ctx->hash_mode); 20878c2ecf20Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 20888c2ecf20Sopenharmony_ci set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE); 20898c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 20908c2ecf20Sopenharmony_ci idx++; 20918c2ecf20Sopenharmony_ci 20928c2ecf20Sopenharmony_ci /* Setup XCBC MAC K2 */ 20938c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 20948c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 20958c2ecf20Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K2_OFFSET), 20968c2ecf20Sopenharmony_ci CC_AES_128_BIT_KEY_SIZE, NS_BIT); 20978c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); 20988c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC); 20998c2ecf20Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 21008c2ecf20Sopenharmony_ci set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE); 21018c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 21028c2ecf20Sopenharmony_ci idx++; 21038c2ecf20Sopenharmony_ci 21048c2ecf20Sopenharmony_ci /* Setup XCBC MAC K3 */ 21058c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 21068c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 21078c2ecf20Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K3_OFFSET), 21088c2ecf20Sopenharmony_ci CC_AES_128_BIT_KEY_SIZE, NS_BIT); 21098c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE2); 21108c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC); 21118c2ecf20Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 21128c2ecf20Sopenharmony_ci set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE); 21138c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 21148c2ecf20Sopenharmony_ci idx++; 21158c2ecf20Sopenharmony_ci 21168c2ecf20Sopenharmony_ci /* Loading MAC state */ 21178c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 21188c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, 21198c2ecf20Sopenharmony_ci CC_AES_BLOCK_SIZE, NS_BIT); 21208c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 21218c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC); 21228c2ecf20Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 21238c2ecf20Sopenharmony_ci set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE); 21248c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 21258c2ecf20Sopenharmony_ci idx++; 21268c2ecf20Sopenharmony_ci *seq_size = idx; 21278c2ecf20Sopenharmony_ci} 21288c2ecf20Sopenharmony_ci 21298c2ecf20Sopenharmony_cistatic void cc_setup_cmac(struct ahash_request *areq, struct cc_hw_desc desc[], 21308c2ecf20Sopenharmony_ci unsigned int *seq_size) 21318c2ecf20Sopenharmony_ci{ 21328c2ecf20Sopenharmony_ci unsigned int idx = *seq_size; 21338c2ecf20Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx(areq); 21348c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 21358c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx(tfm); 21368c2ecf20Sopenharmony_ci 21378c2ecf20Sopenharmony_ci /* Setup CMAC Key */ 21388c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 21398c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, ctx->opad_tmp_keys_dma_addr, 21408c2ecf20Sopenharmony_ci ((ctx->key_params.keylen == 24) ? AES_MAX_KEY_SIZE : 21418c2ecf20Sopenharmony_ci ctx->key_params.keylen), NS_BIT); 21428c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 21438c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC); 21448c2ecf20Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 21458c2ecf20Sopenharmony_ci set_key_size_aes(&desc[idx], ctx->key_params.keylen); 21468c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 21478c2ecf20Sopenharmony_ci idx++; 21488c2ecf20Sopenharmony_ci 21498c2ecf20Sopenharmony_ci /* Load MAC state */ 21508c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 21518c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, 21528c2ecf20Sopenharmony_ci CC_AES_BLOCK_SIZE, NS_BIT); 21538c2ecf20Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 21548c2ecf20Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC); 21558c2ecf20Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 21568c2ecf20Sopenharmony_ci set_key_size_aes(&desc[idx], ctx->key_params.keylen); 21578c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 21588c2ecf20Sopenharmony_ci idx++; 21598c2ecf20Sopenharmony_ci *seq_size = idx; 21608c2ecf20Sopenharmony_ci} 21618c2ecf20Sopenharmony_ci 21628c2ecf20Sopenharmony_cistatic void cc_set_desc(struct ahash_req_ctx *areq_ctx, 21638c2ecf20Sopenharmony_ci struct cc_hash_ctx *ctx, unsigned int flow_mode, 21648c2ecf20Sopenharmony_ci struct cc_hw_desc desc[], bool is_not_last_data, 21658c2ecf20Sopenharmony_ci unsigned int *seq_size) 21668c2ecf20Sopenharmony_ci{ 21678c2ecf20Sopenharmony_ci unsigned int idx = *seq_size; 21688c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 21698c2ecf20Sopenharmony_ci 21708c2ecf20Sopenharmony_ci if (areq_ctx->data_dma_buf_type == CC_DMA_BUF_DLLI) { 21718c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 21728c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 21738c2ecf20Sopenharmony_ci sg_dma_address(areq_ctx->curr_sg), 21748c2ecf20Sopenharmony_ci areq_ctx->curr_sg->length, NS_BIT); 21758c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], flow_mode); 21768c2ecf20Sopenharmony_ci idx++; 21778c2ecf20Sopenharmony_ci } else { 21788c2ecf20Sopenharmony_ci if (areq_ctx->data_dma_buf_type == CC_DMA_BUF_NULL) { 21798c2ecf20Sopenharmony_ci dev_dbg(dev, " NULL mode\n"); 21808c2ecf20Sopenharmony_ci /* nothing to build */ 21818c2ecf20Sopenharmony_ci return; 21828c2ecf20Sopenharmony_ci } 21838c2ecf20Sopenharmony_ci /* bypass */ 21848c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 21858c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 21868c2ecf20Sopenharmony_ci areq_ctx->mlli_params.mlli_dma_addr, 21878c2ecf20Sopenharmony_ci areq_ctx->mlli_params.mlli_len, NS_BIT); 21888c2ecf20Sopenharmony_ci set_dout_sram(&desc[idx], ctx->drvdata->mlli_sram_addr, 21898c2ecf20Sopenharmony_ci areq_ctx->mlli_params.mlli_len); 21908c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], BYPASS); 21918c2ecf20Sopenharmony_ci idx++; 21928c2ecf20Sopenharmony_ci /* process */ 21938c2ecf20Sopenharmony_ci hw_desc_init(&desc[idx]); 21948c2ecf20Sopenharmony_ci set_din_type(&desc[idx], DMA_MLLI, 21958c2ecf20Sopenharmony_ci ctx->drvdata->mlli_sram_addr, 21968c2ecf20Sopenharmony_ci areq_ctx->mlli_nents, NS_BIT); 21978c2ecf20Sopenharmony_ci set_flow_mode(&desc[idx], flow_mode); 21988c2ecf20Sopenharmony_ci idx++; 21998c2ecf20Sopenharmony_ci } 22008c2ecf20Sopenharmony_ci if (is_not_last_data) 22018c2ecf20Sopenharmony_ci set_din_not_last_indication(&desc[(idx - 1)]); 22028c2ecf20Sopenharmony_ci /* return updated desc sequence size */ 22038c2ecf20Sopenharmony_ci *seq_size = idx; 22048c2ecf20Sopenharmony_ci} 22058c2ecf20Sopenharmony_ci 22068c2ecf20Sopenharmony_cistatic const void *cc_larval_digest(struct device *dev, u32 mode) 22078c2ecf20Sopenharmony_ci{ 22088c2ecf20Sopenharmony_ci switch (mode) { 22098c2ecf20Sopenharmony_ci case DRV_HASH_MD5: 22108c2ecf20Sopenharmony_ci return cc_md5_init; 22118c2ecf20Sopenharmony_ci case DRV_HASH_SHA1: 22128c2ecf20Sopenharmony_ci return cc_sha1_init; 22138c2ecf20Sopenharmony_ci case DRV_HASH_SHA224: 22148c2ecf20Sopenharmony_ci return cc_sha224_init; 22158c2ecf20Sopenharmony_ci case DRV_HASH_SHA256: 22168c2ecf20Sopenharmony_ci return cc_sha256_init; 22178c2ecf20Sopenharmony_ci case DRV_HASH_SHA384: 22188c2ecf20Sopenharmony_ci return cc_sha384_init; 22198c2ecf20Sopenharmony_ci case DRV_HASH_SHA512: 22208c2ecf20Sopenharmony_ci return cc_sha512_init; 22218c2ecf20Sopenharmony_ci case DRV_HASH_SM3: 22228c2ecf20Sopenharmony_ci return cc_sm3_init; 22238c2ecf20Sopenharmony_ci default: 22248c2ecf20Sopenharmony_ci dev_err(dev, "Invalid hash mode (%d)\n", mode); 22258c2ecf20Sopenharmony_ci return cc_md5_init; 22268c2ecf20Sopenharmony_ci } 22278c2ecf20Sopenharmony_ci} 22288c2ecf20Sopenharmony_ci 22298c2ecf20Sopenharmony_ci/** 22308c2ecf20Sopenharmony_ci * cc_larval_digest_addr() - Get the address of the initial digest in SRAM 22318c2ecf20Sopenharmony_ci * according to the given hash mode 22328c2ecf20Sopenharmony_ci * 22338c2ecf20Sopenharmony_ci * @drvdata: Associated device driver context 22348c2ecf20Sopenharmony_ci * @mode: The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256 22358c2ecf20Sopenharmony_ci * 22368c2ecf20Sopenharmony_ci * Return: 22378c2ecf20Sopenharmony_ci * The address of the initial digest in SRAM 22388c2ecf20Sopenharmony_ci */ 22398c2ecf20Sopenharmony_ciu32 cc_larval_digest_addr(void *drvdata, u32 mode) 22408c2ecf20Sopenharmony_ci{ 22418c2ecf20Sopenharmony_ci struct cc_drvdata *_drvdata = (struct cc_drvdata *)drvdata; 22428c2ecf20Sopenharmony_ci struct cc_hash_handle *hash_handle = _drvdata->hash_handle; 22438c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(_drvdata); 22448c2ecf20Sopenharmony_ci bool sm3_supported = (_drvdata->hw_rev >= CC_HW_REV_713); 22458c2ecf20Sopenharmony_ci u32 addr; 22468c2ecf20Sopenharmony_ci 22478c2ecf20Sopenharmony_ci switch (mode) { 22488c2ecf20Sopenharmony_ci case DRV_HASH_NULL: 22498c2ecf20Sopenharmony_ci break; /*Ignore*/ 22508c2ecf20Sopenharmony_ci case DRV_HASH_MD5: 22518c2ecf20Sopenharmony_ci return (hash_handle->larval_digest_sram_addr); 22528c2ecf20Sopenharmony_ci case DRV_HASH_SHA1: 22538c2ecf20Sopenharmony_ci return (hash_handle->larval_digest_sram_addr + 22548c2ecf20Sopenharmony_ci sizeof(cc_md5_init)); 22558c2ecf20Sopenharmony_ci case DRV_HASH_SHA224: 22568c2ecf20Sopenharmony_ci return (hash_handle->larval_digest_sram_addr + 22578c2ecf20Sopenharmony_ci sizeof(cc_md5_init) + 22588c2ecf20Sopenharmony_ci sizeof(cc_sha1_init)); 22598c2ecf20Sopenharmony_ci case DRV_HASH_SHA256: 22608c2ecf20Sopenharmony_ci return (hash_handle->larval_digest_sram_addr + 22618c2ecf20Sopenharmony_ci sizeof(cc_md5_init) + 22628c2ecf20Sopenharmony_ci sizeof(cc_sha1_init) + 22638c2ecf20Sopenharmony_ci sizeof(cc_sha224_init)); 22648c2ecf20Sopenharmony_ci case DRV_HASH_SM3: 22658c2ecf20Sopenharmony_ci return (hash_handle->larval_digest_sram_addr + 22668c2ecf20Sopenharmony_ci sizeof(cc_md5_init) + 22678c2ecf20Sopenharmony_ci sizeof(cc_sha1_init) + 22688c2ecf20Sopenharmony_ci sizeof(cc_sha224_init) + 22698c2ecf20Sopenharmony_ci sizeof(cc_sha256_init)); 22708c2ecf20Sopenharmony_ci case DRV_HASH_SHA384: 22718c2ecf20Sopenharmony_ci addr = (hash_handle->larval_digest_sram_addr + 22728c2ecf20Sopenharmony_ci sizeof(cc_md5_init) + 22738c2ecf20Sopenharmony_ci sizeof(cc_sha1_init) + 22748c2ecf20Sopenharmony_ci sizeof(cc_sha224_init) + 22758c2ecf20Sopenharmony_ci sizeof(cc_sha256_init)); 22768c2ecf20Sopenharmony_ci if (sm3_supported) 22778c2ecf20Sopenharmony_ci addr += sizeof(cc_sm3_init); 22788c2ecf20Sopenharmony_ci return addr; 22798c2ecf20Sopenharmony_ci case DRV_HASH_SHA512: 22808c2ecf20Sopenharmony_ci addr = (hash_handle->larval_digest_sram_addr + 22818c2ecf20Sopenharmony_ci sizeof(cc_md5_init) + 22828c2ecf20Sopenharmony_ci sizeof(cc_sha1_init) + 22838c2ecf20Sopenharmony_ci sizeof(cc_sha224_init) + 22848c2ecf20Sopenharmony_ci sizeof(cc_sha256_init) + 22858c2ecf20Sopenharmony_ci sizeof(cc_sha384_init)); 22868c2ecf20Sopenharmony_ci if (sm3_supported) 22878c2ecf20Sopenharmony_ci addr += sizeof(cc_sm3_init); 22888c2ecf20Sopenharmony_ci return addr; 22898c2ecf20Sopenharmony_ci default: 22908c2ecf20Sopenharmony_ci dev_err(dev, "Invalid hash mode (%d)\n", mode); 22918c2ecf20Sopenharmony_ci } 22928c2ecf20Sopenharmony_ci 22938c2ecf20Sopenharmony_ci /*This is valid wrong value to avoid kernel crash*/ 22948c2ecf20Sopenharmony_ci return hash_handle->larval_digest_sram_addr; 22958c2ecf20Sopenharmony_ci} 22968c2ecf20Sopenharmony_ci 22978c2ecf20Sopenharmony_ciu32 cc_digest_len_addr(void *drvdata, u32 mode) 22988c2ecf20Sopenharmony_ci{ 22998c2ecf20Sopenharmony_ci struct cc_drvdata *_drvdata = (struct cc_drvdata *)drvdata; 23008c2ecf20Sopenharmony_ci struct cc_hash_handle *hash_handle = _drvdata->hash_handle; 23018c2ecf20Sopenharmony_ci u32 digest_len_addr = hash_handle->digest_len_sram_addr; 23028c2ecf20Sopenharmony_ci 23038c2ecf20Sopenharmony_ci switch (mode) { 23048c2ecf20Sopenharmony_ci case DRV_HASH_SHA1: 23058c2ecf20Sopenharmony_ci case DRV_HASH_SHA224: 23068c2ecf20Sopenharmony_ci case DRV_HASH_SHA256: 23078c2ecf20Sopenharmony_ci case DRV_HASH_MD5: 23088c2ecf20Sopenharmony_ci return digest_len_addr; 23098c2ecf20Sopenharmony_ci case DRV_HASH_SHA384: 23108c2ecf20Sopenharmony_ci case DRV_HASH_SHA512: 23118c2ecf20Sopenharmony_ci return digest_len_addr + sizeof(cc_digest_len_init); 23128c2ecf20Sopenharmony_ci default: 23138c2ecf20Sopenharmony_ci return digest_len_addr; /*to avoid kernel crash*/ 23148c2ecf20Sopenharmony_ci } 23158c2ecf20Sopenharmony_ci} 2316