162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (C) 2012-2019 ARM Limited (or its affiliates). */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/kernel.h> 562306a36Sopenharmony_ci#include <linux/module.h> 662306a36Sopenharmony_ci#include <crypto/algapi.h> 762306a36Sopenharmony_ci#include <crypto/hash.h> 862306a36Sopenharmony_ci#include <crypto/md5.h> 962306a36Sopenharmony_ci#include <crypto/sm3.h> 1062306a36Sopenharmony_ci#include <crypto/internal/hash.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "cc_driver.h" 1362306a36Sopenharmony_ci#include "cc_request_mgr.h" 1462306a36Sopenharmony_ci#include "cc_buffer_mgr.h" 1562306a36Sopenharmony_ci#include "cc_hash.h" 1662306a36Sopenharmony_ci#include "cc_sram_mgr.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define CC_MAX_HASH_SEQ_LEN 12 1962306a36Sopenharmony_ci#define CC_MAX_OPAD_KEYS_SIZE CC_MAX_HASH_BLCK_SIZE 2062306a36Sopenharmony_ci#define CC_SM3_HASH_LEN_SIZE 8 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistruct cc_hash_handle { 2362306a36Sopenharmony_ci u32 digest_len_sram_addr; /* const value in SRAM*/ 2462306a36Sopenharmony_ci u32 larval_digest_sram_addr; /* const value in SRAM */ 2562306a36Sopenharmony_ci struct list_head hash_list; 2662306a36Sopenharmony_ci}; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic const u32 cc_digest_len_init[] = { 2962306a36Sopenharmony_ci 0x00000040, 0x00000000, 0x00000000, 0x00000000 }; 3062306a36Sopenharmony_cistatic const u32 cc_md5_init[] = { 3162306a36Sopenharmony_ci SHA1_H3, SHA1_H2, SHA1_H1, SHA1_H0 }; 3262306a36Sopenharmony_cistatic const u32 cc_sha1_init[] = { 3362306a36Sopenharmony_ci SHA1_H4, SHA1_H3, SHA1_H2, SHA1_H1, SHA1_H0 }; 3462306a36Sopenharmony_cistatic const u32 cc_sha224_init[] = { 3562306a36Sopenharmony_ci SHA224_H7, SHA224_H6, SHA224_H5, SHA224_H4, 3662306a36Sopenharmony_ci SHA224_H3, SHA224_H2, SHA224_H1, SHA224_H0 }; 3762306a36Sopenharmony_cistatic const u32 cc_sha256_init[] = { 3862306a36Sopenharmony_ci SHA256_H7, SHA256_H6, SHA256_H5, SHA256_H4, 3962306a36Sopenharmony_ci SHA256_H3, SHA256_H2, SHA256_H1, SHA256_H0 }; 4062306a36Sopenharmony_cistatic const u32 cc_digest_len_sha512_init[] = { 4162306a36Sopenharmony_ci 0x00000080, 0x00000000, 0x00000000, 0x00000000 }; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* 4462306a36Sopenharmony_ci * Due to the way the HW works, every double word in the SHA384 and SHA512 4562306a36Sopenharmony_ci * larval hashes must be stored in hi/lo order 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_ci#define hilo(x) upper_32_bits(x), lower_32_bits(x) 4862306a36Sopenharmony_cistatic const u32 cc_sha384_init[] = { 4962306a36Sopenharmony_ci hilo(SHA384_H7), hilo(SHA384_H6), hilo(SHA384_H5), hilo(SHA384_H4), 5062306a36Sopenharmony_ci hilo(SHA384_H3), hilo(SHA384_H2), hilo(SHA384_H1), hilo(SHA384_H0) }; 5162306a36Sopenharmony_cistatic const u32 cc_sha512_init[] = { 5262306a36Sopenharmony_ci hilo(SHA512_H7), hilo(SHA512_H6), hilo(SHA512_H5), hilo(SHA512_H4), 5362306a36Sopenharmony_ci hilo(SHA512_H3), hilo(SHA512_H2), hilo(SHA512_H1), hilo(SHA512_H0) }; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic const u32 cc_sm3_init[] = { 5662306a36Sopenharmony_ci SM3_IVH, SM3_IVG, SM3_IVF, SM3_IVE, 5762306a36Sopenharmony_ci SM3_IVD, SM3_IVC, SM3_IVB, SM3_IVA }; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistatic void cc_setup_xcbc(struct ahash_request *areq, struct cc_hw_desc desc[], 6062306a36Sopenharmony_ci unsigned int *seq_size); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic void cc_setup_cmac(struct ahash_request *areq, struct cc_hw_desc desc[], 6362306a36Sopenharmony_ci unsigned int *seq_size); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic const void *cc_larval_digest(struct device *dev, u32 mode); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistruct cc_hash_alg { 6862306a36Sopenharmony_ci struct list_head entry; 6962306a36Sopenharmony_ci int hash_mode; 7062306a36Sopenharmony_ci int hw_mode; 7162306a36Sopenharmony_ci int inter_digestsize; 7262306a36Sopenharmony_ci struct cc_drvdata *drvdata; 7362306a36Sopenharmony_ci struct ahash_alg ahash_alg; 7462306a36Sopenharmony_ci}; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistruct hash_key_req_ctx { 7762306a36Sopenharmony_ci u32 keylen; 7862306a36Sopenharmony_ci dma_addr_t key_dma_addr; 7962306a36Sopenharmony_ci u8 *key; 8062306a36Sopenharmony_ci}; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci/* hash per-session context */ 8362306a36Sopenharmony_cistruct cc_hash_ctx { 8462306a36Sopenharmony_ci struct cc_drvdata *drvdata; 8562306a36Sopenharmony_ci /* holds the origin digest; the digest after "setkey" if HMAC,* 8662306a36Sopenharmony_ci * the initial digest if HASH. 8762306a36Sopenharmony_ci */ 8862306a36Sopenharmony_ci u8 digest_buff[CC_MAX_HASH_DIGEST_SIZE] ____cacheline_aligned; 8962306a36Sopenharmony_ci u8 opad_tmp_keys_buff[CC_MAX_OPAD_KEYS_SIZE] ____cacheline_aligned; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci dma_addr_t opad_tmp_keys_dma_addr ____cacheline_aligned; 9262306a36Sopenharmony_ci dma_addr_t digest_buff_dma_addr; 9362306a36Sopenharmony_ci /* use for hmac with key large then mode block size */ 9462306a36Sopenharmony_ci struct hash_key_req_ctx key_params; 9562306a36Sopenharmony_ci int hash_mode; 9662306a36Sopenharmony_ci int hw_mode; 9762306a36Sopenharmony_ci int inter_digestsize; 9862306a36Sopenharmony_ci unsigned int hash_len; 9962306a36Sopenharmony_ci struct completion setkey_comp; 10062306a36Sopenharmony_ci bool is_hmac; 10162306a36Sopenharmony_ci}; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic void cc_set_desc(struct ahash_req_ctx *areq_ctx, struct cc_hash_ctx *ctx, 10462306a36Sopenharmony_ci unsigned int flow_mode, struct cc_hw_desc desc[], 10562306a36Sopenharmony_ci bool is_not_last_data, unsigned int *seq_size); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic void cc_set_endianity(u32 mode, struct cc_hw_desc *desc) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci if (mode == DRV_HASH_MD5 || mode == DRV_HASH_SHA384 || 11062306a36Sopenharmony_ci mode == DRV_HASH_SHA512) { 11162306a36Sopenharmony_ci set_bytes_swap(desc, 1); 11262306a36Sopenharmony_ci } else { 11362306a36Sopenharmony_ci set_cipher_config0(desc, HASH_DIGEST_RESULT_LITTLE_ENDIAN); 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic int cc_map_result(struct device *dev, struct ahash_req_ctx *state, 11862306a36Sopenharmony_ci unsigned int digestsize) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci state->digest_result_dma_addr = 12162306a36Sopenharmony_ci dma_map_single(dev, state->digest_result_buff, 12262306a36Sopenharmony_ci digestsize, DMA_BIDIRECTIONAL); 12362306a36Sopenharmony_ci if (dma_mapping_error(dev, state->digest_result_dma_addr)) { 12462306a36Sopenharmony_ci dev_err(dev, "Mapping digest result buffer %u B for DMA failed\n", 12562306a36Sopenharmony_ci digestsize); 12662306a36Sopenharmony_ci return -ENOMEM; 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci dev_dbg(dev, "Mapped digest result buffer %u B at va=%pK to dma=%pad\n", 12962306a36Sopenharmony_ci digestsize, state->digest_result_buff, 13062306a36Sopenharmony_ci &state->digest_result_dma_addr); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci return 0; 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic void cc_init_req(struct device *dev, struct ahash_req_ctx *state, 13662306a36Sopenharmony_ci struct cc_hash_ctx *ctx) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci bool is_hmac = ctx->is_hmac; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci memset(state, 0, sizeof(*state)); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci if (is_hmac) { 14362306a36Sopenharmony_ci if (ctx->hw_mode != DRV_CIPHER_XCBC_MAC && 14462306a36Sopenharmony_ci ctx->hw_mode != DRV_CIPHER_CMAC) { 14562306a36Sopenharmony_ci dma_sync_single_for_cpu(dev, ctx->digest_buff_dma_addr, 14662306a36Sopenharmony_ci ctx->inter_digestsize, 14762306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci memcpy(state->digest_buff, ctx->digest_buff, 15062306a36Sopenharmony_ci ctx->inter_digestsize); 15162306a36Sopenharmony_ci if (ctx->hash_mode == DRV_HASH_SHA512 || 15262306a36Sopenharmony_ci ctx->hash_mode == DRV_HASH_SHA384) 15362306a36Sopenharmony_ci memcpy(state->digest_bytes_len, 15462306a36Sopenharmony_ci cc_digest_len_sha512_init, 15562306a36Sopenharmony_ci ctx->hash_len); 15662306a36Sopenharmony_ci else 15762306a36Sopenharmony_ci memcpy(state->digest_bytes_len, 15862306a36Sopenharmony_ci cc_digest_len_init, 15962306a36Sopenharmony_ci ctx->hash_len); 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci if (ctx->hash_mode != DRV_HASH_NULL) { 16362306a36Sopenharmony_ci dma_sync_single_for_cpu(dev, 16462306a36Sopenharmony_ci ctx->opad_tmp_keys_dma_addr, 16562306a36Sopenharmony_ci ctx->inter_digestsize, 16662306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 16762306a36Sopenharmony_ci memcpy(state->opad_digest_buff, 16862306a36Sopenharmony_ci ctx->opad_tmp_keys_buff, ctx->inter_digestsize); 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci } else { /*hash*/ 17162306a36Sopenharmony_ci /* Copy the initial digests if hash flow. */ 17262306a36Sopenharmony_ci const void *larval = cc_larval_digest(dev, ctx->hash_mode); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci memcpy(state->digest_buff, larval, ctx->inter_digestsize); 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci} 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_cistatic int cc_map_req(struct device *dev, struct ahash_req_ctx *state, 17962306a36Sopenharmony_ci struct cc_hash_ctx *ctx) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci bool is_hmac = ctx->is_hmac; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci state->digest_buff_dma_addr = 18462306a36Sopenharmony_ci dma_map_single(dev, state->digest_buff, 18562306a36Sopenharmony_ci ctx->inter_digestsize, DMA_BIDIRECTIONAL); 18662306a36Sopenharmony_ci if (dma_mapping_error(dev, state->digest_buff_dma_addr)) { 18762306a36Sopenharmony_ci dev_err(dev, "Mapping digest len %d B at va=%pK for DMA failed\n", 18862306a36Sopenharmony_ci ctx->inter_digestsize, state->digest_buff); 18962306a36Sopenharmony_ci return -EINVAL; 19062306a36Sopenharmony_ci } 19162306a36Sopenharmony_ci dev_dbg(dev, "Mapped digest %d B at va=%pK to dma=%pad\n", 19262306a36Sopenharmony_ci ctx->inter_digestsize, state->digest_buff, 19362306a36Sopenharmony_ci &state->digest_buff_dma_addr); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci if (ctx->hw_mode != DRV_CIPHER_XCBC_MAC) { 19662306a36Sopenharmony_ci state->digest_bytes_len_dma_addr = 19762306a36Sopenharmony_ci dma_map_single(dev, state->digest_bytes_len, 19862306a36Sopenharmony_ci HASH_MAX_LEN_SIZE, DMA_BIDIRECTIONAL); 19962306a36Sopenharmony_ci if (dma_mapping_error(dev, state->digest_bytes_len_dma_addr)) { 20062306a36Sopenharmony_ci dev_err(dev, "Mapping digest len %u B at va=%pK for DMA failed\n", 20162306a36Sopenharmony_ci HASH_MAX_LEN_SIZE, state->digest_bytes_len); 20262306a36Sopenharmony_ci goto unmap_digest_buf; 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci dev_dbg(dev, "Mapped digest len %u B at va=%pK to dma=%pad\n", 20562306a36Sopenharmony_ci HASH_MAX_LEN_SIZE, state->digest_bytes_len, 20662306a36Sopenharmony_ci &state->digest_bytes_len_dma_addr); 20762306a36Sopenharmony_ci } 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci if (is_hmac && ctx->hash_mode != DRV_HASH_NULL) { 21062306a36Sopenharmony_ci state->opad_digest_dma_addr = 21162306a36Sopenharmony_ci dma_map_single(dev, state->opad_digest_buff, 21262306a36Sopenharmony_ci ctx->inter_digestsize, 21362306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 21462306a36Sopenharmony_ci if (dma_mapping_error(dev, state->opad_digest_dma_addr)) { 21562306a36Sopenharmony_ci dev_err(dev, "Mapping opad digest %d B at va=%pK for DMA failed\n", 21662306a36Sopenharmony_ci ctx->inter_digestsize, 21762306a36Sopenharmony_ci state->opad_digest_buff); 21862306a36Sopenharmony_ci goto unmap_digest_len; 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci dev_dbg(dev, "Mapped opad digest %d B at va=%pK to dma=%pad\n", 22162306a36Sopenharmony_ci ctx->inter_digestsize, state->opad_digest_buff, 22262306a36Sopenharmony_ci &state->opad_digest_dma_addr); 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci return 0; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ciunmap_digest_len: 22862306a36Sopenharmony_ci if (state->digest_bytes_len_dma_addr) { 22962306a36Sopenharmony_ci dma_unmap_single(dev, state->digest_bytes_len_dma_addr, 23062306a36Sopenharmony_ci HASH_MAX_LEN_SIZE, DMA_BIDIRECTIONAL); 23162306a36Sopenharmony_ci state->digest_bytes_len_dma_addr = 0; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ciunmap_digest_buf: 23462306a36Sopenharmony_ci if (state->digest_buff_dma_addr) { 23562306a36Sopenharmony_ci dma_unmap_single(dev, state->digest_buff_dma_addr, 23662306a36Sopenharmony_ci ctx->inter_digestsize, DMA_BIDIRECTIONAL); 23762306a36Sopenharmony_ci state->digest_buff_dma_addr = 0; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci return -EINVAL; 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_cistatic void cc_unmap_req(struct device *dev, struct ahash_req_ctx *state, 24462306a36Sopenharmony_ci struct cc_hash_ctx *ctx) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci if (state->digest_buff_dma_addr) { 24762306a36Sopenharmony_ci dma_unmap_single(dev, state->digest_buff_dma_addr, 24862306a36Sopenharmony_ci ctx->inter_digestsize, DMA_BIDIRECTIONAL); 24962306a36Sopenharmony_ci dev_dbg(dev, "Unmapped digest-buffer: digest_buff_dma_addr=%pad\n", 25062306a36Sopenharmony_ci &state->digest_buff_dma_addr); 25162306a36Sopenharmony_ci state->digest_buff_dma_addr = 0; 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci if (state->digest_bytes_len_dma_addr) { 25462306a36Sopenharmony_ci dma_unmap_single(dev, state->digest_bytes_len_dma_addr, 25562306a36Sopenharmony_ci HASH_MAX_LEN_SIZE, DMA_BIDIRECTIONAL); 25662306a36Sopenharmony_ci dev_dbg(dev, "Unmapped digest-bytes-len buffer: digest_bytes_len_dma_addr=%pad\n", 25762306a36Sopenharmony_ci &state->digest_bytes_len_dma_addr); 25862306a36Sopenharmony_ci state->digest_bytes_len_dma_addr = 0; 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci if (state->opad_digest_dma_addr) { 26162306a36Sopenharmony_ci dma_unmap_single(dev, state->opad_digest_dma_addr, 26262306a36Sopenharmony_ci ctx->inter_digestsize, DMA_BIDIRECTIONAL); 26362306a36Sopenharmony_ci dev_dbg(dev, "Unmapped opad-digest: opad_digest_dma_addr=%pad\n", 26462306a36Sopenharmony_ci &state->opad_digest_dma_addr); 26562306a36Sopenharmony_ci state->opad_digest_dma_addr = 0; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistatic void cc_unmap_result(struct device *dev, struct ahash_req_ctx *state, 27062306a36Sopenharmony_ci unsigned int digestsize, u8 *result) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci if (state->digest_result_dma_addr) { 27362306a36Sopenharmony_ci dma_unmap_single(dev, state->digest_result_dma_addr, digestsize, 27462306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 27562306a36Sopenharmony_ci dev_dbg(dev, "unmpa digest result buffer va (%pK) pa (%pad) len %u\n", 27662306a36Sopenharmony_ci state->digest_result_buff, 27762306a36Sopenharmony_ci &state->digest_result_dma_addr, digestsize); 27862306a36Sopenharmony_ci memcpy(result, state->digest_result_buff, digestsize); 27962306a36Sopenharmony_ci } 28062306a36Sopenharmony_ci state->digest_result_dma_addr = 0; 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic void cc_update_complete(struct device *dev, void *cc_req, int err) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci struct ahash_request *req = (struct ahash_request *)cc_req; 28662306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(req); 28762306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 28862306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci dev_dbg(dev, "req=%pK\n", req); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci if (err != -EINPROGRESS) { 29362306a36Sopenharmony_ci /* Not a BACKLOG notification */ 29462306a36Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, false); 29562306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci ahash_request_complete(req, err); 29962306a36Sopenharmony_ci} 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_cistatic void cc_digest_complete(struct device *dev, void *cc_req, int err) 30262306a36Sopenharmony_ci{ 30362306a36Sopenharmony_ci struct ahash_request *req = (struct ahash_request *)cc_req; 30462306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(req); 30562306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 30662306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm); 30762306a36Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci dev_dbg(dev, "req=%pK\n", req); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci if (err != -EINPROGRESS) { 31262306a36Sopenharmony_ci /* Not a BACKLOG notification */ 31362306a36Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, false); 31462306a36Sopenharmony_ci cc_unmap_result(dev, state, digestsize, req->result); 31562306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci ahash_request_complete(req, err); 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_cistatic void cc_hash_complete(struct device *dev, void *cc_req, int err) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci struct ahash_request *req = (struct ahash_request *)cc_req; 32462306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(req); 32562306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 32662306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm); 32762306a36Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci dev_dbg(dev, "req=%pK\n", req); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci if (err != -EINPROGRESS) { 33262306a36Sopenharmony_ci /* Not a BACKLOG notification */ 33362306a36Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, false); 33462306a36Sopenharmony_ci cc_unmap_result(dev, state, digestsize, req->result); 33562306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci ahash_request_complete(req, err); 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cistatic int cc_fin_result(struct cc_hw_desc *desc, struct ahash_request *req, 34262306a36Sopenharmony_ci int idx) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(req); 34562306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 34662306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm); 34762306a36Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci /* Get final MAC result */ 35062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 35162306a36Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 35262306a36Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_result_dma_addr, digestsize, 35362306a36Sopenharmony_ci NS_BIT, 1); 35462306a36Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 35562306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 35662306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 35762306a36Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED); 35862306a36Sopenharmony_ci cc_set_endianity(ctx->hash_mode, &desc[idx]); 35962306a36Sopenharmony_ci idx++; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci return idx; 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_cistatic int cc_fin_hmac(struct cc_hw_desc *desc, struct ahash_request *req, 36562306a36Sopenharmony_ci int idx) 36662306a36Sopenharmony_ci{ 36762306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(req); 36862306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 36962306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm); 37062306a36Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci /* store the hash digest result in the context */ 37362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 37462306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 37562306a36Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_buff_dma_addr, digestsize, 37662306a36Sopenharmony_ci NS_BIT, 0); 37762306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 37862306a36Sopenharmony_ci cc_set_endianity(ctx->hash_mode, &desc[idx]); 37962306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 38062306a36Sopenharmony_ci idx++; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci /* Loading hash opad xor key state */ 38362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 38462306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 38562306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->opad_digest_dma_addr, 38662306a36Sopenharmony_ci ctx->inter_digestsize, NS_BIT); 38762306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 38862306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 38962306a36Sopenharmony_ci idx++; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci /* Load the hash current length */ 39262306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 39362306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 39462306a36Sopenharmony_ci set_din_sram(&desc[idx], 39562306a36Sopenharmony_ci cc_digest_len_addr(ctx->drvdata, ctx->hash_mode), 39662306a36Sopenharmony_ci ctx->hash_len); 39762306a36Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); 39862306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 39962306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 40062306a36Sopenharmony_ci idx++; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci /* Memory Barrier: wait for IPAD/OPAD axi write to complete */ 40362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 40462306a36Sopenharmony_ci set_din_no_dma(&desc[idx], 0, 0xfffff0); 40562306a36Sopenharmony_ci set_dout_no_dma(&desc[idx], 0, 0, 1); 40662306a36Sopenharmony_ci idx++; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci /* Perform HASH update */ 40962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 41062306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, 41162306a36Sopenharmony_ci digestsize, NS_BIT); 41262306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_HASH); 41362306a36Sopenharmony_ci idx++; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci return idx; 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_cistatic int cc_hash_digest(struct ahash_request *req) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(req); 42162306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 42262306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm); 42362306a36Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 42462306a36Sopenharmony_ci struct scatterlist *src = req->src; 42562306a36Sopenharmony_ci unsigned int nbytes = req->nbytes; 42662306a36Sopenharmony_ci u8 *result = req->result; 42762306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 42862306a36Sopenharmony_ci bool is_hmac = ctx->is_hmac; 42962306a36Sopenharmony_ci struct cc_crypto_req cc_req = {}; 43062306a36Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 43162306a36Sopenharmony_ci u32 larval_digest_addr; 43262306a36Sopenharmony_ci int idx = 0; 43362306a36Sopenharmony_ci int rc = 0; 43462306a36Sopenharmony_ci gfp_t flags = cc_gfp_flags(&req->base); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci dev_dbg(dev, "===== %s-digest (%d) ====\n", is_hmac ? "hmac" : "hash", 43762306a36Sopenharmony_ci nbytes); 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci cc_init_req(dev, state, ctx); 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci if (cc_map_req(dev, state, ctx)) { 44262306a36Sopenharmony_ci dev_err(dev, "map_ahash_source() failed\n"); 44362306a36Sopenharmony_ci return -ENOMEM; 44462306a36Sopenharmony_ci } 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci if (cc_map_result(dev, state, digestsize)) { 44762306a36Sopenharmony_ci dev_err(dev, "map_ahash_digest() failed\n"); 44862306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 44962306a36Sopenharmony_ci return -ENOMEM; 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci if (cc_map_hash_request_final(ctx->drvdata, state, src, nbytes, 1, 45362306a36Sopenharmony_ci flags)) { 45462306a36Sopenharmony_ci dev_err(dev, "map_ahash_request_final() failed\n"); 45562306a36Sopenharmony_ci cc_unmap_result(dev, state, digestsize, result); 45662306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 45762306a36Sopenharmony_ci return -ENOMEM; 45862306a36Sopenharmony_ci } 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci /* Setup request structure */ 46162306a36Sopenharmony_ci cc_req.user_cb = cc_digest_complete; 46262306a36Sopenharmony_ci cc_req.user_arg = req; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci /* If HMAC then load hash IPAD xor key, if HASH then load initial 46562306a36Sopenharmony_ci * digest 46662306a36Sopenharmony_ci */ 46762306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 46862306a36Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 46962306a36Sopenharmony_ci if (is_hmac) { 47062306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, 47162306a36Sopenharmony_ci ctx->inter_digestsize, NS_BIT); 47262306a36Sopenharmony_ci } else { 47362306a36Sopenharmony_ci larval_digest_addr = cc_larval_digest_addr(ctx->drvdata, 47462306a36Sopenharmony_ci ctx->hash_mode); 47562306a36Sopenharmony_ci set_din_sram(&desc[idx], larval_digest_addr, 47662306a36Sopenharmony_ci ctx->inter_digestsize); 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 47962306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 48062306a36Sopenharmony_ci idx++; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci /* Load the hash current length */ 48362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 48462306a36Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci if (is_hmac) { 48762306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 48862306a36Sopenharmony_ci state->digest_bytes_len_dma_addr, 48962306a36Sopenharmony_ci ctx->hash_len, NS_BIT); 49062306a36Sopenharmony_ci } else { 49162306a36Sopenharmony_ci set_din_const(&desc[idx], 0, ctx->hash_len); 49262306a36Sopenharmony_ci if (nbytes) 49362306a36Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); 49462306a36Sopenharmony_ci else 49562306a36Sopenharmony_ci set_cipher_do(&desc[idx], DO_PAD); 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 49862306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 49962306a36Sopenharmony_ci idx++; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci cc_set_desc(state, ctx, DIN_HASH, desc, false, &idx); 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci if (is_hmac) { 50462306a36Sopenharmony_ci /* HW last hash block padding (aka. "DO_PAD") */ 50562306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 50662306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 50762306a36Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_buff_dma_addr, 50862306a36Sopenharmony_ci ctx->hash_len, NS_BIT, 0); 50962306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 51062306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE1); 51162306a36Sopenharmony_ci set_cipher_do(&desc[idx], DO_PAD); 51262306a36Sopenharmony_ci idx++; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci idx = cc_fin_hmac(desc, req, idx); 51562306a36Sopenharmony_ci } 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci idx = cc_fin_result(desc, req, idx); 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base); 52062306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 52162306a36Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 52262306a36Sopenharmony_ci cc_unmap_hash_request(dev, state, src, true); 52362306a36Sopenharmony_ci cc_unmap_result(dev, state, digestsize, result); 52462306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 52562306a36Sopenharmony_ci } 52662306a36Sopenharmony_ci return rc; 52762306a36Sopenharmony_ci} 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_cistatic int cc_restore_hash(struct cc_hw_desc *desc, struct cc_hash_ctx *ctx, 53062306a36Sopenharmony_ci struct ahash_req_ctx *state, unsigned int idx) 53162306a36Sopenharmony_ci{ 53262306a36Sopenharmony_ci /* Restore hash digest */ 53362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 53462306a36Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 53562306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, 53662306a36Sopenharmony_ci ctx->inter_digestsize, NS_BIT); 53762306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 53862306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 53962306a36Sopenharmony_ci idx++; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci /* Restore hash current length */ 54262306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 54362306a36Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 54462306a36Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED); 54562306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->digest_bytes_len_dma_addr, 54662306a36Sopenharmony_ci ctx->hash_len, NS_BIT); 54762306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 54862306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 54962306a36Sopenharmony_ci idx++; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci cc_set_desc(state, ctx, DIN_HASH, desc, false, &idx); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci return idx; 55462306a36Sopenharmony_ci} 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_cistatic int cc_hash_update(struct ahash_request *req) 55762306a36Sopenharmony_ci{ 55862306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(req); 55962306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 56062306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm); 56162306a36Sopenharmony_ci unsigned int block_size = crypto_tfm_alg_blocksize(&tfm->base); 56262306a36Sopenharmony_ci struct scatterlist *src = req->src; 56362306a36Sopenharmony_ci unsigned int nbytes = req->nbytes; 56462306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 56562306a36Sopenharmony_ci struct cc_crypto_req cc_req = {}; 56662306a36Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 56762306a36Sopenharmony_ci u32 idx = 0; 56862306a36Sopenharmony_ci int rc; 56962306a36Sopenharmony_ci gfp_t flags = cc_gfp_flags(&req->base); 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci dev_dbg(dev, "===== %s-update (%d) ====\n", ctx->is_hmac ? 57262306a36Sopenharmony_ci "hmac" : "hash", nbytes); 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci if (nbytes == 0) { 57562306a36Sopenharmony_ci /* no real updates required */ 57662306a36Sopenharmony_ci return 0; 57762306a36Sopenharmony_ci } 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci rc = cc_map_hash_request_update(ctx->drvdata, state, src, nbytes, 58062306a36Sopenharmony_ci block_size, flags); 58162306a36Sopenharmony_ci if (rc) { 58262306a36Sopenharmony_ci if (rc == 1) { 58362306a36Sopenharmony_ci dev_dbg(dev, " data size not require HW update %x\n", 58462306a36Sopenharmony_ci nbytes); 58562306a36Sopenharmony_ci /* No hardware updates are required */ 58662306a36Sopenharmony_ci return 0; 58762306a36Sopenharmony_ci } 58862306a36Sopenharmony_ci dev_err(dev, "map_ahash_request_update() failed\n"); 58962306a36Sopenharmony_ci return -ENOMEM; 59062306a36Sopenharmony_ci } 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci if (cc_map_req(dev, state, ctx)) { 59362306a36Sopenharmony_ci dev_err(dev, "map_ahash_source() failed\n"); 59462306a36Sopenharmony_ci cc_unmap_hash_request(dev, state, src, true); 59562306a36Sopenharmony_ci return -EINVAL; 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci /* Setup request structure */ 59962306a36Sopenharmony_ci cc_req.user_cb = cc_update_complete; 60062306a36Sopenharmony_ci cc_req.user_arg = req; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci idx = cc_restore_hash(desc, ctx, state, idx); 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci /* store the hash digest result in context */ 60562306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 60662306a36Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 60762306a36Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_buff_dma_addr, 60862306a36Sopenharmony_ci ctx->inter_digestsize, NS_BIT, 0); 60962306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 61062306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 61162306a36Sopenharmony_ci idx++; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci /* store current hash length in context */ 61462306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 61562306a36Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 61662306a36Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_bytes_len_dma_addr, 61762306a36Sopenharmony_ci ctx->hash_len, NS_BIT, 1); 61862306a36Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 61962306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 62062306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE1); 62162306a36Sopenharmony_ci idx++; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base); 62462306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 62562306a36Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 62662306a36Sopenharmony_ci cc_unmap_hash_request(dev, state, src, true); 62762306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 62862306a36Sopenharmony_ci } 62962306a36Sopenharmony_ci return rc; 63062306a36Sopenharmony_ci} 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_cistatic int cc_do_finup(struct ahash_request *req, bool update) 63362306a36Sopenharmony_ci{ 63462306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(req); 63562306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 63662306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm); 63762306a36Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 63862306a36Sopenharmony_ci struct scatterlist *src = req->src; 63962306a36Sopenharmony_ci unsigned int nbytes = req->nbytes; 64062306a36Sopenharmony_ci u8 *result = req->result; 64162306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 64262306a36Sopenharmony_ci bool is_hmac = ctx->is_hmac; 64362306a36Sopenharmony_ci struct cc_crypto_req cc_req = {}; 64462306a36Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 64562306a36Sopenharmony_ci unsigned int idx = 0; 64662306a36Sopenharmony_ci int rc; 64762306a36Sopenharmony_ci gfp_t flags = cc_gfp_flags(&req->base); 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci dev_dbg(dev, "===== %s-%s (%d) ====\n", is_hmac ? "hmac" : "hash", 65062306a36Sopenharmony_ci update ? "finup" : "final", nbytes); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci if (cc_map_req(dev, state, ctx)) { 65362306a36Sopenharmony_ci dev_err(dev, "map_ahash_source() failed\n"); 65462306a36Sopenharmony_ci return -EINVAL; 65562306a36Sopenharmony_ci } 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci if (cc_map_hash_request_final(ctx->drvdata, state, src, nbytes, update, 65862306a36Sopenharmony_ci flags)) { 65962306a36Sopenharmony_ci dev_err(dev, "map_ahash_request_final() failed\n"); 66062306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 66162306a36Sopenharmony_ci return -ENOMEM; 66262306a36Sopenharmony_ci } 66362306a36Sopenharmony_ci if (cc_map_result(dev, state, digestsize)) { 66462306a36Sopenharmony_ci dev_err(dev, "map_ahash_digest() failed\n"); 66562306a36Sopenharmony_ci cc_unmap_hash_request(dev, state, src, true); 66662306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 66762306a36Sopenharmony_ci return -ENOMEM; 66862306a36Sopenharmony_ci } 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci /* Setup request structure */ 67162306a36Sopenharmony_ci cc_req.user_cb = cc_hash_complete; 67262306a36Sopenharmony_ci cc_req.user_arg = req; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci idx = cc_restore_hash(desc, ctx, state, idx); 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci /* Pad the hash */ 67762306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 67862306a36Sopenharmony_ci set_cipher_do(&desc[idx], DO_PAD); 67962306a36Sopenharmony_ci set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode); 68062306a36Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_bytes_len_dma_addr, 68162306a36Sopenharmony_ci ctx->hash_len, NS_BIT, 0); 68262306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE1); 68362306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 68462306a36Sopenharmony_ci idx++; 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci if (is_hmac) 68762306a36Sopenharmony_ci idx = cc_fin_hmac(desc, req, idx); 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci idx = cc_fin_result(desc, req, idx); 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base); 69262306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 69362306a36Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 69462306a36Sopenharmony_ci cc_unmap_hash_request(dev, state, src, true); 69562306a36Sopenharmony_ci cc_unmap_result(dev, state, digestsize, result); 69662306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci return rc; 69962306a36Sopenharmony_ci} 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_cistatic int cc_hash_finup(struct ahash_request *req) 70262306a36Sopenharmony_ci{ 70362306a36Sopenharmony_ci return cc_do_finup(req, true); 70462306a36Sopenharmony_ci} 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_cistatic int cc_hash_final(struct ahash_request *req) 70862306a36Sopenharmony_ci{ 70962306a36Sopenharmony_ci return cc_do_finup(req, false); 71062306a36Sopenharmony_ci} 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_cistatic int cc_hash_init(struct ahash_request *req) 71362306a36Sopenharmony_ci{ 71462306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(req); 71562306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 71662306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm); 71762306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci dev_dbg(dev, "===== init (%d) ====\n", req->nbytes); 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci cc_init_req(dev, state, ctx); 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci return 0; 72462306a36Sopenharmony_ci} 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_cistatic int cc_hash_setkey(struct crypto_ahash *ahash, const u8 *key, 72762306a36Sopenharmony_ci unsigned int keylen) 72862306a36Sopenharmony_ci{ 72962306a36Sopenharmony_ci unsigned int hmac_pad_const[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST }; 73062306a36Sopenharmony_ci struct cc_crypto_req cc_req = {}; 73162306a36Sopenharmony_ci struct cc_hash_ctx *ctx = NULL; 73262306a36Sopenharmony_ci int blocksize = 0; 73362306a36Sopenharmony_ci int digestsize = 0; 73462306a36Sopenharmony_ci int i, idx = 0, rc = 0; 73562306a36Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 73662306a36Sopenharmony_ci u32 larval_addr; 73762306a36Sopenharmony_ci struct device *dev; 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci ctx = crypto_ahash_ctx_dma(ahash); 74062306a36Sopenharmony_ci dev = drvdata_to_dev(ctx->drvdata); 74162306a36Sopenharmony_ci dev_dbg(dev, "start keylen: %d", keylen); 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci blocksize = crypto_tfm_alg_blocksize(&ahash->base); 74462306a36Sopenharmony_ci digestsize = crypto_ahash_digestsize(ahash); 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci larval_addr = cc_larval_digest_addr(ctx->drvdata, ctx->hash_mode); 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci /* The keylen value distinguishes HASH in case keylen is ZERO bytes, 74962306a36Sopenharmony_ci * any NON-ZERO value utilizes HMAC flow 75062306a36Sopenharmony_ci */ 75162306a36Sopenharmony_ci ctx->key_params.keylen = keylen; 75262306a36Sopenharmony_ci ctx->key_params.key_dma_addr = 0; 75362306a36Sopenharmony_ci ctx->is_hmac = true; 75462306a36Sopenharmony_ci ctx->key_params.key = NULL; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci if (keylen) { 75762306a36Sopenharmony_ci ctx->key_params.key = kmemdup(key, keylen, GFP_KERNEL); 75862306a36Sopenharmony_ci if (!ctx->key_params.key) 75962306a36Sopenharmony_ci return -ENOMEM; 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci ctx->key_params.key_dma_addr = 76262306a36Sopenharmony_ci dma_map_single(dev, ctx->key_params.key, keylen, 76362306a36Sopenharmony_ci DMA_TO_DEVICE); 76462306a36Sopenharmony_ci if (dma_mapping_error(dev, ctx->key_params.key_dma_addr)) { 76562306a36Sopenharmony_ci dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n", 76662306a36Sopenharmony_ci ctx->key_params.key, keylen); 76762306a36Sopenharmony_ci kfree_sensitive(ctx->key_params.key); 76862306a36Sopenharmony_ci return -ENOMEM; 76962306a36Sopenharmony_ci } 77062306a36Sopenharmony_ci dev_dbg(dev, "mapping key-buffer: key_dma_addr=%pad keylen=%u\n", 77162306a36Sopenharmony_ci &ctx->key_params.key_dma_addr, ctx->key_params.keylen); 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci if (keylen > blocksize) { 77462306a36Sopenharmony_ci /* Load hash initial state */ 77562306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 77662306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 77762306a36Sopenharmony_ci set_din_sram(&desc[idx], larval_addr, 77862306a36Sopenharmony_ci ctx->inter_digestsize); 77962306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 78062306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 78162306a36Sopenharmony_ci idx++; 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci /* Load the hash current length*/ 78462306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 78562306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 78662306a36Sopenharmony_ci set_din_const(&desc[idx], 0, ctx->hash_len); 78762306a36Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); 78862306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 78962306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 79062306a36Sopenharmony_ci idx++; 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 79362306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 79462306a36Sopenharmony_ci ctx->key_params.key_dma_addr, keylen, 79562306a36Sopenharmony_ci NS_BIT); 79662306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_HASH); 79762306a36Sopenharmony_ci idx++; 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci /* Get hashed key */ 80062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 80162306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 80262306a36Sopenharmony_ci set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr, 80362306a36Sopenharmony_ci digestsize, NS_BIT, 0); 80462306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 80562306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 80662306a36Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED); 80762306a36Sopenharmony_ci cc_set_endianity(ctx->hash_mode, &desc[idx]); 80862306a36Sopenharmony_ci idx++; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 81162306a36Sopenharmony_ci set_din_const(&desc[idx], 0, (blocksize - digestsize)); 81262306a36Sopenharmony_ci set_flow_mode(&desc[idx], BYPASS); 81362306a36Sopenharmony_ci set_dout_dlli(&desc[idx], 81462306a36Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + 81562306a36Sopenharmony_ci digestsize), 81662306a36Sopenharmony_ci (blocksize - digestsize), NS_BIT, 0); 81762306a36Sopenharmony_ci idx++; 81862306a36Sopenharmony_ci } else { 81962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 82062306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 82162306a36Sopenharmony_ci ctx->key_params.key_dma_addr, keylen, 82262306a36Sopenharmony_ci NS_BIT); 82362306a36Sopenharmony_ci set_flow_mode(&desc[idx], BYPASS); 82462306a36Sopenharmony_ci set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr, 82562306a36Sopenharmony_ci keylen, NS_BIT, 0); 82662306a36Sopenharmony_ci idx++; 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci if ((blocksize - keylen)) { 82962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 83062306a36Sopenharmony_ci set_din_const(&desc[idx], 0, 83162306a36Sopenharmony_ci (blocksize - keylen)); 83262306a36Sopenharmony_ci set_flow_mode(&desc[idx], BYPASS); 83362306a36Sopenharmony_ci set_dout_dlli(&desc[idx], 83462306a36Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + 83562306a36Sopenharmony_ci keylen), (blocksize - keylen), 83662306a36Sopenharmony_ci NS_BIT, 0); 83762306a36Sopenharmony_ci idx++; 83862306a36Sopenharmony_ci } 83962306a36Sopenharmony_ci } 84062306a36Sopenharmony_ci } else { 84162306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 84262306a36Sopenharmony_ci set_din_const(&desc[idx], 0, blocksize); 84362306a36Sopenharmony_ci set_flow_mode(&desc[idx], BYPASS); 84462306a36Sopenharmony_ci set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr), 84562306a36Sopenharmony_ci blocksize, NS_BIT, 0); 84662306a36Sopenharmony_ci idx++; 84762306a36Sopenharmony_ci } 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, idx); 85062306a36Sopenharmony_ci if (rc) { 85162306a36Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 85262306a36Sopenharmony_ci goto out; 85362306a36Sopenharmony_ci } 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci /* calc derived HMAC key */ 85662306a36Sopenharmony_ci for (idx = 0, i = 0; i < 2; i++) { 85762306a36Sopenharmony_ci /* Load hash initial state */ 85862306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 85962306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 86062306a36Sopenharmony_ci set_din_sram(&desc[idx], larval_addr, ctx->inter_digestsize); 86162306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 86262306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 86362306a36Sopenharmony_ci idx++; 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci /* Load the hash current length*/ 86662306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 86762306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 86862306a36Sopenharmony_ci set_din_const(&desc[idx], 0, ctx->hash_len); 86962306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 87062306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 87162306a36Sopenharmony_ci idx++; 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci /* Prepare ipad key */ 87462306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 87562306a36Sopenharmony_ci set_xor_val(&desc[idx], hmac_pad_const[i]); 87662306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 87762306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 87862306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); 87962306a36Sopenharmony_ci idx++; 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci /* Perform HASH update */ 88262306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 88362306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, ctx->opad_tmp_keys_dma_addr, 88462306a36Sopenharmony_ci blocksize, NS_BIT); 88562306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 88662306a36Sopenharmony_ci set_xor_active(&desc[idx]); 88762306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_HASH); 88862306a36Sopenharmony_ci idx++; 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci /* Get the IPAD/OPAD xor key (Note, IPAD is the initial digest 89162306a36Sopenharmony_ci * of the first HASH "update" state) 89262306a36Sopenharmony_ci */ 89362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 89462306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 89562306a36Sopenharmony_ci if (i > 0) /* Not first iteration */ 89662306a36Sopenharmony_ci set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr, 89762306a36Sopenharmony_ci ctx->inter_digestsize, NS_BIT, 0); 89862306a36Sopenharmony_ci else /* First iteration */ 89962306a36Sopenharmony_ci set_dout_dlli(&desc[idx], ctx->digest_buff_dma_addr, 90062306a36Sopenharmony_ci ctx->inter_digestsize, NS_BIT, 0); 90162306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 90262306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 90362306a36Sopenharmony_ci idx++; 90462306a36Sopenharmony_ci } 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, idx); 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ciout: 90962306a36Sopenharmony_ci if (ctx->key_params.key_dma_addr) { 91062306a36Sopenharmony_ci dma_unmap_single(dev, ctx->key_params.key_dma_addr, 91162306a36Sopenharmony_ci ctx->key_params.keylen, DMA_TO_DEVICE); 91262306a36Sopenharmony_ci dev_dbg(dev, "Unmapped key-buffer: key_dma_addr=%pad keylen=%u\n", 91362306a36Sopenharmony_ci &ctx->key_params.key_dma_addr, ctx->key_params.keylen); 91462306a36Sopenharmony_ci } 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci kfree_sensitive(ctx->key_params.key); 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci return rc; 91962306a36Sopenharmony_ci} 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_cistatic int cc_xcbc_setkey(struct crypto_ahash *ahash, 92262306a36Sopenharmony_ci const u8 *key, unsigned int keylen) 92362306a36Sopenharmony_ci{ 92462306a36Sopenharmony_ci struct cc_crypto_req cc_req = {}; 92562306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash); 92662306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 92762306a36Sopenharmony_ci int rc = 0; 92862306a36Sopenharmony_ci unsigned int idx = 0; 92962306a36Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci dev_dbg(dev, "===== setkey (%d) ====\n", keylen); 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci switch (keylen) { 93462306a36Sopenharmony_ci case AES_KEYSIZE_128: 93562306a36Sopenharmony_ci case AES_KEYSIZE_192: 93662306a36Sopenharmony_ci case AES_KEYSIZE_256: 93762306a36Sopenharmony_ci break; 93862306a36Sopenharmony_ci default: 93962306a36Sopenharmony_ci return -EINVAL; 94062306a36Sopenharmony_ci } 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci ctx->key_params.keylen = keylen; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci ctx->key_params.key = kmemdup(key, keylen, GFP_KERNEL); 94562306a36Sopenharmony_ci if (!ctx->key_params.key) 94662306a36Sopenharmony_ci return -ENOMEM; 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci ctx->key_params.key_dma_addr = 94962306a36Sopenharmony_ci dma_map_single(dev, ctx->key_params.key, keylen, DMA_TO_DEVICE); 95062306a36Sopenharmony_ci if (dma_mapping_error(dev, ctx->key_params.key_dma_addr)) { 95162306a36Sopenharmony_ci dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n", 95262306a36Sopenharmony_ci key, keylen); 95362306a36Sopenharmony_ci kfree_sensitive(ctx->key_params.key); 95462306a36Sopenharmony_ci return -ENOMEM; 95562306a36Sopenharmony_ci } 95662306a36Sopenharmony_ci dev_dbg(dev, "mapping key-buffer: key_dma_addr=%pad keylen=%u\n", 95762306a36Sopenharmony_ci &ctx->key_params.key_dma_addr, ctx->key_params.keylen); 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci ctx->is_hmac = true; 96062306a36Sopenharmony_ci /* 1. Load the AES key */ 96162306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 96262306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, ctx->key_params.key_dma_addr, 96362306a36Sopenharmony_ci keylen, NS_BIT); 96462306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_ECB); 96562306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT); 96662306a36Sopenharmony_ci set_key_size_aes(&desc[idx], keylen); 96762306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 96862306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 96962306a36Sopenharmony_ci idx++; 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 97262306a36Sopenharmony_ci set_din_const(&desc[idx], 0x01010101, CC_AES_128_BIT_KEY_SIZE); 97362306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_AES_DOUT); 97462306a36Sopenharmony_ci set_dout_dlli(&desc[idx], 97562306a36Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K1_OFFSET), 97662306a36Sopenharmony_ci CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0); 97762306a36Sopenharmony_ci idx++; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 98062306a36Sopenharmony_ci set_din_const(&desc[idx], 0x02020202, CC_AES_128_BIT_KEY_SIZE); 98162306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_AES_DOUT); 98262306a36Sopenharmony_ci set_dout_dlli(&desc[idx], 98362306a36Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K2_OFFSET), 98462306a36Sopenharmony_ci CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0); 98562306a36Sopenharmony_ci idx++; 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 98862306a36Sopenharmony_ci set_din_const(&desc[idx], 0x03030303, CC_AES_128_BIT_KEY_SIZE); 98962306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_AES_DOUT); 99062306a36Sopenharmony_ci set_dout_dlli(&desc[idx], 99162306a36Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K3_OFFSET), 99262306a36Sopenharmony_ci CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0); 99362306a36Sopenharmony_ci idx++; 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, idx); 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci dma_unmap_single(dev, ctx->key_params.key_dma_addr, 99862306a36Sopenharmony_ci ctx->key_params.keylen, DMA_TO_DEVICE); 99962306a36Sopenharmony_ci dev_dbg(dev, "Unmapped key-buffer: key_dma_addr=%pad keylen=%u\n", 100062306a36Sopenharmony_ci &ctx->key_params.key_dma_addr, ctx->key_params.keylen); 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci kfree_sensitive(ctx->key_params.key); 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci return rc; 100562306a36Sopenharmony_ci} 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_cistatic int cc_cmac_setkey(struct crypto_ahash *ahash, 100862306a36Sopenharmony_ci const u8 *key, unsigned int keylen) 100962306a36Sopenharmony_ci{ 101062306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash); 101162306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci dev_dbg(dev, "===== setkey (%d) ====\n", keylen); 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci ctx->is_hmac = true; 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci switch (keylen) { 101862306a36Sopenharmony_ci case AES_KEYSIZE_128: 101962306a36Sopenharmony_ci case AES_KEYSIZE_192: 102062306a36Sopenharmony_ci case AES_KEYSIZE_256: 102162306a36Sopenharmony_ci break; 102262306a36Sopenharmony_ci default: 102362306a36Sopenharmony_ci return -EINVAL; 102462306a36Sopenharmony_ci } 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci ctx->key_params.keylen = keylen; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci /* STAT_PHASE_1: Copy key to ctx */ 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci dma_sync_single_for_cpu(dev, ctx->opad_tmp_keys_dma_addr, 103162306a36Sopenharmony_ci keylen, DMA_TO_DEVICE); 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci memcpy(ctx->opad_tmp_keys_buff, key, keylen); 103462306a36Sopenharmony_ci if (keylen == 24) { 103562306a36Sopenharmony_ci memset(ctx->opad_tmp_keys_buff + 24, 0, 103662306a36Sopenharmony_ci CC_AES_KEY_SIZE_MAX - 24); 103762306a36Sopenharmony_ci } 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci dma_sync_single_for_device(dev, ctx->opad_tmp_keys_dma_addr, 104062306a36Sopenharmony_ci keylen, DMA_TO_DEVICE); 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci ctx->key_params.keylen = keylen; 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci return 0; 104562306a36Sopenharmony_ci} 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_cistatic void cc_free_ctx(struct cc_hash_ctx *ctx) 104862306a36Sopenharmony_ci{ 104962306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci if (ctx->digest_buff_dma_addr) { 105262306a36Sopenharmony_ci dma_unmap_single(dev, ctx->digest_buff_dma_addr, 105362306a36Sopenharmony_ci sizeof(ctx->digest_buff), DMA_BIDIRECTIONAL); 105462306a36Sopenharmony_ci dev_dbg(dev, "Unmapped digest-buffer: digest_buff_dma_addr=%pad\n", 105562306a36Sopenharmony_ci &ctx->digest_buff_dma_addr); 105662306a36Sopenharmony_ci ctx->digest_buff_dma_addr = 0; 105762306a36Sopenharmony_ci } 105862306a36Sopenharmony_ci if (ctx->opad_tmp_keys_dma_addr) { 105962306a36Sopenharmony_ci dma_unmap_single(dev, ctx->opad_tmp_keys_dma_addr, 106062306a36Sopenharmony_ci sizeof(ctx->opad_tmp_keys_buff), 106162306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 106262306a36Sopenharmony_ci dev_dbg(dev, "Unmapped opad-digest: opad_tmp_keys_dma_addr=%pad\n", 106362306a36Sopenharmony_ci &ctx->opad_tmp_keys_dma_addr); 106462306a36Sopenharmony_ci ctx->opad_tmp_keys_dma_addr = 0; 106562306a36Sopenharmony_ci } 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci ctx->key_params.keylen = 0; 106862306a36Sopenharmony_ci} 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_cistatic int cc_alloc_ctx(struct cc_hash_ctx *ctx) 107162306a36Sopenharmony_ci{ 107262306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci ctx->key_params.keylen = 0; 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci ctx->digest_buff_dma_addr = 107762306a36Sopenharmony_ci dma_map_single(dev, ctx->digest_buff, sizeof(ctx->digest_buff), 107862306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 107962306a36Sopenharmony_ci if (dma_mapping_error(dev, ctx->digest_buff_dma_addr)) { 108062306a36Sopenharmony_ci dev_err(dev, "Mapping digest len %zu B at va=%pK for DMA failed\n", 108162306a36Sopenharmony_ci sizeof(ctx->digest_buff), ctx->digest_buff); 108262306a36Sopenharmony_ci goto fail; 108362306a36Sopenharmony_ci } 108462306a36Sopenharmony_ci dev_dbg(dev, "Mapped digest %zu B at va=%pK to dma=%pad\n", 108562306a36Sopenharmony_ci sizeof(ctx->digest_buff), ctx->digest_buff, 108662306a36Sopenharmony_ci &ctx->digest_buff_dma_addr); 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci ctx->opad_tmp_keys_dma_addr = 108962306a36Sopenharmony_ci dma_map_single(dev, ctx->opad_tmp_keys_buff, 109062306a36Sopenharmony_ci sizeof(ctx->opad_tmp_keys_buff), 109162306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 109262306a36Sopenharmony_ci if (dma_mapping_error(dev, ctx->opad_tmp_keys_dma_addr)) { 109362306a36Sopenharmony_ci dev_err(dev, "Mapping opad digest %zu B at va=%pK for DMA failed\n", 109462306a36Sopenharmony_ci sizeof(ctx->opad_tmp_keys_buff), 109562306a36Sopenharmony_ci ctx->opad_tmp_keys_buff); 109662306a36Sopenharmony_ci goto fail; 109762306a36Sopenharmony_ci } 109862306a36Sopenharmony_ci dev_dbg(dev, "Mapped opad_tmp_keys %zu B at va=%pK to dma=%pad\n", 109962306a36Sopenharmony_ci sizeof(ctx->opad_tmp_keys_buff), ctx->opad_tmp_keys_buff, 110062306a36Sopenharmony_ci &ctx->opad_tmp_keys_dma_addr); 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci ctx->is_hmac = false; 110362306a36Sopenharmony_ci return 0; 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_cifail: 110662306a36Sopenharmony_ci cc_free_ctx(ctx); 110762306a36Sopenharmony_ci return -ENOMEM; 110862306a36Sopenharmony_ci} 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_cistatic int cc_get_hash_len(struct crypto_tfm *tfm) 111162306a36Sopenharmony_ci{ 111262306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_tfm_ctx_dma(tfm); 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci if (ctx->hash_mode == DRV_HASH_SM3) 111562306a36Sopenharmony_ci return CC_SM3_HASH_LEN_SIZE; 111662306a36Sopenharmony_ci else 111762306a36Sopenharmony_ci return cc_get_default_hash_len(ctx->drvdata); 111862306a36Sopenharmony_ci} 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_cistatic int cc_cra_init(struct crypto_tfm *tfm) 112162306a36Sopenharmony_ci{ 112262306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_tfm_ctx_dma(tfm); 112362306a36Sopenharmony_ci struct hash_alg_common *hash_alg_common = 112462306a36Sopenharmony_ci container_of(tfm->__crt_alg, struct hash_alg_common, base); 112562306a36Sopenharmony_ci struct ahash_alg *ahash_alg = 112662306a36Sopenharmony_ci container_of(hash_alg_common, struct ahash_alg, halg); 112762306a36Sopenharmony_ci struct cc_hash_alg *cc_alg = 112862306a36Sopenharmony_ci container_of(ahash_alg, struct cc_hash_alg, ahash_alg); 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_ci crypto_ahash_set_reqsize_dma(__crypto_ahash_cast(tfm), 113162306a36Sopenharmony_ci sizeof(struct ahash_req_ctx)); 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci ctx->hash_mode = cc_alg->hash_mode; 113462306a36Sopenharmony_ci ctx->hw_mode = cc_alg->hw_mode; 113562306a36Sopenharmony_ci ctx->inter_digestsize = cc_alg->inter_digestsize; 113662306a36Sopenharmony_ci ctx->drvdata = cc_alg->drvdata; 113762306a36Sopenharmony_ci ctx->hash_len = cc_get_hash_len(tfm); 113862306a36Sopenharmony_ci return cc_alloc_ctx(ctx); 113962306a36Sopenharmony_ci} 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_cistatic void cc_cra_exit(struct crypto_tfm *tfm) 114262306a36Sopenharmony_ci{ 114362306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_tfm_ctx_dma(tfm); 114462306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci dev_dbg(dev, "cc_cra_exit"); 114762306a36Sopenharmony_ci cc_free_ctx(ctx); 114862306a36Sopenharmony_ci} 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_cistatic int cc_mac_update(struct ahash_request *req) 115162306a36Sopenharmony_ci{ 115262306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(req); 115362306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 115462306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm); 115562306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 115662306a36Sopenharmony_ci unsigned int block_size = crypto_tfm_alg_blocksize(&tfm->base); 115762306a36Sopenharmony_ci struct cc_crypto_req cc_req = {}; 115862306a36Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 115962306a36Sopenharmony_ci int rc; 116062306a36Sopenharmony_ci u32 idx = 0; 116162306a36Sopenharmony_ci gfp_t flags = cc_gfp_flags(&req->base); 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_ci if (req->nbytes == 0) { 116462306a36Sopenharmony_ci /* no real updates required */ 116562306a36Sopenharmony_ci return 0; 116662306a36Sopenharmony_ci } 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci state->xcbc_count++; 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci rc = cc_map_hash_request_update(ctx->drvdata, state, req->src, 117162306a36Sopenharmony_ci req->nbytes, block_size, flags); 117262306a36Sopenharmony_ci if (rc) { 117362306a36Sopenharmony_ci if (rc == 1) { 117462306a36Sopenharmony_ci dev_dbg(dev, " data size not require HW update %x\n", 117562306a36Sopenharmony_ci req->nbytes); 117662306a36Sopenharmony_ci /* No hardware updates are required */ 117762306a36Sopenharmony_ci return 0; 117862306a36Sopenharmony_ci } 117962306a36Sopenharmony_ci dev_err(dev, "map_ahash_request_update() failed\n"); 118062306a36Sopenharmony_ci return -ENOMEM; 118162306a36Sopenharmony_ci } 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci if (cc_map_req(dev, state, ctx)) { 118462306a36Sopenharmony_ci dev_err(dev, "map_ahash_source() failed\n"); 118562306a36Sopenharmony_ci return -EINVAL; 118662306a36Sopenharmony_ci } 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_ci if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) 118962306a36Sopenharmony_ci cc_setup_xcbc(req, desc, &idx); 119062306a36Sopenharmony_ci else 119162306a36Sopenharmony_ci cc_setup_cmac(req, desc, &idx); 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_ci cc_set_desc(state, ctx, DIN_AES_DOUT, desc, true, &idx); 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci /* store the hash digest result in context */ 119662306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 119762306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 119862306a36Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_buff_dma_addr, 119962306a36Sopenharmony_ci ctx->inter_digestsize, NS_BIT, 1); 120062306a36Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 120162306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_AES_to_DOUT); 120262306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 120362306a36Sopenharmony_ci idx++; 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci /* Setup request structure */ 120662306a36Sopenharmony_ci cc_req.user_cb = cc_update_complete; 120762306a36Sopenharmony_ci cc_req.user_arg = req; 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base); 121062306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 121162306a36Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 121262306a36Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, true); 121362306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 121462306a36Sopenharmony_ci } 121562306a36Sopenharmony_ci return rc; 121662306a36Sopenharmony_ci} 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_cistatic int cc_mac_final(struct ahash_request *req) 121962306a36Sopenharmony_ci{ 122062306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(req); 122162306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 122262306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm); 122362306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 122462306a36Sopenharmony_ci struct cc_crypto_req cc_req = {}; 122562306a36Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 122662306a36Sopenharmony_ci int idx = 0; 122762306a36Sopenharmony_ci int rc = 0; 122862306a36Sopenharmony_ci u32 key_size, key_len; 122962306a36Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 123062306a36Sopenharmony_ci gfp_t flags = cc_gfp_flags(&req->base); 123162306a36Sopenharmony_ci u32 rem_cnt = *cc_hash_buf_cnt(state); 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) { 123462306a36Sopenharmony_ci key_size = CC_AES_128_BIT_KEY_SIZE; 123562306a36Sopenharmony_ci key_len = CC_AES_128_BIT_KEY_SIZE; 123662306a36Sopenharmony_ci } else { 123762306a36Sopenharmony_ci key_size = (ctx->key_params.keylen == 24) ? AES_MAX_KEY_SIZE : 123862306a36Sopenharmony_ci ctx->key_params.keylen; 123962306a36Sopenharmony_ci key_len = ctx->key_params.keylen; 124062306a36Sopenharmony_ci } 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci dev_dbg(dev, "===== final xcbc reminder (%d) ====\n", rem_cnt); 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci if (cc_map_req(dev, state, ctx)) { 124562306a36Sopenharmony_ci dev_err(dev, "map_ahash_source() failed\n"); 124662306a36Sopenharmony_ci return -EINVAL; 124762306a36Sopenharmony_ci } 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_ci if (cc_map_hash_request_final(ctx->drvdata, state, req->src, 125062306a36Sopenharmony_ci req->nbytes, 0, flags)) { 125162306a36Sopenharmony_ci dev_err(dev, "map_ahash_request_final() failed\n"); 125262306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 125362306a36Sopenharmony_ci return -ENOMEM; 125462306a36Sopenharmony_ci } 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci if (cc_map_result(dev, state, digestsize)) { 125762306a36Sopenharmony_ci dev_err(dev, "map_ahash_digest() failed\n"); 125862306a36Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, true); 125962306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 126062306a36Sopenharmony_ci return -ENOMEM; 126162306a36Sopenharmony_ci } 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci /* Setup request structure */ 126462306a36Sopenharmony_ci cc_req.user_cb = cc_hash_complete; 126562306a36Sopenharmony_ci cc_req.user_arg = req; 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci if (state->xcbc_count && rem_cnt == 0) { 126862306a36Sopenharmony_ci /* Load key for ECB decryption */ 126962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 127062306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_ECB); 127162306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_DECRYPT); 127262306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 127362306a36Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K1_OFFSET), 127462306a36Sopenharmony_ci key_size, NS_BIT); 127562306a36Sopenharmony_ci set_key_size_aes(&desc[idx], key_len); 127662306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 127762306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 127862306a36Sopenharmony_ci idx++; 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci /* Initiate decryption of block state to previous 128162306a36Sopenharmony_ci * block_state-XOR-M[n] 128262306a36Sopenharmony_ci */ 128362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 128462306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, 128562306a36Sopenharmony_ci CC_AES_BLOCK_SIZE, NS_BIT); 128662306a36Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_buff_dma_addr, 128762306a36Sopenharmony_ci CC_AES_BLOCK_SIZE, NS_BIT, 0); 128862306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_AES_DOUT); 128962306a36Sopenharmony_ci idx++; 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci /* Memory Barrier: wait for axi write to complete */ 129262306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 129362306a36Sopenharmony_ci set_din_no_dma(&desc[idx], 0, 0xfffff0); 129462306a36Sopenharmony_ci set_dout_no_dma(&desc[idx], 0, 0, 1); 129562306a36Sopenharmony_ci idx++; 129662306a36Sopenharmony_ci } 129762306a36Sopenharmony_ci 129862306a36Sopenharmony_ci if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) 129962306a36Sopenharmony_ci cc_setup_xcbc(req, desc, &idx); 130062306a36Sopenharmony_ci else 130162306a36Sopenharmony_ci cc_setup_cmac(req, desc, &idx); 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci if (state->xcbc_count == 0) { 130462306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 130562306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 130662306a36Sopenharmony_ci set_key_size_aes(&desc[idx], key_len); 130762306a36Sopenharmony_ci set_cmac_size0_mode(&desc[idx]); 130862306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 130962306a36Sopenharmony_ci idx++; 131062306a36Sopenharmony_ci } else if (rem_cnt > 0) { 131162306a36Sopenharmony_ci cc_set_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx); 131262306a36Sopenharmony_ci } else { 131362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 131462306a36Sopenharmony_ci set_din_const(&desc[idx], 0x00, CC_AES_BLOCK_SIZE); 131562306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_AES_DOUT); 131662306a36Sopenharmony_ci idx++; 131762306a36Sopenharmony_ci } 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci /* Get final MAC result */ 132062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 132162306a36Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_result_dma_addr, 132262306a36Sopenharmony_ci digestsize, NS_BIT, 1); 132362306a36Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 132462306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_AES_to_DOUT); 132562306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 132662306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 132762306a36Sopenharmony_ci idx++; 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base); 133062306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 133162306a36Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 133262306a36Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, true); 133362306a36Sopenharmony_ci cc_unmap_result(dev, state, digestsize, req->result); 133462306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 133562306a36Sopenharmony_ci } 133662306a36Sopenharmony_ci return rc; 133762306a36Sopenharmony_ci} 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_cistatic int cc_mac_finup(struct ahash_request *req) 134062306a36Sopenharmony_ci{ 134162306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(req); 134262306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 134362306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm); 134462306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 134562306a36Sopenharmony_ci struct cc_crypto_req cc_req = {}; 134662306a36Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 134762306a36Sopenharmony_ci int idx = 0; 134862306a36Sopenharmony_ci int rc = 0; 134962306a36Sopenharmony_ci u32 key_len = 0; 135062306a36Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 135162306a36Sopenharmony_ci gfp_t flags = cc_gfp_flags(&req->base); 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci dev_dbg(dev, "===== finup xcbc(%d) ====\n", req->nbytes); 135462306a36Sopenharmony_ci if (state->xcbc_count > 0 && req->nbytes == 0) { 135562306a36Sopenharmony_ci dev_dbg(dev, "No data to update. Call to fdx_mac_final\n"); 135662306a36Sopenharmony_ci return cc_mac_final(req); 135762306a36Sopenharmony_ci } 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci if (cc_map_req(dev, state, ctx)) { 136062306a36Sopenharmony_ci dev_err(dev, "map_ahash_source() failed\n"); 136162306a36Sopenharmony_ci return -EINVAL; 136262306a36Sopenharmony_ci } 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci if (cc_map_hash_request_final(ctx->drvdata, state, req->src, 136562306a36Sopenharmony_ci req->nbytes, 1, flags)) { 136662306a36Sopenharmony_ci dev_err(dev, "map_ahash_request_final() failed\n"); 136762306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 136862306a36Sopenharmony_ci return -ENOMEM; 136962306a36Sopenharmony_ci } 137062306a36Sopenharmony_ci if (cc_map_result(dev, state, digestsize)) { 137162306a36Sopenharmony_ci dev_err(dev, "map_ahash_digest() failed\n"); 137262306a36Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, true); 137362306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 137462306a36Sopenharmony_ci return -ENOMEM; 137562306a36Sopenharmony_ci } 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci /* Setup request structure */ 137862306a36Sopenharmony_ci cc_req.user_cb = cc_hash_complete; 137962306a36Sopenharmony_ci cc_req.user_arg = req; 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) { 138262306a36Sopenharmony_ci key_len = CC_AES_128_BIT_KEY_SIZE; 138362306a36Sopenharmony_ci cc_setup_xcbc(req, desc, &idx); 138462306a36Sopenharmony_ci } else { 138562306a36Sopenharmony_ci key_len = ctx->key_params.keylen; 138662306a36Sopenharmony_ci cc_setup_cmac(req, desc, &idx); 138762306a36Sopenharmony_ci } 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci if (req->nbytes == 0) { 139062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 139162306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 139262306a36Sopenharmony_ci set_key_size_aes(&desc[idx], key_len); 139362306a36Sopenharmony_ci set_cmac_size0_mode(&desc[idx]); 139462306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 139562306a36Sopenharmony_ci idx++; 139662306a36Sopenharmony_ci } else { 139762306a36Sopenharmony_ci cc_set_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx); 139862306a36Sopenharmony_ci } 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ci /* Get final MAC result */ 140162306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 140262306a36Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_result_dma_addr, 140362306a36Sopenharmony_ci digestsize, NS_BIT, 1); 140462306a36Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 140562306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_AES_to_DOUT); 140662306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 140762306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 140862306a36Sopenharmony_ci idx++; 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base); 141162306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 141262306a36Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 141362306a36Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, true); 141462306a36Sopenharmony_ci cc_unmap_result(dev, state, digestsize, req->result); 141562306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 141662306a36Sopenharmony_ci } 141762306a36Sopenharmony_ci return rc; 141862306a36Sopenharmony_ci} 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_cistatic int cc_mac_digest(struct ahash_request *req) 142162306a36Sopenharmony_ci{ 142262306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(req); 142362306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 142462306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm); 142562306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 142662306a36Sopenharmony_ci u32 digestsize = crypto_ahash_digestsize(tfm); 142762306a36Sopenharmony_ci struct cc_crypto_req cc_req = {}; 142862306a36Sopenharmony_ci struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN]; 142962306a36Sopenharmony_ci u32 key_len; 143062306a36Sopenharmony_ci unsigned int idx = 0; 143162306a36Sopenharmony_ci int rc; 143262306a36Sopenharmony_ci gfp_t flags = cc_gfp_flags(&req->base); 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci dev_dbg(dev, "===== -digest mac (%d) ====\n", req->nbytes); 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci cc_init_req(dev, state, ctx); 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_ci if (cc_map_req(dev, state, ctx)) { 143962306a36Sopenharmony_ci dev_err(dev, "map_ahash_source() failed\n"); 144062306a36Sopenharmony_ci return -ENOMEM; 144162306a36Sopenharmony_ci } 144262306a36Sopenharmony_ci if (cc_map_result(dev, state, digestsize)) { 144362306a36Sopenharmony_ci dev_err(dev, "map_ahash_digest() failed\n"); 144462306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 144562306a36Sopenharmony_ci return -ENOMEM; 144662306a36Sopenharmony_ci } 144762306a36Sopenharmony_ci 144862306a36Sopenharmony_ci if (cc_map_hash_request_final(ctx->drvdata, state, req->src, 144962306a36Sopenharmony_ci req->nbytes, 1, flags)) { 145062306a36Sopenharmony_ci dev_err(dev, "map_ahash_request_final() failed\n"); 145162306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 145262306a36Sopenharmony_ci return -ENOMEM; 145362306a36Sopenharmony_ci } 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci /* Setup request structure */ 145662306a36Sopenharmony_ci cc_req.user_cb = cc_digest_complete; 145762306a36Sopenharmony_ci cc_req.user_arg = req; 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) { 146062306a36Sopenharmony_ci key_len = CC_AES_128_BIT_KEY_SIZE; 146162306a36Sopenharmony_ci cc_setup_xcbc(req, desc, &idx); 146262306a36Sopenharmony_ci } else { 146362306a36Sopenharmony_ci key_len = ctx->key_params.keylen; 146462306a36Sopenharmony_ci cc_setup_cmac(req, desc, &idx); 146562306a36Sopenharmony_ci } 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ci if (req->nbytes == 0) { 146862306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 146962306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 147062306a36Sopenharmony_ci set_key_size_aes(&desc[idx], key_len); 147162306a36Sopenharmony_ci set_cmac_size0_mode(&desc[idx]); 147262306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 147362306a36Sopenharmony_ci idx++; 147462306a36Sopenharmony_ci } else { 147562306a36Sopenharmony_ci cc_set_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx); 147662306a36Sopenharmony_ci } 147762306a36Sopenharmony_ci 147862306a36Sopenharmony_ci /* Get final MAC result */ 147962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 148062306a36Sopenharmony_ci set_dout_dlli(&desc[idx], state->digest_result_dma_addr, 148162306a36Sopenharmony_ci CC_AES_BLOCK_SIZE, NS_BIT, 1); 148262306a36Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 148362306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_AES_to_DOUT); 148462306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 148562306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 148662306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->hw_mode); 148762306a36Sopenharmony_ci idx++; 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_ci rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base); 149062306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 149162306a36Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 149262306a36Sopenharmony_ci cc_unmap_hash_request(dev, state, req->src, true); 149362306a36Sopenharmony_ci cc_unmap_result(dev, state, digestsize, req->result); 149462306a36Sopenharmony_ci cc_unmap_req(dev, state, ctx); 149562306a36Sopenharmony_ci } 149662306a36Sopenharmony_ci return rc; 149762306a36Sopenharmony_ci} 149862306a36Sopenharmony_ci 149962306a36Sopenharmony_cistatic int cc_hash_export(struct ahash_request *req, void *out) 150062306a36Sopenharmony_ci{ 150162306a36Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 150262306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash); 150362306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(req); 150462306a36Sopenharmony_ci u8 *curr_buff = cc_hash_buf(state); 150562306a36Sopenharmony_ci u32 curr_buff_cnt = *cc_hash_buf_cnt(state); 150662306a36Sopenharmony_ci const u32 tmp = CC_EXPORT_MAGIC; 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci memcpy(out, &tmp, sizeof(u32)); 150962306a36Sopenharmony_ci out += sizeof(u32); 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci memcpy(out, state->digest_buff, ctx->inter_digestsize); 151262306a36Sopenharmony_ci out += ctx->inter_digestsize; 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_ci memcpy(out, state->digest_bytes_len, ctx->hash_len); 151562306a36Sopenharmony_ci out += ctx->hash_len; 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci memcpy(out, &curr_buff_cnt, sizeof(u32)); 151862306a36Sopenharmony_ci out += sizeof(u32); 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_ci memcpy(out, curr_buff, curr_buff_cnt); 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci return 0; 152362306a36Sopenharmony_ci} 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_cistatic int cc_hash_import(struct ahash_request *req, const void *in) 152662306a36Sopenharmony_ci{ 152762306a36Sopenharmony_ci struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); 152862306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash); 152962306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 153062306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(req); 153162306a36Sopenharmony_ci u32 tmp; 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_ci memcpy(&tmp, in, sizeof(u32)); 153462306a36Sopenharmony_ci if (tmp != CC_EXPORT_MAGIC) 153562306a36Sopenharmony_ci return -EINVAL; 153662306a36Sopenharmony_ci in += sizeof(u32); 153762306a36Sopenharmony_ci 153862306a36Sopenharmony_ci cc_init_req(dev, state, ctx); 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci memcpy(state->digest_buff, in, ctx->inter_digestsize); 154162306a36Sopenharmony_ci in += ctx->inter_digestsize; 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci memcpy(state->digest_bytes_len, in, ctx->hash_len); 154462306a36Sopenharmony_ci in += ctx->hash_len; 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci /* Sanity check the data as much as possible */ 154762306a36Sopenharmony_ci memcpy(&tmp, in, sizeof(u32)); 154862306a36Sopenharmony_ci if (tmp > CC_MAX_HASH_BLCK_SIZE) 154962306a36Sopenharmony_ci return -EINVAL; 155062306a36Sopenharmony_ci in += sizeof(u32); 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci state->buf_cnt[0] = tmp; 155362306a36Sopenharmony_ci memcpy(state->buffers[0], in, tmp); 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci return 0; 155662306a36Sopenharmony_ci} 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_cistruct cc_hash_template { 155962306a36Sopenharmony_ci char name[CRYPTO_MAX_ALG_NAME]; 156062306a36Sopenharmony_ci char driver_name[CRYPTO_MAX_ALG_NAME]; 156162306a36Sopenharmony_ci char mac_name[CRYPTO_MAX_ALG_NAME]; 156262306a36Sopenharmony_ci char mac_driver_name[CRYPTO_MAX_ALG_NAME]; 156362306a36Sopenharmony_ci unsigned int blocksize; 156462306a36Sopenharmony_ci bool is_mac; 156562306a36Sopenharmony_ci bool synchronize; 156662306a36Sopenharmony_ci struct ahash_alg template_ahash; 156762306a36Sopenharmony_ci int hash_mode; 156862306a36Sopenharmony_ci int hw_mode; 156962306a36Sopenharmony_ci int inter_digestsize; 157062306a36Sopenharmony_ci struct cc_drvdata *drvdata; 157162306a36Sopenharmony_ci u32 min_hw_rev; 157262306a36Sopenharmony_ci enum cc_std_body std_body; 157362306a36Sopenharmony_ci}; 157462306a36Sopenharmony_ci 157562306a36Sopenharmony_ci#define CC_STATE_SIZE(_x) \ 157662306a36Sopenharmony_ci ((_x) + HASH_MAX_LEN_SIZE + CC_MAX_HASH_BLCK_SIZE + (2 * sizeof(u32))) 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_ci/* hash descriptors */ 157962306a36Sopenharmony_cistatic struct cc_hash_template driver_hash[] = { 158062306a36Sopenharmony_ci //Asynchronize hash template 158162306a36Sopenharmony_ci { 158262306a36Sopenharmony_ci .name = "sha1", 158362306a36Sopenharmony_ci .driver_name = "sha1-ccree", 158462306a36Sopenharmony_ci .mac_name = "hmac(sha1)", 158562306a36Sopenharmony_ci .mac_driver_name = "hmac-sha1-ccree", 158662306a36Sopenharmony_ci .blocksize = SHA1_BLOCK_SIZE, 158762306a36Sopenharmony_ci .is_mac = true, 158862306a36Sopenharmony_ci .synchronize = false, 158962306a36Sopenharmony_ci .template_ahash = { 159062306a36Sopenharmony_ci .init = cc_hash_init, 159162306a36Sopenharmony_ci .update = cc_hash_update, 159262306a36Sopenharmony_ci .final = cc_hash_final, 159362306a36Sopenharmony_ci .finup = cc_hash_finup, 159462306a36Sopenharmony_ci .digest = cc_hash_digest, 159562306a36Sopenharmony_ci .export = cc_hash_export, 159662306a36Sopenharmony_ci .import = cc_hash_import, 159762306a36Sopenharmony_ci .setkey = cc_hash_setkey, 159862306a36Sopenharmony_ci .halg = { 159962306a36Sopenharmony_ci .digestsize = SHA1_DIGEST_SIZE, 160062306a36Sopenharmony_ci .statesize = CC_STATE_SIZE(SHA1_DIGEST_SIZE), 160162306a36Sopenharmony_ci }, 160262306a36Sopenharmony_ci }, 160362306a36Sopenharmony_ci .hash_mode = DRV_HASH_SHA1, 160462306a36Sopenharmony_ci .hw_mode = DRV_HASH_HW_SHA1, 160562306a36Sopenharmony_ci .inter_digestsize = SHA1_DIGEST_SIZE, 160662306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 160762306a36Sopenharmony_ci .std_body = CC_STD_NIST, 160862306a36Sopenharmony_ci }, 160962306a36Sopenharmony_ci { 161062306a36Sopenharmony_ci .name = "sha256", 161162306a36Sopenharmony_ci .driver_name = "sha256-ccree", 161262306a36Sopenharmony_ci .mac_name = "hmac(sha256)", 161362306a36Sopenharmony_ci .mac_driver_name = "hmac-sha256-ccree", 161462306a36Sopenharmony_ci .blocksize = SHA256_BLOCK_SIZE, 161562306a36Sopenharmony_ci .is_mac = true, 161662306a36Sopenharmony_ci .template_ahash = { 161762306a36Sopenharmony_ci .init = cc_hash_init, 161862306a36Sopenharmony_ci .update = cc_hash_update, 161962306a36Sopenharmony_ci .final = cc_hash_final, 162062306a36Sopenharmony_ci .finup = cc_hash_finup, 162162306a36Sopenharmony_ci .digest = cc_hash_digest, 162262306a36Sopenharmony_ci .export = cc_hash_export, 162362306a36Sopenharmony_ci .import = cc_hash_import, 162462306a36Sopenharmony_ci .setkey = cc_hash_setkey, 162562306a36Sopenharmony_ci .halg = { 162662306a36Sopenharmony_ci .digestsize = SHA256_DIGEST_SIZE, 162762306a36Sopenharmony_ci .statesize = CC_STATE_SIZE(SHA256_DIGEST_SIZE) 162862306a36Sopenharmony_ci }, 162962306a36Sopenharmony_ci }, 163062306a36Sopenharmony_ci .hash_mode = DRV_HASH_SHA256, 163162306a36Sopenharmony_ci .hw_mode = DRV_HASH_HW_SHA256, 163262306a36Sopenharmony_ci .inter_digestsize = SHA256_DIGEST_SIZE, 163362306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 163462306a36Sopenharmony_ci .std_body = CC_STD_NIST, 163562306a36Sopenharmony_ci }, 163662306a36Sopenharmony_ci { 163762306a36Sopenharmony_ci .name = "sha224", 163862306a36Sopenharmony_ci .driver_name = "sha224-ccree", 163962306a36Sopenharmony_ci .mac_name = "hmac(sha224)", 164062306a36Sopenharmony_ci .mac_driver_name = "hmac-sha224-ccree", 164162306a36Sopenharmony_ci .blocksize = SHA224_BLOCK_SIZE, 164262306a36Sopenharmony_ci .is_mac = true, 164362306a36Sopenharmony_ci .template_ahash = { 164462306a36Sopenharmony_ci .init = cc_hash_init, 164562306a36Sopenharmony_ci .update = cc_hash_update, 164662306a36Sopenharmony_ci .final = cc_hash_final, 164762306a36Sopenharmony_ci .finup = cc_hash_finup, 164862306a36Sopenharmony_ci .digest = cc_hash_digest, 164962306a36Sopenharmony_ci .export = cc_hash_export, 165062306a36Sopenharmony_ci .import = cc_hash_import, 165162306a36Sopenharmony_ci .setkey = cc_hash_setkey, 165262306a36Sopenharmony_ci .halg = { 165362306a36Sopenharmony_ci .digestsize = SHA224_DIGEST_SIZE, 165462306a36Sopenharmony_ci .statesize = CC_STATE_SIZE(SHA256_DIGEST_SIZE), 165562306a36Sopenharmony_ci }, 165662306a36Sopenharmony_ci }, 165762306a36Sopenharmony_ci .hash_mode = DRV_HASH_SHA224, 165862306a36Sopenharmony_ci .hw_mode = DRV_HASH_HW_SHA256, 165962306a36Sopenharmony_ci .inter_digestsize = SHA256_DIGEST_SIZE, 166062306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 166162306a36Sopenharmony_ci .std_body = CC_STD_NIST, 166262306a36Sopenharmony_ci }, 166362306a36Sopenharmony_ci { 166462306a36Sopenharmony_ci .name = "sha384", 166562306a36Sopenharmony_ci .driver_name = "sha384-ccree", 166662306a36Sopenharmony_ci .mac_name = "hmac(sha384)", 166762306a36Sopenharmony_ci .mac_driver_name = "hmac-sha384-ccree", 166862306a36Sopenharmony_ci .blocksize = SHA384_BLOCK_SIZE, 166962306a36Sopenharmony_ci .is_mac = true, 167062306a36Sopenharmony_ci .template_ahash = { 167162306a36Sopenharmony_ci .init = cc_hash_init, 167262306a36Sopenharmony_ci .update = cc_hash_update, 167362306a36Sopenharmony_ci .final = cc_hash_final, 167462306a36Sopenharmony_ci .finup = cc_hash_finup, 167562306a36Sopenharmony_ci .digest = cc_hash_digest, 167662306a36Sopenharmony_ci .export = cc_hash_export, 167762306a36Sopenharmony_ci .import = cc_hash_import, 167862306a36Sopenharmony_ci .setkey = cc_hash_setkey, 167962306a36Sopenharmony_ci .halg = { 168062306a36Sopenharmony_ci .digestsize = SHA384_DIGEST_SIZE, 168162306a36Sopenharmony_ci .statesize = CC_STATE_SIZE(SHA512_DIGEST_SIZE), 168262306a36Sopenharmony_ci }, 168362306a36Sopenharmony_ci }, 168462306a36Sopenharmony_ci .hash_mode = DRV_HASH_SHA384, 168562306a36Sopenharmony_ci .hw_mode = DRV_HASH_HW_SHA512, 168662306a36Sopenharmony_ci .inter_digestsize = SHA512_DIGEST_SIZE, 168762306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_712, 168862306a36Sopenharmony_ci .std_body = CC_STD_NIST, 168962306a36Sopenharmony_ci }, 169062306a36Sopenharmony_ci { 169162306a36Sopenharmony_ci .name = "sha512", 169262306a36Sopenharmony_ci .driver_name = "sha512-ccree", 169362306a36Sopenharmony_ci .mac_name = "hmac(sha512)", 169462306a36Sopenharmony_ci .mac_driver_name = "hmac-sha512-ccree", 169562306a36Sopenharmony_ci .blocksize = SHA512_BLOCK_SIZE, 169662306a36Sopenharmony_ci .is_mac = true, 169762306a36Sopenharmony_ci .template_ahash = { 169862306a36Sopenharmony_ci .init = cc_hash_init, 169962306a36Sopenharmony_ci .update = cc_hash_update, 170062306a36Sopenharmony_ci .final = cc_hash_final, 170162306a36Sopenharmony_ci .finup = cc_hash_finup, 170262306a36Sopenharmony_ci .digest = cc_hash_digest, 170362306a36Sopenharmony_ci .export = cc_hash_export, 170462306a36Sopenharmony_ci .import = cc_hash_import, 170562306a36Sopenharmony_ci .setkey = cc_hash_setkey, 170662306a36Sopenharmony_ci .halg = { 170762306a36Sopenharmony_ci .digestsize = SHA512_DIGEST_SIZE, 170862306a36Sopenharmony_ci .statesize = CC_STATE_SIZE(SHA512_DIGEST_SIZE), 170962306a36Sopenharmony_ci }, 171062306a36Sopenharmony_ci }, 171162306a36Sopenharmony_ci .hash_mode = DRV_HASH_SHA512, 171262306a36Sopenharmony_ci .hw_mode = DRV_HASH_HW_SHA512, 171362306a36Sopenharmony_ci .inter_digestsize = SHA512_DIGEST_SIZE, 171462306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_712, 171562306a36Sopenharmony_ci .std_body = CC_STD_NIST, 171662306a36Sopenharmony_ci }, 171762306a36Sopenharmony_ci { 171862306a36Sopenharmony_ci .name = "md5", 171962306a36Sopenharmony_ci .driver_name = "md5-ccree", 172062306a36Sopenharmony_ci .mac_name = "hmac(md5)", 172162306a36Sopenharmony_ci .mac_driver_name = "hmac-md5-ccree", 172262306a36Sopenharmony_ci .blocksize = MD5_HMAC_BLOCK_SIZE, 172362306a36Sopenharmony_ci .is_mac = true, 172462306a36Sopenharmony_ci .template_ahash = { 172562306a36Sopenharmony_ci .init = cc_hash_init, 172662306a36Sopenharmony_ci .update = cc_hash_update, 172762306a36Sopenharmony_ci .final = cc_hash_final, 172862306a36Sopenharmony_ci .finup = cc_hash_finup, 172962306a36Sopenharmony_ci .digest = cc_hash_digest, 173062306a36Sopenharmony_ci .export = cc_hash_export, 173162306a36Sopenharmony_ci .import = cc_hash_import, 173262306a36Sopenharmony_ci .setkey = cc_hash_setkey, 173362306a36Sopenharmony_ci .halg = { 173462306a36Sopenharmony_ci .digestsize = MD5_DIGEST_SIZE, 173562306a36Sopenharmony_ci .statesize = CC_STATE_SIZE(MD5_DIGEST_SIZE), 173662306a36Sopenharmony_ci }, 173762306a36Sopenharmony_ci }, 173862306a36Sopenharmony_ci .hash_mode = DRV_HASH_MD5, 173962306a36Sopenharmony_ci .hw_mode = DRV_HASH_HW_MD5, 174062306a36Sopenharmony_ci .inter_digestsize = MD5_DIGEST_SIZE, 174162306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 174262306a36Sopenharmony_ci .std_body = CC_STD_NIST, 174362306a36Sopenharmony_ci }, 174462306a36Sopenharmony_ci { 174562306a36Sopenharmony_ci .name = "sm3", 174662306a36Sopenharmony_ci .driver_name = "sm3-ccree", 174762306a36Sopenharmony_ci .blocksize = SM3_BLOCK_SIZE, 174862306a36Sopenharmony_ci .is_mac = false, 174962306a36Sopenharmony_ci .template_ahash = { 175062306a36Sopenharmony_ci .init = cc_hash_init, 175162306a36Sopenharmony_ci .update = cc_hash_update, 175262306a36Sopenharmony_ci .final = cc_hash_final, 175362306a36Sopenharmony_ci .finup = cc_hash_finup, 175462306a36Sopenharmony_ci .digest = cc_hash_digest, 175562306a36Sopenharmony_ci .export = cc_hash_export, 175662306a36Sopenharmony_ci .import = cc_hash_import, 175762306a36Sopenharmony_ci .setkey = cc_hash_setkey, 175862306a36Sopenharmony_ci .halg = { 175962306a36Sopenharmony_ci .digestsize = SM3_DIGEST_SIZE, 176062306a36Sopenharmony_ci .statesize = CC_STATE_SIZE(SM3_DIGEST_SIZE), 176162306a36Sopenharmony_ci }, 176262306a36Sopenharmony_ci }, 176362306a36Sopenharmony_ci .hash_mode = DRV_HASH_SM3, 176462306a36Sopenharmony_ci .hw_mode = DRV_HASH_HW_SM3, 176562306a36Sopenharmony_ci .inter_digestsize = SM3_DIGEST_SIZE, 176662306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_713, 176762306a36Sopenharmony_ci .std_body = CC_STD_OSCCA, 176862306a36Sopenharmony_ci }, 176962306a36Sopenharmony_ci { 177062306a36Sopenharmony_ci .mac_name = "xcbc(aes)", 177162306a36Sopenharmony_ci .mac_driver_name = "xcbc-aes-ccree", 177262306a36Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 177362306a36Sopenharmony_ci .is_mac = true, 177462306a36Sopenharmony_ci .template_ahash = { 177562306a36Sopenharmony_ci .init = cc_hash_init, 177662306a36Sopenharmony_ci .update = cc_mac_update, 177762306a36Sopenharmony_ci .final = cc_mac_final, 177862306a36Sopenharmony_ci .finup = cc_mac_finup, 177962306a36Sopenharmony_ci .digest = cc_mac_digest, 178062306a36Sopenharmony_ci .setkey = cc_xcbc_setkey, 178162306a36Sopenharmony_ci .export = cc_hash_export, 178262306a36Sopenharmony_ci .import = cc_hash_import, 178362306a36Sopenharmony_ci .halg = { 178462306a36Sopenharmony_ci .digestsize = AES_BLOCK_SIZE, 178562306a36Sopenharmony_ci .statesize = CC_STATE_SIZE(AES_BLOCK_SIZE), 178662306a36Sopenharmony_ci }, 178762306a36Sopenharmony_ci }, 178862306a36Sopenharmony_ci .hash_mode = DRV_HASH_NULL, 178962306a36Sopenharmony_ci .hw_mode = DRV_CIPHER_XCBC_MAC, 179062306a36Sopenharmony_ci .inter_digestsize = AES_BLOCK_SIZE, 179162306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 179262306a36Sopenharmony_ci .std_body = CC_STD_NIST, 179362306a36Sopenharmony_ci }, 179462306a36Sopenharmony_ci { 179562306a36Sopenharmony_ci .mac_name = "cmac(aes)", 179662306a36Sopenharmony_ci .mac_driver_name = "cmac-aes-ccree", 179762306a36Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 179862306a36Sopenharmony_ci .is_mac = true, 179962306a36Sopenharmony_ci .template_ahash = { 180062306a36Sopenharmony_ci .init = cc_hash_init, 180162306a36Sopenharmony_ci .update = cc_mac_update, 180262306a36Sopenharmony_ci .final = cc_mac_final, 180362306a36Sopenharmony_ci .finup = cc_mac_finup, 180462306a36Sopenharmony_ci .digest = cc_mac_digest, 180562306a36Sopenharmony_ci .setkey = cc_cmac_setkey, 180662306a36Sopenharmony_ci .export = cc_hash_export, 180762306a36Sopenharmony_ci .import = cc_hash_import, 180862306a36Sopenharmony_ci .halg = { 180962306a36Sopenharmony_ci .digestsize = AES_BLOCK_SIZE, 181062306a36Sopenharmony_ci .statesize = CC_STATE_SIZE(AES_BLOCK_SIZE), 181162306a36Sopenharmony_ci }, 181262306a36Sopenharmony_ci }, 181362306a36Sopenharmony_ci .hash_mode = DRV_HASH_NULL, 181462306a36Sopenharmony_ci .hw_mode = DRV_CIPHER_CMAC, 181562306a36Sopenharmony_ci .inter_digestsize = AES_BLOCK_SIZE, 181662306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 181762306a36Sopenharmony_ci .std_body = CC_STD_NIST, 181862306a36Sopenharmony_ci }, 181962306a36Sopenharmony_ci}; 182062306a36Sopenharmony_ci 182162306a36Sopenharmony_cistatic struct cc_hash_alg *cc_alloc_hash_alg(struct cc_hash_template *template, 182262306a36Sopenharmony_ci struct device *dev, bool keyed) 182362306a36Sopenharmony_ci{ 182462306a36Sopenharmony_ci struct cc_hash_alg *t_crypto_alg; 182562306a36Sopenharmony_ci struct crypto_alg *alg; 182662306a36Sopenharmony_ci struct ahash_alg *halg; 182762306a36Sopenharmony_ci 182862306a36Sopenharmony_ci t_crypto_alg = devm_kzalloc(dev, sizeof(*t_crypto_alg), GFP_KERNEL); 182962306a36Sopenharmony_ci if (!t_crypto_alg) 183062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_ci t_crypto_alg->ahash_alg = template->template_ahash; 183362306a36Sopenharmony_ci halg = &t_crypto_alg->ahash_alg; 183462306a36Sopenharmony_ci alg = &halg->halg.base; 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci if (keyed) { 183762306a36Sopenharmony_ci snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", 183862306a36Sopenharmony_ci template->mac_name); 183962306a36Sopenharmony_ci snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", 184062306a36Sopenharmony_ci template->mac_driver_name); 184162306a36Sopenharmony_ci } else { 184262306a36Sopenharmony_ci halg->setkey = NULL; 184362306a36Sopenharmony_ci snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", 184462306a36Sopenharmony_ci template->name); 184562306a36Sopenharmony_ci snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", 184662306a36Sopenharmony_ci template->driver_name); 184762306a36Sopenharmony_ci } 184862306a36Sopenharmony_ci alg->cra_module = THIS_MODULE; 184962306a36Sopenharmony_ci alg->cra_ctxsize = sizeof(struct cc_hash_ctx) + crypto_dma_padding(); 185062306a36Sopenharmony_ci alg->cra_priority = CC_CRA_PRIO; 185162306a36Sopenharmony_ci alg->cra_blocksize = template->blocksize; 185262306a36Sopenharmony_ci alg->cra_alignmask = 0; 185362306a36Sopenharmony_ci alg->cra_exit = cc_cra_exit; 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_ci alg->cra_init = cc_cra_init; 185662306a36Sopenharmony_ci alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY; 185762306a36Sopenharmony_ci 185862306a36Sopenharmony_ci t_crypto_alg->hash_mode = template->hash_mode; 185962306a36Sopenharmony_ci t_crypto_alg->hw_mode = template->hw_mode; 186062306a36Sopenharmony_ci t_crypto_alg->inter_digestsize = template->inter_digestsize; 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci return t_crypto_alg; 186362306a36Sopenharmony_ci} 186462306a36Sopenharmony_ci 186562306a36Sopenharmony_cistatic int cc_init_copy_sram(struct cc_drvdata *drvdata, const u32 *data, 186662306a36Sopenharmony_ci unsigned int size, u32 *sram_buff_ofs) 186762306a36Sopenharmony_ci{ 186862306a36Sopenharmony_ci struct cc_hw_desc larval_seq[CC_DIGEST_SIZE_MAX / sizeof(u32)]; 186962306a36Sopenharmony_ci unsigned int larval_seq_len = 0; 187062306a36Sopenharmony_ci int rc; 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_ci cc_set_sram_desc(data, *sram_buff_ofs, size / sizeof(*data), 187362306a36Sopenharmony_ci larval_seq, &larval_seq_len); 187462306a36Sopenharmony_ci rc = send_request_init(drvdata, larval_seq, larval_seq_len); 187562306a36Sopenharmony_ci if (rc) 187662306a36Sopenharmony_ci return rc; 187762306a36Sopenharmony_ci 187862306a36Sopenharmony_ci *sram_buff_ofs += size; 187962306a36Sopenharmony_ci return 0; 188062306a36Sopenharmony_ci} 188162306a36Sopenharmony_ci 188262306a36Sopenharmony_ciint cc_init_hash_sram(struct cc_drvdata *drvdata) 188362306a36Sopenharmony_ci{ 188462306a36Sopenharmony_ci struct cc_hash_handle *hash_handle = drvdata->hash_handle; 188562306a36Sopenharmony_ci u32 sram_buff_ofs = hash_handle->digest_len_sram_addr; 188662306a36Sopenharmony_ci bool large_sha_supported = (drvdata->hw_rev >= CC_HW_REV_712); 188762306a36Sopenharmony_ci bool sm3_supported = (drvdata->hw_rev >= CC_HW_REV_713); 188862306a36Sopenharmony_ci int rc = 0; 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_ci /* Copy-to-sram digest-len */ 189162306a36Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_digest_len_init, 189262306a36Sopenharmony_ci sizeof(cc_digest_len_init), &sram_buff_ofs); 189362306a36Sopenharmony_ci if (rc) 189462306a36Sopenharmony_ci goto init_digest_const_err; 189562306a36Sopenharmony_ci 189662306a36Sopenharmony_ci if (large_sha_supported) { 189762306a36Sopenharmony_ci /* Copy-to-sram digest-len for sha384/512 */ 189862306a36Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_digest_len_sha512_init, 189962306a36Sopenharmony_ci sizeof(cc_digest_len_sha512_init), 190062306a36Sopenharmony_ci &sram_buff_ofs); 190162306a36Sopenharmony_ci if (rc) 190262306a36Sopenharmony_ci goto init_digest_const_err; 190362306a36Sopenharmony_ci } 190462306a36Sopenharmony_ci 190562306a36Sopenharmony_ci /* The initial digests offset */ 190662306a36Sopenharmony_ci hash_handle->larval_digest_sram_addr = sram_buff_ofs; 190762306a36Sopenharmony_ci 190862306a36Sopenharmony_ci /* Copy-to-sram initial SHA* digests */ 190962306a36Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_md5_init, sizeof(cc_md5_init), 191062306a36Sopenharmony_ci &sram_buff_ofs); 191162306a36Sopenharmony_ci if (rc) 191262306a36Sopenharmony_ci goto init_digest_const_err; 191362306a36Sopenharmony_ci 191462306a36Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_sha1_init, sizeof(cc_sha1_init), 191562306a36Sopenharmony_ci &sram_buff_ofs); 191662306a36Sopenharmony_ci if (rc) 191762306a36Sopenharmony_ci goto init_digest_const_err; 191862306a36Sopenharmony_ci 191962306a36Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_sha224_init, sizeof(cc_sha224_init), 192062306a36Sopenharmony_ci &sram_buff_ofs); 192162306a36Sopenharmony_ci if (rc) 192262306a36Sopenharmony_ci goto init_digest_const_err; 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_sha256_init, sizeof(cc_sha256_init), 192562306a36Sopenharmony_ci &sram_buff_ofs); 192662306a36Sopenharmony_ci if (rc) 192762306a36Sopenharmony_ci goto init_digest_const_err; 192862306a36Sopenharmony_ci 192962306a36Sopenharmony_ci if (sm3_supported) { 193062306a36Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_sm3_init, 193162306a36Sopenharmony_ci sizeof(cc_sm3_init), &sram_buff_ofs); 193262306a36Sopenharmony_ci if (rc) 193362306a36Sopenharmony_ci goto init_digest_const_err; 193462306a36Sopenharmony_ci } 193562306a36Sopenharmony_ci 193662306a36Sopenharmony_ci if (large_sha_supported) { 193762306a36Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_sha384_init, 193862306a36Sopenharmony_ci sizeof(cc_sha384_init), &sram_buff_ofs); 193962306a36Sopenharmony_ci if (rc) 194062306a36Sopenharmony_ci goto init_digest_const_err; 194162306a36Sopenharmony_ci 194262306a36Sopenharmony_ci rc = cc_init_copy_sram(drvdata, cc_sha512_init, 194362306a36Sopenharmony_ci sizeof(cc_sha512_init), &sram_buff_ofs); 194462306a36Sopenharmony_ci if (rc) 194562306a36Sopenharmony_ci goto init_digest_const_err; 194662306a36Sopenharmony_ci } 194762306a36Sopenharmony_ci 194862306a36Sopenharmony_ciinit_digest_const_err: 194962306a36Sopenharmony_ci return rc; 195062306a36Sopenharmony_ci} 195162306a36Sopenharmony_ci 195262306a36Sopenharmony_ciint cc_hash_alloc(struct cc_drvdata *drvdata) 195362306a36Sopenharmony_ci{ 195462306a36Sopenharmony_ci struct cc_hash_handle *hash_handle; 195562306a36Sopenharmony_ci u32 sram_buff; 195662306a36Sopenharmony_ci u32 sram_size_to_alloc; 195762306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(drvdata); 195862306a36Sopenharmony_ci int rc = 0; 195962306a36Sopenharmony_ci int alg; 196062306a36Sopenharmony_ci 196162306a36Sopenharmony_ci hash_handle = devm_kzalloc(dev, sizeof(*hash_handle), GFP_KERNEL); 196262306a36Sopenharmony_ci if (!hash_handle) 196362306a36Sopenharmony_ci return -ENOMEM; 196462306a36Sopenharmony_ci 196562306a36Sopenharmony_ci INIT_LIST_HEAD(&hash_handle->hash_list); 196662306a36Sopenharmony_ci drvdata->hash_handle = hash_handle; 196762306a36Sopenharmony_ci 196862306a36Sopenharmony_ci sram_size_to_alloc = sizeof(cc_digest_len_init) + 196962306a36Sopenharmony_ci sizeof(cc_md5_init) + 197062306a36Sopenharmony_ci sizeof(cc_sha1_init) + 197162306a36Sopenharmony_ci sizeof(cc_sha224_init) + 197262306a36Sopenharmony_ci sizeof(cc_sha256_init); 197362306a36Sopenharmony_ci 197462306a36Sopenharmony_ci if (drvdata->hw_rev >= CC_HW_REV_713) 197562306a36Sopenharmony_ci sram_size_to_alloc += sizeof(cc_sm3_init); 197662306a36Sopenharmony_ci 197762306a36Sopenharmony_ci if (drvdata->hw_rev >= CC_HW_REV_712) 197862306a36Sopenharmony_ci sram_size_to_alloc += sizeof(cc_digest_len_sha512_init) + 197962306a36Sopenharmony_ci sizeof(cc_sha384_init) + sizeof(cc_sha512_init); 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_ci sram_buff = cc_sram_alloc(drvdata, sram_size_to_alloc); 198262306a36Sopenharmony_ci if (sram_buff == NULL_SRAM_ADDR) { 198362306a36Sopenharmony_ci rc = -ENOMEM; 198462306a36Sopenharmony_ci goto fail; 198562306a36Sopenharmony_ci } 198662306a36Sopenharmony_ci 198762306a36Sopenharmony_ci /* The initial digest-len offset */ 198862306a36Sopenharmony_ci hash_handle->digest_len_sram_addr = sram_buff; 198962306a36Sopenharmony_ci 199062306a36Sopenharmony_ci /*must be set before the alg registration as it is being used there*/ 199162306a36Sopenharmony_ci rc = cc_init_hash_sram(drvdata); 199262306a36Sopenharmony_ci if (rc) { 199362306a36Sopenharmony_ci dev_err(dev, "Init digest CONST failed (rc=%d)\n", rc); 199462306a36Sopenharmony_ci goto fail; 199562306a36Sopenharmony_ci } 199662306a36Sopenharmony_ci 199762306a36Sopenharmony_ci /* ahash registration */ 199862306a36Sopenharmony_ci for (alg = 0; alg < ARRAY_SIZE(driver_hash); alg++) { 199962306a36Sopenharmony_ci struct cc_hash_alg *t_alg; 200062306a36Sopenharmony_ci int hw_mode = driver_hash[alg].hw_mode; 200162306a36Sopenharmony_ci 200262306a36Sopenharmony_ci /* Check that the HW revision and variants are suitable */ 200362306a36Sopenharmony_ci if ((driver_hash[alg].min_hw_rev > drvdata->hw_rev) || 200462306a36Sopenharmony_ci !(drvdata->std_bodies & driver_hash[alg].std_body)) 200562306a36Sopenharmony_ci continue; 200662306a36Sopenharmony_ci 200762306a36Sopenharmony_ci if (driver_hash[alg].is_mac) { 200862306a36Sopenharmony_ci /* register hmac version */ 200962306a36Sopenharmony_ci t_alg = cc_alloc_hash_alg(&driver_hash[alg], dev, true); 201062306a36Sopenharmony_ci if (IS_ERR(t_alg)) { 201162306a36Sopenharmony_ci rc = PTR_ERR(t_alg); 201262306a36Sopenharmony_ci dev_err(dev, "%s alg allocation failed\n", 201362306a36Sopenharmony_ci driver_hash[alg].driver_name); 201462306a36Sopenharmony_ci goto fail; 201562306a36Sopenharmony_ci } 201662306a36Sopenharmony_ci t_alg->drvdata = drvdata; 201762306a36Sopenharmony_ci 201862306a36Sopenharmony_ci rc = crypto_register_ahash(&t_alg->ahash_alg); 201962306a36Sopenharmony_ci if (rc) { 202062306a36Sopenharmony_ci dev_err(dev, "%s alg registration failed\n", 202162306a36Sopenharmony_ci driver_hash[alg].driver_name); 202262306a36Sopenharmony_ci goto fail; 202362306a36Sopenharmony_ci } 202462306a36Sopenharmony_ci 202562306a36Sopenharmony_ci list_add_tail(&t_alg->entry, &hash_handle->hash_list); 202662306a36Sopenharmony_ci } 202762306a36Sopenharmony_ci if (hw_mode == DRV_CIPHER_XCBC_MAC || 202862306a36Sopenharmony_ci hw_mode == DRV_CIPHER_CMAC) 202962306a36Sopenharmony_ci continue; 203062306a36Sopenharmony_ci 203162306a36Sopenharmony_ci /* register hash version */ 203262306a36Sopenharmony_ci t_alg = cc_alloc_hash_alg(&driver_hash[alg], dev, false); 203362306a36Sopenharmony_ci if (IS_ERR(t_alg)) { 203462306a36Sopenharmony_ci rc = PTR_ERR(t_alg); 203562306a36Sopenharmony_ci dev_err(dev, "%s alg allocation failed\n", 203662306a36Sopenharmony_ci driver_hash[alg].driver_name); 203762306a36Sopenharmony_ci goto fail; 203862306a36Sopenharmony_ci } 203962306a36Sopenharmony_ci t_alg->drvdata = drvdata; 204062306a36Sopenharmony_ci 204162306a36Sopenharmony_ci rc = crypto_register_ahash(&t_alg->ahash_alg); 204262306a36Sopenharmony_ci if (rc) { 204362306a36Sopenharmony_ci dev_err(dev, "%s alg registration failed\n", 204462306a36Sopenharmony_ci driver_hash[alg].driver_name); 204562306a36Sopenharmony_ci goto fail; 204662306a36Sopenharmony_ci } 204762306a36Sopenharmony_ci 204862306a36Sopenharmony_ci list_add_tail(&t_alg->entry, &hash_handle->hash_list); 204962306a36Sopenharmony_ci } 205062306a36Sopenharmony_ci 205162306a36Sopenharmony_ci return 0; 205262306a36Sopenharmony_ci 205362306a36Sopenharmony_cifail: 205462306a36Sopenharmony_ci cc_hash_free(drvdata); 205562306a36Sopenharmony_ci return rc; 205662306a36Sopenharmony_ci} 205762306a36Sopenharmony_ci 205862306a36Sopenharmony_ciint cc_hash_free(struct cc_drvdata *drvdata) 205962306a36Sopenharmony_ci{ 206062306a36Sopenharmony_ci struct cc_hash_alg *t_hash_alg, *hash_n; 206162306a36Sopenharmony_ci struct cc_hash_handle *hash_handle = drvdata->hash_handle; 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ci list_for_each_entry_safe(t_hash_alg, hash_n, &hash_handle->hash_list, 206462306a36Sopenharmony_ci entry) { 206562306a36Sopenharmony_ci crypto_unregister_ahash(&t_hash_alg->ahash_alg); 206662306a36Sopenharmony_ci list_del(&t_hash_alg->entry); 206762306a36Sopenharmony_ci } 206862306a36Sopenharmony_ci 206962306a36Sopenharmony_ci return 0; 207062306a36Sopenharmony_ci} 207162306a36Sopenharmony_ci 207262306a36Sopenharmony_cistatic void cc_setup_xcbc(struct ahash_request *areq, struct cc_hw_desc desc[], 207362306a36Sopenharmony_ci unsigned int *seq_size) 207462306a36Sopenharmony_ci{ 207562306a36Sopenharmony_ci unsigned int idx = *seq_size; 207662306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(areq); 207762306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 207862306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm); 207962306a36Sopenharmony_ci 208062306a36Sopenharmony_ci /* Setup XCBC MAC K1 */ 208162306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 208262306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, (ctx->opad_tmp_keys_dma_addr + 208362306a36Sopenharmony_ci XCBC_MAC_K1_OFFSET), 208462306a36Sopenharmony_ci CC_AES_128_BIT_KEY_SIZE, NS_BIT); 208562306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 208662306a36Sopenharmony_ci set_hash_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC, ctx->hash_mode); 208762306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 208862306a36Sopenharmony_ci set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE); 208962306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 209062306a36Sopenharmony_ci idx++; 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_ci /* Setup XCBC MAC K2 */ 209362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 209462306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 209562306a36Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K2_OFFSET), 209662306a36Sopenharmony_ci CC_AES_128_BIT_KEY_SIZE, NS_BIT); 209762306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); 209862306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC); 209962306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 210062306a36Sopenharmony_ci set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE); 210162306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 210262306a36Sopenharmony_ci idx++; 210362306a36Sopenharmony_ci 210462306a36Sopenharmony_ci /* Setup XCBC MAC K3 */ 210562306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 210662306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 210762306a36Sopenharmony_ci (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K3_OFFSET), 210862306a36Sopenharmony_ci CC_AES_128_BIT_KEY_SIZE, NS_BIT); 210962306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE2); 211062306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC); 211162306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 211262306a36Sopenharmony_ci set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE); 211362306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 211462306a36Sopenharmony_ci idx++; 211562306a36Sopenharmony_ci 211662306a36Sopenharmony_ci /* Loading MAC state */ 211762306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 211862306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, 211962306a36Sopenharmony_ci CC_AES_BLOCK_SIZE, NS_BIT); 212062306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 212162306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC); 212262306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 212362306a36Sopenharmony_ci set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE); 212462306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 212562306a36Sopenharmony_ci idx++; 212662306a36Sopenharmony_ci *seq_size = idx; 212762306a36Sopenharmony_ci} 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_cistatic void cc_setup_cmac(struct ahash_request *areq, struct cc_hw_desc desc[], 213062306a36Sopenharmony_ci unsigned int *seq_size) 213162306a36Sopenharmony_ci{ 213262306a36Sopenharmony_ci unsigned int idx = *seq_size; 213362306a36Sopenharmony_ci struct ahash_req_ctx *state = ahash_request_ctx_dma(areq); 213462306a36Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); 213562306a36Sopenharmony_ci struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm); 213662306a36Sopenharmony_ci 213762306a36Sopenharmony_ci /* Setup CMAC Key */ 213862306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 213962306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, ctx->opad_tmp_keys_dma_addr, 214062306a36Sopenharmony_ci ((ctx->key_params.keylen == 24) ? AES_MAX_KEY_SIZE : 214162306a36Sopenharmony_ci ctx->key_params.keylen), NS_BIT); 214262306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 214362306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC); 214462306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 214562306a36Sopenharmony_ci set_key_size_aes(&desc[idx], ctx->key_params.keylen); 214662306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 214762306a36Sopenharmony_ci idx++; 214862306a36Sopenharmony_ci 214962306a36Sopenharmony_ci /* Load MAC state */ 215062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 215162306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr, 215262306a36Sopenharmony_ci CC_AES_BLOCK_SIZE, NS_BIT); 215362306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 215462306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC); 215562306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 215662306a36Sopenharmony_ci set_key_size_aes(&desc[idx], ctx->key_params.keylen); 215762306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 215862306a36Sopenharmony_ci idx++; 215962306a36Sopenharmony_ci *seq_size = idx; 216062306a36Sopenharmony_ci} 216162306a36Sopenharmony_ci 216262306a36Sopenharmony_cistatic void cc_set_desc(struct ahash_req_ctx *areq_ctx, 216362306a36Sopenharmony_ci struct cc_hash_ctx *ctx, unsigned int flow_mode, 216462306a36Sopenharmony_ci struct cc_hw_desc desc[], bool is_not_last_data, 216562306a36Sopenharmony_ci unsigned int *seq_size) 216662306a36Sopenharmony_ci{ 216762306a36Sopenharmony_ci unsigned int idx = *seq_size; 216862306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 216962306a36Sopenharmony_ci 217062306a36Sopenharmony_ci if (areq_ctx->data_dma_buf_type == CC_DMA_BUF_DLLI) { 217162306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 217262306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 217362306a36Sopenharmony_ci sg_dma_address(areq_ctx->curr_sg), 217462306a36Sopenharmony_ci areq_ctx->curr_sg->length, NS_BIT); 217562306a36Sopenharmony_ci set_flow_mode(&desc[idx], flow_mode); 217662306a36Sopenharmony_ci idx++; 217762306a36Sopenharmony_ci } else { 217862306a36Sopenharmony_ci if (areq_ctx->data_dma_buf_type == CC_DMA_BUF_NULL) { 217962306a36Sopenharmony_ci dev_dbg(dev, " NULL mode\n"); 218062306a36Sopenharmony_ci /* nothing to build */ 218162306a36Sopenharmony_ci return; 218262306a36Sopenharmony_ci } 218362306a36Sopenharmony_ci /* bypass */ 218462306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 218562306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 218662306a36Sopenharmony_ci areq_ctx->mlli_params.mlli_dma_addr, 218762306a36Sopenharmony_ci areq_ctx->mlli_params.mlli_len, NS_BIT); 218862306a36Sopenharmony_ci set_dout_sram(&desc[idx], ctx->drvdata->mlli_sram_addr, 218962306a36Sopenharmony_ci areq_ctx->mlli_params.mlli_len); 219062306a36Sopenharmony_ci set_flow_mode(&desc[idx], BYPASS); 219162306a36Sopenharmony_ci idx++; 219262306a36Sopenharmony_ci /* process */ 219362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 219462306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_MLLI, 219562306a36Sopenharmony_ci ctx->drvdata->mlli_sram_addr, 219662306a36Sopenharmony_ci areq_ctx->mlli_nents, NS_BIT); 219762306a36Sopenharmony_ci set_flow_mode(&desc[idx], flow_mode); 219862306a36Sopenharmony_ci idx++; 219962306a36Sopenharmony_ci } 220062306a36Sopenharmony_ci if (is_not_last_data) 220162306a36Sopenharmony_ci set_din_not_last_indication(&desc[(idx - 1)]); 220262306a36Sopenharmony_ci /* return updated desc sequence size */ 220362306a36Sopenharmony_ci *seq_size = idx; 220462306a36Sopenharmony_ci} 220562306a36Sopenharmony_ci 220662306a36Sopenharmony_cistatic const void *cc_larval_digest(struct device *dev, u32 mode) 220762306a36Sopenharmony_ci{ 220862306a36Sopenharmony_ci switch (mode) { 220962306a36Sopenharmony_ci case DRV_HASH_MD5: 221062306a36Sopenharmony_ci return cc_md5_init; 221162306a36Sopenharmony_ci case DRV_HASH_SHA1: 221262306a36Sopenharmony_ci return cc_sha1_init; 221362306a36Sopenharmony_ci case DRV_HASH_SHA224: 221462306a36Sopenharmony_ci return cc_sha224_init; 221562306a36Sopenharmony_ci case DRV_HASH_SHA256: 221662306a36Sopenharmony_ci return cc_sha256_init; 221762306a36Sopenharmony_ci case DRV_HASH_SHA384: 221862306a36Sopenharmony_ci return cc_sha384_init; 221962306a36Sopenharmony_ci case DRV_HASH_SHA512: 222062306a36Sopenharmony_ci return cc_sha512_init; 222162306a36Sopenharmony_ci case DRV_HASH_SM3: 222262306a36Sopenharmony_ci return cc_sm3_init; 222362306a36Sopenharmony_ci default: 222462306a36Sopenharmony_ci dev_err(dev, "Invalid hash mode (%d)\n", mode); 222562306a36Sopenharmony_ci return cc_md5_init; 222662306a36Sopenharmony_ci } 222762306a36Sopenharmony_ci} 222862306a36Sopenharmony_ci 222962306a36Sopenharmony_ci/** 223062306a36Sopenharmony_ci * cc_larval_digest_addr() - Get the address of the initial digest in SRAM 223162306a36Sopenharmony_ci * according to the given hash mode 223262306a36Sopenharmony_ci * 223362306a36Sopenharmony_ci * @drvdata: Associated device driver context 223462306a36Sopenharmony_ci * @mode: The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256 223562306a36Sopenharmony_ci * 223662306a36Sopenharmony_ci * Return: 223762306a36Sopenharmony_ci * The address of the initial digest in SRAM 223862306a36Sopenharmony_ci */ 223962306a36Sopenharmony_ciu32 cc_larval_digest_addr(void *drvdata, u32 mode) 224062306a36Sopenharmony_ci{ 224162306a36Sopenharmony_ci struct cc_drvdata *_drvdata = (struct cc_drvdata *)drvdata; 224262306a36Sopenharmony_ci struct cc_hash_handle *hash_handle = _drvdata->hash_handle; 224362306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(_drvdata); 224462306a36Sopenharmony_ci bool sm3_supported = (_drvdata->hw_rev >= CC_HW_REV_713); 224562306a36Sopenharmony_ci u32 addr; 224662306a36Sopenharmony_ci 224762306a36Sopenharmony_ci switch (mode) { 224862306a36Sopenharmony_ci case DRV_HASH_NULL: 224962306a36Sopenharmony_ci break; /*Ignore*/ 225062306a36Sopenharmony_ci case DRV_HASH_MD5: 225162306a36Sopenharmony_ci return (hash_handle->larval_digest_sram_addr); 225262306a36Sopenharmony_ci case DRV_HASH_SHA1: 225362306a36Sopenharmony_ci return (hash_handle->larval_digest_sram_addr + 225462306a36Sopenharmony_ci sizeof(cc_md5_init)); 225562306a36Sopenharmony_ci case DRV_HASH_SHA224: 225662306a36Sopenharmony_ci return (hash_handle->larval_digest_sram_addr + 225762306a36Sopenharmony_ci sizeof(cc_md5_init) + 225862306a36Sopenharmony_ci sizeof(cc_sha1_init)); 225962306a36Sopenharmony_ci case DRV_HASH_SHA256: 226062306a36Sopenharmony_ci return (hash_handle->larval_digest_sram_addr + 226162306a36Sopenharmony_ci sizeof(cc_md5_init) + 226262306a36Sopenharmony_ci sizeof(cc_sha1_init) + 226362306a36Sopenharmony_ci sizeof(cc_sha224_init)); 226462306a36Sopenharmony_ci case DRV_HASH_SM3: 226562306a36Sopenharmony_ci return (hash_handle->larval_digest_sram_addr + 226662306a36Sopenharmony_ci sizeof(cc_md5_init) + 226762306a36Sopenharmony_ci sizeof(cc_sha1_init) + 226862306a36Sopenharmony_ci sizeof(cc_sha224_init) + 226962306a36Sopenharmony_ci sizeof(cc_sha256_init)); 227062306a36Sopenharmony_ci case DRV_HASH_SHA384: 227162306a36Sopenharmony_ci addr = (hash_handle->larval_digest_sram_addr + 227262306a36Sopenharmony_ci sizeof(cc_md5_init) + 227362306a36Sopenharmony_ci sizeof(cc_sha1_init) + 227462306a36Sopenharmony_ci sizeof(cc_sha224_init) + 227562306a36Sopenharmony_ci sizeof(cc_sha256_init)); 227662306a36Sopenharmony_ci if (sm3_supported) 227762306a36Sopenharmony_ci addr += sizeof(cc_sm3_init); 227862306a36Sopenharmony_ci return addr; 227962306a36Sopenharmony_ci case DRV_HASH_SHA512: 228062306a36Sopenharmony_ci addr = (hash_handle->larval_digest_sram_addr + 228162306a36Sopenharmony_ci sizeof(cc_md5_init) + 228262306a36Sopenharmony_ci sizeof(cc_sha1_init) + 228362306a36Sopenharmony_ci sizeof(cc_sha224_init) + 228462306a36Sopenharmony_ci sizeof(cc_sha256_init) + 228562306a36Sopenharmony_ci sizeof(cc_sha384_init)); 228662306a36Sopenharmony_ci if (sm3_supported) 228762306a36Sopenharmony_ci addr += sizeof(cc_sm3_init); 228862306a36Sopenharmony_ci return addr; 228962306a36Sopenharmony_ci default: 229062306a36Sopenharmony_ci dev_err(dev, "Invalid hash mode (%d)\n", mode); 229162306a36Sopenharmony_ci } 229262306a36Sopenharmony_ci 229362306a36Sopenharmony_ci /*This is valid wrong value to avoid kernel crash*/ 229462306a36Sopenharmony_ci return hash_handle->larval_digest_sram_addr; 229562306a36Sopenharmony_ci} 229662306a36Sopenharmony_ci 229762306a36Sopenharmony_ciu32 cc_digest_len_addr(void *drvdata, u32 mode) 229862306a36Sopenharmony_ci{ 229962306a36Sopenharmony_ci struct cc_drvdata *_drvdata = (struct cc_drvdata *)drvdata; 230062306a36Sopenharmony_ci struct cc_hash_handle *hash_handle = _drvdata->hash_handle; 230162306a36Sopenharmony_ci u32 digest_len_addr = hash_handle->digest_len_sram_addr; 230262306a36Sopenharmony_ci 230362306a36Sopenharmony_ci switch (mode) { 230462306a36Sopenharmony_ci case DRV_HASH_SHA1: 230562306a36Sopenharmony_ci case DRV_HASH_SHA224: 230662306a36Sopenharmony_ci case DRV_HASH_SHA256: 230762306a36Sopenharmony_ci case DRV_HASH_MD5: 230862306a36Sopenharmony_ci return digest_len_addr; 230962306a36Sopenharmony_ci case DRV_HASH_SHA384: 231062306a36Sopenharmony_ci case DRV_HASH_SHA512: 231162306a36Sopenharmony_ci return digest_len_addr + sizeof(cc_digest_len_init); 231262306a36Sopenharmony_ci default: 231362306a36Sopenharmony_ci return digest_len_addr; /*to avoid kernel crash*/ 231462306a36Sopenharmony_ci } 231562306a36Sopenharmony_ci} 2316