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/internal/aead.h> 862306a36Sopenharmony_ci#include <crypto/authenc.h> 962306a36Sopenharmony_ci#include <crypto/gcm.h> 1062306a36Sopenharmony_ci#include <linux/rtnetlink.h> 1162306a36Sopenharmony_ci#include <crypto/internal/des.h> 1262306a36Sopenharmony_ci#include "cc_driver.h" 1362306a36Sopenharmony_ci#include "cc_buffer_mgr.h" 1462306a36Sopenharmony_ci#include "cc_aead.h" 1562306a36Sopenharmony_ci#include "cc_request_mgr.h" 1662306a36Sopenharmony_ci#include "cc_hash.h" 1762306a36Sopenharmony_ci#include "cc_sram_mgr.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define template_aead template_u.aead 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define MAX_AEAD_SETKEY_SEQ 12 2262306a36Sopenharmony_ci#define MAX_AEAD_PROCESS_SEQ 23 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define MAX_HMAC_DIGEST_SIZE (SHA256_DIGEST_SIZE) 2562306a36Sopenharmony_ci#define MAX_HMAC_BLOCK_SIZE (SHA256_BLOCK_SIZE) 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define MAX_NONCE_SIZE CTR_RFC3686_NONCE_SIZE 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistruct cc_aead_handle { 3062306a36Sopenharmony_ci u32 sram_workspace_addr; 3162306a36Sopenharmony_ci struct list_head aead_list; 3262306a36Sopenharmony_ci}; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistruct cc_hmac_s { 3562306a36Sopenharmony_ci u8 *padded_authkey; 3662306a36Sopenharmony_ci u8 *ipad_opad; /* IPAD, OPAD*/ 3762306a36Sopenharmony_ci dma_addr_t padded_authkey_dma_addr; 3862306a36Sopenharmony_ci dma_addr_t ipad_opad_dma_addr; 3962306a36Sopenharmony_ci}; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistruct cc_xcbc_s { 4262306a36Sopenharmony_ci u8 *xcbc_keys; /* K1,K2,K3 */ 4362306a36Sopenharmony_ci dma_addr_t xcbc_keys_dma_addr; 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistruct cc_aead_ctx { 4762306a36Sopenharmony_ci struct cc_drvdata *drvdata; 4862306a36Sopenharmony_ci u8 ctr_nonce[MAX_NONCE_SIZE]; /* used for ctr3686 iv and aes ccm */ 4962306a36Sopenharmony_ci u8 *enckey; 5062306a36Sopenharmony_ci dma_addr_t enckey_dma_addr; 5162306a36Sopenharmony_ci union { 5262306a36Sopenharmony_ci struct cc_hmac_s hmac; 5362306a36Sopenharmony_ci struct cc_xcbc_s xcbc; 5462306a36Sopenharmony_ci } auth_state; 5562306a36Sopenharmony_ci unsigned int enc_keylen; 5662306a36Sopenharmony_ci unsigned int auth_keylen; 5762306a36Sopenharmony_ci unsigned int authsize; /* Actual (reduced?) size of the MAC/ICv */ 5862306a36Sopenharmony_ci unsigned int hash_len; 5962306a36Sopenharmony_ci enum drv_cipher_mode cipher_mode; 6062306a36Sopenharmony_ci enum cc_flow_mode flow_mode; 6162306a36Sopenharmony_ci enum drv_hash_mode auth_mode; 6262306a36Sopenharmony_ci}; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic void cc_aead_exit(struct crypto_aead *tfm) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 6762306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci dev_dbg(dev, "Clearing context @%p for %s\n", crypto_aead_ctx(tfm), 7062306a36Sopenharmony_ci crypto_tfm_alg_name(&tfm->base)); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci /* Unmap enckey buffer */ 7362306a36Sopenharmony_ci if (ctx->enckey) { 7462306a36Sopenharmony_ci dma_free_coherent(dev, AES_MAX_KEY_SIZE, ctx->enckey, 7562306a36Sopenharmony_ci ctx->enckey_dma_addr); 7662306a36Sopenharmony_ci dev_dbg(dev, "Freed enckey DMA buffer enckey_dma_addr=%pad\n", 7762306a36Sopenharmony_ci &ctx->enckey_dma_addr); 7862306a36Sopenharmony_ci ctx->enckey_dma_addr = 0; 7962306a36Sopenharmony_ci ctx->enckey = NULL; 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { /* XCBC authetication */ 8362306a36Sopenharmony_ci struct cc_xcbc_s *xcbc = &ctx->auth_state.xcbc; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci if (xcbc->xcbc_keys) { 8662306a36Sopenharmony_ci dma_free_coherent(dev, CC_AES_128_BIT_KEY_SIZE * 3, 8762306a36Sopenharmony_ci xcbc->xcbc_keys, 8862306a36Sopenharmony_ci xcbc->xcbc_keys_dma_addr); 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci dev_dbg(dev, "Freed xcbc_keys DMA buffer xcbc_keys_dma_addr=%pad\n", 9162306a36Sopenharmony_ci &xcbc->xcbc_keys_dma_addr); 9262306a36Sopenharmony_ci xcbc->xcbc_keys_dma_addr = 0; 9362306a36Sopenharmony_ci xcbc->xcbc_keys = NULL; 9462306a36Sopenharmony_ci } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC auth. */ 9562306a36Sopenharmony_ci struct cc_hmac_s *hmac = &ctx->auth_state.hmac; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci if (hmac->ipad_opad) { 9862306a36Sopenharmony_ci dma_free_coherent(dev, 2 * MAX_HMAC_DIGEST_SIZE, 9962306a36Sopenharmony_ci hmac->ipad_opad, 10062306a36Sopenharmony_ci hmac->ipad_opad_dma_addr); 10162306a36Sopenharmony_ci dev_dbg(dev, "Freed ipad_opad DMA buffer ipad_opad_dma_addr=%pad\n", 10262306a36Sopenharmony_ci &hmac->ipad_opad_dma_addr); 10362306a36Sopenharmony_ci hmac->ipad_opad_dma_addr = 0; 10462306a36Sopenharmony_ci hmac->ipad_opad = NULL; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci if (hmac->padded_authkey) { 10762306a36Sopenharmony_ci dma_free_coherent(dev, MAX_HMAC_BLOCK_SIZE, 10862306a36Sopenharmony_ci hmac->padded_authkey, 10962306a36Sopenharmony_ci hmac->padded_authkey_dma_addr); 11062306a36Sopenharmony_ci dev_dbg(dev, "Freed padded_authkey DMA buffer padded_authkey_dma_addr=%pad\n", 11162306a36Sopenharmony_ci &hmac->padded_authkey_dma_addr); 11262306a36Sopenharmony_ci hmac->padded_authkey_dma_addr = 0; 11362306a36Sopenharmony_ci hmac->padded_authkey = NULL; 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cistatic unsigned int cc_get_aead_hash_len(struct crypto_aead *tfm) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci return cc_get_default_hash_len(ctx->drvdata); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic int cc_aead_init(struct crypto_aead *tfm) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci struct aead_alg *alg = crypto_aead_alg(tfm); 12862306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 12962306a36Sopenharmony_ci struct cc_crypto_alg *cc_alg = 13062306a36Sopenharmony_ci container_of(alg, struct cc_crypto_alg, aead_alg); 13162306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(cc_alg->drvdata); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci dev_dbg(dev, "Initializing context @%p for %s\n", ctx, 13462306a36Sopenharmony_ci crypto_tfm_alg_name(&tfm->base)); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci /* Initialize modes in instance */ 13762306a36Sopenharmony_ci ctx->cipher_mode = cc_alg->cipher_mode; 13862306a36Sopenharmony_ci ctx->flow_mode = cc_alg->flow_mode; 13962306a36Sopenharmony_ci ctx->auth_mode = cc_alg->auth_mode; 14062306a36Sopenharmony_ci ctx->drvdata = cc_alg->drvdata; 14162306a36Sopenharmony_ci crypto_aead_set_reqsize_dma(tfm, sizeof(struct aead_req_ctx)); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci /* Allocate key buffer, cache line aligned */ 14462306a36Sopenharmony_ci ctx->enckey = dma_alloc_coherent(dev, AES_MAX_KEY_SIZE, 14562306a36Sopenharmony_ci &ctx->enckey_dma_addr, GFP_KERNEL); 14662306a36Sopenharmony_ci if (!ctx->enckey) { 14762306a36Sopenharmony_ci dev_err(dev, "Failed allocating key buffer\n"); 14862306a36Sopenharmony_ci goto init_failed; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci dev_dbg(dev, "Allocated enckey buffer in context ctx->enckey=@%p\n", 15162306a36Sopenharmony_ci ctx->enckey); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci /* Set default authlen value */ 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { /* XCBC authetication */ 15662306a36Sopenharmony_ci struct cc_xcbc_s *xcbc = &ctx->auth_state.xcbc; 15762306a36Sopenharmony_ci const unsigned int key_size = CC_AES_128_BIT_KEY_SIZE * 3; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci /* Allocate dma-coherent buffer for XCBC's K1+K2+K3 */ 16062306a36Sopenharmony_ci /* (and temporary for user key - up to 256b) */ 16162306a36Sopenharmony_ci xcbc->xcbc_keys = dma_alloc_coherent(dev, key_size, 16262306a36Sopenharmony_ci &xcbc->xcbc_keys_dma_addr, 16362306a36Sopenharmony_ci GFP_KERNEL); 16462306a36Sopenharmony_ci if (!xcbc->xcbc_keys) { 16562306a36Sopenharmony_ci dev_err(dev, "Failed allocating buffer for XCBC keys\n"); 16662306a36Sopenharmony_ci goto init_failed; 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC authentication */ 16962306a36Sopenharmony_ci struct cc_hmac_s *hmac = &ctx->auth_state.hmac; 17062306a36Sopenharmony_ci const unsigned int digest_size = 2 * MAX_HMAC_DIGEST_SIZE; 17162306a36Sopenharmony_ci dma_addr_t *pkey_dma = &hmac->padded_authkey_dma_addr; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci /* Allocate dma-coherent buffer for IPAD + OPAD */ 17462306a36Sopenharmony_ci hmac->ipad_opad = dma_alloc_coherent(dev, digest_size, 17562306a36Sopenharmony_ci &hmac->ipad_opad_dma_addr, 17662306a36Sopenharmony_ci GFP_KERNEL); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci if (!hmac->ipad_opad) { 17962306a36Sopenharmony_ci dev_err(dev, "Failed allocating IPAD/OPAD buffer\n"); 18062306a36Sopenharmony_ci goto init_failed; 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci dev_dbg(dev, "Allocated authkey buffer in context ctx->authkey=@%p\n", 18462306a36Sopenharmony_ci hmac->ipad_opad); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci hmac->padded_authkey = dma_alloc_coherent(dev, 18762306a36Sopenharmony_ci MAX_HMAC_BLOCK_SIZE, 18862306a36Sopenharmony_ci pkey_dma, 18962306a36Sopenharmony_ci GFP_KERNEL); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci if (!hmac->padded_authkey) { 19262306a36Sopenharmony_ci dev_err(dev, "failed to allocate padded_authkey\n"); 19362306a36Sopenharmony_ci goto init_failed; 19462306a36Sopenharmony_ci } 19562306a36Sopenharmony_ci } else { 19662306a36Sopenharmony_ci ctx->auth_state.hmac.ipad_opad = NULL; 19762306a36Sopenharmony_ci ctx->auth_state.hmac.padded_authkey = NULL; 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci ctx->hash_len = cc_get_aead_hash_len(tfm); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci return 0; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ciinit_failed: 20462306a36Sopenharmony_ci cc_aead_exit(tfm); 20562306a36Sopenharmony_ci return -ENOMEM; 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic void cc_aead_complete(struct device *dev, void *cc_req, int err) 20962306a36Sopenharmony_ci{ 21062306a36Sopenharmony_ci struct aead_request *areq = (struct aead_request *)cc_req; 21162306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(areq); 21262306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(cc_req); 21362306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci /* BACKLOG notification */ 21662306a36Sopenharmony_ci if (err == -EINPROGRESS) 21762306a36Sopenharmony_ci goto done; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci cc_unmap_aead_request(dev, areq); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci /* Restore ordinary iv pointer */ 22262306a36Sopenharmony_ci areq->iv = areq_ctx->backup_iv; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci if (err) 22562306a36Sopenharmony_ci goto done; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) { 22862306a36Sopenharmony_ci if (memcmp(areq_ctx->mac_buf, areq_ctx->icv_virt_addr, 22962306a36Sopenharmony_ci ctx->authsize) != 0) { 23062306a36Sopenharmony_ci dev_dbg(dev, "Payload authentication failure, (auth-size=%d, cipher=%d)\n", 23162306a36Sopenharmony_ci ctx->authsize, ctx->cipher_mode); 23262306a36Sopenharmony_ci /* In case of payload authentication failure, MUST NOT 23362306a36Sopenharmony_ci * revealed the decrypted message --> zero its memory. 23462306a36Sopenharmony_ci */ 23562306a36Sopenharmony_ci sg_zero_buffer(areq->dst, sg_nents(areq->dst), 23662306a36Sopenharmony_ci areq->cryptlen, areq->assoclen); 23762306a36Sopenharmony_ci err = -EBADMSG; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci /*ENCRYPT*/ 24062306a36Sopenharmony_ci } else if (areq_ctx->is_icv_fragmented) { 24162306a36Sopenharmony_ci u32 skip = areq->cryptlen + areq_ctx->dst_offset; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci cc_copy_sg_portion(dev, areq_ctx->mac_buf, areq_ctx->dst_sgl, 24462306a36Sopenharmony_ci skip, (skip + ctx->authsize), 24562306a36Sopenharmony_ci CC_SG_FROM_BUF); 24662306a36Sopenharmony_ci } 24762306a36Sopenharmony_cidone: 24862306a36Sopenharmony_ci aead_request_complete(areq, err); 24962306a36Sopenharmony_ci} 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic unsigned int xcbc_setkey(struct cc_hw_desc *desc, 25262306a36Sopenharmony_ci struct cc_aead_ctx *ctx) 25362306a36Sopenharmony_ci{ 25462306a36Sopenharmony_ci /* Load the AES key */ 25562306a36Sopenharmony_ci hw_desc_init(&desc[0]); 25662306a36Sopenharmony_ci /* We are using for the source/user key the same buffer 25762306a36Sopenharmony_ci * as for the output keys, * because after this key loading it 25862306a36Sopenharmony_ci * is not needed anymore 25962306a36Sopenharmony_ci */ 26062306a36Sopenharmony_ci set_din_type(&desc[0], DMA_DLLI, 26162306a36Sopenharmony_ci ctx->auth_state.xcbc.xcbc_keys_dma_addr, ctx->auth_keylen, 26262306a36Sopenharmony_ci NS_BIT); 26362306a36Sopenharmony_ci set_cipher_mode(&desc[0], DRV_CIPHER_ECB); 26462306a36Sopenharmony_ci set_cipher_config0(&desc[0], DRV_CRYPTO_DIRECTION_ENCRYPT); 26562306a36Sopenharmony_ci set_key_size_aes(&desc[0], ctx->auth_keylen); 26662306a36Sopenharmony_ci set_flow_mode(&desc[0], S_DIN_to_AES); 26762306a36Sopenharmony_ci set_setup_mode(&desc[0], SETUP_LOAD_KEY0); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci hw_desc_init(&desc[1]); 27062306a36Sopenharmony_ci set_din_const(&desc[1], 0x01010101, CC_AES_128_BIT_KEY_SIZE); 27162306a36Sopenharmony_ci set_flow_mode(&desc[1], DIN_AES_DOUT); 27262306a36Sopenharmony_ci set_dout_dlli(&desc[1], ctx->auth_state.xcbc.xcbc_keys_dma_addr, 27362306a36Sopenharmony_ci AES_KEYSIZE_128, NS_BIT, 0); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci hw_desc_init(&desc[2]); 27662306a36Sopenharmony_ci set_din_const(&desc[2], 0x02020202, CC_AES_128_BIT_KEY_SIZE); 27762306a36Sopenharmony_ci set_flow_mode(&desc[2], DIN_AES_DOUT); 27862306a36Sopenharmony_ci set_dout_dlli(&desc[2], (ctx->auth_state.xcbc.xcbc_keys_dma_addr 27962306a36Sopenharmony_ci + AES_KEYSIZE_128), 28062306a36Sopenharmony_ci AES_KEYSIZE_128, NS_BIT, 0); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci hw_desc_init(&desc[3]); 28362306a36Sopenharmony_ci set_din_const(&desc[3], 0x03030303, CC_AES_128_BIT_KEY_SIZE); 28462306a36Sopenharmony_ci set_flow_mode(&desc[3], DIN_AES_DOUT); 28562306a36Sopenharmony_ci set_dout_dlli(&desc[3], (ctx->auth_state.xcbc.xcbc_keys_dma_addr 28662306a36Sopenharmony_ci + 2 * AES_KEYSIZE_128), 28762306a36Sopenharmony_ci AES_KEYSIZE_128, NS_BIT, 0); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci return 4; 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cistatic unsigned int hmac_setkey(struct cc_hw_desc *desc, 29362306a36Sopenharmony_ci struct cc_aead_ctx *ctx) 29462306a36Sopenharmony_ci{ 29562306a36Sopenharmony_ci unsigned int hmac_pad_const[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST }; 29662306a36Sopenharmony_ci unsigned int digest_ofs = 0; 29762306a36Sopenharmony_ci unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ? 29862306a36Sopenharmony_ci DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256; 29962306a36Sopenharmony_ci unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ? 30062306a36Sopenharmony_ci CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE; 30162306a36Sopenharmony_ci struct cc_hmac_s *hmac = &ctx->auth_state.hmac; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci unsigned int idx = 0; 30462306a36Sopenharmony_ci int i; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci /* calc derived HMAC key */ 30762306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 30862306a36Sopenharmony_ci /* Load hash initial state */ 30962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 31062306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hash_mode); 31162306a36Sopenharmony_ci set_din_sram(&desc[idx], 31262306a36Sopenharmony_ci cc_larval_digest_addr(ctx->drvdata, 31362306a36Sopenharmony_ci ctx->auth_mode), 31462306a36Sopenharmony_ci digest_size); 31562306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 31662306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 31762306a36Sopenharmony_ci idx++; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci /* Load the hash current length*/ 32062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 32162306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hash_mode); 32262306a36Sopenharmony_ci set_din_const(&desc[idx], 0, ctx->hash_len); 32362306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 32462306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 32562306a36Sopenharmony_ci idx++; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci /* Prepare ipad key */ 32862306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 32962306a36Sopenharmony_ci set_xor_val(&desc[idx], hmac_pad_const[i]); 33062306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hash_mode); 33162306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 33262306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); 33362306a36Sopenharmony_ci idx++; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci /* Perform HASH update */ 33662306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 33762306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 33862306a36Sopenharmony_ci hmac->padded_authkey_dma_addr, 33962306a36Sopenharmony_ci SHA256_BLOCK_SIZE, NS_BIT); 34062306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hash_mode); 34162306a36Sopenharmony_ci set_xor_active(&desc[idx]); 34262306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_HASH); 34362306a36Sopenharmony_ci idx++; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci /* Get the digset */ 34662306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 34762306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hash_mode); 34862306a36Sopenharmony_ci set_dout_dlli(&desc[idx], 34962306a36Sopenharmony_ci (hmac->ipad_opad_dma_addr + digest_ofs), 35062306a36Sopenharmony_ci digest_size, NS_BIT, 0); 35162306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 35262306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 35362306a36Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED); 35462306a36Sopenharmony_ci idx++; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci digest_ofs += digest_size; 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci return idx; 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_cistatic int validate_keys_sizes(struct cc_aead_ctx *ctx) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci dev_dbg(dev, "enc_keylen=%u authkeylen=%u\n", 36762306a36Sopenharmony_ci ctx->enc_keylen, ctx->auth_keylen); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci switch (ctx->auth_mode) { 37062306a36Sopenharmony_ci case DRV_HASH_SHA1: 37162306a36Sopenharmony_ci case DRV_HASH_SHA256: 37262306a36Sopenharmony_ci break; 37362306a36Sopenharmony_ci case DRV_HASH_XCBC_MAC: 37462306a36Sopenharmony_ci if (ctx->auth_keylen != AES_KEYSIZE_128 && 37562306a36Sopenharmony_ci ctx->auth_keylen != AES_KEYSIZE_192 && 37662306a36Sopenharmony_ci ctx->auth_keylen != AES_KEYSIZE_256) 37762306a36Sopenharmony_ci return -ENOTSUPP; 37862306a36Sopenharmony_ci break; 37962306a36Sopenharmony_ci case DRV_HASH_NULL: /* Not authenc (e.g., CCM) - no auth_key) */ 38062306a36Sopenharmony_ci if (ctx->auth_keylen > 0) 38162306a36Sopenharmony_ci return -EINVAL; 38262306a36Sopenharmony_ci break; 38362306a36Sopenharmony_ci default: 38462306a36Sopenharmony_ci dev_dbg(dev, "Invalid auth_mode=%d\n", ctx->auth_mode); 38562306a36Sopenharmony_ci return -EINVAL; 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci /* Check cipher key size */ 38862306a36Sopenharmony_ci if (ctx->flow_mode == S_DIN_to_DES) { 38962306a36Sopenharmony_ci if (ctx->enc_keylen != DES3_EDE_KEY_SIZE) { 39062306a36Sopenharmony_ci dev_dbg(dev, "Invalid cipher(3DES) key size: %u\n", 39162306a36Sopenharmony_ci ctx->enc_keylen); 39262306a36Sopenharmony_ci return -EINVAL; 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci } else { /* Default assumed to be AES ciphers */ 39562306a36Sopenharmony_ci if (ctx->enc_keylen != AES_KEYSIZE_128 && 39662306a36Sopenharmony_ci ctx->enc_keylen != AES_KEYSIZE_192 && 39762306a36Sopenharmony_ci ctx->enc_keylen != AES_KEYSIZE_256) { 39862306a36Sopenharmony_ci dev_dbg(dev, "Invalid cipher(AES) key size: %u\n", 39962306a36Sopenharmony_ci ctx->enc_keylen); 40062306a36Sopenharmony_ci return -EINVAL; 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci return 0; /* All tests of keys sizes passed */ 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci/* This function prepers the user key so it can pass to the hmac processing 40862306a36Sopenharmony_ci * (copy to intenral buffer or hash in case of key longer than block 40962306a36Sopenharmony_ci */ 41062306a36Sopenharmony_cistatic int cc_get_plain_hmac_key(struct crypto_aead *tfm, const u8 *authkey, 41162306a36Sopenharmony_ci unsigned int keylen) 41262306a36Sopenharmony_ci{ 41362306a36Sopenharmony_ci dma_addr_t key_dma_addr = 0; 41462306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 41562306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 41662306a36Sopenharmony_ci u32 larval_addr; 41762306a36Sopenharmony_ci struct cc_crypto_req cc_req = {}; 41862306a36Sopenharmony_ci unsigned int blocksize; 41962306a36Sopenharmony_ci unsigned int digestsize; 42062306a36Sopenharmony_ci unsigned int hashmode; 42162306a36Sopenharmony_ci unsigned int idx = 0; 42262306a36Sopenharmony_ci int rc = 0; 42362306a36Sopenharmony_ci u8 *key = NULL; 42462306a36Sopenharmony_ci struct cc_hw_desc desc[MAX_AEAD_SETKEY_SEQ]; 42562306a36Sopenharmony_ci dma_addr_t padded_authkey_dma_addr = 42662306a36Sopenharmony_ci ctx->auth_state.hmac.padded_authkey_dma_addr; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci switch (ctx->auth_mode) { /* auth_key required and >0 */ 42962306a36Sopenharmony_ci case DRV_HASH_SHA1: 43062306a36Sopenharmony_ci blocksize = SHA1_BLOCK_SIZE; 43162306a36Sopenharmony_ci digestsize = SHA1_DIGEST_SIZE; 43262306a36Sopenharmony_ci hashmode = DRV_HASH_HW_SHA1; 43362306a36Sopenharmony_ci break; 43462306a36Sopenharmony_ci case DRV_HASH_SHA256: 43562306a36Sopenharmony_ci default: 43662306a36Sopenharmony_ci blocksize = SHA256_BLOCK_SIZE; 43762306a36Sopenharmony_ci digestsize = SHA256_DIGEST_SIZE; 43862306a36Sopenharmony_ci hashmode = DRV_HASH_HW_SHA256; 43962306a36Sopenharmony_ci } 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci if (keylen != 0) { 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci key = kmemdup(authkey, keylen, GFP_KERNEL); 44462306a36Sopenharmony_ci if (!key) 44562306a36Sopenharmony_ci return -ENOMEM; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci key_dma_addr = dma_map_single(dev, key, keylen, DMA_TO_DEVICE); 44862306a36Sopenharmony_ci if (dma_mapping_error(dev, key_dma_addr)) { 44962306a36Sopenharmony_ci dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n", 45062306a36Sopenharmony_ci key, keylen); 45162306a36Sopenharmony_ci kfree_sensitive(key); 45262306a36Sopenharmony_ci return -ENOMEM; 45362306a36Sopenharmony_ci } 45462306a36Sopenharmony_ci if (keylen > blocksize) { 45562306a36Sopenharmony_ci /* Load hash initial state */ 45662306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 45762306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hashmode); 45862306a36Sopenharmony_ci larval_addr = cc_larval_digest_addr(ctx->drvdata, 45962306a36Sopenharmony_ci ctx->auth_mode); 46062306a36Sopenharmony_ci set_din_sram(&desc[idx], larval_addr, digestsize); 46162306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 46262306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 46362306a36Sopenharmony_ci idx++; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci /* Load the hash current length*/ 46662306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 46762306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hashmode); 46862306a36Sopenharmony_ci set_din_const(&desc[idx], 0, ctx->hash_len); 46962306a36Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); 47062306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 47162306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 47262306a36Sopenharmony_ci idx++; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 47562306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 47662306a36Sopenharmony_ci key_dma_addr, keylen, NS_BIT); 47762306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_HASH); 47862306a36Sopenharmony_ci idx++; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci /* Get hashed key */ 48162306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 48262306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hashmode); 48362306a36Sopenharmony_ci set_dout_dlli(&desc[idx], padded_authkey_dma_addr, 48462306a36Sopenharmony_ci digestsize, NS_BIT, 0); 48562306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 48662306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 48762306a36Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED); 48862306a36Sopenharmony_ci set_cipher_config0(&desc[idx], 48962306a36Sopenharmony_ci HASH_DIGEST_RESULT_LITTLE_ENDIAN); 49062306a36Sopenharmony_ci idx++; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 49362306a36Sopenharmony_ci set_din_const(&desc[idx], 0, (blocksize - digestsize)); 49462306a36Sopenharmony_ci set_flow_mode(&desc[idx], BYPASS); 49562306a36Sopenharmony_ci set_dout_dlli(&desc[idx], (padded_authkey_dma_addr + 49662306a36Sopenharmony_ci digestsize), (blocksize - digestsize), 49762306a36Sopenharmony_ci NS_BIT, 0); 49862306a36Sopenharmony_ci idx++; 49962306a36Sopenharmony_ci } else { 50062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 50162306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, key_dma_addr, 50262306a36Sopenharmony_ci keylen, NS_BIT); 50362306a36Sopenharmony_ci set_flow_mode(&desc[idx], BYPASS); 50462306a36Sopenharmony_ci set_dout_dlli(&desc[idx], padded_authkey_dma_addr, 50562306a36Sopenharmony_ci keylen, NS_BIT, 0); 50662306a36Sopenharmony_ci idx++; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci if ((blocksize - keylen) != 0) { 50962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 51062306a36Sopenharmony_ci set_din_const(&desc[idx], 0, 51162306a36Sopenharmony_ci (blocksize - keylen)); 51262306a36Sopenharmony_ci set_flow_mode(&desc[idx], BYPASS); 51362306a36Sopenharmony_ci set_dout_dlli(&desc[idx], 51462306a36Sopenharmony_ci (padded_authkey_dma_addr + 51562306a36Sopenharmony_ci keylen), 51662306a36Sopenharmony_ci (blocksize - keylen), NS_BIT, 0); 51762306a36Sopenharmony_ci idx++; 51862306a36Sopenharmony_ci } 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci } else { 52162306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 52262306a36Sopenharmony_ci set_din_const(&desc[idx], 0, (blocksize - keylen)); 52362306a36Sopenharmony_ci set_flow_mode(&desc[idx], BYPASS); 52462306a36Sopenharmony_ci set_dout_dlli(&desc[idx], padded_authkey_dma_addr, 52562306a36Sopenharmony_ci blocksize, NS_BIT, 0); 52662306a36Sopenharmony_ci idx++; 52762306a36Sopenharmony_ci } 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, idx); 53062306a36Sopenharmony_ci if (rc) 53162306a36Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci if (key_dma_addr) 53462306a36Sopenharmony_ci dma_unmap_single(dev, key_dma_addr, keylen, DMA_TO_DEVICE); 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci kfree_sensitive(key); 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci return rc; 53962306a36Sopenharmony_ci} 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_cistatic int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key, 54262306a36Sopenharmony_ci unsigned int keylen) 54362306a36Sopenharmony_ci{ 54462306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 54562306a36Sopenharmony_ci struct cc_crypto_req cc_req = {}; 54662306a36Sopenharmony_ci struct cc_hw_desc desc[MAX_AEAD_SETKEY_SEQ]; 54762306a36Sopenharmony_ci unsigned int seq_len = 0; 54862306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 54962306a36Sopenharmony_ci const u8 *enckey, *authkey; 55062306a36Sopenharmony_ci int rc; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci dev_dbg(dev, "Setting key in context @%p for %s. key=%p keylen=%u\n", 55362306a36Sopenharmony_ci ctx, crypto_tfm_alg_name(crypto_aead_tfm(tfm)), key, keylen); 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci /* STAT_PHASE_0: Init and sanity checks */ 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci if (ctx->auth_mode != DRV_HASH_NULL) { /* authenc() alg. */ 55862306a36Sopenharmony_ci struct crypto_authenc_keys keys; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci rc = crypto_authenc_extractkeys(&keys, key, keylen); 56162306a36Sopenharmony_ci if (rc) 56262306a36Sopenharmony_ci return rc; 56362306a36Sopenharmony_ci enckey = keys.enckey; 56462306a36Sopenharmony_ci authkey = keys.authkey; 56562306a36Sopenharmony_ci ctx->enc_keylen = keys.enckeylen; 56662306a36Sopenharmony_ci ctx->auth_keylen = keys.authkeylen; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci if (ctx->cipher_mode == DRV_CIPHER_CTR) { 56962306a36Sopenharmony_ci /* the nonce is stored in bytes at end of key */ 57062306a36Sopenharmony_ci if (ctx->enc_keylen < 57162306a36Sopenharmony_ci (AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE)) 57262306a36Sopenharmony_ci return -EINVAL; 57362306a36Sopenharmony_ci /* Copy nonce from last 4 bytes in CTR key to 57462306a36Sopenharmony_ci * first 4 bytes in CTR IV 57562306a36Sopenharmony_ci */ 57662306a36Sopenharmony_ci memcpy(ctx->ctr_nonce, enckey + ctx->enc_keylen - 57762306a36Sopenharmony_ci CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_NONCE_SIZE); 57862306a36Sopenharmony_ci /* Set CTR key size */ 57962306a36Sopenharmony_ci ctx->enc_keylen -= CTR_RFC3686_NONCE_SIZE; 58062306a36Sopenharmony_ci } 58162306a36Sopenharmony_ci } else { /* non-authenc - has just one key */ 58262306a36Sopenharmony_ci enckey = key; 58362306a36Sopenharmony_ci authkey = NULL; 58462306a36Sopenharmony_ci ctx->enc_keylen = keylen; 58562306a36Sopenharmony_ci ctx->auth_keylen = 0; 58662306a36Sopenharmony_ci } 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci rc = validate_keys_sizes(ctx); 58962306a36Sopenharmony_ci if (rc) 59062306a36Sopenharmony_ci return rc; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci /* STAT_PHASE_1: Copy key to ctx */ 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci /* Get key material */ 59562306a36Sopenharmony_ci memcpy(ctx->enckey, enckey, ctx->enc_keylen); 59662306a36Sopenharmony_ci if (ctx->enc_keylen == 24) 59762306a36Sopenharmony_ci memset(ctx->enckey + 24, 0, CC_AES_KEY_SIZE_MAX - 24); 59862306a36Sopenharmony_ci if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { 59962306a36Sopenharmony_ci memcpy(ctx->auth_state.xcbc.xcbc_keys, authkey, 60062306a36Sopenharmony_ci ctx->auth_keylen); 60162306a36Sopenharmony_ci } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC */ 60262306a36Sopenharmony_ci rc = cc_get_plain_hmac_key(tfm, authkey, ctx->auth_keylen); 60362306a36Sopenharmony_ci if (rc) 60462306a36Sopenharmony_ci return rc; 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci /* STAT_PHASE_2: Create sequence */ 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci switch (ctx->auth_mode) { 61062306a36Sopenharmony_ci case DRV_HASH_SHA1: 61162306a36Sopenharmony_ci case DRV_HASH_SHA256: 61262306a36Sopenharmony_ci seq_len = hmac_setkey(desc, ctx); 61362306a36Sopenharmony_ci break; 61462306a36Sopenharmony_ci case DRV_HASH_XCBC_MAC: 61562306a36Sopenharmony_ci seq_len = xcbc_setkey(desc, ctx); 61662306a36Sopenharmony_ci break; 61762306a36Sopenharmony_ci case DRV_HASH_NULL: /* non-authenc modes, e.g., CCM */ 61862306a36Sopenharmony_ci break; /* No auth. key setup */ 61962306a36Sopenharmony_ci default: 62062306a36Sopenharmony_ci dev_err(dev, "Unsupported authenc (%d)\n", ctx->auth_mode); 62162306a36Sopenharmony_ci return -ENOTSUPP; 62262306a36Sopenharmony_ci } 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci /* STAT_PHASE_3: Submit sequence to HW */ 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci if (seq_len > 0) { /* For CCM there is no sequence to setup the key */ 62762306a36Sopenharmony_ci rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, seq_len); 62862306a36Sopenharmony_ci if (rc) { 62962306a36Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 63062306a36Sopenharmony_ci return rc; 63162306a36Sopenharmony_ci } 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci /* Update STAT_PHASE_3 */ 63562306a36Sopenharmony_ci return rc; 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_cistatic int cc_des3_aead_setkey(struct crypto_aead *aead, const u8 *key, 63962306a36Sopenharmony_ci unsigned int keylen) 64062306a36Sopenharmony_ci{ 64162306a36Sopenharmony_ci struct crypto_authenc_keys keys; 64262306a36Sopenharmony_ci int err; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci err = crypto_authenc_extractkeys(&keys, key, keylen); 64562306a36Sopenharmony_ci if (unlikely(err)) 64662306a36Sopenharmony_ci return err; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci err = verify_aead_des3_key(aead, keys.enckey, keys.enckeylen) ?: 64962306a36Sopenharmony_ci cc_aead_setkey(aead, key, keylen); 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci memzero_explicit(&keys, sizeof(keys)); 65262306a36Sopenharmony_ci return err; 65362306a36Sopenharmony_ci} 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_cistatic int cc_rfc4309_ccm_setkey(struct crypto_aead *tfm, const u8 *key, 65662306a36Sopenharmony_ci unsigned int keylen) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci if (keylen < 3) 66162306a36Sopenharmony_ci return -EINVAL; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci keylen -= 3; 66462306a36Sopenharmony_ci memcpy(ctx->ctr_nonce, key + keylen, 3); 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci return cc_aead_setkey(tfm, key, keylen); 66762306a36Sopenharmony_ci} 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_cistatic int cc_aead_setauthsize(struct crypto_aead *authenc, 67062306a36Sopenharmony_ci unsigned int authsize) 67162306a36Sopenharmony_ci{ 67262306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(authenc); 67362306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci /* Unsupported auth. sizes */ 67662306a36Sopenharmony_ci if (authsize == 0 || 67762306a36Sopenharmony_ci authsize > crypto_aead_maxauthsize(authenc)) { 67862306a36Sopenharmony_ci return -ENOTSUPP; 67962306a36Sopenharmony_ci } 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci ctx->authsize = authsize; 68262306a36Sopenharmony_ci dev_dbg(dev, "authlen=%d\n", ctx->authsize); 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci return 0; 68562306a36Sopenharmony_ci} 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_cistatic int cc_rfc4309_ccm_setauthsize(struct crypto_aead *authenc, 68862306a36Sopenharmony_ci unsigned int authsize) 68962306a36Sopenharmony_ci{ 69062306a36Sopenharmony_ci switch (authsize) { 69162306a36Sopenharmony_ci case 8: 69262306a36Sopenharmony_ci case 12: 69362306a36Sopenharmony_ci case 16: 69462306a36Sopenharmony_ci break; 69562306a36Sopenharmony_ci default: 69662306a36Sopenharmony_ci return -EINVAL; 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci return cc_aead_setauthsize(authenc, authsize); 70062306a36Sopenharmony_ci} 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_cistatic int cc_ccm_setauthsize(struct crypto_aead *authenc, 70362306a36Sopenharmony_ci unsigned int authsize) 70462306a36Sopenharmony_ci{ 70562306a36Sopenharmony_ci switch (authsize) { 70662306a36Sopenharmony_ci case 4: 70762306a36Sopenharmony_ci case 6: 70862306a36Sopenharmony_ci case 8: 70962306a36Sopenharmony_ci case 10: 71062306a36Sopenharmony_ci case 12: 71162306a36Sopenharmony_ci case 14: 71262306a36Sopenharmony_ci case 16: 71362306a36Sopenharmony_ci break; 71462306a36Sopenharmony_ci default: 71562306a36Sopenharmony_ci return -EINVAL; 71662306a36Sopenharmony_ci } 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci return cc_aead_setauthsize(authenc, authsize); 71962306a36Sopenharmony_ci} 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_cistatic void cc_set_assoc_desc(struct aead_request *areq, unsigned int flow_mode, 72262306a36Sopenharmony_ci struct cc_hw_desc desc[], unsigned int *seq_size) 72362306a36Sopenharmony_ci{ 72462306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(areq); 72562306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 72662306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(areq); 72762306a36Sopenharmony_ci enum cc_req_dma_buf_type assoc_dma_type = areq_ctx->assoc_buff_type; 72862306a36Sopenharmony_ci unsigned int idx = *seq_size; 72962306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci switch (assoc_dma_type) { 73262306a36Sopenharmony_ci case CC_DMA_BUF_DLLI: 73362306a36Sopenharmony_ci dev_dbg(dev, "ASSOC buffer type DLLI\n"); 73462306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 73562306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, sg_dma_address(areq->src), 73662306a36Sopenharmony_ci areq_ctx->assoclen, NS_BIT); 73762306a36Sopenharmony_ci set_flow_mode(&desc[idx], flow_mode); 73862306a36Sopenharmony_ci if (ctx->auth_mode == DRV_HASH_XCBC_MAC && 73962306a36Sopenharmony_ci areq_ctx->cryptlen > 0) 74062306a36Sopenharmony_ci set_din_not_last_indication(&desc[idx]); 74162306a36Sopenharmony_ci break; 74262306a36Sopenharmony_ci case CC_DMA_BUF_MLLI: 74362306a36Sopenharmony_ci dev_dbg(dev, "ASSOC buffer type MLLI\n"); 74462306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 74562306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_MLLI, areq_ctx->assoc.sram_addr, 74662306a36Sopenharmony_ci areq_ctx->assoc.mlli_nents, NS_BIT); 74762306a36Sopenharmony_ci set_flow_mode(&desc[idx], flow_mode); 74862306a36Sopenharmony_ci if (ctx->auth_mode == DRV_HASH_XCBC_MAC && 74962306a36Sopenharmony_ci areq_ctx->cryptlen > 0) 75062306a36Sopenharmony_ci set_din_not_last_indication(&desc[idx]); 75162306a36Sopenharmony_ci break; 75262306a36Sopenharmony_ci case CC_DMA_BUF_NULL: 75362306a36Sopenharmony_ci default: 75462306a36Sopenharmony_ci dev_err(dev, "Invalid ASSOC buffer type\n"); 75562306a36Sopenharmony_ci } 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci *seq_size = (++idx); 75862306a36Sopenharmony_ci} 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_cistatic void cc_proc_authen_desc(struct aead_request *areq, 76162306a36Sopenharmony_ci unsigned int flow_mode, 76262306a36Sopenharmony_ci struct cc_hw_desc desc[], 76362306a36Sopenharmony_ci unsigned int *seq_size, int direct) 76462306a36Sopenharmony_ci{ 76562306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(areq); 76662306a36Sopenharmony_ci enum cc_req_dma_buf_type data_dma_type = areq_ctx->data_buff_type; 76762306a36Sopenharmony_ci unsigned int idx = *seq_size; 76862306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(areq); 76962306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 77062306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci switch (data_dma_type) { 77362306a36Sopenharmony_ci case CC_DMA_BUF_DLLI: 77462306a36Sopenharmony_ci { 77562306a36Sopenharmony_ci struct scatterlist *cipher = 77662306a36Sopenharmony_ci (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? 77762306a36Sopenharmony_ci areq_ctx->dst_sgl : areq_ctx->src_sgl; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci unsigned int offset = 78062306a36Sopenharmony_ci (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? 78162306a36Sopenharmony_ci areq_ctx->dst_offset : areq_ctx->src_offset; 78262306a36Sopenharmony_ci dev_dbg(dev, "AUTHENC: SRC/DST buffer type DLLI\n"); 78362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 78462306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 78562306a36Sopenharmony_ci (sg_dma_address(cipher) + offset), 78662306a36Sopenharmony_ci areq_ctx->cryptlen, NS_BIT); 78762306a36Sopenharmony_ci set_flow_mode(&desc[idx], flow_mode); 78862306a36Sopenharmony_ci break; 78962306a36Sopenharmony_ci } 79062306a36Sopenharmony_ci case CC_DMA_BUF_MLLI: 79162306a36Sopenharmony_ci { 79262306a36Sopenharmony_ci /* DOUBLE-PASS flow (as default) 79362306a36Sopenharmony_ci * assoc. + iv + data -compact in one table 79462306a36Sopenharmony_ci * if assoclen is ZERO only IV perform 79562306a36Sopenharmony_ci */ 79662306a36Sopenharmony_ci u32 mlli_addr = areq_ctx->assoc.sram_addr; 79762306a36Sopenharmony_ci u32 mlli_nents = areq_ctx->assoc.mlli_nents; 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci if (areq_ctx->is_single_pass) { 80062306a36Sopenharmony_ci if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) { 80162306a36Sopenharmony_ci mlli_addr = areq_ctx->dst.sram_addr; 80262306a36Sopenharmony_ci mlli_nents = areq_ctx->dst.mlli_nents; 80362306a36Sopenharmony_ci } else { 80462306a36Sopenharmony_ci mlli_addr = areq_ctx->src.sram_addr; 80562306a36Sopenharmony_ci mlli_nents = areq_ctx->src.mlli_nents; 80662306a36Sopenharmony_ci } 80762306a36Sopenharmony_ci } 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci dev_dbg(dev, "AUTHENC: SRC/DST buffer type MLLI\n"); 81062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 81162306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_MLLI, mlli_addr, mlli_nents, 81262306a36Sopenharmony_ci NS_BIT); 81362306a36Sopenharmony_ci set_flow_mode(&desc[idx], flow_mode); 81462306a36Sopenharmony_ci break; 81562306a36Sopenharmony_ci } 81662306a36Sopenharmony_ci case CC_DMA_BUF_NULL: 81762306a36Sopenharmony_ci default: 81862306a36Sopenharmony_ci dev_err(dev, "AUTHENC: Invalid SRC/DST buffer type\n"); 81962306a36Sopenharmony_ci } 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci *seq_size = (++idx); 82262306a36Sopenharmony_ci} 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_cistatic void cc_proc_cipher_desc(struct aead_request *areq, 82562306a36Sopenharmony_ci unsigned int flow_mode, 82662306a36Sopenharmony_ci struct cc_hw_desc desc[], 82762306a36Sopenharmony_ci unsigned int *seq_size) 82862306a36Sopenharmony_ci{ 82962306a36Sopenharmony_ci unsigned int idx = *seq_size; 83062306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(areq); 83162306a36Sopenharmony_ci enum cc_req_dma_buf_type data_dma_type = areq_ctx->data_buff_type; 83262306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(areq); 83362306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 83462306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci if (areq_ctx->cryptlen == 0) 83762306a36Sopenharmony_ci return; /*null processing*/ 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci switch (data_dma_type) { 84062306a36Sopenharmony_ci case CC_DMA_BUF_DLLI: 84162306a36Sopenharmony_ci dev_dbg(dev, "CIPHER: SRC/DST buffer type DLLI\n"); 84262306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 84362306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 84462306a36Sopenharmony_ci (sg_dma_address(areq_ctx->src_sgl) + 84562306a36Sopenharmony_ci areq_ctx->src_offset), areq_ctx->cryptlen, 84662306a36Sopenharmony_ci NS_BIT); 84762306a36Sopenharmony_ci set_dout_dlli(&desc[idx], 84862306a36Sopenharmony_ci (sg_dma_address(areq_ctx->dst_sgl) + 84962306a36Sopenharmony_ci areq_ctx->dst_offset), 85062306a36Sopenharmony_ci areq_ctx->cryptlen, NS_BIT, 0); 85162306a36Sopenharmony_ci set_flow_mode(&desc[idx], flow_mode); 85262306a36Sopenharmony_ci break; 85362306a36Sopenharmony_ci case CC_DMA_BUF_MLLI: 85462306a36Sopenharmony_ci dev_dbg(dev, "CIPHER: SRC/DST buffer type MLLI\n"); 85562306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 85662306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_MLLI, areq_ctx->src.sram_addr, 85762306a36Sopenharmony_ci areq_ctx->src.mlli_nents, NS_BIT); 85862306a36Sopenharmony_ci set_dout_mlli(&desc[idx], areq_ctx->dst.sram_addr, 85962306a36Sopenharmony_ci areq_ctx->dst.mlli_nents, NS_BIT, 0); 86062306a36Sopenharmony_ci set_flow_mode(&desc[idx], flow_mode); 86162306a36Sopenharmony_ci break; 86262306a36Sopenharmony_ci case CC_DMA_BUF_NULL: 86362306a36Sopenharmony_ci default: 86462306a36Sopenharmony_ci dev_err(dev, "CIPHER: Invalid SRC/DST buffer type\n"); 86562306a36Sopenharmony_ci } 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci *seq_size = (++idx); 86862306a36Sopenharmony_ci} 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_cistatic void cc_proc_digest_desc(struct aead_request *req, 87162306a36Sopenharmony_ci struct cc_hw_desc desc[], 87262306a36Sopenharmony_ci unsigned int *seq_size) 87362306a36Sopenharmony_ci{ 87462306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 87562306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 87662306a36Sopenharmony_ci struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req); 87762306a36Sopenharmony_ci unsigned int idx = *seq_size; 87862306a36Sopenharmony_ci unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ? 87962306a36Sopenharmony_ci DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256; 88062306a36Sopenharmony_ci int direct = req_ctx->gen_ctx.op_type; 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci /* Get final ICV result */ 88362306a36Sopenharmony_ci if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) { 88462306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 88562306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 88662306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 88762306a36Sopenharmony_ci set_dout_dlli(&desc[idx], req_ctx->icv_dma_addr, ctx->authsize, 88862306a36Sopenharmony_ci NS_BIT, 1); 88962306a36Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 89062306a36Sopenharmony_ci if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { 89162306a36Sopenharmony_ci set_aes_not_hash_mode(&desc[idx]); 89262306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC); 89362306a36Sopenharmony_ci } else { 89462306a36Sopenharmony_ci set_cipher_config0(&desc[idx], 89562306a36Sopenharmony_ci HASH_DIGEST_RESULT_LITTLE_ENDIAN); 89662306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hash_mode); 89762306a36Sopenharmony_ci } 89862306a36Sopenharmony_ci } else { /*Decrypt*/ 89962306a36Sopenharmony_ci /* Get ICV out from hardware */ 90062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 90162306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 90262306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 90362306a36Sopenharmony_ci set_dout_dlli(&desc[idx], req_ctx->mac_buf_dma_addr, 90462306a36Sopenharmony_ci ctx->authsize, NS_BIT, 1); 90562306a36Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 90662306a36Sopenharmony_ci set_cipher_config0(&desc[idx], 90762306a36Sopenharmony_ci HASH_DIGEST_RESULT_LITTLE_ENDIAN); 90862306a36Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED); 90962306a36Sopenharmony_ci if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { 91062306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC); 91162306a36Sopenharmony_ci set_aes_not_hash_mode(&desc[idx]); 91262306a36Sopenharmony_ci } else { 91362306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hash_mode); 91462306a36Sopenharmony_ci } 91562306a36Sopenharmony_ci } 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci *seq_size = (++idx); 91862306a36Sopenharmony_ci} 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_cistatic void cc_set_cipher_desc(struct aead_request *req, 92162306a36Sopenharmony_ci struct cc_hw_desc desc[], 92262306a36Sopenharmony_ci unsigned int *seq_size) 92362306a36Sopenharmony_ci{ 92462306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 92562306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 92662306a36Sopenharmony_ci struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req); 92762306a36Sopenharmony_ci unsigned int hw_iv_size = req_ctx->hw_iv_size; 92862306a36Sopenharmony_ci unsigned int idx = *seq_size; 92962306a36Sopenharmony_ci int direct = req_ctx->gen_ctx.op_type; 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci /* Setup cipher state */ 93262306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 93362306a36Sopenharmony_ci set_cipher_config0(&desc[idx], direct); 93462306a36Sopenharmony_ci set_flow_mode(&desc[idx], ctx->flow_mode); 93562306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, req_ctx->gen_ctx.iv_dma_addr, 93662306a36Sopenharmony_ci hw_iv_size, NS_BIT); 93762306a36Sopenharmony_ci if (ctx->cipher_mode == DRV_CIPHER_CTR) 93862306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); 93962306a36Sopenharmony_ci else 94062306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 94162306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->cipher_mode); 94262306a36Sopenharmony_ci idx++; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci /* Setup enc. key */ 94562306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 94662306a36Sopenharmony_ci set_cipher_config0(&desc[idx], direct); 94762306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 94862306a36Sopenharmony_ci set_flow_mode(&desc[idx], ctx->flow_mode); 94962306a36Sopenharmony_ci if (ctx->flow_mode == S_DIN_to_AES) { 95062306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr, 95162306a36Sopenharmony_ci ((ctx->enc_keylen == 24) ? CC_AES_KEY_SIZE_MAX : 95262306a36Sopenharmony_ci ctx->enc_keylen), NS_BIT); 95362306a36Sopenharmony_ci set_key_size_aes(&desc[idx], ctx->enc_keylen); 95462306a36Sopenharmony_ci } else { 95562306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr, 95662306a36Sopenharmony_ci ctx->enc_keylen, NS_BIT); 95762306a36Sopenharmony_ci set_key_size_des(&desc[idx], ctx->enc_keylen); 95862306a36Sopenharmony_ci } 95962306a36Sopenharmony_ci set_cipher_mode(&desc[idx], ctx->cipher_mode); 96062306a36Sopenharmony_ci idx++; 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci *seq_size = idx; 96362306a36Sopenharmony_ci} 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_cistatic void cc_proc_cipher(struct aead_request *req, struct cc_hw_desc desc[], 96662306a36Sopenharmony_ci unsigned int *seq_size, unsigned int data_flow_mode) 96762306a36Sopenharmony_ci{ 96862306a36Sopenharmony_ci struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req); 96962306a36Sopenharmony_ci int direct = req_ctx->gen_ctx.op_type; 97062306a36Sopenharmony_ci unsigned int idx = *seq_size; 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci if (req_ctx->cryptlen == 0) 97362306a36Sopenharmony_ci return; /*null processing*/ 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci cc_set_cipher_desc(req, desc, &idx); 97662306a36Sopenharmony_ci cc_proc_cipher_desc(req, data_flow_mode, desc, &idx); 97762306a36Sopenharmony_ci if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) { 97862306a36Sopenharmony_ci /* We must wait for DMA to write all cipher */ 97962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 98062306a36Sopenharmony_ci set_din_no_dma(&desc[idx], 0, 0xfffff0); 98162306a36Sopenharmony_ci set_dout_no_dma(&desc[idx], 0, 0, 1); 98262306a36Sopenharmony_ci idx++; 98362306a36Sopenharmony_ci } 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci *seq_size = idx; 98662306a36Sopenharmony_ci} 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_cistatic void cc_set_hmac_desc(struct aead_request *req, struct cc_hw_desc desc[], 98962306a36Sopenharmony_ci unsigned int *seq_size) 99062306a36Sopenharmony_ci{ 99162306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 99262306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 99362306a36Sopenharmony_ci unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ? 99462306a36Sopenharmony_ci DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256; 99562306a36Sopenharmony_ci unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ? 99662306a36Sopenharmony_ci CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE; 99762306a36Sopenharmony_ci unsigned int idx = *seq_size; 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci /* Loading hash ipad xor key state */ 100062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 100162306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hash_mode); 100262306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 100362306a36Sopenharmony_ci ctx->auth_state.hmac.ipad_opad_dma_addr, digest_size, 100462306a36Sopenharmony_ci NS_BIT); 100562306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 100662306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 100762306a36Sopenharmony_ci idx++; 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci /* Load init. digest len (64 bytes) */ 101062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 101162306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hash_mode); 101262306a36Sopenharmony_ci set_din_sram(&desc[idx], cc_digest_len_addr(ctx->drvdata, hash_mode), 101362306a36Sopenharmony_ci ctx->hash_len); 101462306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 101562306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 101662306a36Sopenharmony_ci idx++; 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci *seq_size = idx; 101962306a36Sopenharmony_ci} 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_cistatic void cc_set_xcbc_desc(struct aead_request *req, struct cc_hw_desc desc[], 102262306a36Sopenharmony_ci unsigned int *seq_size) 102362306a36Sopenharmony_ci{ 102462306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 102562306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 102662306a36Sopenharmony_ci unsigned int idx = *seq_size; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci /* Loading MAC state */ 102962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 103062306a36Sopenharmony_ci set_din_const(&desc[idx], 0, CC_AES_BLOCK_SIZE); 103162306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 103262306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC); 103362306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 103462306a36Sopenharmony_ci set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE); 103562306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 103662306a36Sopenharmony_ci set_aes_not_hash_mode(&desc[idx]); 103762306a36Sopenharmony_ci idx++; 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci /* Setup XCBC MAC K1 */ 104062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 104162306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 104262306a36Sopenharmony_ci ctx->auth_state.xcbc.xcbc_keys_dma_addr, 104362306a36Sopenharmony_ci AES_KEYSIZE_128, NS_BIT); 104462306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 104562306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC); 104662306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 104762306a36Sopenharmony_ci set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE); 104862306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 104962306a36Sopenharmony_ci set_aes_not_hash_mode(&desc[idx]); 105062306a36Sopenharmony_ci idx++; 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ci /* Setup XCBC MAC K2 */ 105362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 105462306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 105562306a36Sopenharmony_ci (ctx->auth_state.xcbc.xcbc_keys_dma_addr + 105662306a36Sopenharmony_ci AES_KEYSIZE_128), AES_KEYSIZE_128, NS_BIT); 105762306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); 105862306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC); 105962306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 106062306a36Sopenharmony_ci set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE); 106162306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 106262306a36Sopenharmony_ci set_aes_not_hash_mode(&desc[idx]); 106362306a36Sopenharmony_ci idx++; 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci /* Setup XCBC MAC K3 */ 106662306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 106762306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 106862306a36Sopenharmony_ci (ctx->auth_state.xcbc.xcbc_keys_dma_addr + 106962306a36Sopenharmony_ci 2 * AES_KEYSIZE_128), AES_KEYSIZE_128, NS_BIT); 107062306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE2); 107162306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC); 107262306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 107362306a36Sopenharmony_ci set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE); 107462306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 107562306a36Sopenharmony_ci set_aes_not_hash_mode(&desc[idx]); 107662306a36Sopenharmony_ci idx++; 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci *seq_size = idx; 107962306a36Sopenharmony_ci} 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_cistatic void cc_proc_header_desc(struct aead_request *req, 108262306a36Sopenharmony_ci struct cc_hw_desc desc[], 108362306a36Sopenharmony_ci unsigned int *seq_size) 108462306a36Sopenharmony_ci{ 108562306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req); 108662306a36Sopenharmony_ci unsigned int idx = *seq_size; 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci /* Hash associated data */ 108962306a36Sopenharmony_ci if (areq_ctx->assoclen > 0) 109062306a36Sopenharmony_ci cc_set_assoc_desc(req, DIN_HASH, desc, &idx); 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci /* Hash IV */ 109362306a36Sopenharmony_ci *seq_size = idx; 109462306a36Sopenharmony_ci} 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_cistatic void cc_proc_scheme_desc(struct aead_request *req, 109762306a36Sopenharmony_ci struct cc_hw_desc desc[], 109862306a36Sopenharmony_ci unsigned int *seq_size) 109962306a36Sopenharmony_ci{ 110062306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 110162306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 110262306a36Sopenharmony_ci struct cc_aead_handle *aead_handle = ctx->drvdata->aead_handle; 110362306a36Sopenharmony_ci unsigned int hash_mode = (ctx->auth_mode == DRV_HASH_SHA1) ? 110462306a36Sopenharmony_ci DRV_HASH_HW_SHA1 : DRV_HASH_HW_SHA256; 110562306a36Sopenharmony_ci unsigned int digest_size = (ctx->auth_mode == DRV_HASH_SHA1) ? 110662306a36Sopenharmony_ci CC_SHA1_DIGEST_SIZE : CC_SHA256_DIGEST_SIZE; 110762306a36Sopenharmony_ci unsigned int idx = *seq_size; 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 111062306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hash_mode); 111162306a36Sopenharmony_ci set_dout_sram(&desc[idx], aead_handle->sram_workspace_addr, 111262306a36Sopenharmony_ci ctx->hash_len); 111362306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 111462306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE1); 111562306a36Sopenharmony_ci set_cipher_do(&desc[idx], DO_PAD); 111662306a36Sopenharmony_ci idx++; 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ci /* Get final ICV result */ 111962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 112062306a36Sopenharmony_ci set_dout_sram(&desc[idx], aead_handle->sram_workspace_addr, 112162306a36Sopenharmony_ci digest_size); 112262306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 112362306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 112462306a36Sopenharmony_ci set_cipher_config0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN); 112562306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hash_mode); 112662306a36Sopenharmony_ci idx++; 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci /* Loading hash opad xor key state */ 112962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 113062306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hash_mode); 113162306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 113262306a36Sopenharmony_ci (ctx->auth_state.hmac.ipad_opad_dma_addr + digest_size), 113362306a36Sopenharmony_ci digest_size, NS_BIT); 113462306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 113562306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 113662306a36Sopenharmony_ci idx++; 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci /* Load init. digest len (64 bytes) */ 113962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 114062306a36Sopenharmony_ci set_cipher_mode(&desc[idx], hash_mode); 114162306a36Sopenharmony_ci set_din_sram(&desc[idx], cc_digest_len_addr(ctx->drvdata, hash_mode), 114262306a36Sopenharmony_ci ctx->hash_len); 114362306a36Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); 114462306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 114562306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 114662306a36Sopenharmony_ci idx++; 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_ci /* Perform HASH update */ 114962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 115062306a36Sopenharmony_ci set_din_sram(&desc[idx], aead_handle->sram_workspace_addr, 115162306a36Sopenharmony_ci digest_size); 115262306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_HASH); 115362306a36Sopenharmony_ci idx++; 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci *seq_size = idx; 115662306a36Sopenharmony_ci} 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_cistatic void cc_mlli_to_sram(struct aead_request *req, 115962306a36Sopenharmony_ci struct cc_hw_desc desc[], unsigned int *seq_size) 116062306a36Sopenharmony_ci{ 116162306a36Sopenharmony_ci struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req); 116262306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 116362306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 116462306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci if ((req_ctx->assoc_buff_type == CC_DMA_BUF_MLLI || 116762306a36Sopenharmony_ci req_ctx->data_buff_type == CC_DMA_BUF_MLLI || 116862306a36Sopenharmony_ci !req_ctx->is_single_pass) && req_ctx->mlli_params.mlli_len) { 116962306a36Sopenharmony_ci dev_dbg(dev, "Copy-to-sram: mlli_dma=%08x, mlli_size=%u\n", 117062306a36Sopenharmony_ci ctx->drvdata->mlli_sram_addr, 117162306a36Sopenharmony_ci req_ctx->mlli_params.mlli_len); 117262306a36Sopenharmony_ci /* Copy MLLI table host-to-sram */ 117362306a36Sopenharmony_ci hw_desc_init(&desc[*seq_size]); 117462306a36Sopenharmony_ci set_din_type(&desc[*seq_size], DMA_DLLI, 117562306a36Sopenharmony_ci req_ctx->mlli_params.mlli_dma_addr, 117662306a36Sopenharmony_ci req_ctx->mlli_params.mlli_len, NS_BIT); 117762306a36Sopenharmony_ci set_dout_sram(&desc[*seq_size], 117862306a36Sopenharmony_ci ctx->drvdata->mlli_sram_addr, 117962306a36Sopenharmony_ci req_ctx->mlli_params.mlli_len); 118062306a36Sopenharmony_ci set_flow_mode(&desc[*seq_size], BYPASS); 118162306a36Sopenharmony_ci (*seq_size)++; 118262306a36Sopenharmony_ci } 118362306a36Sopenharmony_ci} 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_cistatic enum cc_flow_mode cc_get_data_flow(enum drv_crypto_direction direct, 118662306a36Sopenharmony_ci enum cc_flow_mode setup_flow_mode, 118762306a36Sopenharmony_ci bool is_single_pass) 118862306a36Sopenharmony_ci{ 118962306a36Sopenharmony_ci enum cc_flow_mode data_flow_mode; 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) { 119262306a36Sopenharmony_ci if (setup_flow_mode == S_DIN_to_AES) 119362306a36Sopenharmony_ci data_flow_mode = is_single_pass ? 119462306a36Sopenharmony_ci AES_to_HASH_and_DOUT : DIN_AES_DOUT; 119562306a36Sopenharmony_ci else 119662306a36Sopenharmony_ci data_flow_mode = is_single_pass ? 119762306a36Sopenharmony_ci DES_to_HASH_and_DOUT : DIN_DES_DOUT; 119862306a36Sopenharmony_ci } else { /* Decrypt */ 119962306a36Sopenharmony_ci if (setup_flow_mode == S_DIN_to_AES) 120062306a36Sopenharmony_ci data_flow_mode = is_single_pass ? 120162306a36Sopenharmony_ci AES_and_HASH : DIN_AES_DOUT; 120262306a36Sopenharmony_ci else 120362306a36Sopenharmony_ci data_flow_mode = is_single_pass ? 120462306a36Sopenharmony_ci DES_and_HASH : DIN_DES_DOUT; 120562306a36Sopenharmony_ci } 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci return data_flow_mode; 120862306a36Sopenharmony_ci} 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_cistatic void cc_hmac_authenc(struct aead_request *req, struct cc_hw_desc desc[], 121162306a36Sopenharmony_ci unsigned int *seq_size) 121262306a36Sopenharmony_ci{ 121362306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 121462306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 121562306a36Sopenharmony_ci struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req); 121662306a36Sopenharmony_ci int direct = req_ctx->gen_ctx.op_type; 121762306a36Sopenharmony_ci unsigned int data_flow_mode = 121862306a36Sopenharmony_ci cc_get_data_flow(direct, ctx->flow_mode, 121962306a36Sopenharmony_ci req_ctx->is_single_pass); 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci if (req_ctx->is_single_pass) { 122262306a36Sopenharmony_ci /* 122362306a36Sopenharmony_ci * Single-pass flow 122462306a36Sopenharmony_ci */ 122562306a36Sopenharmony_ci cc_set_hmac_desc(req, desc, seq_size); 122662306a36Sopenharmony_ci cc_set_cipher_desc(req, desc, seq_size); 122762306a36Sopenharmony_ci cc_proc_header_desc(req, desc, seq_size); 122862306a36Sopenharmony_ci cc_proc_cipher_desc(req, data_flow_mode, desc, seq_size); 122962306a36Sopenharmony_ci cc_proc_scheme_desc(req, desc, seq_size); 123062306a36Sopenharmony_ci cc_proc_digest_desc(req, desc, seq_size); 123162306a36Sopenharmony_ci return; 123262306a36Sopenharmony_ci } 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci /* 123562306a36Sopenharmony_ci * Double-pass flow 123662306a36Sopenharmony_ci * Fallback for unsupported single-pass modes, 123762306a36Sopenharmony_ci * i.e. using assoc. data of non-word-multiple 123862306a36Sopenharmony_ci */ 123962306a36Sopenharmony_ci if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) { 124062306a36Sopenharmony_ci /* encrypt first.. */ 124162306a36Sopenharmony_ci cc_proc_cipher(req, desc, seq_size, data_flow_mode); 124262306a36Sopenharmony_ci /* authenc after..*/ 124362306a36Sopenharmony_ci cc_set_hmac_desc(req, desc, seq_size); 124462306a36Sopenharmony_ci cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct); 124562306a36Sopenharmony_ci cc_proc_scheme_desc(req, desc, seq_size); 124662306a36Sopenharmony_ci cc_proc_digest_desc(req, desc, seq_size); 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci } else { /*DECRYPT*/ 124962306a36Sopenharmony_ci /* authenc first..*/ 125062306a36Sopenharmony_ci cc_set_hmac_desc(req, desc, seq_size); 125162306a36Sopenharmony_ci cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct); 125262306a36Sopenharmony_ci cc_proc_scheme_desc(req, desc, seq_size); 125362306a36Sopenharmony_ci /* decrypt after.. */ 125462306a36Sopenharmony_ci cc_proc_cipher(req, desc, seq_size, data_flow_mode); 125562306a36Sopenharmony_ci /* read the digest result with setting the completion bit 125662306a36Sopenharmony_ci * must be after the cipher operation 125762306a36Sopenharmony_ci */ 125862306a36Sopenharmony_ci cc_proc_digest_desc(req, desc, seq_size); 125962306a36Sopenharmony_ci } 126062306a36Sopenharmony_ci} 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_cistatic void 126362306a36Sopenharmony_cicc_xcbc_authenc(struct aead_request *req, struct cc_hw_desc desc[], 126462306a36Sopenharmony_ci unsigned int *seq_size) 126562306a36Sopenharmony_ci{ 126662306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 126762306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 126862306a36Sopenharmony_ci struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req); 126962306a36Sopenharmony_ci int direct = req_ctx->gen_ctx.op_type; 127062306a36Sopenharmony_ci unsigned int data_flow_mode = 127162306a36Sopenharmony_ci cc_get_data_flow(direct, ctx->flow_mode, 127262306a36Sopenharmony_ci req_ctx->is_single_pass); 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci if (req_ctx->is_single_pass) { 127562306a36Sopenharmony_ci /* 127662306a36Sopenharmony_ci * Single-pass flow 127762306a36Sopenharmony_ci */ 127862306a36Sopenharmony_ci cc_set_xcbc_desc(req, desc, seq_size); 127962306a36Sopenharmony_ci cc_set_cipher_desc(req, desc, seq_size); 128062306a36Sopenharmony_ci cc_proc_header_desc(req, desc, seq_size); 128162306a36Sopenharmony_ci cc_proc_cipher_desc(req, data_flow_mode, desc, seq_size); 128262306a36Sopenharmony_ci cc_proc_digest_desc(req, desc, seq_size); 128362306a36Sopenharmony_ci return; 128462306a36Sopenharmony_ci } 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_ci /* 128762306a36Sopenharmony_ci * Double-pass flow 128862306a36Sopenharmony_ci * Fallback for unsupported single-pass modes, 128962306a36Sopenharmony_ci * i.e. using assoc. data of non-word-multiple 129062306a36Sopenharmony_ci */ 129162306a36Sopenharmony_ci if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) { 129262306a36Sopenharmony_ci /* encrypt first.. */ 129362306a36Sopenharmony_ci cc_proc_cipher(req, desc, seq_size, data_flow_mode); 129462306a36Sopenharmony_ci /* authenc after.. */ 129562306a36Sopenharmony_ci cc_set_xcbc_desc(req, desc, seq_size); 129662306a36Sopenharmony_ci cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct); 129762306a36Sopenharmony_ci cc_proc_digest_desc(req, desc, seq_size); 129862306a36Sopenharmony_ci } else { /*DECRYPT*/ 129962306a36Sopenharmony_ci /* authenc first.. */ 130062306a36Sopenharmony_ci cc_set_xcbc_desc(req, desc, seq_size); 130162306a36Sopenharmony_ci cc_proc_authen_desc(req, DIN_HASH, desc, seq_size, direct); 130262306a36Sopenharmony_ci /* decrypt after..*/ 130362306a36Sopenharmony_ci cc_proc_cipher(req, desc, seq_size, data_flow_mode); 130462306a36Sopenharmony_ci /* read the digest result with setting the completion bit 130562306a36Sopenharmony_ci * must be after the cipher operation 130662306a36Sopenharmony_ci */ 130762306a36Sopenharmony_ci cc_proc_digest_desc(req, desc, seq_size); 130862306a36Sopenharmony_ci } 130962306a36Sopenharmony_ci} 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_cistatic int validate_data_size(struct cc_aead_ctx *ctx, 131262306a36Sopenharmony_ci enum drv_crypto_direction direct, 131362306a36Sopenharmony_ci struct aead_request *req) 131462306a36Sopenharmony_ci{ 131562306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req); 131662306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 131762306a36Sopenharmony_ci unsigned int assoclen = areq_ctx->assoclen; 131862306a36Sopenharmony_ci unsigned int cipherlen = (direct == DRV_CRYPTO_DIRECTION_DECRYPT) ? 131962306a36Sopenharmony_ci (req->cryptlen - ctx->authsize) : req->cryptlen; 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ci if (direct == DRV_CRYPTO_DIRECTION_DECRYPT && 132262306a36Sopenharmony_ci req->cryptlen < ctx->authsize) 132362306a36Sopenharmony_ci goto data_size_err; 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ci areq_ctx->is_single_pass = true; /*defaulted to fast flow*/ 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_ci switch (ctx->flow_mode) { 132862306a36Sopenharmony_ci case S_DIN_to_AES: 132962306a36Sopenharmony_ci if (ctx->cipher_mode == DRV_CIPHER_CBC && 133062306a36Sopenharmony_ci !IS_ALIGNED(cipherlen, AES_BLOCK_SIZE)) 133162306a36Sopenharmony_ci goto data_size_err; 133262306a36Sopenharmony_ci if (ctx->cipher_mode == DRV_CIPHER_CCM) 133362306a36Sopenharmony_ci break; 133462306a36Sopenharmony_ci if (ctx->cipher_mode == DRV_CIPHER_GCTR) { 133562306a36Sopenharmony_ci if (areq_ctx->plaintext_authenticate_only) 133662306a36Sopenharmony_ci areq_ctx->is_single_pass = false; 133762306a36Sopenharmony_ci break; 133862306a36Sopenharmony_ci } 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci if (!IS_ALIGNED(assoclen, sizeof(u32))) 134162306a36Sopenharmony_ci areq_ctx->is_single_pass = false; 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci if (ctx->cipher_mode == DRV_CIPHER_CTR && 134462306a36Sopenharmony_ci !IS_ALIGNED(cipherlen, sizeof(u32))) 134562306a36Sopenharmony_ci areq_ctx->is_single_pass = false; 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ci break; 134862306a36Sopenharmony_ci case S_DIN_to_DES: 134962306a36Sopenharmony_ci if (!IS_ALIGNED(cipherlen, DES_BLOCK_SIZE)) 135062306a36Sopenharmony_ci goto data_size_err; 135162306a36Sopenharmony_ci if (!IS_ALIGNED(assoclen, DES_BLOCK_SIZE)) 135262306a36Sopenharmony_ci areq_ctx->is_single_pass = false; 135362306a36Sopenharmony_ci break; 135462306a36Sopenharmony_ci default: 135562306a36Sopenharmony_ci dev_err(dev, "Unexpected flow mode (%d)\n", ctx->flow_mode); 135662306a36Sopenharmony_ci goto data_size_err; 135762306a36Sopenharmony_ci } 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci return 0; 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_cidata_size_err: 136262306a36Sopenharmony_ci return -EINVAL; 136362306a36Sopenharmony_ci} 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_cistatic unsigned int format_ccm_a0(u8 *pa0_buff, u32 header_size) 136662306a36Sopenharmony_ci{ 136762306a36Sopenharmony_ci unsigned int len = 0; 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci if (header_size == 0) 137062306a36Sopenharmony_ci return 0; 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci if (header_size < ((1UL << 16) - (1UL << 8))) { 137362306a36Sopenharmony_ci len = 2; 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci pa0_buff[0] = (header_size >> 8) & 0xFF; 137662306a36Sopenharmony_ci pa0_buff[1] = header_size & 0xFF; 137762306a36Sopenharmony_ci } else { 137862306a36Sopenharmony_ci len = 6; 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci pa0_buff[0] = 0xFF; 138162306a36Sopenharmony_ci pa0_buff[1] = 0xFE; 138262306a36Sopenharmony_ci pa0_buff[2] = (header_size >> 24) & 0xFF; 138362306a36Sopenharmony_ci pa0_buff[3] = (header_size >> 16) & 0xFF; 138462306a36Sopenharmony_ci pa0_buff[4] = (header_size >> 8) & 0xFF; 138562306a36Sopenharmony_ci pa0_buff[5] = header_size & 0xFF; 138662306a36Sopenharmony_ci } 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci return len; 138962306a36Sopenharmony_ci} 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_cistatic int set_msg_len(u8 *block, unsigned int msglen, unsigned int csize) 139262306a36Sopenharmony_ci{ 139362306a36Sopenharmony_ci __be32 data; 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci memset(block, 0, csize); 139662306a36Sopenharmony_ci block += csize; 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci if (csize >= 4) 139962306a36Sopenharmony_ci csize = 4; 140062306a36Sopenharmony_ci else if (msglen > (1 << (8 * csize))) 140162306a36Sopenharmony_ci return -EOVERFLOW; 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci data = cpu_to_be32(msglen); 140462306a36Sopenharmony_ci memcpy(block - csize, (u8 *)&data + 4 - csize, csize); 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci return 0; 140762306a36Sopenharmony_ci} 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_cistatic int cc_ccm(struct aead_request *req, struct cc_hw_desc desc[], 141062306a36Sopenharmony_ci unsigned int *seq_size) 141162306a36Sopenharmony_ci{ 141262306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 141362306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 141462306a36Sopenharmony_ci struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req); 141562306a36Sopenharmony_ci unsigned int idx = *seq_size; 141662306a36Sopenharmony_ci unsigned int cipher_flow_mode; 141762306a36Sopenharmony_ci dma_addr_t mac_result; 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) { 142062306a36Sopenharmony_ci cipher_flow_mode = AES_to_HASH_and_DOUT; 142162306a36Sopenharmony_ci mac_result = req_ctx->mac_buf_dma_addr; 142262306a36Sopenharmony_ci } else { /* Encrypt */ 142362306a36Sopenharmony_ci cipher_flow_mode = AES_and_HASH; 142462306a36Sopenharmony_ci mac_result = req_ctx->icv_dma_addr; 142562306a36Sopenharmony_ci } 142662306a36Sopenharmony_ci 142762306a36Sopenharmony_ci /* load key */ 142862306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 142962306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_CTR); 143062306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr, 143162306a36Sopenharmony_ci ((ctx->enc_keylen == 24) ? CC_AES_KEY_SIZE_MAX : 143262306a36Sopenharmony_ci ctx->enc_keylen), NS_BIT); 143362306a36Sopenharmony_ci set_key_size_aes(&desc[idx], ctx->enc_keylen); 143462306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 143562306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 143662306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 143762306a36Sopenharmony_ci idx++; 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_ci /* load ctr state */ 144062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 144162306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_CTR); 144262306a36Sopenharmony_ci set_key_size_aes(&desc[idx], ctx->enc_keylen); 144362306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 144462306a36Sopenharmony_ci req_ctx->gen_ctx.iv_dma_addr, AES_BLOCK_SIZE, NS_BIT); 144562306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 144662306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); 144762306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 144862306a36Sopenharmony_ci idx++; 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci /* load MAC key */ 145162306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 145262306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC); 145362306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr, 145462306a36Sopenharmony_ci ((ctx->enc_keylen == 24) ? CC_AES_KEY_SIZE_MAX : 145562306a36Sopenharmony_ci ctx->enc_keylen), NS_BIT); 145662306a36Sopenharmony_ci set_key_size_aes(&desc[idx], ctx->enc_keylen); 145762306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 145862306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 145962306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 146062306a36Sopenharmony_ci set_aes_not_hash_mode(&desc[idx]); 146162306a36Sopenharmony_ci idx++; 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_ci /* load MAC state */ 146462306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 146562306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC); 146662306a36Sopenharmony_ci set_key_size_aes(&desc[idx], ctx->enc_keylen); 146762306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, req_ctx->mac_buf_dma_addr, 146862306a36Sopenharmony_ci AES_BLOCK_SIZE, NS_BIT); 146962306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT); 147062306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 147162306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 147262306a36Sopenharmony_ci set_aes_not_hash_mode(&desc[idx]); 147362306a36Sopenharmony_ci idx++; 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_ci /* process assoc data */ 147662306a36Sopenharmony_ci if (req_ctx->assoclen > 0) { 147762306a36Sopenharmony_ci cc_set_assoc_desc(req, DIN_HASH, desc, &idx); 147862306a36Sopenharmony_ci } else { 147962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 148062306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 148162306a36Sopenharmony_ci sg_dma_address(&req_ctx->ccm_adata_sg), 148262306a36Sopenharmony_ci AES_BLOCK_SIZE + req_ctx->ccm_hdr_size, NS_BIT); 148362306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_HASH); 148462306a36Sopenharmony_ci idx++; 148562306a36Sopenharmony_ci } 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci /* process the cipher */ 148862306a36Sopenharmony_ci if (req_ctx->cryptlen) 148962306a36Sopenharmony_ci cc_proc_cipher_desc(req, cipher_flow_mode, desc, &idx); 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_ci /* Read temporal MAC */ 149262306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 149362306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_CBC_MAC); 149462306a36Sopenharmony_ci set_dout_dlli(&desc[idx], req_ctx->mac_buf_dma_addr, ctx->authsize, 149562306a36Sopenharmony_ci NS_BIT, 0); 149662306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 149762306a36Sopenharmony_ci set_cipher_config0(&desc[idx], HASH_DIGEST_RESULT_LITTLE_ENDIAN); 149862306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 149962306a36Sopenharmony_ci set_aes_not_hash_mode(&desc[idx]); 150062306a36Sopenharmony_ci idx++; 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_ci /* load AES-CTR state (for last MAC calculation)*/ 150362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 150462306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_CTR); 150562306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT); 150662306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, req_ctx->ccm_iv0_dma_addr, 150762306a36Sopenharmony_ci AES_BLOCK_SIZE, NS_BIT); 150862306a36Sopenharmony_ci set_key_size_aes(&desc[idx], ctx->enc_keylen); 150962306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); 151062306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 151162306a36Sopenharmony_ci idx++; 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 151462306a36Sopenharmony_ci set_din_no_dma(&desc[idx], 0, 0xfffff0); 151562306a36Sopenharmony_ci set_dout_no_dma(&desc[idx], 0, 0, 1); 151662306a36Sopenharmony_ci idx++; 151762306a36Sopenharmony_ci 151862306a36Sopenharmony_ci /* encrypt the "T" value and store MAC in mac_state */ 151962306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 152062306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, req_ctx->mac_buf_dma_addr, 152162306a36Sopenharmony_ci ctx->authsize, NS_BIT); 152262306a36Sopenharmony_ci set_dout_dlli(&desc[idx], mac_result, ctx->authsize, NS_BIT, 1); 152362306a36Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 152462306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_AES_DOUT); 152562306a36Sopenharmony_ci idx++; 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci *seq_size = idx; 152862306a36Sopenharmony_ci return 0; 152962306a36Sopenharmony_ci} 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_cistatic int config_ccm_adata(struct aead_request *req) 153262306a36Sopenharmony_ci{ 153362306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 153462306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 153562306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 153662306a36Sopenharmony_ci struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req); 153762306a36Sopenharmony_ci //unsigned int size_of_a = 0, rem_a_size = 0; 153862306a36Sopenharmony_ci unsigned int lp = req->iv[0]; 153962306a36Sopenharmony_ci /* Note: The code assume that req->iv[0] already contains the value 154062306a36Sopenharmony_ci * of L' of RFC3610 154162306a36Sopenharmony_ci */ 154262306a36Sopenharmony_ci unsigned int l = lp + 1; /* This is L' of RFC 3610. */ 154362306a36Sopenharmony_ci unsigned int m = ctx->authsize; /* This is M' of RFC 3610. */ 154462306a36Sopenharmony_ci u8 *b0 = req_ctx->ccm_config + CCM_B0_OFFSET; 154562306a36Sopenharmony_ci u8 *a0 = req_ctx->ccm_config + CCM_A0_OFFSET; 154662306a36Sopenharmony_ci u8 *ctr_count_0 = req_ctx->ccm_config + CCM_CTR_COUNT_0_OFFSET; 154762306a36Sopenharmony_ci unsigned int cryptlen = (req_ctx->gen_ctx.op_type == 154862306a36Sopenharmony_ci DRV_CRYPTO_DIRECTION_ENCRYPT) ? 154962306a36Sopenharmony_ci req->cryptlen : 155062306a36Sopenharmony_ci (req->cryptlen - ctx->authsize); 155162306a36Sopenharmony_ci int rc; 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci memset(req_ctx->mac_buf, 0, AES_BLOCK_SIZE); 155462306a36Sopenharmony_ci memset(req_ctx->ccm_config, 0, AES_BLOCK_SIZE * 3); 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci /* taken from crypto/ccm.c */ 155762306a36Sopenharmony_ci /* 2 <= L <= 8, so 1 <= L' <= 7. */ 155862306a36Sopenharmony_ci if (l < 2 || l > 8) { 155962306a36Sopenharmony_ci dev_dbg(dev, "illegal iv value %X\n", req->iv[0]); 156062306a36Sopenharmony_ci return -EINVAL; 156162306a36Sopenharmony_ci } 156262306a36Sopenharmony_ci memcpy(b0, req->iv, AES_BLOCK_SIZE); 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci /* format control info per RFC 3610 and 156562306a36Sopenharmony_ci * NIST Special Publication 800-38C 156662306a36Sopenharmony_ci */ 156762306a36Sopenharmony_ci *b0 |= (8 * ((m - 2) / 2)); 156862306a36Sopenharmony_ci if (req_ctx->assoclen > 0) 156962306a36Sopenharmony_ci *b0 |= 64; /* Enable bit 6 if Adata exists. */ 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_ci rc = set_msg_len(b0 + 16 - l, cryptlen, l); /* Write L'. */ 157262306a36Sopenharmony_ci if (rc) { 157362306a36Sopenharmony_ci dev_err(dev, "message len overflow detected"); 157462306a36Sopenharmony_ci return rc; 157562306a36Sopenharmony_ci } 157662306a36Sopenharmony_ci /* END of "taken from crypto/ccm.c" */ 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_ci /* l(a) - size of associated data. */ 157962306a36Sopenharmony_ci req_ctx->ccm_hdr_size = format_ccm_a0(a0, req_ctx->assoclen); 158062306a36Sopenharmony_ci 158162306a36Sopenharmony_ci memset(req->iv + 15 - req->iv[0], 0, req->iv[0] + 1); 158262306a36Sopenharmony_ci req->iv[15] = 1; 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_ci memcpy(ctr_count_0, req->iv, AES_BLOCK_SIZE); 158562306a36Sopenharmony_ci ctr_count_0[15] = 0; 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_ci return 0; 158862306a36Sopenharmony_ci} 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_cistatic void cc_proc_rfc4309_ccm(struct aead_request *req) 159162306a36Sopenharmony_ci{ 159262306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 159362306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 159462306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req); 159562306a36Sopenharmony_ci 159662306a36Sopenharmony_ci /* L' */ 159762306a36Sopenharmony_ci memset(areq_ctx->ctr_iv, 0, AES_BLOCK_SIZE); 159862306a36Sopenharmony_ci /* For RFC 4309, always use 4 bytes for message length 159962306a36Sopenharmony_ci * (at most 2^32-1 bytes). 160062306a36Sopenharmony_ci */ 160162306a36Sopenharmony_ci areq_ctx->ctr_iv[0] = 3; 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci /* In RFC 4309 there is an 11-bytes nonce+IV part, 160462306a36Sopenharmony_ci * that we build here. 160562306a36Sopenharmony_ci */ 160662306a36Sopenharmony_ci memcpy(areq_ctx->ctr_iv + CCM_BLOCK_NONCE_OFFSET, ctx->ctr_nonce, 160762306a36Sopenharmony_ci CCM_BLOCK_NONCE_SIZE); 160862306a36Sopenharmony_ci memcpy(areq_ctx->ctr_iv + CCM_BLOCK_IV_OFFSET, req->iv, 160962306a36Sopenharmony_ci CCM_BLOCK_IV_SIZE); 161062306a36Sopenharmony_ci req->iv = areq_ctx->ctr_iv; 161162306a36Sopenharmony_ci} 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_cistatic void cc_set_ghash_desc(struct aead_request *req, 161462306a36Sopenharmony_ci struct cc_hw_desc desc[], unsigned int *seq_size) 161562306a36Sopenharmony_ci{ 161662306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 161762306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 161862306a36Sopenharmony_ci struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req); 161962306a36Sopenharmony_ci unsigned int idx = *seq_size; 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_ci /* load key to AES*/ 162262306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 162362306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_ECB); 162462306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT); 162562306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr, 162662306a36Sopenharmony_ci ctx->enc_keylen, NS_BIT); 162762306a36Sopenharmony_ci set_key_size_aes(&desc[idx], ctx->enc_keylen); 162862306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 162962306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 163062306a36Sopenharmony_ci idx++; 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci /* process one zero block to generate hkey */ 163362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 163462306a36Sopenharmony_ci set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE); 163562306a36Sopenharmony_ci set_dout_dlli(&desc[idx], req_ctx->hkey_dma_addr, AES_BLOCK_SIZE, 163662306a36Sopenharmony_ci NS_BIT, 0); 163762306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_AES_DOUT); 163862306a36Sopenharmony_ci idx++; 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_ci /* Memory Barrier */ 164162306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 164262306a36Sopenharmony_ci set_din_no_dma(&desc[idx], 0, 0xfffff0); 164362306a36Sopenharmony_ci set_dout_no_dma(&desc[idx], 0, 0, 1); 164462306a36Sopenharmony_ci idx++; 164562306a36Sopenharmony_ci 164662306a36Sopenharmony_ci /* Load GHASH subkey */ 164762306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 164862306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, req_ctx->hkey_dma_addr, 164962306a36Sopenharmony_ci AES_BLOCK_SIZE, NS_BIT); 165062306a36Sopenharmony_ci set_dout_no_dma(&desc[idx], 0, 0, 1); 165162306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 165262306a36Sopenharmony_ci set_aes_not_hash_mode(&desc[idx]); 165362306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH); 165462306a36Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); 165562306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 165662306a36Sopenharmony_ci idx++; 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci /* Configure Hash Engine to work with GHASH. 165962306a36Sopenharmony_ci * Since it was not possible to extend HASH submodes to add GHASH, 166062306a36Sopenharmony_ci * The following command is necessary in order to 166162306a36Sopenharmony_ci * select GHASH (according to HW designers) 166262306a36Sopenharmony_ci */ 166362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 166462306a36Sopenharmony_ci set_din_no_dma(&desc[idx], 0, 0xfffff0); 166562306a36Sopenharmony_ci set_dout_no_dma(&desc[idx], 0, 0, 1); 166662306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 166762306a36Sopenharmony_ci set_aes_not_hash_mode(&desc[idx]); 166862306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH); 166962306a36Sopenharmony_ci set_cipher_do(&desc[idx], 1); //1=AES_SK RKEK 167062306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT); 167162306a36Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); 167262306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 167362306a36Sopenharmony_ci idx++; 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_ci /* Load GHASH initial STATE (which is 0). (for any hash there is an 167662306a36Sopenharmony_ci * initial state) 167762306a36Sopenharmony_ci */ 167862306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 167962306a36Sopenharmony_ci set_din_const(&desc[idx], 0x0, AES_BLOCK_SIZE); 168062306a36Sopenharmony_ci set_dout_no_dma(&desc[idx], 0, 0, 1); 168162306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_HASH); 168262306a36Sopenharmony_ci set_aes_not_hash_mode(&desc[idx]); 168362306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH); 168462306a36Sopenharmony_ci set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED); 168562306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE0); 168662306a36Sopenharmony_ci idx++; 168762306a36Sopenharmony_ci 168862306a36Sopenharmony_ci *seq_size = idx; 168962306a36Sopenharmony_ci} 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_cistatic void cc_set_gctr_desc(struct aead_request *req, struct cc_hw_desc desc[], 169262306a36Sopenharmony_ci unsigned int *seq_size) 169362306a36Sopenharmony_ci{ 169462306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 169562306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 169662306a36Sopenharmony_ci struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req); 169762306a36Sopenharmony_ci unsigned int idx = *seq_size; 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_ci /* load key to AES*/ 170062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 170162306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR); 170262306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT); 170362306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, ctx->enckey_dma_addr, 170462306a36Sopenharmony_ci ctx->enc_keylen, NS_BIT); 170562306a36Sopenharmony_ci set_key_size_aes(&desc[idx], ctx->enc_keylen); 170662306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_KEY0); 170762306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 170862306a36Sopenharmony_ci idx++; 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_ci if (req_ctx->cryptlen && !req_ctx->plaintext_authenticate_only) { 171162306a36Sopenharmony_ci /* load AES/CTR initial CTR value inc by 2*/ 171262306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 171362306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR); 171462306a36Sopenharmony_ci set_key_size_aes(&desc[idx], ctx->enc_keylen); 171562306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, 171662306a36Sopenharmony_ci req_ctx->gcm_iv_inc2_dma_addr, AES_BLOCK_SIZE, 171762306a36Sopenharmony_ci NS_BIT); 171862306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT); 171962306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); 172062306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 172162306a36Sopenharmony_ci idx++; 172262306a36Sopenharmony_ci } 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ci *seq_size = idx; 172562306a36Sopenharmony_ci} 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_cistatic void cc_proc_gcm_result(struct aead_request *req, 172862306a36Sopenharmony_ci struct cc_hw_desc desc[], 172962306a36Sopenharmony_ci unsigned int *seq_size) 173062306a36Sopenharmony_ci{ 173162306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 173262306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 173362306a36Sopenharmony_ci struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req); 173462306a36Sopenharmony_ci dma_addr_t mac_result; 173562306a36Sopenharmony_ci unsigned int idx = *seq_size; 173662306a36Sopenharmony_ci 173762306a36Sopenharmony_ci if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) { 173862306a36Sopenharmony_ci mac_result = req_ctx->mac_buf_dma_addr; 173962306a36Sopenharmony_ci } else { /* Encrypt */ 174062306a36Sopenharmony_ci mac_result = req_ctx->icv_dma_addr; 174162306a36Sopenharmony_ci } 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci /* process(ghash) gcm_block_len */ 174462306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 174562306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, req_ctx->gcm_block_len_dma_addr, 174662306a36Sopenharmony_ci AES_BLOCK_SIZE, NS_BIT); 174762306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_HASH); 174862306a36Sopenharmony_ci idx++; 174962306a36Sopenharmony_ci 175062306a36Sopenharmony_ci /* Store GHASH state after GHASH(Associated Data + Cipher +LenBlock) */ 175162306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 175262306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_HASH_HW_GHASH); 175362306a36Sopenharmony_ci set_din_no_dma(&desc[idx], 0, 0xfffff0); 175462306a36Sopenharmony_ci set_dout_dlli(&desc[idx], req_ctx->mac_buf_dma_addr, AES_BLOCK_SIZE, 175562306a36Sopenharmony_ci NS_BIT, 0); 175662306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_WRITE_STATE0); 175762306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_HASH_to_DOUT); 175862306a36Sopenharmony_ci set_aes_not_hash_mode(&desc[idx]); 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci idx++; 176162306a36Sopenharmony_ci 176262306a36Sopenharmony_ci /* load AES/CTR initial CTR value inc by 1*/ 176362306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 176462306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR); 176562306a36Sopenharmony_ci set_key_size_aes(&desc[idx], ctx->enc_keylen); 176662306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, req_ctx->gcm_iv_inc1_dma_addr, 176762306a36Sopenharmony_ci AES_BLOCK_SIZE, NS_BIT); 176862306a36Sopenharmony_ci set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT); 176962306a36Sopenharmony_ci set_setup_mode(&desc[idx], SETUP_LOAD_STATE1); 177062306a36Sopenharmony_ci set_flow_mode(&desc[idx], S_DIN_to_AES); 177162306a36Sopenharmony_ci idx++; 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_ci /* Memory Barrier */ 177462306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 177562306a36Sopenharmony_ci set_din_no_dma(&desc[idx], 0, 0xfffff0); 177662306a36Sopenharmony_ci set_dout_no_dma(&desc[idx], 0, 0, 1); 177762306a36Sopenharmony_ci idx++; 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci /* process GCTR on stored GHASH and store MAC in mac_state*/ 178062306a36Sopenharmony_ci hw_desc_init(&desc[idx]); 178162306a36Sopenharmony_ci set_cipher_mode(&desc[idx], DRV_CIPHER_GCTR); 178262306a36Sopenharmony_ci set_din_type(&desc[idx], DMA_DLLI, req_ctx->mac_buf_dma_addr, 178362306a36Sopenharmony_ci AES_BLOCK_SIZE, NS_BIT); 178462306a36Sopenharmony_ci set_dout_dlli(&desc[idx], mac_result, ctx->authsize, NS_BIT, 1); 178562306a36Sopenharmony_ci set_queue_last_ind(ctx->drvdata, &desc[idx]); 178662306a36Sopenharmony_ci set_flow_mode(&desc[idx], DIN_AES_DOUT); 178762306a36Sopenharmony_ci idx++; 178862306a36Sopenharmony_ci 178962306a36Sopenharmony_ci *seq_size = idx; 179062306a36Sopenharmony_ci} 179162306a36Sopenharmony_ci 179262306a36Sopenharmony_cistatic int cc_gcm(struct aead_request *req, struct cc_hw_desc desc[], 179362306a36Sopenharmony_ci unsigned int *seq_size) 179462306a36Sopenharmony_ci{ 179562306a36Sopenharmony_ci struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req); 179662306a36Sopenharmony_ci unsigned int cipher_flow_mode; 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_ci //in RFC4543 no data to encrypt. just copy data from src to dest. 179962306a36Sopenharmony_ci if (req_ctx->plaintext_authenticate_only) { 180062306a36Sopenharmony_ci cc_proc_cipher_desc(req, BYPASS, desc, seq_size); 180162306a36Sopenharmony_ci cc_set_ghash_desc(req, desc, seq_size); 180262306a36Sopenharmony_ci /* process(ghash) assoc data */ 180362306a36Sopenharmony_ci cc_set_assoc_desc(req, DIN_HASH, desc, seq_size); 180462306a36Sopenharmony_ci cc_set_gctr_desc(req, desc, seq_size); 180562306a36Sopenharmony_ci cc_proc_gcm_result(req, desc, seq_size); 180662306a36Sopenharmony_ci return 0; 180762306a36Sopenharmony_ci } 180862306a36Sopenharmony_ci 180962306a36Sopenharmony_ci if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) { 181062306a36Sopenharmony_ci cipher_flow_mode = AES_and_HASH; 181162306a36Sopenharmony_ci } else { /* Encrypt */ 181262306a36Sopenharmony_ci cipher_flow_mode = AES_to_HASH_and_DOUT; 181362306a36Sopenharmony_ci } 181462306a36Sopenharmony_ci 181562306a36Sopenharmony_ci // for gcm and rfc4106. 181662306a36Sopenharmony_ci cc_set_ghash_desc(req, desc, seq_size); 181762306a36Sopenharmony_ci /* process(ghash) assoc data */ 181862306a36Sopenharmony_ci if (req_ctx->assoclen > 0) 181962306a36Sopenharmony_ci cc_set_assoc_desc(req, DIN_HASH, desc, seq_size); 182062306a36Sopenharmony_ci cc_set_gctr_desc(req, desc, seq_size); 182162306a36Sopenharmony_ci /* process(gctr+ghash) */ 182262306a36Sopenharmony_ci if (req_ctx->cryptlen) 182362306a36Sopenharmony_ci cc_proc_cipher_desc(req, cipher_flow_mode, desc, seq_size); 182462306a36Sopenharmony_ci cc_proc_gcm_result(req, desc, seq_size); 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_ci return 0; 182762306a36Sopenharmony_ci} 182862306a36Sopenharmony_ci 182962306a36Sopenharmony_cistatic int config_gcm_context(struct aead_request *req) 183062306a36Sopenharmony_ci{ 183162306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 183262306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 183362306a36Sopenharmony_ci struct aead_req_ctx *req_ctx = aead_request_ctx_dma(req); 183462306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci unsigned int cryptlen = (req_ctx->gen_ctx.op_type == 183762306a36Sopenharmony_ci DRV_CRYPTO_DIRECTION_ENCRYPT) ? 183862306a36Sopenharmony_ci req->cryptlen : 183962306a36Sopenharmony_ci (req->cryptlen - ctx->authsize); 184062306a36Sopenharmony_ci __be32 counter = cpu_to_be32(2); 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_ci dev_dbg(dev, "%s() cryptlen = %d, req_ctx->assoclen = %d ctx->authsize = %d\n", 184362306a36Sopenharmony_ci __func__, cryptlen, req_ctx->assoclen, ctx->authsize); 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci memset(req_ctx->hkey, 0, AES_BLOCK_SIZE); 184662306a36Sopenharmony_ci 184762306a36Sopenharmony_ci memset(req_ctx->mac_buf, 0, AES_BLOCK_SIZE); 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci memcpy(req->iv + 12, &counter, 4); 185062306a36Sopenharmony_ci memcpy(req_ctx->gcm_iv_inc2, req->iv, 16); 185162306a36Sopenharmony_ci 185262306a36Sopenharmony_ci counter = cpu_to_be32(1); 185362306a36Sopenharmony_ci memcpy(req->iv + 12, &counter, 4); 185462306a36Sopenharmony_ci memcpy(req_ctx->gcm_iv_inc1, req->iv, 16); 185562306a36Sopenharmony_ci 185662306a36Sopenharmony_ci if (!req_ctx->plaintext_authenticate_only) { 185762306a36Sopenharmony_ci __be64 temp64; 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ci temp64 = cpu_to_be64(req_ctx->assoclen * 8); 186062306a36Sopenharmony_ci memcpy(&req_ctx->gcm_len_block.len_a, &temp64, sizeof(temp64)); 186162306a36Sopenharmony_ci temp64 = cpu_to_be64(cryptlen * 8); 186262306a36Sopenharmony_ci memcpy(&req_ctx->gcm_len_block.len_c, &temp64, 8); 186362306a36Sopenharmony_ci } else { 186462306a36Sopenharmony_ci /* rfc4543=> all data(AAD,IV,Plain) are considered additional 186562306a36Sopenharmony_ci * data that is nothing is encrypted. 186662306a36Sopenharmony_ci */ 186762306a36Sopenharmony_ci __be64 temp64; 186862306a36Sopenharmony_ci 186962306a36Sopenharmony_ci temp64 = cpu_to_be64((req_ctx->assoclen + cryptlen) * 8); 187062306a36Sopenharmony_ci memcpy(&req_ctx->gcm_len_block.len_a, &temp64, sizeof(temp64)); 187162306a36Sopenharmony_ci temp64 = 0; 187262306a36Sopenharmony_ci memcpy(&req_ctx->gcm_len_block.len_c, &temp64, 8); 187362306a36Sopenharmony_ci } 187462306a36Sopenharmony_ci 187562306a36Sopenharmony_ci return 0; 187662306a36Sopenharmony_ci} 187762306a36Sopenharmony_ci 187862306a36Sopenharmony_cistatic void cc_proc_rfc4_gcm(struct aead_request *req) 187962306a36Sopenharmony_ci{ 188062306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 188162306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 188262306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req); 188362306a36Sopenharmony_ci 188462306a36Sopenharmony_ci memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_NONCE_OFFSET, 188562306a36Sopenharmony_ci ctx->ctr_nonce, GCM_BLOCK_RFC4_NONCE_SIZE); 188662306a36Sopenharmony_ci memcpy(areq_ctx->ctr_iv + GCM_BLOCK_RFC4_IV_OFFSET, req->iv, 188762306a36Sopenharmony_ci GCM_BLOCK_RFC4_IV_SIZE); 188862306a36Sopenharmony_ci req->iv = areq_ctx->ctr_iv; 188962306a36Sopenharmony_ci} 189062306a36Sopenharmony_ci 189162306a36Sopenharmony_cistatic int cc_proc_aead(struct aead_request *req, 189262306a36Sopenharmony_ci enum drv_crypto_direction direct) 189362306a36Sopenharmony_ci{ 189462306a36Sopenharmony_ci int rc = 0; 189562306a36Sopenharmony_ci int seq_len = 0; 189662306a36Sopenharmony_ci struct cc_hw_desc desc[MAX_AEAD_PROCESS_SEQ]; 189762306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 189862306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 189962306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req); 190062306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 190162306a36Sopenharmony_ci struct cc_crypto_req cc_req = {}; 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_ci dev_dbg(dev, "%s context=%p req=%p iv=%p src=%p src_ofs=%d dst=%p dst_ofs=%d cryptolen=%d\n", 190462306a36Sopenharmony_ci ((direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ? "Enc" : "Dec"), 190562306a36Sopenharmony_ci ctx, req, req->iv, sg_virt(req->src), req->src->offset, 190662306a36Sopenharmony_ci sg_virt(req->dst), req->dst->offset, req->cryptlen); 190762306a36Sopenharmony_ci 190862306a36Sopenharmony_ci /* STAT_PHASE_0: Init and sanity checks */ 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci /* Check data length according to mode */ 191162306a36Sopenharmony_ci if (validate_data_size(ctx, direct, req)) { 191262306a36Sopenharmony_ci dev_err(dev, "Unsupported crypt/assoc len %d/%d.\n", 191362306a36Sopenharmony_ci req->cryptlen, areq_ctx->assoclen); 191462306a36Sopenharmony_ci return -EINVAL; 191562306a36Sopenharmony_ci } 191662306a36Sopenharmony_ci 191762306a36Sopenharmony_ci /* Setup request structure */ 191862306a36Sopenharmony_ci cc_req.user_cb = cc_aead_complete; 191962306a36Sopenharmony_ci cc_req.user_arg = req; 192062306a36Sopenharmony_ci 192162306a36Sopenharmony_ci /* Setup request context */ 192262306a36Sopenharmony_ci areq_ctx->gen_ctx.op_type = direct; 192362306a36Sopenharmony_ci areq_ctx->req_authsize = ctx->authsize; 192462306a36Sopenharmony_ci areq_ctx->cipher_mode = ctx->cipher_mode; 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_ci /* STAT_PHASE_1: Map buffers */ 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_ci if (ctx->cipher_mode == DRV_CIPHER_CTR) { 192962306a36Sopenharmony_ci /* Build CTR IV - Copy nonce from last 4 bytes in 193062306a36Sopenharmony_ci * CTR key to first 4 bytes in CTR IV 193162306a36Sopenharmony_ci */ 193262306a36Sopenharmony_ci memcpy(areq_ctx->ctr_iv, ctx->ctr_nonce, 193362306a36Sopenharmony_ci CTR_RFC3686_NONCE_SIZE); 193462306a36Sopenharmony_ci memcpy(areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE, req->iv, 193562306a36Sopenharmony_ci CTR_RFC3686_IV_SIZE); 193662306a36Sopenharmony_ci /* Initialize counter portion of counter block */ 193762306a36Sopenharmony_ci *(__be32 *)(areq_ctx->ctr_iv + CTR_RFC3686_NONCE_SIZE + 193862306a36Sopenharmony_ci CTR_RFC3686_IV_SIZE) = cpu_to_be32(1); 193962306a36Sopenharmony_ci 194062306a36Sopenharmony_ci /* Replace with counter iv */ 194162306a36Sopenharmony_ci req->iv = areq_ctx->ctr_iv; 194262306a36Sopenharmony_ci areq_ctx->hw_iv_size = CTR_RFC3686_BLOCK_SIZE; 194362306a36Sopenharmony_ci } else if ((ctx->cipher_mode == DRV_CIPHER_CCM) || 194462306a36Sopenharmony_ci (ctx->cipher_mode == DRV_CIPHER_GCTR)) { 194562306a36Sopenharmony_ci areq_ctx->hw_iv_size = AES_BLOCK_SIZE; 194662306a36Sopenharmony_ci if (areq_ctx->ctr_iv != req->iv) { 194762306a36Sopenharmony_ci memcpy(areq_ctx->ctr_iv, req->iv, 194862306a36Sopenharmony_ci crypto_aead_ivsize(tfm)); 194962306a36Sopenharmony_ci req->iv = areq_ctx->ctr_iv; 195062306a36Sopenharmony_ci } 195162306a36Sopenharmony_ci } else { 195262306a36Sopenharmony_ci areq_ctx->hw_iv_size = crypto_aead_ivsize(tfm); 195362306a36Sopenharmony_ci } 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_ci if (ctx->cipher_mode == DRV_CIPHER_CCM) { 195662306a36Sopenharmony_ci rc = config_ccm_adata(req); 195762306a36Sopenharmony_ci if (rc) { 195862306a36Sopenharmony_ci dev_dbg(dev, "config_ccm_adata() returned with a failure %d!", 195962306a36Sopenharmony_ci rc); 196062306a36Sopenharmony_ci goto exit; 196162306a36Sopenharmony_ci } 196262306a36Sopenharmony_ci } else { 196362306a36Sopenharmony_ci areq_ctx->ccm_hdr_size = ccm_header_size_null; 196462306a36Sopenharmony_ci } 196562306a36Sopenharmony_ci 196662306a36Sopenharmony_ci if (ctx->cipher_mode == DRV_CIPHER_GCTR) { 196762306a36Sopenharmony_ci rc = config_gcm_context(req); 196862306a36Sopenharmony_ci if (rc) { 196962306a36Sopenharmony_ci dev_dbg(dev, "config_gcm_context() returned with a failure %d!", 197062306a36Sopenharmony_ci rc); 197162306a36Sopenharmony_ci goto exit; 197262306a36Sopenharmony_ci } 197362306a36Sopenharmony_ci } 197462306a36Sopenharmony_ci 197562306a36Sopenharmony_ci rc = cc_map_aead_request(ctx->drvdata, req); 197662306a36Sopenharmony_ci if (rc) { 197762306a36Sopenharmony_ci dev_err(dev, "map_request() failed\n"); 197862306a36Sopenharmony_ci goto exit; 197962306a36Sopenharmony_ci } 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_ci /* STAT_PHASE_2: Create sequence */ 198262306a36Sopenharmony_ci 198362306a36Sopenharmony_ci /* Load MLLI tables to SRAM if necessary */ 198462306a36Sopenharmony_ci cc_mlli_to_sram(req, desc, &seq_len); 198562306a36Sopenharmony_ci 198662306a36Sopenharmony_ci switch (ctx->auth_mode) { 198762306a36Sopenharmony_ci case DRV_HASH_SHA1: 198862306a36Sopenharmony_ci case DRV_HASH_SHA256: 198962306a36Sopenharmony_ci cc_hmac_authenc(req, desc, &seq_len); 199062306a36Sopenharmony_ci break; 199162306a36Sopenharmony_ci case DRV_HASH_XCBC_MAC: 199262306a36Sopenharmony_ci cc_xcbc_authenc(req, desc, &seq_len); 199362306a36Sopenharmony_ci break; 199462306a36Sopenharmony_ci case DRV_HASH_NULL: 199562306a36Sopenharmony_ci if (ctx->cipher_mode == DRV_CIPHER_CCM) 199662306a36Sopenharmony_ci cc_ccm(req, desc, &seq_len); 199762306a36Sopenharmony_ci if (ctx->cipher_mode == DRV_CIPHER_GCTR) 199862306a36Sopenharmony_ci cc_gcm(req, desc, &seq_len); 199962306a36Sopenharmony_ci break; 200062306a36Sopenharmony_ci default: 200162306a36Sopenharmony_ci dev_err(dev, "Unsupported authenc (%d)\n", ctx->auth_mode); 200262306a36Sopenharmony_ci cc_unmap_aead_request(dev, req); 200362306a36Sopenharmony_ci rc = -ENOTSUPP; 200462306a36Sopenharmony_ci goto exit; 200562306a36Sopenharmony_ci } 200662306a36Sopenharmony_ci 200762306a36Sopenharmony_ci /* STAT_PHASE_3: Lock HW and push sequence */ 200862306a36Sopenharmony_ci 200962306a36Sopenharmony_ci rc = cc_send_request(ctx->drvdata, &cc_req, desc, seq_len, &req->base); 201062306a36Sopenharmony_ci 201162306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 201262306a36Sopenharmony_ci dev_err(dev, "send_request() failed (rc=%d)\n", rc); 201362306a36Sopenharmony_ci cc_unmap_aead_request(dev, req); 201462306a36Sopenharmony_ci } 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ciexit: 201762306a36Sopenharmony_ci return rc; 201862306a36Sopenharmony_ci} 201962306a36Sopenharmony_ci 202062306a36Sopenharmony_cistatic int cc_aead_encrypt(struct aead_request *req) 202162306a36Sopenharmony_ci{ 202262306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req); 202362306a36Sopenharmony_ci int rc; 202462306a36Sopenharmony_ci 202562306a36Sopenharmony_ci memset(areq_ctx, 0, sizeof(*areq_ctx)); 202662306a36Sopenharmony_ci 202762306a36Sopenharmony_ci /* No generated IV required */ 202862306a36Sopenharmony_ci areq_ctx->backup_iv = req->iv; 202962306a36Sopenharmony_ci areq_ctx->assoclen = req->assoclen; 203062306a36Sopenharmony_ci 203162306a36Sopenharmony_ci rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT); 203262306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) 203362306a36Sopenharmony_ci req->iv = areq_ctx->backup_iv; 203462306a36Sopenharmony_ci 203562306a36Sopenharmony_ci return rc; 203662306a36Sopenharmony_ci} 203762306a36Sopenharmony_ci 203862306a36Sopenharmony_cistatic int cc_rfc4309_ccm_encrypt(struct aead_request *req) 203962306a36Sopenharmony_ci{ 204062306a36Sopenharmony_ci /* Very similar to cc_aead_encrypt() above. */ 204162306a36Sopenharmony_ci 204262306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req); 204362306a36Sopenharmony_ci int rc; 204462306a36Sopenharmony_ci 204562306a36Sopenharmony_ci rc = crypto_ipsec_check_assoclen(req->assoclen); 204662306a36Sopenharmony_ci if (rc) 204762306a36Sopenharmony_ci goto out; 204862306a36Sopenharmony_ci 204962306a36Sopenharmony_ci memset(areq_ctx, 0, sizeof(*areq_ctx)); 205062306a36Sopenharmony_ci 205162306a36Sopenharmony_ci /* No generated IV required */ 205262306a36Sopenharmony_ci areq_ctx->backup_iv = req->iv; 205362306a36Sopenharmony_ci areq_ctx->assoclen = req->assoclen - CCM_BLOCK_IV_SIZE; 205462306a36Sopenharmony_ci 205562306a36Sopenharmony_ci cc_proc_rfc4309_ccm(req); 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_ci rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT); 205862306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) 205962306a36Sopenharmony_ci req->iv = areq_ctx->backup_iv; 206062306a36Sopenharmony_ciout: 206162306a36Sopenharmony_ci return rc; 206262306a36Sopenharmony_ci} 206362306a36Sopenharmony_ci 206462306a36Sopenharmony_cistatic int cc_aead_decrypt(struct aead_request *req) 206562306a36Sopenharmony_ci{ 206662306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req); 206762306a36Sopenharmony_ci int rc; 206862306a36Sopenharmony_ci 206962306a36Sopenharmony_ci memset(areq_ctx, 0, sizeof(*areq_ctx)); 207062306a36Sopenharmony_ci 207162306a36Sopenharmony_ci /* No generated IV required */ 207262306a36Sopenharmony_ci areq_ctx->backup_iv = req->iv; 207362306a36Sopenharmony_ci areq_ctx->assoclen = req->assoclen; 207462306a36Sopenharmony_ci 207562306a36Sopenharmony_ci rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT); 207662306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) 207762306a36Sopenharmony_ci req->iv = areq_ctx->backup_iv; 207862306a36Sopenharmony_ci 207962306a36Sopenharmony_ci return rc; 208062306a36Sopenharmony_ci} 208162306a36Sopenharmony_ci 208262306a36Sopenharmony_cistatic int cc_rfc4309_ccm_decrypt(struct aead_request *req) 208362306a36Sopenharmony_ci{ 208462306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req); 208562306a36Sopenharmony_ci int rc; 208662306a36Sopenharmony_ci 208762306a36Sopenharmony_ci rc = crypto_ipsec_check_assoclen(req->assoclen); 208862306a36Sopenharmony_ci if (rc) 208962306a36Sopenharmony_ci goto out; 209062306a36Sopenharmony_ci 209162306a36Sopenharmony_ci memset(areq_ctx, 0, sizeof(*areq_ctx)); 209262306a36Sopenharmony_ci 209362306a36Sopenharmony_ci /* No generated IV required */ 209462306a36Sopenharmony_ci areq_ctx->backup_iv = req->iv; 209562306a36Sopenharmony_ci areq_ctx->assoclen = req->assoclen - CCM_BLOCK_IV_SIZE; 209662306a36Sopenharmony_ci 209762306a36Sopenharmony_ci cc_proc_rfc4309_ccm(req); 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT); 210062306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) 210162306a36Sopenharmony_ci req->iv = areq_ctx->backup_iv; 210262306a36Sopenharmony_ci 210362306a36Sopenharmony_ciout: 210462306a36Sopenharmony_ci return rc; 210562306a36Sopenharmony_ci} 210662306a36Sopenharmony_ci 210762306a36Sopenharmony_cistatic int cc_rfc4106_gcm_setkey(struct crypto_aead *tfm, const u8 *key, 210862306a36Sopenharmony_ci unsigned int keylen) 210962306a36Sopenharmony_ci{ 211062306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 211162306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 211262306a36Sopenharmony_ci 211362306a36Sopenharmony_ci dev_dbg(dev, "%s() keylen %d, key %p\n", __func__, keylen, key); 211462306a36Sopenharmony_ci 211562306a36Sopenharmony_ci if (keylen < 4) 211662306a36Sopenharmony_ci return -EINVAL; 211762306a36Sopenharmony_ci 211862306a36Sopenharmony_ci keylen -= 4; 211962306a36Sopenharmony_ci memcpy(ctx->ctr_nonce, key + keylen, 4); 212062306a36Sopenharmony_ci 212162306a36Sopenharmony_ci return cc_aead_setkey(tfm, key, keylen); 212262306a36Sopenharmony_ci} 212362306a36Sopenharmony_ci 212462306a36Sopenharmony_cistatic int cc_rfc4543_gcm_setkey(struct crypto_aead *tfm, const u8 *key, 212562306a36Sopenharmony_ci unsigned int keylen) 212662306a36Sopenharmony_ci{ 212762306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); 212862306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 212962306a36Sopenharmony_ci 213062306a36Sopenharmony_ci dev_dbg(dev, "%s() keylen %d, key %p\n", __func__, keylen, key); 213162306a36Sopenharmony_ci 213262306a36Sopenharmony_ci if (keylen < 4) 213362306a36Sopenharmony_ci return -EINVAL; 213462306a36Sopenharmony_ci 213562306a36Sopenharmony_ci keylen -= 4; 213662306a36Sopenharmony_ci memcpy(ctx->ctr_nonce, key + keylen, 4); 213762306a36Sopenharmony_ci 213862306a36Sopenharmony_ci return cc_aead_setkey(tfm, key, keylen); 213962306a36Sopenharmony_ci} 214062306a36Sopenharmony_ci 214162306a36Sopenharmony_cistatic int cc_gcm_setauthsize(struct crypto_aead *authenc, 214262306a36Sopenharmony_ci unsigned int authsize) 214362306a36Sopenharmony_ci{ 214462306a36Sopenharmony_ci switch (authsize) { 214562306a36Sopenharmony_ci case 4: 214662306a36Sopenharmony_ci case 8: 214762306a36Sopenharmony_ci case 12: 214862306a36Sopenharmony_ci case 13: 214962306a36Sopenharmony_ci case 14: 215062306a36Sopenharmony_ci case 15: 215162306a36Sopenharmony_ci case 16: 215262306a36Sopenharmony_ci break; 215362306a36Sopenharmony_ci default: 215462306a36Sopenharmony_ci return -EINVAL; 215562306a36Sopenharmony_ci } 215662306a36Sopenharmony_ci 215762306a36Sopenharmony_ci return cc_aead_setauthsize(authenc, authsize); 215862306a36Sopenharmony_ci} 215962306a36Sopenharmony_ci 216062306a36Sopenharmony_cistatic int cc_rfc4106_gcm_setauthsize(struct crypto_aead *authenc, 216162306a36Sopenharmony_ci unsigned int authsize) 216262306a36Sopenharmony_ci{ 216362306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(authenc); 216462306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 216562306a36Sopenharmony_ci 216662306a36Sopenharmony_ci dev_dbg(dev, "authsize %d\n", authsize); 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_ci switch (authsize) { 216962306a36Sopenharmony_ci case 8: 217062306a36Sopenharmony_ci case 12: 217162306a36Sopenharmony_ci case 16: 217262306a36Sopenharmony_ci break; 217362306a36Sopenharmony_ci default: 217462306a36Sopenharmony_ci return -EINVAL; 217562306a36Sopenharmony_ci } 217662306a36Sopenharmony_ci 217762306a36Sopenharmony_ci return cc_aead_setauthsize(authenc, authsize); 217862306a36Sopenharmony_ci} 217962306a36Sopenharmony_ci 218062306a36Sopenharmony_cistatic int cc_rfc4543_gcm_setauthsize(struct crypto_aead *authenc, 218162306a36Sopenharmony_ci unsigned int authsize) 218262306a36Sopenharmony_ci{ 218362306a36Sopenharmony_ci struct cc_aead_ctx *ctx = crypto_aead_ctx(authenc); 218462306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx->drvdata); 218562306a36Sopenharmony_ci 218662306a36Sopenharmony_ci dev_dbg(dev, "authsize %d\n", authsize); 218762306a36Sopenharmony_ci 218862306a36Sopenharmony_ci if (authsize != 16) 218962306a36Sopenharmony_ci return -EINVAL; 219062306a36Sopenharmony_ci 219162306a36Sopenharmony_ci return cc_aead_setauthsize(authenc, authsize); 219262306a36Sopenharmony_ci} 219362306a36Sopenharmony_ci 219462306a36Sopenharmony_cistatic int cc_rfc4106_gcm_encrypt(struct aead_request *req) 219562306a36Sopenharmony_ci{ 219662306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req); 219762306a36Sopenharmony_ci int rc; 219862306a36Sopenharmony_ci 219962306a36Sopenharmony_ci rc = crypto_ipsec_check_assoclen(req->assoclen); 220062306a36Sopenharmony_ci if (rc) 220162306a36Sopenharmony_ci goto out; 220262306a36Sopenharmony_ci 220362306a36Sopenharmony_ci memset(areq_ctx, 0, sizeof(*areq_ctx)); 220462306a36Sopenharmony_ci 220562306a36Sopenharmony_ci /* No generated IV required */ 220662306a36Sopenharmony_ci areq_ctx->backup_iv = req->iv; 220762306a36Sopenharmony_ci areq_ctx->assoclen = req->assoclen - GCM_BLOCK_RFC4_IV_SIZE; 220862306a36Sopenharmony_ci 220962306a36Sopenharmony_ci cc_proc_rfc4_gcm(req); 221062306a36Sopenharmony_ci 221162306a36Sopenharmony_ci rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT); 221262306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) 221362306a36Sopenharmony_ci req->iv = areq_ctx->backup_iv; 221462306a36Sopenharmony_ciout: 221562306a36Sopenharmony_ci return rc; 221662306a36Sopenharmony_ci} 221762306a36Sopenharmony_ci 221862306a36Sopenharmony_cistatic int cc_rfc4543_gcm_encrypt(struct aead_request *req) 221962306a36Sopenharmony_ci{ 222062306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req); 222162306a36Sopenharmony_ci int rc; 222262306a36Sopenharmony_ci 222362306a36Sopenharmony_ci rc = crypto_ipsec_check_assoclen(req->assoclen); 222462306a36Sopenharmony_ci if (rc) 222562306a36Sopenharmony_ci goto out; 222662306a36Sopenharmony_ci 222762306a36Sopenharmony_ci memset(areq_ctx, 0, sizeof(*areq_ctx)); 222862306a36Sopenharmony_ci 222962306a36Sopenharmony_ci //plaintext is not encryped with rfc4543 223062306a36Sopenharmony_ci areq_ctx->plaintext_authenticate_only = true; 223162306a36Sopenharmony_ci 223262306a36Sopenharmony_ci /* No generated IV required */ 223362306a36Sopenharmony_ci areq_ctx->backup_iv = req->iv; 223462306a36Sopenharmony_ci areq_ctx->assoclen = req->assoclen; 223562306a36Sopenharmony_ci 223662306a36Sopenharmony_ci cc_proc_rfc4_gcm(req); 223762306a36Sopenharmony_ci 223862306a36Sopenharmony_ci rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_ENCRYPT); 223962306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) 224062306a36Sopenharmony_ci req->iv = areq_ctx->backup_iv; 224162306a36Sopenharmony_ciout: 224262306a36Sopenharmony_ci return rc; 224362306a36Sopenharmony_ci} 224462306a36Sopenharmony_ci 224562306a36Sopenharmony_cistatic int cc_rfc4106_gcm_decrypt(struct aead_request *req) 224662306a36Sopenharmony_ci{ 224762306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req); 224862306a36Sopenharmony_ci int rc; 224962306a36Sopenharmony_ci 225062306a36Sopenharmony_ci rc = crypto_ipsec_check_assoclen(req->assoclen); 225162306a36Sopenharmony_ci if (rc) 225262306a36Sopenharmony_ci goto out; 225362306a36Sopenharmony_ci 225462306a36Sopenharmony_ci memset(areq_ctx, 0, sizeof(*areq_ctx)); 225562306a36Sopenharmony_ci 225662306a36Sopenharmony_ci /* No generated IV required */ 225762306a36Sopenharmony_ci areq_ctx->backup_iv = req->iv; 225862306a36Sopenharmony_ci areq_ctx->assoclen = req->assoclen - GCM_BLOCK_RFC4_IV_SIZE; 225962306a36Sopenharmony_ci 226062306a36Sopenharmony_ci cc_proc_rfc4_gcm(req); 226162306a36Sopenharmony_ci 226262306a36Sopenharmony_ci rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT); 226362306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) 226462306a36Sopenharmony_ci req->iv = areq_ctx->backup_iv; 226562306a36Sopenharmony_ciout: 226662306a36Sopenharmony_ci return rc; 226762306a36Sopenharmony_ci} 226862306a36Sopenharmony_ci 226962306a36Sopenharmony_cistatic int cc_rfc4543_gcm_decrypt(struct aead_request *req) 227062306a36Sopenharmony_ci{ 227162306a36Sopenharmony_ci struct aead_req_ctx *areq_ctx = aead_request_ctx_dma(req); 227262306a36Sopenharmony_ci int rc; 227362306a36Sopenharmony_ci 227462306a36Sopenharmony_ci rc = crypto_ipsec_check_assoclen(req->assoclen); 227562306a36Sopenharmony_ci if (rc) 227662306a36Sopenharmony_ci goto out; 227762306a36Sopenharmony_ci 227862306a36Sopenharmony_ci memset(areq_ctx, 0, sizeof(*areq_ctx)); 227962306a36Sopenharmony_ci 228062306a36Sopenharmony_ci //plaintext is not decryped with rfc4543 228162306a36Sopenharmony_ci areq_ctx->plaintext_authenticate_only = true; 228262306a36Sopenharmony_ci 228362306a36Sopenharmony_ci /* No generated IV required */ 228462306a36Sopenharmony_ci areq_ctx->backup_iv = req->iv; 228562306a36Sopenharmony_ci areq_ctx->assoclen = req->assoclen; 228662306a36Sopenharmony_ci 228762306a36Sopenharmony_ci cc_proc_rfc4_gcm(req); 228862306a36Sopenharmony_ci 228962306a36Sopenharmony_ci rc = cc_proc_aead(req, DRV_CRYPTO_DIRECTION_DECRYPT); 229062306a36Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) 229162306a36Sopenharmony_ci req->iv = areq_ctx->backup_iv; 229262306a36Sopenharmony_ciout: 229362306a36Sopenharmony_ci return rc; 229462306a36Sopenharmony_ci} 229562306a36Sopenharmony_ci 229662306a36Sopenharmony_ci/* aead alg */ 229762306a36Sopenharmony_cistatic struct cc_alg_template aead_algs[] = { 229862306a36Sopenharmony_ci { 229962306a36Sopenharmony_ci .name = "authenc(hmac(sha1),cbc(aes))", 230062306a36Sopenharmony_ci .driver_name = "authenc-hmac-sha1-cbc-aes-ccree", 230162306a36Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 230262306a36Sopenharmony_ci .template_aead = { 230362306a36Sopenharmony_ci .setkey = cc_aead_setkey, 230462306a36Sopenharmony_ci .setauthsize = cc_aead_setauthsize, 230562306a36Sopenharmony_ci .encrypt = cc_aead_encrypt, 230662306a36Sopenharmony_ci .decrypt = cc_aead_decrypt, 230762306a36Sopenharmony_ci .init = cc_aead_init, 230862306a36Sopenharmony_ci .exit = cc_aead_exit, 230962306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 231062306a36Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 231162306a36Sopenharmony_ci }, 231262306a36Sopenharmony_ci .cipher_mode = DRV_CIPHER_CBC, 231362306a36Sopenharmony_ci .flow_mode = S_DIN_to_AES, 231462306a36Sopenharmony_ci .auth_mode = DRV_HASH_SHA1, 231562306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 231662306a36Sopenharmony_ci .std_body = CC_STD_NIST, 231762306a36Sopenharmony_ci }, 231862306a36Sopenharmony_ci { 231962306a36Sopenharmony_ci .name = "authenc(hmac(sha1),cbc(des3_ede))", 232062306a36Sopenharmony_ci .driver_name = "authenc-hmac-sha1-cbc-des3-ccree", 232162306a36Sopenharmony_ci .blocksize = DES3_EDE_BLOCK_SIZE, 232262306a36Sopenharmony_ci .template_aead = { 232362306a36Sopenharmony_ci .setkey = cc_des3_aead_setkey, 232462306a36Sopenharmony_ci .setauthsize = cc_aead_setauthsize, 232562306a36Sopenharmony_ci .encrypt = cc_aead_encrypt, 232662306a36Sopenharmony_ci .decrypt = cc_aead_decrypt, 232762306a36Sopenharmony_ci .init = cc_aead_init, 232862306a36Sopenharmony_ci .exit = cc_aead_exit, 232962306a36Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 233062306a36Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 233162306a36Sopenharmony_ci }, 233262306a36Sopenharmony_ci .cipher_mode = DRV_CIPHER_CBC, 233362306a36Sopenharmony_ci .flow_mode = S_DIN_to_DES, 233462306a36Sopenharmony_ci .auth_mode = DRV_HASH_SHA1, 233562306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 233662306a36Sopenharmony_ci .std_body = CC_STD_NIST, 233762306a36Sopenharmony_ci }, 233862306a36Sopenharmony_ci { 233962306a36Sopenharmony_ci .name = "authenc(hmac(sha256),cbc(aes))", 234062306a36Sopenharmony_ci .driver_name = "authenc-hmac-sha256-cbc-aes-ccree", 234162306a36Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 234262306a36Sopenharmony_ci .template_aead = { 234362306a36Sopenharmony_ci .setkey = cc_aead_setkey, 234462306a36Sopenharmony_ci .setauthsize = cc_aead_setauthsize, 234562306a36Sopenharmony_ci .encrypt = cc_aead_encrypt, 234662306a36Sopenharmony_ci .decrypt = cc_aead_decrypt, 234762306a36Sopenharmony_ci .init = cc_aead_init, 234862306a36Sopenharmony_ci .exit = cc_aead_exit, 234962306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 235062306a36Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 235162306a36Sopenharmony_ci }, 235262306a36Sopenharmony_ci .cipher_mode = DRV_CIPHER_CBC, 235362306a36Sopenharmony_ci .flow_mode = S_DIN_to_AES, 235462306a36Sopenharmony_ci .auth_mode = DRV_HASH_SHA256, 235562306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 235662306a36Sopenharmony_ci .std_body = CC_STD_NIST, 235762306a36Sopenharmony_ci }, 235862306a36Sopenharmony_ci { 235962306a36Sopenharmony_ci .name = "authenc(hmac(sha256),cbc(des3_ede))", 236062306a36Sopenharmony_ci .driver_name = "authenc-hmac-sha256-cbc-des3-ccree", 236162306a36Sopenharmony_ci .blocksize = DES3_EDE_BLOCK_SIZE, 236262306a36Sopenharmony_ci .template_aead = { 236362306a36Sopenharmony_ci .setkey = cc_des3_aead_setkey, 236462306a36Sopenharmony_ci .setauthsize = cc_aead_setauthsize, 236562306a36Sopenharmony_ci .encrypt = cc_aead_encrypt, 236662306a36Sopenharmony_ci .decrypt = cc_aead_decrypt, 236762306a36Sopenharmony_ci .init = cc_aead_init, 236862306a36Sopenharmony_ci .exit = cc_aead_exit, 236962306a36Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 237062306a36Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 237162306a36Sopenharmony_ci }, 237262306a36Sopenharmony_ci .cipher_mode = DRV_CIPHER_CBC, 237362306a36Sopenharmony_ci .flow_mode = S_DIN_to_DES, 237462306a36Sopenharmony_ci .auth_mode = DRV_HASH_SHA256, 237562306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 237662306a36Sopenharmony_ci .std_body = CC_STD_NIST, 237762306a36Sopenharmony_ci }, 237862306a36Sopenharmony_ci { 237962306a36Sopenharmony_ci .name = "authenc(xcbc(aes),cbc(aes))", 238062306a36Sopenharmony_ci .driver_name = "authenc-xcbc-aes-cbc-aes-ccree", 238162306a36Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 238262306a36Sopenharmony_ci .template_aead = { 238362306a36Sopenharmony_ci .setkey = cc_aead_setkey, 238462306a36Sopenharmony_ci .setauthsize = cc_aead_setauthsize, 238562306a36Sopenharmony_ci .encrypt = cc_aead_encrypt, 238662306a36Sopenharmony_ci .decrypt = cc_aead_decrypt, 238762306a36Sopenharmony_ci .init = cc_aead_init, 238862306a36Sopenharmony_ci .exit = cc_aead_exit, 238962306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 239062306a36Sopenharmony_ci .maxauthsize = AES_BLOCK_SIZE, 239162306a36Sopenharmony_ci }, 239262306a36Sopenharmony_ci .cipher_mode = DRV_CIPHER_CBC, 239362306a36Sopenharmony_ci .flow_mode = S_DIN_to_AES, 239462306a36Sopenharmony_ci .auth_mode = DRV_HASH_XCBC_MAC, 239562306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 239662306a36Sopenharmony_ci .std_body = CC_STD_NIST, 239762306a36Sopenharmony_ci }, 239862306a36Sopenharmony_ci { 239962306a36Sopenharmony_ci .name = "authenc(hmac(sha1),rfc3686(ctr(aes)))", 240062306a36Sopenharmony_ci .driver_name = "authenc-hmac-sha1-rfc3686-ctr-aes-ccree", 240162306a36Sopenharmony_ci .blocksize = 1, 240262306a36Sopenharmony_ci .template_aead = { 240362306a36Sopenharmony_ci .setkey = cc_aead_setkey, 240462306a36Sopenharmony_ci .setauthsize = cc_aead_setauthsize, 240562306a36Sopenharmony_ci .encrypt = cc_aead_encrypt, 240662306a36Sopenharmony_ci .decrypt = cc_aead_decrypt, 240762306a36Sopenharmony_ci .init = cc_aead_init, 240862306a36Sopenharmony_ci .exit = cc_aead_exit, 240962306a36Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 241062306a36Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 241162306a36Sopenharmony_ci }, 241262306a36Sopenharmony_ci .cipher_mode = DRV_CIPHER_CTR, 241362306a36Sopenharmony_ci .flow_mode = S_DIN_to_AES, 241462306a36Sopenharmony_ci .auth_mode = DRV_HASH_SHA1, 241562306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 241662306a36Sopenharmony_ci .std_body = CC_STD_NIST, 241762306a36Sopenharmony_ci }, 241862306a36Sopenharmony_ci { 241962306a36Sopenharmony_ci .name = "authenc(hmac(sha256),rfc3686(ctr(aes)))", 242062306a36Sopenharmony_ci .driver_name = "authenc-hmac-sha256-rfc3686-ctr-aes-ccree", 242162306a36Sopenharmony_ci .blocksize = 1, 242262306a36Sopenharmony_ci .template_aead = { 242362306a36Sopenharmony_ci .setkey = cc_aead_setkey, 242462306a36Sopenharmony_ci .setauthsize = cc_aead_setauthsize, 242562306a36Sopenharmony_ci .encrypt = cc_aead_encrypt, 242662306a36Sopenharmony_ci .decrypt = cc_aead_decrypt, 242762306a36Sopenharmony_ci .init = cc_aead_init, 242862306a36Sopenharmony_ci .exit = cc_aead_exit, 242962306a36Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 243062306a36Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 243162306a36Sopenharmony_ci }, 243262306a36Sopenharmony_ci .cipher_mode = DRV_CIPHER_CTR, 243362306a36Sopenharmony_ci .flow_mode = S_DIN_to_AES, 243462306a36Sopenharmony_ci .auth_mode = DRV_HASH_SHA256, 243562306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 243662306a36Sopenharmony_ci .std_body = CC_STD_NIST, 243762306a36Sopenharmony_ci }, 243862306a36Sopenharmony_ci { 243962306a36Sopenharmony_ci .name = "authenc(xcbc(aes),rfc3686(ctr(aes)))", 244062306a36Sopenharmony_ci .driver_name = "authenc-xcbc-aes-rfc3686-ctr-aes-ccree", 244162306a36Sopenharmony_ci .blocksize = 1, 244262306a36Sopenharmony_ci .template_aead = { 244362306a36Sopenharmony_ci .setkey = cc_aead_setkey, 244462306a36Sopenharmony_ci .setauthsize = cc_aead_setauthsize, 244562306a36Sopenharmony_ci .encrypt = cc_aead_encrypt, 244662306a36Sopenharmony_ci .decrypt = cc_aead_decrypt, 244762306a36Sopenharmony_ci .init = cc_aead_init, 244862306a36Sopenharmony_ci .exit = cc_aead_exit, 244962306a36Sopenharmony_ci .ivsize = CTR_RFC3686_IV_SIZE, 245062306a36Sopenharmony_ci .maxauthsize = AES_BLOCK_SIZE, 245162306a36Sopenharmony_ci }, 245262306a36Sopenharmony_ci .cipher_mode = DRV_CIPHER_CTR, 245362306a36Sopenharmony_ci .flow_mode = S_DIN_to_AES, 245462306a36Sopenharmony_ci .auth_mode = DRV_HASH_XCBC_MAC, 245562306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 245662306a36Sopenharmony_ci .std_body = CC_STD_NIST, 245762306a36Sopenharmony_ci }, 245862306a36Sopenharmony_ci { 245962306a36Sopenharmony_ci .name = "ccm(aes)", 246062306a36Sopenharmony_ci .driver_name = "ccm-aes-ccree", 246162306a36Sopenharmony_ci .blocksize = 1, 246262306a36Sopenharmony_ci .template_aead = { 246362306a36Sopenharmony_ci .setkey = cc_aead_setkey, 246462306a36Sopenharmony_ci .setauthsize = cc_ccm_setauthsize, 246562306a36Sopenharmony_ci .encrypt = cc_aead_encrypt, 246662306a36Sopenharmony_ci .decrypt = cc_aead_decrypt, 246762306a36Sopenharmony_ci .init = cc_aead_init, 246862306a36Sopenharmony_ci .exit = cc_aead_exit, 246962306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 247062306a36Sopenharmony_ci .maxauthsize = AES_BLOCK_SIZE, 247162306a36Sopenharmony_ci }, 247262306a36Sopenharmony_ci .cipher_mode = DRV_CIPHER_CCM, 247362306a36Sopenharmony_ci .flow_mode = S_DIN_to_AES, 247462306a36Sopenharmony_ci .auth_mode = DRV_HASH_NULL, 247562306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 247662306a36Sopenharmony_ci .std_body = CC_STD_NIST, 247762306a36Sopenharmony_ci }, 247862306a36Sopenharmony_ci { 247962306a36Sopenharmony_ci .name = "rfc4309(ccm(aes))", 248062306a36Sopenharmony_ci .driver_name = "rfc4309-ccm-aes-ccree", 248162306a36Sopenharmony_ci .blocksize = 1, 248262306a36Sopenharmony_ci .template_aead = { 248362306a36Sopenharmony_ci .setkey = cc_rfc4309_ccm_setkey, 248462306a36Sopenharmony_ci .setauthsize = cc_rfc4309_ccm_setauthsize, 248562306a36Sopenharmony_ci .encrypt = cc_rfc4309_ccm_encrypt, 248662306a36Sopenharmony_ci .decrypt = cc_rfc4309_ccm_decrypt, 248762306a36Sopenharmony_ci .init = cc_aead_init, 248862306a36Sopenharmony_ci .exit = cc_aead_exit, 248962306a36Sopenharmony_ci .ivsize = CCM_BLOCK_IV_SIZE, 249062306a36Sopenharmony_ci .maxauthsize = AES_BLOCK_SIZE, 249162306a36Sopenharmony_ci }, 249262306a36Sopenharmony_ci .cipher_mode = DRV_CIPHER_CCM, 249362306a36Sopenharmony_ci .flow_mode = S_DIN_to_AES, 249462306a36Sopenharmony_ci .auth_mode = DRV_HASH_NULL, 249562306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 249662306a36Sopenharmony_ci .std_body = CC_STD_NIST, 249762306a36Sopenharmony_ci }, 249862306a36Sopenharmony_ci { 249962306a36Sopenharmony_ci .name = "gcm(aes)", 250062306a36Sopenharmony_ci .driver_name = "gcm-aes-ccree", 250162306a36Sopenharmony_ci .blocksize = 1, 250262306a36Sopenharmony_ci .template_aead = { 250362306a36Sopenharmony_ci .setkey = cc_aead_setkey, 250462306a36Sopenharmony_ci .setauthsize = cc_gcm_setauthsize, 250562306a36Sopenharmony_ci .encrypt = cc_aead_encrypt, 250662306a36Sopenharmony_ci .decrypt = cc_aead_decrypt, 250762306a36Sopenharmony_ci .init = cc_aead_init, 250862306a36Sopenharmony_ci .exit = cc_aead_exit, 250962306a36Sopenharmony_ci .ivsize = 12, 251062306a36Sopenharmony_ci .maxauthsize = AES_BLOCK_SIZE, 251162306a36Sopenharmony_ci }, 251262306a36Sopenharmony_ci .cipher_mode = DRV_CIPHER_GCTR, 251362306a36Sopenharmony_ci .flow_mode = S_DIN_to_AES, 251462306a36Sopenharmony_ci .auth_mode = DRV_HASH_NULL, 251562306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 251662306a36Sopenharmony_ci .std_body = CC_STD_NIST, 251762306a36Sopenharmony_ci }, 251862306a36Sopenharmony_ci { 251962306a36Sopenharmony_ci .name = "rfc4106(gcm(aes))", 252062306a36Sopenharmony_ci .driver_name = "rfc4106-gcm-aes-ccree", 252162306a36Sopenharmony_ci .blocksize = 1, 252262306a36Sopenharmony_ci .template_aead = { 252362306a36Sopenharmony_ci .setkey = cc_rfc4106_gcm_setkey, 252462306a36Sopenharmony_ci .setauthsize = cc_rfc4106_gcm_setauthsize, 252562306a36Sopenharmony_ci .encrypt = cc_rfc4106_gcm_encrypt, 252662306a36Sopenharmony_ci .decrypt = cc_rfc4106_gcm_decrypt, 252762306a36Sopenharmony_ci .init = cc_aead_init, 252862306a36Sopenharmony_ci .exit = cc_aead_exit, 252962306a36Sopenharmony_ci .ivsize = GCM_BLOCK_RFC4_IV_SIZE, 253062306a36Sopenharmony_ci .maxauthsize = AES_BLOCK_SIZE, 253162306a36Sopenharmony_ci }, 253262306a36Sopenharmony_ci .cipher_mode = DRV_CIPHER_GCTR, 253362306a36Sopenharmony_ci .flow_mode = S_DIN_to_AES, 253462306a36Sopenharmony_ci .auth_mode = DRV_HASH_NULL, 253562306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 253662306a36Sopenharmony_ci .std_body = CC_STD_NIST, 253762306a36Sopenharmony_ci }, 253862306a36Sopenharmony_ci { 253962306a36Sopenharmony_ci .name = "rfc4543(gcm(aes))", 254062306a36Sopenharmony_ci .driver_name = "rfc4543-gcm-aes-ccree", 254162306a36Sopenharmony_ci .blocksize = 1, 254262306a36Sopenharmony_ci .template_aead = { 254362306a36Sopenharmony_ci .setkey = cc_rfc4543_gcm_setkey, 254462306a36Sopenharmony_ci .setauthsize = cc_rfc4543_gcm_setauthsize, 254562306a36Sopenharmony_ci .encrypt = cc_rfc4543_gcm_encrypt, 254662306a36Sopenharmony_ci .decrypt = cc_rfc4543_gcm_decrypt, 254762306a36Sopenharmony_ci .init = cc_aead_init, 254862306a36Sopenharmony_ci .exit = cc_aead_exit, 254962306a36Sopenharmony_ci .ivsize = GCM_BLOCK_RFC4_IV_SIZE, 255062306a36Sopenharmony_ci .maxauthsize = AES_BLOCK_SIZE, 255162306a36Sopenharmony_ci }, 255262306a36Sopenharmony_ci .cipher_mode = DRV_CIPHER_GCTR, 255362306a36Sopenharmony_ci .flow_mode = S_DIN_to_AES, 255462306a36Sopenharmony_ci .auth_mode = DRV_HASH_NULL, 255562306a36Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 255662306a36Sopenharmony_ci .std_body = CC_STD_NIST, 255762306a36Sopenharmony_ci }, 255862306a36Sopenharmony_ci}; 255962306a36Sopenharmony_ci 256062306a36Sopenharmony_cistatic struct cc_crypto_alg *cc_create_aead_alg(struct cc_alg_template *tmpl, 256162306a36Sopenharmony_ci struct device *dev) 256262306a36Sopenharmony_ci{ 256362306a36Sopenharmony_ci struct cc_crypto_alg *t_alg; 256462306a36Sopenharmony_ci struct aead_alg *alg; 256562306a36Sopenharmony_ci 256662306a36Sopenharmony_ci t_alg = devm_kzalloc(dev, sizeof(*t_alg), GFP_KERNEL); 256762306a36Sopenharmony_ci if (!t_alg) 256862306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 256962306a36Sopenharmony_ci 257062306a36Sopenharmony_ci alg = &tmpl->template_aead; 257162306a36Sopenharmony_ci 257262306a36Sopenharmony_ci snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", tmpl->name); 257362306a36Sopenharmony_ci snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", 257462306a36Sopenharmony_ci tmpl->driver_name); 257562306a36Sopenharmony_ci alg->base.cra_module = THIS_MODULE; 257662306a36Sopenharmony_ci alg->base.cra_priority = CC_CRA_PRIO; 257762306a36Sopenharmony_ci 257862306a36Sopenharmony_ci alg->base.cra_ctxsize = sizeof(struct cc_aead_ctx); 257962306a36Sopenharmony_ci alg->base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY; 258062306a36Sopenharmony_ci alg->base.cra_blocksize = tmpl->blocksize; 258162306a36Sopenharmony_ci alg->init = cc_aead_init; 258262306a36Sopenharmony_ci alg->exit = cc_aead_exit; 258362306a36Sopenharmony_ci 258462306a36Sopenharmony_ci t_alg->aead_alg = *alg; 258562306a36Sopenharmony_ci 258662306a36Sopenharmony_ci t_alg->cipher_mode = tmpl->cipher_mode; 258762306a36Sopenharmony_ci t_alg->flow_mode = tmpl->flow_mode; 258862306a36Sopenharmony_ci t_alg->auth_mode = tmpl->auth_mode; 258962306a36Sopenharmony_ci 259062306a36Sopenharmony_ci return t_alg; 259162306a36Sopenharmony_ci} 259262306a36Sopenharmony_ci 259362306a36Sopenharmony_ciint cc_aead_free(struct cc_drvdata *drvdata) 259462306a36Sopenharmony_ci{ 259562306a36Sopenharmony_ci struct cc_crypto_alg *t_alg, *n; 259662306a36Sopenharmony_ci struct cc_aead_handle *aead_handle = drvdata->aead_handle; 259762306a36Sopenharmony_ci 259862306a36Sopenharmony_ci /* Remove registered algs */ 259962306a36Sopenharmony_ci list_for_each_entry_safe(t_alg, n, &aead_handle->aead_list, entry) { 260062306a36Sopenharmony_ci crypto_unregister_aead(&t_alg->aead_alg); 260162306a36Sopenharmony_ci list_del(&t_alg->entry); 260262306a36Sopenharmony_ci } 260362306a36Sopenharmony_ci 260462306a36Sopenharmony_ci return 0; 260562306a36Sopenharmony_ci} 260662306a36Sopenharmony_ci 260762306a36Sopenharmony_ciint cc_aead_alloc(struct cc_drvdata *drvdata) 260862306a36Sopenharmony_ci{ 260962306a36Sopenharmony_ci struct cc_aead_handle *aead_handle; 261062306a36Sopenharmony_ci struct cc_crypto_alg *t_alg; 261162306a36Sopenharmony_ci int rc = -ENOMEM; 261262306a36Sopenharmony_ci int alg; 261362306a36Sopenharmony_ci struct device *dev = drvdata_to_dev(drvdata); 261462306a36Sopenharmony_ci 261562306a36Sopenharmony_ci aead_handle = devm_kmalloc(dev, sizeof(*aead_handle), GFP_KERNEL); 261662306a36Sopenharmony_ci if (!aead_handle) { 261762306a36Sopenharmony_ci rc = -ENOMEM; 261862306a36Sopenharmony_ci goto fail0; 261962306a36Sopenharmony_ci } 262062306a36Sopenharmony_ci 262162306a36Sopenharmony_ci INIT_LIST_HEAD(&aead_handle->aead_list); 262262306a36Sopenharmony_ci drvdata->aead_handle = aead_handle; 262362306a36Sopenharmony_ci 262462306a36Sopenharmony_ci aead_handle->sram_workspace_addr = cc_sram_alloc(drvdata, 262562306a36Sopenharmony_ci MAX_HMAC_DIGEST_SIZE); 262662306a36Sopenharmony_ci 262762306a36Sopenharmony_ci if (aead_handle->sram_workspace_addr == NULL_SRAM_ADDR) { 262862306a36Sopenharmony_ci rc = -ENOMEM; 262962306a36Sopenharmony_ci goto fail1; 263062306a36Sopenharmony_ci } 263162306a36Sopenharmony_ci 263262306a36Sopenharmony_ci /* Linux crypto */ 263362306a36Sopenharmony_ci for (alg = 0; alg < ARRAY_SIZE(aead_algs); alg++) { 263462306a36Sopenharmony_ci if ((aead_algs[alg].min_hw_rev > drvdata->hw_rev) || 263562306a36Sopenharmony_ci !(drvdata->std_bodies & aead_algs[alg].std_body)) 263662306a36Sopenharmony_ci continue; 263762306a36Sopenharmony_ci 263862306a36Sopenharmony_ci t_alg = cc_create_aead_alg(&aead_algs[alg], dev); 263962306a36Sopenharmony_ci if (IS_ERR(t_alg)) { 264062306a36Sopenharmony_ci rc = PTR_ERR(t_alg); 264162306a36Sopenharmony_ci dev_err(dev, "%s alg allocation failed\n", 264262306a36Sopenharmony_ci aead_algs[alg].driver_name); 264362306a36Sopenharmony_ci goto fail1; 264462306a36Sopenharmony_ci } 264562306a36Sopenharmony_ci t_alg->drvdata = drvdata; 264662306a36Sopenharmony_ci rc = crypto_register_aead(&t_alg->aead_alg); 264762306a36Sopenharmony_ci if (rc) { 264862306a36Sopenharmony_ci dev_err(dev, "%s alg registration failed\n", 264962306a36Sopenharmony_ci t_alg->aead_alg.base.cra_driver_name); 265062306a36Sopenharmony_ci goto fail1; 265162306a36Sopenharmony_ci } 265262306a36Sopenharmony_ci 265362306a36Sopenharmony_ci list_add_tail(&t_alg->entry, &aead_handle->aead_list); 265462306a36Sopenharmony_ci dev_dbg(dev, "Registered %s\n", 265562306a36Sopenharmony_ci t_alg->aead_alg.base.cra_driver_name); 265662306a36Sopenharmony_ci } 265762306a36Sopenharmony_ci 265862306a36Sopenharmony_ci return 0; 265962306a36Sopenharmony_ci 266062306a36Sopenharmony_cifail1: 266162306a36Sopenharmony_ci cc_aead_free(drvdata); 266262306a36Sopenharmony_cifail0: 266362306a36Sopenharmony_ci return rc; 266462306a36Sopenharmony_ci} 2665