162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/* Copyright (C) 2020 Marvell. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <crypto/aes.h>
562306a36Sopenharmony_ci#include <crypto/authenc.h>
662306a36Sopenharmony_ci#include <crypto/cryptd.h>
762306a36Sopenharmony_ci#include <crypto/des.h>
862306a36Sopenharmony_ci#include <crypto/internal/aead.h>
962306a36Sopenharmony_ci#include <crypto/sha1.h>
1062306a36Sopenharmony_ci#include <crypto/sha2.h>
1162306a36Sopenharmony_ci#include <crypto/xts.h>
1262306a36Sopenharmony_ci#include <crypto/gcm.h>
1362306a36Sopenharmony_ci#include <crypto/scatterwalk.h>
1462306a36Sopenharmony_ci#include <linux/rtnetlink.h>
1562306a36Sopenharmony_ci#include <linux/sort.h>
1662306a36Sopenharmony_ci#include <linux/module.h>
1762306a36Sopenharmony_ci#include "otx2_cptvf.h"
1862306a36Sopenharmony_ci#include "otx2_cptvf_algs.h"
1962306a36Sopenharmony_ci#include "otx2_cpt_reqmgr.h"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/* Size of salt in AES GCM mode */
2262306a36Sopenharmony_ci#define AES_GCM_SALT_SIZE 4
2362306a36Sopenharmony_ci/* Size of IV in AES GCM mode */
2462306a36Sopenharmony_ci#define AES_GCM_IV_SIZE 8
2562306a36Sopenharmony_ci/* Size of ICV (Integrity Check Value) in AES GCM mode */
2662306a36Sopenharmony_ci#define AES_GCM_ICV_SIZE 16
2762306a36Sopenharmony_ci/* Offset of IV in AES GCM mode */
2862306a36Sopenharmony_ci#define AES_GCM_IV_OFFSET 8
2962306a36Sopenharmony_ci#define CONTROL_WORD_LEN 8
3062306a36Sopenharmony_ci#define KEY2_OFFSET 48
3162306a36Sopenharmony_ci#define DMA_MODE_FLAG(dma_mode) \
3262306a36Sopenharmony_ci	(((dma_mode) == OTX2_CPT_DMA_MODE_SG) ? (1 << 7) : 0)
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/* Truncated SHA digest size */
3562306a36Sopenharmony_ci#define SHA1_TRUNC_DIGEST_SIZE 12
3662306a36Sopenharmony_ci#define SHA256_TRUNC_DIGEST_SIZE 16
3762306a36Sopenharmony_ci#define SHA384_TRUNC_DIGEST_SIZE 24
3862306a36Sopenharmony_ci#define SHA512_TRUNC_DIGEST_SIZE 32
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistatic DEFINE_MUTEX(mutex);
4162306a36Sopenharmony_cistatic int is_crypto_registered;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistruct cpt_device_desc {
4462306a36Sopenharmony_ci	struct pci_dev *dev;
4562306a36Sopenharmony_ci	int num_queues;
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistruct cpt_device_table {
4962306a36Sopenharmony_ci	atomic_t count;
5062306a36Sopenharmony_ci	struct cpt_device_desc desc[OTX2_CPT_MAX_LFS_NUM];
5162306a36Sopenharmony_ci};
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cistatic struct cpt_device_table se_devices = {
5462306a36Sopenharmony_ci	.count = ATOMIC_INIT(0)
5562306a36Sopenharmony_ci};
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic inline int get_se_device(struct pci_dev **pdev, int *cpu_num)
5862306a36Sopenharmony_ci{
5962306a36Sopenharmony_ci	int count;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	count = atomic_read(&se_devices.count);
6262306a36Sopenharmony_ci	if (count < 1)
6362306a36Sopenharmony_ci		return -ENODEV;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	*cpu_num = get_cpu();
6662306a36Sopenharmony_ci	/*
6762306a36Sopenharmony_ci	 * On OcteonTX2 platform CPT instruction queue is bound to each
6862306a36Sopenharmony_ci	 * local function LF, in turn LFs can be attached to PF
6962306a36Sopenharmony_ci	 * or VF therefore we always use first device. We get maximum
7062306a36Sopenharmony_ci	 * performance if one CPT queue is available for each cpu
7162306a36Sopenharmony_ci	 * otherwise CPT queues need to be shared between cpus.
7262306a36Sopenharmony_ci	 */
7362306a36Sopenharmony_ci	if (*cpu_num >= se_devices.desc[0].num_queues)
7462306a36Sopenharmony_ci		*cpu_num %= se_devices.desc[0].num_queues;
7562306a36Sopenharmony_ci	*pdev = se_devices.desc[0].dev;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	put_cpu();
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	return 0;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic inline int validate_hmac_cipher_null(struct otx2_cpt_req_info *cpt_req)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	struct otx2_cpt_req_ctx *rctx;
8562306a36Sopenharmony_ci	struct aead_request *req;
8662306a36Sopenharmony_ci	struct crypto_aead *tfm;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	req = container_of(cpt_req->areq, struct aead_request, base);
8962306a36Sopenharmony_ci	tfm = crypto_aead_reqtfm(req);
9062306a36Sopenharmony_ci	rctx = aead_request_ctx_dma(req);
9162306a36Sopenharmony_ci	if (memcmp(rctx->fctx.hmac.s.hmac_calc,
9262306a36Sopenharmony_ci		   rctx->fctx.hmac.s.hmac_recv,
9362306a36Sopenharmony_ci		   crypto_aead_authsize(tfm)) != 0)
9462306a36Sopenharmony_ci		return -EBADMSG;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	return 0;
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic void otx2_cpt_aead_callback(int status, void *arg1, void *arg2)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	struct otx2_cpt_inst_info *inst_info = arg2;
10262306a36Sopenharmony_ci	struct crypto_async_request *areq = arg1;
10362306a36Sopenharmony_ci	struct otx2_cpt_req_info *cpt_req;
10462306a36Sopenharmony_ci	struct pci_dev *pdev;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	if (inst_info) {
10762306a36Sopenharmony_ci		cpt_req = inst_info->req;
10862306a36Sopenharmony_ci		if (!status) {
10962306a36Sopenharmony_ci			/*
11062306a36Sopenharmony_ci			 * When selected cipher is NULL we need to manually
11162306a36Sopenharmony_ci			 * verify whether calculated hmac value matches
11262306a36Sopenharmony_ci			 * received hmac value
11362306a36Sopenharmony_ci			 */
11462306a36Sopenharmony_ci			if (cpt_req->req_type ==
11562306a36Sopenharmony_ci			    OTX2_CPT_AEAD_ENC_DEC_NULL_REQ &&
11662306a36Sopenharmony_ci			    !cpt_req->is_enc)
11762306a36Sopenharmony_ci				status = validate_hmac_cipher_null(cpt_req);
11862306a36Sopenharmony_ci		}
11962306a36Sopenharmony_ci		pdev = inst_info->pdev;
12062306a36Sopenharmony_ci		otx2_cpt_info_destroy(pdev, inst_info);
12162306a36Sopenharmony_ci	}
12262306a36Sopenharmony_ci	if (areq)
12362306a36Sopenharmony_ci		crypto_request_complete(areq, status);
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistatic void output_iv_copyback(struct crypto_async_request *areq)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	struct otx2_cpt_req_info *req_info;
12962306a36Sopenharmony_ci	struct otx2_cpt_req_ctx *rctx;
13062306a36Sopenharmony_ci	struct skcipher_request *sreq;
13162306a36Sopenharmony_ci	struct crypto_skcipher *stfm;
13262306a36Sopenharmony_ci	struct otx2_cpt_enc_ctx *ctx;
13362306a36Sopenharmony_ci	u32 start, ivsize;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	sreq = container_of(areq, struct skcipher_request, base);
13662306a36Sopenharmony_ci	stfm = crypto_skcipher_reqtfm(sreq);
13762306a36Sopenharmony_ci	ctx = crypto_skcipher_ctx(stfm);
13862306a36Sopenharmony_ci	if (ctx->cipher_type == OTX2_CPT_AES_CBC ||
13962306a36Sopenharmony_ci	    ctx->cipher_type == OTX2_CPT_DES3_CBC) {
14062306a36Sopenharmony_ci		rctx = skcipher_request_ctx_dma(sreq);
14162306a36Sopenharmony_ci		req_info = &rctx->cpt_req;
14262306a36Sopenharmony_ci		ivsize = crypto_skcipher_ivsize(stfm);
14362306a36Sopenharmony_ci		start = sreq->cryptlen - ivsize;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci		if (req_info->is_enc) {
14662306a36Sopenharmony_ci			scatterwalk_map_and_copy(sreq->iv, sreq->dst, start,
14762306a36Sopenharmony_ci						 ivsize, 0);
14862306a36Sopenharmony_ci		} else {
14962306a36Sopenharmony_ci			if (sreq->src != sreq->dst) {
15062306a36Sopenharmony_ci				scatterwalk_map_and_copy(sreq->iv, sreq->src,
15162306a36Sopenharmony_ci							 start, ivsize, 0);
15262306a36Sopenharmony_ci			} else {
15362306a36Sopenharmony_ci				memcpy(sreq->iv, req_info->iv_out, ivsize);
15462306a36Sopenharmony_ci				kfree(req_info->iv_out);
15562306a36Sopenharmony_ci			}
15662306a36Sopenharmony_ci		}
15762306a36Sopenharmony_ci	}
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic void otx2_cpt_skcipher_callback(int status, void *arg1, void *arg2)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	struct otx2_cpt_inst_info *inst_info = arg2;
16362306a36Sopenharmony_ci	struct crypto_async_request *areq = arg1;
16462306a36Sopenharmony_ci	struct pci_dev *pdev;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	if (areq) {
16762306a36Sopenharmony_ci		if (!status)
16862306a36Sopenharmony_ci			output_iv_copyback(areq);
16962306a36Sopenharmony_ci		if (inst_info) {
17062306a36Sopenharmony_ci			pdev = inst_info->pdev;
17162306a36Sopenharmony_ci			otx2_cpt_info_destroy(pdev, inst_info);
17262306a36Sopenharmony_ci		}
17362306a36Sopenharmony_ci		crypto_request_complete(areq, status);
17462306a36Sopenharmony_ci	}
17562306a36Sopenharmony_ci}
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_cistatic inline void update_input_data(struct otx2_cpt_req_info *req_info,
17862306a36Sopenharmony_ci				     struct scatterlist *inp_sg,
17962306a36Sopenharmony_ci				     u32 nbytes, u32 *argcnt)
18062306a36Sopenharmony_ci{
18162306a36Sopenharmony_ci	req_info->req.dlen += nbytes;
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	while (nbytes) {
18462306a36Sopenharmony_ci		u32 len = (nbytes < inp_sg->length) ? nbytes : inp_sg->length;
18562306a36Sopenharmony_ci		u8 *ptr = sg_virt(inp_sg);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci		req_info->in[*argcnt].vptr = (void *)ptr;
18862306a36Sopenharmony_ci		req_info->in[*argcnt].size = len;
18962306a36Sopenharmony_ci		nbytes -= len;
19062306a36Sopenharmony_ci		++(*argcnt);
19162306a36Sopenharmony_ci		inp_sg = sg_next(inp_sg);
19262306a36Sopenharmony_ci	}
19362306a36Sopenharmony_ci}
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_cistatic inline void update_output_data(struct otx2_cpt_req_info *req_info,
19662306a36Sopenharmony_ci				      struct scatterlist *outp_sg,
19762306a36Sopenharmony_ci				      u32 offset, u32 nbytes, u32 *argcnt)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	u32 len, sg_len;
20062306a36Sopenharmony_ci	u8 *ptr;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	req_info->rlen += nbytes;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	while (nbytes) {
20562306a36Sopenharmony_ci		sg_len = outp_sg->length - offset;
20662306a36Sopenharmony_ci		len = (nbytes < sg_len) ? nbytes : sg_len;
20762306a36Sopenharmony_ci		ptr = sg_virt(outp_sg);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci		req_info->out[*argcnt].vptr = (void *) (ptr + offset);
21062306a36Sopenharmony_ci		req_info->out[*argcnt].size = len;
21162306a36Sopenharmony_ci		nbytes -= len;
21262306a36Sopenharmony_ci		++(*argcnt);
21362306a36Sopenharmony_ci		offset = 0;
21462306a36Sopenharmony_ci		outp_sg = sg_next(outp_sg);
21562306a36Sopenharmony_ci	}
21662306a36Sopenharmony_ci}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_cistatic inline int create_ctx_hdr(struct skcipher_request *req, u32 enc,
21962306a36Sopenharmony_ci				 u32 *argcnt)
22062306a36Sopenharmony_ci{
22162306a36Sopenharmony_ci	struct crypto_skcipher *stfm = crypto_skcipher_reqtfm(req);
22262306a36Sopenharmony_ci	struct otx2_cpt_req_ctx *rctx = skcipher_request_ctx_dma(req);
22362306a36Sopenharmony_ci	struct otx2_cpt_enc_ctx *ctx = crypto_skcipher_ctx(stfm);
22462306a36Sopenharmony_ci	struct otx2_cpt_req_info *req_info = &rctx->cpt_req;
22562306a36Sopenharmony_ci	struct otx2_cpt_fc_ctx *fctx = &rctx->fctx;
22662306a36Sopenharmony_ci	int ivsize = crypto_skcipher_ivsize(stfm);
22762306a36Sopenharmony_ci	u32 start = req->cryptlen - ivsize;
22862306a36Sopenharmony_ci	gfp_t flags;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
23162306a36Sopenharmony_ci			GFP_KERNEL : GFP_ATOMIC;
23262306a36Sopenharmony_ci	req_info->ctrl.s.dma_mode = OTX2_CPT_DMA_MODE_SG;
23362306a36Sopenharmony_ci	req_info->ctrl.s.se_req = 1;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	req_info->req.opcode.s.major = OTX2_CPT_MAJOR_OP_FC |
23662306a36Sopenharmony_ci				DMA_MODE_FLAG(OTX2_CPT_DMA_MODE_SG);
23762306a36Sopenharmony_ci	if (enc) {
23862306a36Sopenharmony_ci		req_info->req.opcode.s.minor = 2;
23962306a36Sopenharmony_ci	} else {
24062306a36Sopenharmony_ci		req_info->req.opcode.s.minor = 3;
24162306a36Sopenharmony_ci		if ((ctx->cipher_type == OTX2_CPT_AES_CBC ||
24262306a36Sopenharmony_ci		    ctx->cipher_type == OTX2_CPT_DES3_CBC) &&
24362306a36Sopenharmony_ci		    req->src == req->dst) {
24462306a36Sopenharmony_ci			req_info->iv_out = kmalloc(ivsize, flags);
24562306a36Sopenharmony_ci			if (!req_info->iv_out)
24662306a36Sopenharmony_ci				return -ENOMEM;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci			scatterwalk_map_and_copy(req_info->iv_out, req->src,
24962306a36Sopenharmony_ci						 start, ivsize, 0);
25062306a36Sopenharmony_ci		}
25162306a36Sopenharmony_ci	}
25262306a36Sopenharmony_ci	/* Encryption data length */
25362306a36Sopenharmony_ci	req_info->req.param1 = req->cryptlen;
25462306a36Sopenharmony_ci	/* Authentication data length */
25562306a36Sopenharmony_ci	req_info->req.param2 = 0;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.enc_cipher = ctx->cipher_type;
25862306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.aes_key = ctx->key_type;
25962306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.iv_source = OTX2_CPT_FROM_CPTR;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	if (ctx->cipher_type == OTX2_CPT_AES_XTS)
26262306a36Sopenharmony_ci		memcpy(fctx->enc.encr_key, ctx->enc_key, ctx->key_len * 2);
26362306a36Sopenharmony_ci	else
26462306a36Sopenharmony_ci		memcpy(fctx->enc.encr_key, ctx->enc_key, ctx->key_len);
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	memcpy(fctx->enc.encr_iv, req->iv, crypto_skcipher_ivsize(stfm));
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	cpu_to_be64s(&fctx->enc.enc_ctrl.u);
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	/*
27162306a36Sopenharmony_ci	 * Storing  Packet Data Information in offset
27262306a36Sopenharmony_ci	 * Control Word First 8 bytes
27362306a36Sopenharmony_ci	 */
27462306a36Sopenharmony_ci	req_info->in[*argcnt].vptr = (u8 *)&rctx->ctrl_word;
27562306a36Sopenharmony_ci	req_info->in[*argcnt].size = CONTROL_WORD_LEN;
27662306a36Sopenharmony_ci	req_info->req.dlen += CONTROL_WORD_LEN;
27762306a36Sopenharmony_ci	++(*argcnt);
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	req_info->in[*argcnt].vptr = (u8 *)fctx;
28062306a36Sopenharmony_ci	req_info->in[*argcnt].size = sizeof(struct otx2_cpt_fc_ctx);
28162306a36Sopenharmony_ci	req_info->req.dlen += sizeof(struct otx2_cpt_fc_ctx);
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	++(*argcnt);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	return 0;
28662306a36Sopenharmony_ci}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_cistatic inline int create_input_list(struct skcipher_request *req, u32 enc,
28962306a36Sopenharmony_ci				    u32 enc_iv_len)
29062306a36Sopenharmony_ci{
29162306a36Sopenharmony_ci	struct otx2_cpt_req_ctx *rctx = skcipher_request_ctx_dma(req);
29262306a36Sopenharmony_ci	struct otx2_cpt_req_info *req_info = &rctx->cpt_req;
29362306a36Sopenharmony_ci	u32 argcnt =  0;
29462306a36Sopenharmony_ci	int ret;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	ret = create_ctx_hdr(req, enc, &argcnt);
29762306a36Sopenharmony_ci	if (ret)
29862306a36Sopenharmony_ci		return ret;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	update_input_data(req_info, req->src, req->cryptlen, &argcnt);
30162306a36Sopenharmony_ci	req_info->in_cnt = argcnt;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	return 0;
30462306a36Sopenharmony_ci}
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_cistatic inline void create_output_list(struct skcipher_request *req,
30762306a36Sopenharmony_ci				      u32 enc_iv_len)
30862306a36Sopenharmony_ci{
30962306a36Sopenharmony_ci	struct otx2_cpt_req_ctx *rctx = skcipher_request_ctx_dma(req);
31062306a36Sopenharmony_ci	struct otx2_cpt_req_info *req_info = &rctx->cpt_req;
31162306a36Sopenharmony_ci	u32 argcnt = 0;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	/*
31462306a36Sopenharmony_ci	 * OUTPUT Buffer Processing
31562306a36Sopenharmony_ci	 * AES encryption/decryption output would be
31662306a36Sopenharmony_ci	 * received in the following format
31762306a36Sopenharmony_ci	 *
31862306a36Sopenharmony_ci	 * ------IV--------|------ENCRYPTED/DECRYPTED DATA-----|
31962306a36Sopenharmony_ci	 * [ 16 Bytes/     [   Request Enc/Dec/ DATA Len AES CBC ]
32062306a36Sopenharmony_ci	 */
32162306a36Sopenharmony_ci	update_output_data(req_info, req->dst, 0, req->cryptlen, &argcnt);
32262306a36Sopenharmony_ci	req_info->out_cnt = argcnt;
32362306a36Sopenharmony_ci}
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_cistatic int skcipher_do_fallback(struct skcipher_request *req, bool is_enc)
32662306a36Sopenharmony_ci{
32762306a36Sopenharmony_ci	struct crypto_skcipher *stfm = crypto_skcipher_reqtfm(req);
32862306a36Sopenharmony_ci	struct otx2_cpt_req_ctx *rctx = skcipher_request_ctx_dma(req);
32962306a36Sopenharmony_ci	struct otx2_cpt_enc_ctx *ctx = crypto_skcipher_ctx(stfm);
33062306a36Sopenharmony_ci	int ret;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	if (ctx->fbk_cipher) {
33362306a36Sopenharmony_ci		skcipher_request_set_tfm(&rctx->sk_fbk_req, ctx->fbk_cipher);
33462306a36Sopenharmony_ci		skcipher_request_set_callback(&rctx->sk_fbk_req,
33562306a36Sopenharmony_ci					      req->base.flags,
33662306a36Sopenharmony_ci					      req->base.complete,
33762306a36Sopenharmony_ci					      req->base.data);
33862306a36Sopenharmony_ci		skcipher_request_set_crypt(&rctx->sk_fbk_req, req->src,
33962306a36Sopenharmony_ci					   req->dst, req->cryptlen, req->iv);
34062306a36Sopenharmony_ci		ret = is_enc ? crypto_skcipher_encrypt(&rctx->sk_fbk_req) :
34162306a36Sopenharmony_ci			       crypto_skcipher_decrypt(&rctx->sk_fbk_req);
34262306a36Sopenharmony_ci	} else {
34362306a36Sopenharmony_ci		ret = -EINVAL;
34462306a36Sopenharmony_ci	}
34562306a36Sopenharmony_ci	return ret;
34662306a36Sopenharmony_ci}
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_cistatic inline int cpt_enc_dec(struct skcipher_request *req, u32 enc)
34962306a36Sopenharmony_ci{
35062306a36Sopenharmony_ci	struct crypto_skcipher *stfm = crypto_skcipher_reqtfm(req);
35162306a36Sopenharmony_ci	struct otx2_cpt_req_ctx *rctx = skcipher_request_ctx_dma(req);
35262306a36Sopenharmony_ci	struct otx2_cpt_enc_ctx *ctx = crypto_skcipher_ctx(stfm);
35362306a36Sopenharmony_ci	struct otx2_cpt_req_info *req_info = &rctx->cpt_req;
35462306a36Sopenharmony_ci	u32 enc_iv_len = crypto_skcipher_ivsize(stfm);
35562306a36Sopenharmony_ci	struct pci_dev *pdev;
35662306a36Sopenharmony_ci	int status, cpu_num;
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	if (req->cryptlen == 0)
35962306a36Sopenharmony_ci		return 0;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	if (!IS_ALIGNED(req->cryptlen, ctx->enc_align_len))
36262306a36Sopenharmony_ci		return -EINVAL;
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	if (req->cryptlen > OTX2_CPT_MAX_REQ_SIZE)
36562306a36Sopenharmony_ci		return skcipher_do_fallback(req, enc);
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	/* Clear control words */
36862306a36Sopenharmony_ci	rctx->ctrl_word.flags = 0;
36962306a36Sopenharmony_ci	rctx->fctx.enc.enc_ctrl.u = 0;
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	status = create_input_list(req, enc, enc_iv_len);
37262306a36Sopenharmony_ci	if (status)
37362306a36Sopenharmony_ci		return status;
37462306a36Sopenharmony_ci	create_output_list(req, enc_iv_len);
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	status = get_se_device(&pdev, &cpu_num);
37762306a36Sopenharmony_ci	if (status)
37862306a36Sopenharmony_ci		return status;
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	req_info->callback = otx2_cpt_skcipher_callback;
38162306a36Sopenharmony_ci	req_info->areq = &req->base;
38262306a36Sopenharmony_ci	req_info->req_type = OTX2_CPT_ENC_DEC_REQ;
38362306a36Sopenharmony_ci	req_info->is_enc = enc;
38462306a36Sopenharmony_ci	req_info->is_trunc_hmac = false;
38562306a36Sopenharmony_ci	req_info->ctrl.s.grp = otx2_cpt_get_kcrypto_eng_grp_num(pdev);
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	/*
38862306a36Sopenharmony_ci	 * We perform an asynchronous send and once
38962306a36Sopenharmony_ci	 * the request is completed the driver would
39062306a36Sopenharmony_ci	 * intimate through registered call back functions
39162306a36Sopenharmony_ci	 */
39262306a36Sopenharmony_ci	status = otx2_cpt_do_request(pdev, req_info, cpu_num);
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	return status;
39562306a36Sopenharmony_ci}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_cistatic int otx2_cpt_skcipher_encrypt(struct skcipher_request *req)
39862306a36Sopenharmony_ci{
39962306a36Sopenharmony_ci	return cpt_enc_dec(req, true);
40062306a36Sopenharmony_ci}
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_cistatic int otx2_cpt_skcipher_decrypt(struct skcipher_request *req)
40362306a36Sopenharmony_ci{
40462306a36Sopenharmony_ci	return cpt_enc_dec(req, false);
40562306a36Sopenharmony_ci}
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_cistatic int otx2_cpt_skcipher_xts_setkey(struct crypto_skcipher *tfm,
40862306a36Sopenharmony_ci				       const u8 *key, u32 keylen)
40962306a36Sopenharmony_ci{
41062306a36Sopenharmony_ci	struct otx2_cpt_enc_ctx *ctx = crypto_skcipher_ctx(tfm);
41162306a36Sopenharmony_ci	const u8 *key2 = key + (keylen / 2);
41262306a36Sopenharmony_ci	const u8 *key1 = key;
41362306a36Sopenharmony_ci	int ret;
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	ret = xts_verify_key(tfm, key, keylen);
41662306a36Sopenharmony_ci	if (ret)
41762306a36Sopenharmony_ci		return ret;
41862306a36Sopenharmony_ci	ctx->key_len = keylen;
41962306a36Sopenharmony_ci	ctx->enc_align_len = 1;
42062306a36Sopenharmony_ci	memcpy(ctx->enc_key, key1, keylen / 2);
42162306a36Sopenharmony_ci	memcpy(ctx->enc_key + KEY2_OFFSET, key2, keylen / 2);
42262306a36Sopenharmony_ci	ctx->cipher_type = OTX2_CPT_AES_XTS;
42362306a36Sopenharmony_ci	switch (ctx->key_len) {
42462306a36Sopenharmony_ci	case 2 * AES_KEYSIZE_128:
42562306a36Sopenharmony_ci		ctx->key_type = OTX2_CPT_AES_128_BIT;
42662306a36Sopenharmony_ci		break;
42762306a36Sopenharmony_ci	case 2 * AES_KEYSIZE_192:
42862306a36Sopenharmony_ci		ctx->key_type = OTX2_CPT_AES_192_BIT;
42962306a36Sopenharmony_ci		break;
43062306a36Sopenharmony_ci	case 2 * AES_KEYSIZE_256:
43162306a36Sopenharmony_ci		ctx->key_type = OTX2_CPT_AES_256_BIT;
43262306a36Sopenharmony_ci		break;
43362306a36Sopenharmony_ci	default:
43462306a36Sopenharmony_ci		return -EINVAL;
43562306a36Sopenharmony_ci	}
43662306a36Sopenharmony_ci	return crypto_skcipher_setkey(ctx->fbk_cipher, key, keylen);
43762306a36Sopenharmony_ci}
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_cistatic int cpt_des_setkey(struct crypto_skcipher *tfm, const u8 *key,
44062306a36Sopenharmony_ci			  u32 keylen, u8 cipher_type)
44162306a36Sopenharmony_ci{
44262306a36Sopenharmony_ci	struct otx2_cpt_enc_ctx *ctx = crypto_skcipher_ctx(tfm);
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	if (keylen != DES3_EDE_KEY_SIZE)
44562306a36Sopenharmony_ci		return -EINVAL;
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	ctx->key_len = keylen;
44862306a36Sopenharmony_ci	ctx->cipher_type = cipher_type;
44962306a36Sopenharmony_ci	ctx->enc_align_len = 8;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	memcpy(ctx->enc_key, key, keylen);
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	return crypto_skcipher_setkey(ctx->fbk_cipher, key, keylen);
45462306a36Sopenharmony_ci}
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_cistatic int cpt_aes_setkey(struct crypto_skcipher *tfm, const u8 *key,
45762306a36Sopenharmony_ci			  u32 keylen, u8 cipher_type)
45862306a36Sopenharmony_ci{
45962306a36Sopenharmony_ci	struct otx2_cpt_enc_ctx *ctx = crypto_skcipher_ctx(tfm);
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	switch (keylen) {
46262306a36Sopenharmony_ci	case AES_KEYSIZE_128:
46362306a36Sopenharmony_ci		ctx->key_type = OTX2_CPT_AES_128_BIT;
46462306a36Sopenharmony_ci		break;
46562306a36Sopenharmony_ci	case AES_KEYSIZE_192:
46662306a36Sopenharmony_ci		ctx->key_type = OTX2_CPT_AES_192_BIT;
46762306a36Sopenharmony_ci		break;
46862306a36Sopenharmony_ci	case AES_KEYSIZE_256:
46962306a36Sopenharmony_ci		ctx->key_type = OTX2_CPT_AES_256_BIT;
47062306a36Sopenharmony_ci		break;
47162306a36Sopenharmony_ci	default:
47262306a36Sopenharmony_ci		return -EINVAL;
47362306a36Sopenharmony_ci	}
47462306a36Sopenharmony_ci	if (cipher_type == OTX2_CPT_AES_CBC || cipher_type == OTX2_CPT_AES_ECB)
47562306a36Sopenharmony_ci		ctx->enc_align_len = 16;
47662306a36Sopenharmony_ci	else
47762306a36Sopenharmony_ci		ctx->enc_align_len = 1;
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	ctx->key_len = keylen;
48062306a36Sopenharmony_ci	ctx->cipher_type = cipher_type;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	memcpy(ctx->enc_key, key, keylen);
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	return crypto_skcipher_setkey(ctx->fbk_cipher, key, keylen);
48562306a36Sopenharmony_ci}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_cistatic int otx2_cpt_skcipher_cbc_aes_setkey(struct crypto_skcipher *tfm,
48862306a36Sopenharmony_ci					    const u8 *key, u32 keylen)
48962306a36Sopenharmony_ci{
49062306a36Sopenharmony_ci	return cpt_aes_setkey(tfm, key, keylen, OTX2_CPT_AES_CBC);
49162306a36Sopenharmony_ci}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_cistatic int otx2_cpt_skcipher_ecb_aes_setkey(struct crypto_skcipher *tfm,
49462306a36Sopenharmony_ci					    const u8 *key, u32 keylen)
49562306a36Sopenharmony_ci{
49662306a36Sopenharmony_ci	return cpt_aes_setkey(tfm, key, keylen, OTX2_CPT_AES_ECB);
49762306a36Sopenharmony_ci}
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_cistatic int otx2_cpt_skcipher_cbc_des3_setkey(struct crypto_skcipher *tfm,
50062306a36Sopenharmony_ci					     const u8 *key, u32 keylen)
50162306a36Sopenharmony_ci{
50262306a36Sopenharmony_ci	return cpt_des_setkey(tfm, key, keylen, OTX2_CPT_DES3_CBC);
50362306a36Sopenharmony_ci}
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_cistatic int otx2_cpt_skcipher_ecb_des3_setkey(struct crypto_skcipher *tfm,
50662306a36Sopenharmony_ci					     const u8 *key, u32 keylen)
50762306a36Sopenharmony_ci{
50862306a36Sopenharmony_ci	return cpt_des_setkey(tfm, key, keylen, OTX2_CPT_DES3_ECB);
50962306a36Sopenharmony_ci}
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_cistatic int cpt_skcipher_fallback_init(struct otx2_cpt_enc_ctx *ctx,
51262306a36Sopenharmony_ci				      struct crypto_alg *alg)
51362306a36Sopenharmony_ci{
51462306a36Sopenharmony_ci	if (alg->cra_flags & CRYPTO_ALG_NEED_FALLBACK) {
51562306a36Sopenharmony_ci		ctx->fbk_cipher =
51662306a36Sopenharmony_ci				crypto_alloc_skcipher(alg->cra_name, 0,
51762306a36Sopenharmony_ci						      CRYPTO_ALG_ASYNC |
51862306a36Sopenharmony_ci						      CRYPTO_ALG_NEED_FALLBACK);
51962306a36Sopenharmony_ci		if (IS_ERR(ctx->fbk_cipher)) {
52062306a36Sopenharmony_ci			pr_err("%s() failed to allocate fallback for %s\n",
52162306a36Sopenharmony_ci				__func__, alg->cra_name);
52262306a36Sopenharmony_ci			return PTR_ERR(ctx->fbk_cipher);
52362306a36Sopenharmony_ci		}
52462306a36Sopenharmony_ci	}
52562306a36Sopenharmony_ci	return 0;
52662306a36Sopenharmony_ci}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_cistatic int otx2_cpt_enc_dec_init(struct crypto_skcipher *stfm)
52962306a36Sopenharmony_ci{
53062306a36Sopenharmony_ci	struct otx2_cpt_enc_ctx *ctx = crypto_skcipher_ctx(stfm);
53162306a36Sopenharmony_ci	struct crypto_tfm *tfm = crypto_skcipher_tfm(stfm);
53262306a36Sopenharmony_ci	struct crypto_alg *alg = tfm->__crt_alg;
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	memset(ctx, 0, sizeof(*ctx));
53562306a36Sopenharmony_ci	/*
53662306a36Sopenharmony_ci	 * Additional memory for skcipher_request is
53762306a36Sopenharmony_ci	 * allocated since the cryptd daemon uses
53862306a36Sopenharmony_ci	 * this memory for request_ctx information
53962306a36Sopenharmony_ci	 */
54062306a36Sopenharmony_ci	crypto_skcipher_set_reqsize_dma(
54162306a36Sopenharmony_ci		stfm, sizeof(struct otx2_cpt_req_ctx) +
54262306a36Sopenharmony_ci		      sizeof(struct skcipher_request));
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	return cpt_skcipher_fallback_init(ctx, alg);
54562306a36Sopenharmony_ci}
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_cistatic void otx2_cpt_skcipher_exit(struct crypto_skcipher *tfm)
54862306a36Sopenharmony_ci{
54962306a36Sopenharmony_ci	struct otx2_cpt_enc_ctx *ctx = crypto_skcipher_ctx(tfm);
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	if (ctx->fbk_cipher) {
55262306a36Sopenharmony_ci		crypto_free_skcipher(ctx->fbk_cipher);
55362306a36Sopenharmony_ci		ctx->fbk_cipher = NULL;
55462306a36Sopenharmony_ci	}
55562306a36Sopenharmony_ci}
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_cistatic int cpt_aead_fallback_init(struct otx2_cpt_aead_ctx *ctx,
55862306a36Sopenharmony_ci				  struct crypto_alg *alg)
55962306a36Sopenharmony_ci{
56062306a36Sopenharmony_ci	if (alg->cra_flags & CRYPTO_ALG_NEED_FALLBACK) {
56162306a36Sopenharmony_ci		ctx->fbk_cipher =
56262306a36Sopenharmony_ci			    crypto_alloc_aead(alg->cra_name, 0,
56362306a36Sopenharmony_ci					      CRYPTO_ALG_ASYNC |
56462306a36Sopenharmony_ci					      CRYPTO_ALG_NEED_FALLBACK);
56562306a36Sopenharmony_ci		if (IS_ERR(ctx->fbk_cipher)) {
56662306a36Sopenharmony_ci			pr_err("%s() failed to allocate fallback for %s\n",
56762306a36Sopenharmony_ci				__func__, alg->cra_name);
56862306a36Sopenharmony_ci			return PTR_ERR(ctx->fbk_cipher);
56962306a36Sopenharmony_ci		}
57062306a36Sopenharmony_ci	}
57162306a36Sopenharmony_ci	return 0;
57262306a36Sopenharmony_ci}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_cistatic int cpt_aead_init(struct crypto_aead *atfm, u8 cipher_type, u8 mac_type)
57562306a36Sopenharmony_ci{
57662306a36Sopenharmony_ci	struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(atfm);
57762306a36Sopenharmony_ci	struct crypto_tfm *tfm = crypto_aead_tfm(atfm);
57862306a36Sopenharmony_ci	struct crypto_alg *alg = tfm->__crt_alg;
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	ctx->cipher_type = cipher_type;
58162306a36Sopenharmony_ci	ctx->mac_type = mac_type;
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci	/*
58462306a36Sopenharmony_ci	 * When selected cipher is NULL we use HMAC opcode instead of
58562306a36Sopenharmony_ci	 * FLEXICRYPTO opcode therefore we don't need to use HASH algorithms
58662306a36Sopenharmony_ci	 * for calculating ipad and opad
58762306a36Sopenharmony_ci	 */
58862306a36Sopenharmony_ci	if (ctx->cipher_type != OTX2_CPT_CIPHER_NULL) {
58962306a36Sopenharmony_ci		switch (ctx->mac_type) {
59062306a36Sopenharmony_ci		case OTX2_CPT_SHA1:
59162306a36Sopenharmony_ci			ctx->hashalg = crypto_alloc_shash("sha1", 0,
59262306a36Sopenharmony_ci							  CRYPTO_ALG_ASYNC);
59362306a36Sopenharmony_ci			if (IS_ERR(ctx->hashalg))
59462306a36Sopenharmony_ci				return PTR_ERR(ctx->hashalg);
59562306a36Sopenharmony_ci			break;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci		case OTX2_CPT_SHA256:
59862306a36Sopenharmony_ci			ctx->hashalg = crypto_alloc_shash("sha256", 0,
59962306a36Sopenharmony_ci							  CRYPTO_ALG_ASYNC);
60062306a36Sopenharmony_ci			if (IS_ERR(ctx->hashalg))
60162306a36Sopenharmony_ci				return PTR_ERR(ctx->hashalg);
60262306a36Sopenharmony_ci			break;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci		case OTX2_CPT_SHA384:
60562306a36Sopenharmony_ci			ctx->hashalg = crypto_alloc_shash("sha384", 0,
60662306a36Sopenharmony_ci							  CRYPTO_ALG_ASYNC);
60762306a36Sopenharmony_ci			if (IS_ERR(ctx->hashalg))
60862306a36Sopenharmony_ci				return PTR_ERR(ctx->hashalg);
60962306a36Sopenharmony_ci			break;
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci		case OTX2_CPT_SHA512:
61262306a36Sopenharmony_ci			ctx->hashalg = crypto_alloc_shash("sha512", 0,
61362306a36Sopenharmony_ci							  CRYPTO_ALG_ASYNC);
61462306a36Sopenharmony_ci			if (IS_ERR(ctx->hashalg))
61562306a36Sopenharmony_ci				return PTR_ERR(ctx->hashalg);
61662306a36Sopenharmony_ci			break;
61762306a36Sopenharmony_ci		}
61862306a36Sopenharmony_ci	}
61962306a36Sopenharmony_ci	switch (ctx->cipher_type) {
62062306a36Sopenharmony_ci	case OTX2_CPT_AES_CBC:
62162306a36Sopenharmony_ci	case OTX2_CPT_AES_ECB:
62262306a36Sopenharmony_ci		ctx->enc_align_len = 16;
62362306a36Sopenharmony_ci		break;
62462306a36Sopenharmony_ci	case OTX2_CPT_DES3_CBC:
62562306a36Sopenharmony_ci	case OTX2_CPT_DES3_ECB:
62662306a36Sopenharmony_ci		ctx->enc_align_len = 8;
62762306a36Sopenharmony_ci		break;
62862306a36Sopenharmony_ci	case OTX2_CPT_AES_GCM:
62962306a36Sopenharmony_ci	case OTX2_CPT_CIPHER_NULL:
63062306a36Sopenharmony_ci		ctx->enc_align_len = 1;
63162306a36Sopenharmony_ci		break;
63262306a36Sopenharmony_ci	}
63362306a36Sopenharmony_ci	crypto_aead_set_reqsize_dma(atfm, sizeof(struct otx2_cpt_req_ctx));
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	return cpt_aead_fallback_init(ctx, alg);
63662306a36Sopenharmony_ci}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_cistatic int otx2_cpt_aead_cbc_aes_sha1_init(struct crypto_aead *tfm)
63962306a36Sopenharmony_ci{
64062306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX2_CPT_AES_CBC, OTX2_CPT_SHA1);
64162306a36Sopenharmony_ci}
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_cistatic int otx2_cpt_aead_cbc_aes_sha256_init(struct crypto_aead *tfm)
64462306a36Sopenharmony_ci{
64562306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX2_CPT_AES_CBC, OTX2_CPT_SHA256);
64662306a36Sopenharmony_ci}
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_cistatic int otx2_cpt_aead_cbc_aes_sha384_init(struct crypto_aead *tfm)
64962306a36Sopenharmony_ci{
65062306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX2_CPT_AES_CBC, OTX2_CPT_SHA384);
65162306a36Sopenharmony_ci}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_cistatic int otx2_cpt_aead_cbc_aes_sha512_init(struct crypto_aead *tfm)
65462306a36Sopenharmony_ci{
65562306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX2_CPT_AES_CBC, OTX2_CPT_SHA512);
65662306a36Sopenharmony_ci}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_cistatic int otx2_cpt_aead_ecb_null_sha1_init(struct crypto_aead *tfm)
65962306a36Sopenharmony_ci{
66062306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX2_CPT_CIPHER_NULL, OTX2_CPT_SHA1);
66162306a36Sopenharmony_ci}
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_cistatic int otx2_cpt_aead_ecb_null_sha256_init(struct crypto_aead *tfm)
66462306a36Sopenharmony_ci{
66562306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX2_CPT_CIPHER_NULL, OTX2_CPT_SHA256);
66662306a36Sopenharmony_ci}
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_cistatic int otx2_cpt_aead_ecb_null_sha384_init(struct crypto_aead *tfm)
66962306a36Sopenharmony_ci{
67062306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX2_CPT_CIPHER_NULL, OTX2_CPT_SHA384);
67162306a36Sopenharmony_ci}
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_cistatic int otx2_cpt_aead_ecb_null_sha512_init(struct crypto_aead *tfm)
67462306a36Sopenharmony_ci{
67562306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX2_CPT_CIPHER_NULL, OTX2_CPT_SHA512);
67662306a36Sopenharmony_ci}
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_cistatic int otx2_cpt_aead_gcm_aes_init(struct crypto_aead *tfm)
67962306a36Sopenharmony_ci{
68062306a36Sopenharmony_ci	return cpt_aead_init(tfm, OTX2_CPT_AES_GCM, OTX2_CPT_MAC_NULL);
68162306a36Sopenharmony_ci}
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_cistatic void otx2_cpt_aead_exit(struct crypto_aead *tfm)
68462306a36Sopenharmony_ci{
68562306a36Sopenharmony_ci	struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(tfm);
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	kfree(ctx->ipad);
68862306a36Sopenharmony_ci	kfree(ctx->opad);
68962306a36Sopenharmony_ci	if (ctx->hashalg)
69062306a36Sopenharmony_ci		crypto_free_shash(ctx->hashalg);
69162306a36Sopenharmony_ci	kfree(ctx->sdesc);
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	if (ctx->fbk_cipher) {
69462306a36Sopenharmony_ci		crypto_free_aead(ctx->fbk_cipher);
69562306a36Sopenharmony_ci		ctx->fbk_cipher = NULL;
69662306a36Sopenharmony_ci	}
69762306a36Sopenharmony_ci}
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_cistatic int otx2_cpt_aead_gcm_set_authsize(struct crypto_aead *tfm,
70062306a36Sopenharmony_ci					  unsigned int authsize)
70162306a36Sopenharmony_ci{
70262306a36Sopenharmony_ci	struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(tfm);
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	if (crypto_rfc4106_check_authsize(authsize))
70562306a36Sopenharmony_ci		return -EINVAL;
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci	tfm->authsize = authsize;
70862306a36Sopenharmony_ci	/* Set authsize for fallback case */
70962306a36Sopenharmony_ci	if (ctx->fbk_cipher)
71062306a36Sopenharmony_ci		ctx->fbk_cipher->authsize = authsize;
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci	return 0;
71362306a36Sopenharmony_ci}
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_cistatic int otx2_cpt_aead_set_authsize(struct crypto_aead *tfm,
71662306a36Sopenharmony_ci				      unsigned int authsize)
71762306a36Sopenharmony_ci{
71862306a36Sopenharmony_ci	tfm->authsize = authsize;
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci	return 0;
72162306a36Sopenharmony_ci}
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_cistatic int otx2_cpt_aead_null_set_authsize(struct crypto_aead *tfm,
72462306a36Sopenharmony_ci					   unsigned int authsize)
72562306a36Sopenharmony_ci{
72662306a36Sopenharmony_ci	struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(tfm);
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci	ctx->is_trunc_hmac = true;
72962306a36Sopenharmony_ci	tfm->authsize = authsize;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	return 0;
73262306a36Sopenharmony_ci}
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_cistatic struct otx2_cpt_sdesc *alloc_sdesc(struct crypto_shash *alg)
73562306a36Sopenharmony_ci{
73662306a36Sopenharmony_ci	struct otx2_cpt_sdesc *sdesc;
73762306a36Sopenharmony_ci	int size;
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci	size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
74062306a36Sopenharmony_ci	sdesc = kmalloc(size, GFP_KERNEL);
74162306a36Sopenharmony_ci	if (!sdesc)
74262306a36Sopenharmony_ci		return NULL;
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci	sdesc->shash.tfm = alg;
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	return sdesc;
74762306a36Sopenharmony_ci}
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_cistatic inline void swap_data32(void *buf, u32 len)
75062306a36Sopenharmony_ci{
75162306a36Sopenharmony_ci	cpu_to_be32_array(buf, buf, len / 4);
75262306a36Sopenharmony_ci}
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_cistatic inline void swap_data64(void *buf, u32 len)
75562306a36Sopenharmony_ci{
75662306a36Sopenharmony_ci	u64 *src = buf;
75762306a36Sopenharmony_ci	int i = 0;
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci	for (i = 0 ; i < len / 8; i++, src++)
76062306a36Sopenharmony_ci		cpu_to_be64s(src);
76162306a36Sopenharmony_ci}
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_cistatic int copy_pad(u8 mac_type, u8 *out_pad, u8 *in_pad)
76462306a36Sopenharmony_ci{
76562306a36Sopenharmony_ci	struct sha512_state *sha512;
76662306a36Sopenharmony_ci	struct sha256_state *sha256;
76762306a36Sopenharmony_ci	struct sha1_state *sha1;
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci	switch (mac_type) {
77062306a36Sopenharmony_ci	case OTX2_CPT_SHA1:
77162306a36Sopenharmony_ci		sha1 = (struct sha1_state *) in_pad;
77262306a36Sopenharmony_ci		swap_data32(sha1->state, SHA1_DIGEST_SIZE);
77362306a36Sopenharmony_ci		memcpy(out_pad, &sha1->state, SHA1_DIGEST_SIZE);
77462306a36Sopenharmony_ci		break;
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	case OTX2_CPT_SHA256:
77762306a36Sopenharmony_ci		sha256 = (struct sha256_state *) in_pad;
77862306a36Sopenharmony_ci		swap_data32(sha256->state, SHA256_DIGEST_SIZE);
77962306a36Sopenharmony_ci		memcpy(out_pad, &sha256->state, SHA256_DIGEST_SIZE);
78062306a36Sopenharmony_ci		break;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	case OTX2_CPT_SHA384:
78362306a36Sopenharmony_ci	case OTX2_CPT_SHA512:
78462306a36Sopenharmony_ci		sha512 = (struct sha512_state *) in_pad;
78562306a36Sopenharmony_ci		swap_data64(sha512->state, SHA512_DIGEST_SIZE);
78662306a36Sopenharmony_ci		memcpy(out_pad, &sha512->state, SHA512_DIGEST_SIZE);
78762306a36Sopenharmony_ci		break;
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	default:
79062306a36Sopenharmony_ci		return -EINVAL;
79162306a36Sopenharmony_ci	}
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	return 0;
79462306a36Sopenharmony_ci}
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_cistatic int aead_hmac_init(struct crypto_aead *cipher)
79762306a36Sopenharmony_ci{
79862306a36Sopenharmony_ci	struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
79962306a36Sopenharmony_ci	int state_size = crypto_shash_statesize(ctx->hashalg);
80062306a36Sopenharmony_ci	int ds = crypto_shash_digestsize(ctx->hashalg);
80162306a36Sopenharmony_ci	int bs = crypto_shash_blocksize(ctx->hashalg);
80262306a36Sopenharmony_ci	int authkeylen = ctx->auth_key_len;
80362306a36Sopenharmony_ci	u8 *ipad = NULL, *opad = NULL;
80462306a36Sopenharmony_ci	int ret = 0, icount = 0;
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	ctx->sdesc = alloc_sdesc(ctx->hashalg);
80762306a36Sopenharmony_ci	if (!ctx->sdesc)
80862306a36Sopenharmony_ci		return -ENOMEM;
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_ci	ctx->ipad = kzalloc(bs, GFP_KERNEL);
81162306a36Sopenharmony_ci	if (!ctx->ipad) {
81262306a36Sopenharmony_ci		ret = -ENOMEM;
81362306a36Sopenharmony_ci		goto calc_fail;
81462306a36Sopenharmony_ci	}
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	ctx->opad = kzalloc(bs, GFP_KERNEL);
81762306a36Sopenharmony_ci	if (!ctx->opad) {
81862306a36Sopenharmony_ci		ret = -ENOMEM;
81962306a36Sopenharmony_ci		goto calc_fail;
82062306a36Sopenharmony_ci	}
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci	ipad = kzalloc(state_size, GFP_KERNEL);
82362306a36Sopenharmony_ci	if (!ipad) {
82462306a36Sopenharmony_ci		ret = -ENOMEM;
82562306a36Sopenharmony_ci		goto calc_fail;
82662306a36Sopenharmony_ci	}
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_ci	opad = kzalloc(state_size, GFP_KERNEL);
82962306a36Sopenharmony_ci	if (!opad) {
83062306a36Sopenharmony_ci		ret = -ENOMEM;
83162306a36Sopenharmony_ci		goto calc_fail;
83262306a36Sopenharmony_ci	}
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	if (authkeylen > bs) {
83562306a36Sopenharmony_ci		ret = crypto_shash_digest(&ctx->sdesc->shash, ctx->key,
83662306a36Sopenharmony_ci					  authkeylen, ipad);
83762306a36Sopenharmony_ci		if (ret)
83862306a36Sopenharmony_ci			goto calc_fail;
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_ci		authkeylen = ds;
84162306a36Sopenharmony_ci	} else {
84262306a36Sopenharmony_ci		memcpy(ipad, ctx->key, authkeylen);
84362306a36Sopenharmony_ci	}
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_ci	memset(ipad + authkeylen, 0, bs - authkeylen);
84662306a36Sopenharmony_ci	memcpy(opad, ipad, bs);
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	for (icount = 0; icount < bs; icount++) {
84962306a36Sopenharmony_ci		ipad[icount] ^= 0x36;
85062306a36Sopenharmony_ci		opad[icount] ^= 0x5c;
85162306a36Sopenharmony_ci	}
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	/*
85462306a36Sopenharmony_ci	 * Partial Hash calculated from the software
85562306a36Sopenharmony_ci	 * algorithm is retrieved for IPAD & OPAD
85662306a36Sopenharmony_ci	 */
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	/* IPAD Calculation */
85962306a36Sopenharmony_ci	crypto_shash_init(&ctx->sdesc->shash);
86062306a36Sopenharmony_ci	crypto_shash_update(&ctx->sdesc->shash, ipad, bs);
86162306a36Sopenharmony_ci	crypto_shash_export(&ctx->sdesc->shash, ipad);
86262306a36Sopenharmony_ci	ret = copy_pad(ctx->mac_type, ctx->ipad, ipad);
86362306a36Sopenharmony_ci	if (ret)
86462306a36Sopenharmony_ci		goto calc_fail;
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci	/* OPAD Calculation */
86762306a36Sopenharmony_ci	crypto_shash_init(&ctx->sdesc->shash);
86862306a36Sopenharmony_ci	crypto_shash_update(&ctx->sdesc->shash, opad, bs);
86962306a36Sopenharmony_ci	crypto_shash_export(&ctx->sdesc->shash, opad);
87062306a36Sopenharmony_ci	ret = copy_pad(ctx->mac_type, ctx->opad, opad);
87162306a36Sopenharmony_ci	if (ret)
87262306a36Sopenharmony_ci		goto calc_fail;
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	kfree(ipad);
87562306a36Sopenharmony_ci	kfree(opad);
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci	return 0;
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_cicalc_fail:
88062306a36Sopenharmony_ci	kfree(ctx->ipad);
88162306a36Sopenharmony_ci	ctx->ipad = NULL;
88262306a36Sopenharmony_ci	kfree(ctx->opad);
88362306a36Sopenharmony_ci	ctx->opad = NULL;
88462306a36Sopenharmony_ci	kfree(ipad);
88562306a36Sopenharmony_ci	kfree(opad);
88662306a36Sopenharmony_ci	kfree(ctx->sdesc);
88762306a36Sopenharmony_ci	ctx->sdesc = NULL;
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci	return ret;
89062306a36Sopenharmony_ci}
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_cistatic int otx2_cpt_aead_cbc_aes_sha_setkey(struct crypto_aead *cipher,
89362306a36Sopenharmony_ci					    const unsigned char *key,
89462306a36Sopenharmony_ci					    unsigned int keylen)
89562306a36Sopenharmony_ci{
89662306a36Sopenharmony_ci	struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
89762306a36Sopenharmony_ci	struct crypto_authenc_key_param *param;
89862306a36Sopenharmony_ci	int enckeylen = 0, authkeylen = 0;
89962306a36Sopenharmony_ci	struct rtattr *rta = (void *)key;
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	if (!RTA_OK(rta, keylen))
90262306a36Sopenharmony_ci		return -EINVAL;
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
90562306a36Sopenharmony_ci		return -EINVAL;
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci	if (RTA_PAYLOAD(rta) < sizeof(*param))
90862306a36Sopenharmony_ci		return -EINVAL;
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	param = RTA_DATA(rta);
91162306a36Sopenharmony_ci	enckeylen = be32_to_cpu(param->enckeylen);
91262306a36Sopenharmony_ci	key += RTA_ALIGN(rta->rta_len);
91362306a36Sopenharmony_ci	keylen -= RTA_ALIGN(rta->rta_len);
91462306a36Sopenharmony_ci	if (keylen < enckeylen)
91562306a36Sopenharmony_ci		return -EINVAL;
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	if (keylen > OTX2_CPT_MAX_KEY_SIZE)
91862306a36Sopenharmony_ci		return -EINVAL;
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci	authkeylen = keylen - enckeylen;
92162306a36Sopenharmony_ci	memcpy(ctx->key, key, keylen);
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_ci	switch (enckeylen) {
92462306a36Sopenharmony_ci	case AES_KEYSIZE_128:
92562306a36Sopenharmony_ci		ctx->key_type = OTX2_CPT_AES_128_BIT;
92662306a36Sopenharmony_ci		break;
92762306a36Sopenharmony_ci	case AES_KEYSIZE_192:
92862306a36Sopenharmony_ci		ctx->key_type = OTX2_CPT_AES_192_BIT;
92962306a36Sopenharmony_ci		break;
93062306a36Sopenharmony_ci	case AES_KEYSIZE_256:
93162306a36Sopenharmony_ci		ctx->key_type = OTX2_CPT_AES_256_BIT;
93262306a36Sopenharmony_ci		break;
93362306a36Sopenharmony_ci	default:
93462306a36Sopenharmony_ci		/* Invalid key length */
93562306a36Sopenharmony_ci		return -EINVAL;
93662306a36Sopenharmony_ci	}
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	ctx->enc_key_len = enckeylen;
93962306a36Sopenharmony_ci	ctx->auth_key_len = authkeylen;
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci	return aead_hmac_init(cipher);
94262306a36Sopenharmony_ci}
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_cistatic int otx2_cpt_aead_ecb_null_sha_setkey(struct crypto_aead *cipher,
94562306a36Sopenharmony_ci					     const unsigned char *key,
94662306a36Sopenharmony_ci					     unsigned int keylen)
94762306a36Sopenharmony_ci{
94862306a36Sopenharmony_ci	struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
94962306a36Sopenharmony_ci	struct crypto_authenc_key_param *param;
95062306a36Sopenharmony_ci	struct rtattr *rta = (void *)key;
95162306a36Sopenharmony_ci	int enckeylen = 0;
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	if (!RTA_OK(rta, keylen))
95462306a36Sopenharmony_ci		return -EINVAL;
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci	if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
95762306a36Sopenharmony_ci		return -EINVAL;
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci	if (RTA_PAYLOAD(rta) < sizeof(*param))
96062306a36Sopenharmony_ci		return -EINVAL;
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci	param = RTA_DATA(rta);
96362306a36Sopenharmony_ci	enckeylen = be32_to_cpu(param->enckeylen);
96462306a36Sopenharmony_ci	key += RTA_ALIGN(rta->rta_len);
96562306a36Sopenharmony_ci	keylen -= RTA_ALIGN(rta->rta_len);
96662306a36Sopenharmony_ci	if (enckeylen != 0)
96762306a36Sopenharmony_ci		return -EINVAL;
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci	if (keylen > OTX2_CPT_MAX_KEY_SIZE)
97062306a36Sopenharmony_ci		return -EINVAL;
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci	memcpy(ctx->key, key, keylen);
97362306a36Sopenharmony_ci	ctx->enc_key_len = enckeylen;
97462306a36Sopenharmony_ci	ctx->auth_key_len = keylen;
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	return 0;
97762306a36Sopenharmony_ci}
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_cistatic int otx2_cpt_aead_gcm_aes_setkey(struct crypto_aead *cipher,
98062306a36Sopenharmony_ci					const unsigned char *key,
98162306a36Sopenharmony_ci					unsigned int keylen)
98262306a36Sopenharmony_ci{
98362306a36Sopenharmony_ci	struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(cipher);
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci	/*
98662306a36Sopenharmony_ci	 * For aes gcm we expect to get encryption key (16, 24, 32 bytes)
98762306a36Sopenharmony_ci	 * and salt (4 bytes)
98862306a36Sopenharmony_ci	 */
98962306a36Sopenharmony_ci	switch (keylen) {
99062306a36Sopenharmony_ci	case AES_KEYSIZE_128 + AES_GCM_SALT_SIZE:
99162306a36Sopenharmony_ci		ctx->key_type = OTX2_CPT_AES_128_BIT;
99262306a36Sopenharmony_ci		ctx->enc_key_len = AES_KEYSIZE_128;
99362306a36Sopenharmony_ci		break;
99462306a36Sopenharmony_ci	case AES_KEYSIZE_192 + AES_GCM_SALT_SIZE:
99562306a36Sopenharmony_ci		ctx->key_type = OTX2_CPT_AES_192_BIT;
99662306a36Sopenharmony_ci		ctx->enc_key_len = AES_KEYSIZE_192;
99762306a36Sopenharmony_ci		break;
99862306a36Sopenharmony_ci	case AES_KEYSIZE_256 + AES_GCM_SALT_SIZE:
99962306a36Sopenharmony_ci		ctx->key_type = OTX2_CPT_AES_256_BIT;
100062306a36Sopenharmony_ci		ctx->enc_key_len = AES_KEYSIZE_256;
100162306a36Sopenharmony_ci		break;
100262306a36Sopenharmony_ci	default:
100362306a36Sopenharmony_ci		/* Invalid key and salt length */
100462306a36Sopenharmony_ci		return -EINVAL;
100562306a36Sopenharmony_ci	}
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	/* Store encryption key and salt */
100862306a36Sopenharmony_ci	memcpy(ctx->key, key, keylen);
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	return crypto_aead_setkey(ctx->fbk_cipher, key, keylen);
101162306a36Sopenharmony_ci}
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_cistatic inline int create_aead_ctx_hdr(struct aead_request *req, u32 enc,
101462306a36Sopenharmony_ci				      u32 *argcnt)
101562306a36Sopenharmony_ci{
101662306a36Sopenharmony_ci	struct otx2_cpt_req_ctx *rctx = aead_request_ctx_dma(req);
101762306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
101862306a36Sopenharmony_ci	struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(tfm);
101962306a36Sopenharmony_ci	struct otx2_cpt_req_info *req_info = &rctx->cpt_req;
102062306a36Sopenharmony_ci	struct otx2_cpt_fc_ctx *fctx = &rctx->fctx;
102162306a36Sopenharmony_ci	int mac_len = crypto_aead_authsize(tfm);
102262306a36Sopenharmony_ci	int ds;
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci	rctx->ctrl_word.e.enc_data_offset = req->assoclen;
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	switch (ctx->cipher_type) {
102762306a36Sopenharmony_ci	case OTX2_CPT_AES_CBC:
102862306a36Sopenharmony_ci		if (req->assoclen > 248 || !IS_ALIGNED(req->assoclen, 8))
102962306a36Sopenharmony_ci			return -EINVAL;
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci		fctx->enc.enc_ctrl.e.iv_source = OTX2_CPT_FROM_CPTR;
103262306a36Sopenharmony_ci		/* Copy encryption key to context */
103362306a36Sopenharmony_ci		memcpy(fctx->enc.encr_key, ctx->key + ctx->auth_key_len,
103462306a36Sopenharmony_ci		       ctx->enc_key_len);
103562306a36Sopenharmony_ci		/* Copy IV to context */
103662306a36Sopenharmony_ci		memcpy(fctx->enc.encr_iv, req->iv, crypto_aead_ivsize(tfm));
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci		ds = crypto_shash_digestsize(ctx->hashalg);
103962306a36Sopenharmony_ci		if (ctx->mac_type == OTX2_CPT_SHA384)
104062306a36Sopenharmony_ci			ds = SHA512_DIGEST_SIZE;
104162306a36Sopenharmony_ci		if (ctx->ipad)
104262306a36Sopenharmony_ci			memcpy(fctx->hmac.e.ipad, ctx->ipad, ds);
104362306a36Sopenharmony_ci		if (ctx->opad)
104462306a36Sopenharmony_ci			memcpy(fctx->hmac.e.opad, ctx->opad, ds);
104562306a36Sopenharmony_ci		break;
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	case OTX2_CPT_AES_GCM:
104862306a36Sopenharmony_ci		if (crypto_ipsec_check_assoclen(req->assoclen))
104962306a36Sopenharmony_ci			return -EINVAL;
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_ci		fctx->enc.enc_ctrl.e.iv_source = OTX2_CPT_FROM_DPTR;
105262306a36Sopenharmony_ci		/* Copy encryption key to context */
105362306a36Sopenharmony_ci		memcpy(fctx->enc.encr_key, ctx->key, ctx->enc_key_len);
105462306a36Sopenharmony_ci		/* Copy salt to context */
105562306a36Sopenharmony_ci		memcpy(fctx->enc.encr_iv, ctx->key + ctx->enc_key_len,
105662306a36Sopenharmony_ci		       AES_GCM_SALT_SIZE);
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci		rctx->ctrl_word.e.iv_offset = req->assoclen - AES_GCM_IV_OFFSET;
105962306a36Sopenharmony_ci		break;
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci	default:
106262306a36Sopenharmony_ci		/* Unknown cipher type */
106362306a36Sopenharmony_ci		return -EINVAL;
106462306a36Sopenharmony_ci	}
106562306a36Sopenharmony_ci	cpu_to_be64s(&rctx->ctrl_word.flags);
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci	req_info->ctrl.s.dma_mode = OTX2_CPT_DMA_MODE_SG;
106862306a36Sopenharmony_ci	req_info->ctrl.s.se_req = 1;
106962306a36Sopenharmony_ci	req_info->req.opcode.s.major = OTX2_CPT_MAJOR_OP_FC |
107062306a36Sopenharmony_ci				 DMA_MODE_FLAG(OTX2_CPT_DMA_MODE_SG);
107162306a36Sopenharmony_ci	if (enc) {
107262306a36Sopenharmony_ci		req_info->req.opcode.s.minor = 2;
107362306a36Sopenharmony_ci		req_info->req.param1 = req->cryptlen;
107462306a36Sopenharmony_ci		req_info->req.param2 = req->cryptlen + req->assoclen;
107562306a36Sopenharmony_ci	} else {
107662306a36Sopenharmony_ci		req_info->req.opcode.s.minor = 3;
107762306a36Sopenharmony_ci		req_info->req.param1 = req->cryptlen - mac_len;
107862306a36Sopenharmony_ci		req_info->req.param2 = req->cryptlen + req->assoclen - mac_len;
107962306a36Sopenharmony_ci	}
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.enc_cipher = ctx->cipher_type;
108262306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.aes_key = ctx->key_type;
108362306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.mac_type = ctx->mac_type;
108462306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.mac_len = mac_len;
108562306a36Sopenharmony_ci	cpu_to_be64s(&fctx->enc.enc_ctrl.u);
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci	/*
108862306a36Sopenharmony_ci	 * Storing Packet Data Information in offset
108962306a36Sopenharmony_ci	 * Control Word First 8 bytes
109062306a36Sopenharmony_ci	 */
109162306a36Sopenharmony_ci	req_info->in[*argcnt].vptr = (u8 *)&rctx->ctrl_word;
109262306a36Sopenharmony_ci	req_info->in[*argcnt].size = CONTROL_WORD_LEN;
109362306a36Sopenharmony_ci	req_info->req.dlen += CONTROL_WORD_LEN;
109462306a36Sopenharmony_ci	++(*argcnt);
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	req_info->in[*argcnt].vptr = (u8 *)fctx;
109762306a36Sopenharmony_ci	req_info->in[*argcnt].size = sizeof(struct otx2_cpt_fc_ctx);
109862306a36Sopenharmony_ci	req_info->req.dlen += sizeof(struct otx2_cpt_fc_ctx);
109962306a36Sopenharmony_ci	++(*argcnt);
110062306a36Sopenharmony_ci
110162306a36Sopenharmony_ci	return 0;
110262306a36Sopenharmony_ci}
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_cistatic inline void create_hmac_ctx_hdr(struct aead_request *req, u32 *argcnt,
110562306a36Sopenharmony_ci				      u32 enc)
110662306a36Sopenharmony_ci{
110762306a36Sopenharmony_ci	struct otx2_cpt_req_ctx *rctx = aead_request_ctx_dma(req);
110862306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
110962306a36Sopenharmony_ci	struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(tfm);
111062306a36Sopenharmony_ci	struct otx2_cpt_req_info *req_info = &rctx->cpt_req;
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci	req_info->ctrl.s.dma_mode = OTX2_CPT_DMA_MODE_SG;
111362306a36Sopenharmony_ci	req_info->ctrl.s.se_req = 1;
111462306a36Sopenharmony_ci	req_info->req.opcode.s.major = OTX2_CPT_MAJOR_OP_HMAC |
111562306a36Sopenharmony_ci				 DMA_MODE_FLAG(OTX2_CPT_DMA_MODE_SG);
111662306a36Sopenharmony_ci	req_info->is_trunc_hmac = ctx->is_trunc_hmac;
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci	req_info->req.opcode.s.minor = 0;
111962306a36Sopenharmony_ci	req_info->req.param1 = ctx->auth_key_len;
112062306a36Sopenharmony_ci	req_info->req.param2 = ctx->mac_type << 8;
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci	/* Add authentication key */
112362306a36Sopenharmony_ci	req_info->in[*argcnt].vptr = ctx->key;
112462306a36Sopenharmony_ci	req_info->in[*argcnt].size = round_up(ctx->auth_key_len, 8);
112562306a36Sopenharmony_ci	req_info->req.dlen += round_up(ctx->auth_key_len, 8);
112662306a36Sopenharmony_ci	++(*argcnt);
112762306a36Sopenharmony_ci}
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_cistatic inline int create_aead_input_list(struct aead_request *req, u32 enc)
113062306a36Sopenharmony_ci{
113162306a36Sopenharmony_ci	struct otx2_cpt_req_ctx *rctx = aead_request_ctx_dma(req);
113262306a36Sopenharmony_ci	struct otx2_cpt_req_info *req_info = &rctx->cpt_req;
113362306a36Sopenharmony_ci	u32 inputlen =  req->cryptlen + req->assoclen;
113462306a36Sopenharmony_ci	u32 status, argcnt = 0;
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci	status = create_aead_ctx_hdr(req, enc, &argcnt);
113762306a36Sopenharmony_ci	if (status)
113862306a36Sopenharmony_ci		return status;
113962306a36Sopenharmony_ci	update_input_data(req_info, req->src, inputlen, &argcnt);
114062306a36Sopenharmony_ci	req_info->in_cnt = argcnt;
114162306a36Sopenharmony_ci
114262306a36Sopenharmony_ci	return 0;
114362306a36Sopenharmony_ci}
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_cistatic inline void create_aead_output_list(struct aead_request *req, u32 enc,
114662306a36Sopenharmony_ci					   u32 mac_len)
114762306a36Sopenharmony_ci{
114862306a36Sopenharmony_ci	struct otx2_cpt_req_ctx *rctx = aead_request_ctx_dma(req);
114962306a36Sopenharmony_ci	struct otx2_cpt_req_info *req_info =  &rctx->cpt_req;
115062306a36Sopenharmony_ci	u32 argcnt = 0, outputlen = 0;
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ci	if (enc)
115362306a36Sopenharmony_ci		outputlen = req->cryptlen +  req->assoclen + mac_len;
115462306a36Sopenharmony_ci	else
115562306a36Sopenharmony_ci		outputlen = req->cryptlen + req->assoclen - mac_len;
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	update_output_data(req_info, req->dst, 0, outputlen, &argcnt);
115862306a36Sopenharmony_ci	req_info->out_cnt = argcnt;
115962306a36Sopenharmony_ci}
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_cistatic inline void create_aead_null_input_list(struct aead_request *req,
116262306a36Sopenharmony_ci					       u32 enc, u32 mac_len)
116362306a36Sopenharmony_ci{
116462306a36Sopenharmony_ci	struct otx2_cpt_req_ctx *rctx = aead_request_ctx_dma(req);
116562306a36Sopenharmony_ci	struct otx2_cpt_req_info *req_info = &rctx->cpt_req;
116662306a36Sopenharmony_ci	u32 inputlen, argcnt = 0;
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	if (enc)
116962306a36Sopenharmony_ci		inputlen =  req->cryptlen + req->assoclen;
117062306a36Sopenharmony_ci	else
117162306a36Sopenharmony_ci		inputlen =  req->cryptlen + req->assoclen - mac_len;
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	create_hmac_ctx_hdr(req, &argcnt, enc);
117462306a36Sopenharmony_ci	update_input_data(req_info, req->src, inputlen, &argcnt);
117562306a36Sopenharmony_ci	req_info->in_cnt = argcnt;
117662306a36Sopenharmony_ci}
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_cistatic inline int create_aead_null_output_list(struct aead_request *req,
117962306a36Sopenharmony_ci					       u32 enc, u32 mac_len)
118062306a36Sopenharmony_ci{
118162306a36Sopenharmony_ci	struct otx2_cpt_req_ctx *rctx = aead_request_ctx_dma(req);
118262306a36Sopenharmony_ci	struct otx2_cpt_req_info *req_info =  &rctx->cpt_req;
118362306a36Sopenharmony_ci	struct scatterlist *dst;
118462306a36Sopenharmony_ci	u8 *ptr = NULL;
118562306a36Sopenharmony_ci	int argcnt = 0, status, offset;
118662306a36Sopenharmony_ci	u32 inputlen;
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci	if (enc)
118962306a36Sopenharmony_ci		inputlen =  req->cryptlen + req->assoclen;
119062306a36Sopenharmony_ci	else
119162306a36Sopenharmony_ci		inputlen =  req->cryptlen + req->assoclen - mac_len;
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_ci	/*
119462306a36Sopenharmony_ci	 * If source and destination are different
119562306a36Sopenharmony_ci	 * then copy payload to destination
119662306a36Sopenharmony_ci	 */
119762306a36Sopenharmony_ci	if (req->src != req->dst) {
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_ci		ptr = kmalloc(inputlen, (req_info->areq->flags &
120062306a36Sopenharmony_ci					 CRYPTO_TFM_REQ_MAY_SLEEP) ?
120162306a36Sopenharmony_ci					 GFP_KERNEL : GFP_ATOMIC);
120262306a36Sopenharmony_ci		if (!ptr)
120362306a36Sopenharmony_ci			return -ENOMEM;
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci		status = sg_copy_to_buffer(req->src, sg_nents(req->src), ptr,
120662306a36Sopenharmony_ci					   inputlen);
120762306a36Sopenharmony_ci		if (status != inputlen) {
120862306a36Sopenharmony_ci			status = -EINVAL;
120962306a36Sopenharmony_ci			goto error_free;
121062306a36Sopenharmony_ci		}
121162306a36Sopenharmony_ci		status = sg_copy_from_buffer(req->dst, sg_nents(req->dst), ptr,
121262306a36Sopenharmony_ci					     inputlen);
121362306a36Sopenharmony_ci		if (status != inputlen) {
121462306a36Sopenharmony_ci			status = -EINVAL;
121562306a36Sopenharmony_ci			goto error_free;
121662306a36Sopenharmony_ci		}
121762306a36Sopenharmony_ci		kfree(ptr);
121862306a36Sopenharmony_ci	}
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci	if (enc) {
122162306a36Sopenharmony_ci		/*
122262306a36Sopenharmony_ci		 * In an encryption scenario hmac needs
122362306a36Sopenharmony_ci		 * to be appended after payload
122462306a36Sopenharmony_ci		 */
122562306a36Sopenharmony_ci		dst = req->dst;
122662306a36Sopenharmony_ci		offset = inputlen;
122762306a36Sopenharmony_ci		while (offset >= dst->length) {
122862306a36Sopenharmony_ci			offset -= dst->length;
122962306a36Sopenharmony_ci			dst = sg_next(dst);
123062306a36Sopenharmony_ci			if (!dst)
123162306a36Sopenharmony_ci				return -ENOENT;
123262306a36Sopenharmony_ci		}
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci		update_output_data(req_info, dst, offset, mac_len, &argcnt);
123562306a36Sopenharmony_ci	} else {
123662306a36Sopenharmony_ci		/*
123762306a36Sopenharmony_ci		 * In a decryption scenario calculated hmac for received
123862306a36Sopenharmony_ci		 * payload needs to be compare with hmac received
123962306a36Sopenharmony_ci		 */
124062306a36Sopenharmony_ci		status = sg_copy_buffer(req->src, sg_nents(req->src),
124162306a36Sopenharmony_ci					rctx->fctx.hmac.s.hmac_recv, mac_len,
124262306a36Sopenharmony_ci					inputlen, true);
124362306a36Sopenharmony_ci		if (status != mac_len)
124462306a36Sopenharmony_ci			return -EINVAL;
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_ci		req_info->out[argcnt].vptr = rctx->fctx.hmac.s.hmac_calc;
124762306a36Sopenharmony_ci		req_info->out[argcnt].size = mac_len;
124862306a36Sopenharmony_ci		argcnt++;
124962306a36Sopenharmony_ci	}
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_ci	req_info->out_cnt = argcnt;
125262306a36Sopenharmony_ci	return 0;
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_cierror_free:
125562306a36Sopenharmony_ci	kfree(ptr);
125662306a36Sopenharmony_ci	return status;
125762306a36Sopenharmony_ci}
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_cistatic int aead_do_fallback(struct aead_request *req, bool is_enc)
126062306a36Sopenharmony_ci{
126162306a36Sopenharmony_ci	struct otx2_cpt_req_ctx *rctx = aead_request_ctx_dma(req);
126262306a36Sopenharmony_ci	struct crypto_aead *aead = crypto_aead_reqtfm(req);
126362306a36Sopenharmony_ci	struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(aead);
126462306a36Sopenharmony_ci	int ret;
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_ci	if (ctx->fbk_cipher) {
126762306a36Sopenharmony_ci		/* Store the cipher tfm and then use the fallback tfm */
126862306a36Sopenharmony_ci		aead_request_set_tfm(&rctx->fbk_req, ctx->fbk_cipher);
126962306a36Sopenharmony_ci		aead_request_set_callback(&rctx->fbk_req, req->base.flags,
127062306a36Sopenharmony_ci					  req->base.complete, req->base.data);
127162306a36Sopenharmony_ci		aead_request_set_crypt(&rctx->fbk_req, req->src,
127262306a36Sopenharmony_ci				       req->dst, req->cryptlen, req->iv);
127362306a36Sopenharmony_ci		aead_request_set_ad(&rctx->fbk_req, req->assoclen);
127462306a36Sopenharmony_ci		ret = is_enc ? crypto_aead_encrypt(&rctx->fbk_req) :
127562306a36Sopenharmony_ci			       crypto_aead_decrypt(&rctx->fbk_req);
127662306a36Sopenharmony_ci	} else {
127762306a36Sopenharmony_ci		ret = -EINVAL;
127862306a36Sopenharmony_ci	}
127962306a36Sopenharmony_ci
128062306a36Sopenharmony_ci	return ret;
128162306a36Sopenharmony_ci}
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_cistatic int cpt_aead_enc_dec(struct aead_request *req, u8 reg_type, u8 enc)
128462306a36Sopenharmony_ci{
128562306a36Sopenharmony_ci	struct otx2_cpt_req_ctx *rctx = aead_request_ctx_dma(req);
128662306a36Sopenharmony_ci	struct otx2_cpt_req_info *req_info = &rctx->cpt_req;
128762306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
128862306a36Sopenharmony_ci	struct otx2_cpt_aead_ctx *ctx = crypto_aead_ctx_dma(tfm);
128962306a36Sopenharmony_ci	struct pci_dev *pdev;
129062306a36Sopenharmony_ci	int status, cpu_num;
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci	/* Clear control words */
129362306a36Sopenharmony_ci	rctx->ctrl_word.flags = 0;
129462306a36Sopenharmony_ci	rctx->fctx.enc.enc_ctrl.u = 0;
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci	req_info->callback = otx2_cpt_aead_callback;
129762306a36Sopenharmony_ci	req_info->areq = &req->base;
129862306a36Sopenharmony_ci	req_info->req_type = reg_type;
129962306a36Sopenharmony_ci	req_info->is_enc = enc;
130062306a36Sopenharmony_ci	req_info->is_trunc_hmac = false;
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	switch (reg_type) {
130362306a36Sopenharmony_ci	case OTX2_CPT_AEAD_ENC_DEC_REQ:
130462306a36Sopenharmony_ci		status = create_aead_input_list(req, enc);
130562306a36Sopenharmony_ci		if (status)
130662306a36Sopenharmony_ci			return status;
130762306a36Sopenharmony_ci		create_aead_output_list(req, enc, crypto_aead_authsize(tfm));
130862306a36Sopenharmony_ci		break;
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_ci	case OTX2_CPT_AEAD_ENC_DEC_NULL_REQ:
131162306a36Sopenharmony_ci		create_aead_null_input_list(req, enc,
131262306a36Sopenharmony_ci					    crypto_aead_authsize(tfm));
131362306a36Sopenharmony_ci		status = create_aead_null_output_list(req, enc,
131462306a36Sopenharmony_ci						crypto_aead_authsize(tfm));
131562306a36Sopenharmony_ci		if (status)
131662306a36Sopenharmony_ci			return status;
131762306a36Sopenharmony_ci		break;
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci	default:
132062306a36Sopenharmony_ci		return -EINVAL;
132162306a36Sopenharmony_ci	}
132262306a36Sopenharmony_ci	if (!IS_ALIGNED(req_info->req.param1, ctx->enc_align_len))
132362306a36Sopenharmony_ci		return -EINVAL;
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci	if (!req_info->req.param2 ||
132662306a36Sopenharmony_ci	    (req_info->req.param1 > OTX2_CPT_MAX_REQ_SIZE) ||
132762306a36Sopenharmony_ci	    (req_info->req.param2 > OTX2_CPT_MAX_REQ_SIZE))
132862306a36Sopenharmony_ci		return aead_do_fallback(req, enc);
132962306a36Sopenharmony_ci
133062306a36Sopenharmony_ci	status = get_se_device(&pdev, &cpu_num);
133162306a36Sopenharmony_ci	if (status)
133262306a36Sopenharmony_ci		return status;
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_ci	req_info->ctrl.s.grp = otx2_cpt_get_kcrypto_eng_grp_num(pdev);
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	/*
133762306a36Sopenharmony_ci	 * We perform an asynchronous send and once
133862306a36Sopenharmony_ci	 * the request is completed the driver would
133962306a36Sopenharmony_ci	 * intimate through registered call back functions
134062306a36Sopenharmony_ci	 */
134162306a36Sopenharmony_ci	return otx2_cpt_do_request(pdev, req_info, cpu_num);
134262306a36Sopenharmony_ci}
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_cistatic int otx2_cpt_aead_encrypt(struct aead_request *req)
134562306a36Sopenharmony_ci{
134662306a36Sopenharmony_ci	return cpt_aead_enc_dec(req, OTX2_CPT_AEAD_ENC_DEC_REQ, true);
134762306a36Sopenharmony_ci}
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_cistatic int otx2_cpt_aead_decrypt(struct aead_request *req)
135062306a36Sopenharmony_ci{
135162306a36Sopenharmony_ci	return cpt_aead_enc_dec(req, OTX2_CPT_AEAD_ENC_DEC_REQ, false);
135262306a36Sopenharmony_ci}
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_cistatic int otx2_cpt_aead_null_encrypt(struct aead_request *req)
135562306a36Sopenharmony_ci{
135662306a36Sopenharmony_ci	return cpt_aead_enc_dec(req, OTX2_CPT_AEAD_ENC_DEC_NULL_REQ, true);
135762306a36Sopenharmony_ci}
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_cistatic int otx2_cpt_aead_null_decrypt(struct aead_request *req)
136062306a36Sopenharmony_ci{
136162306a36Sopenharmony_ci	return cpt_aead_enc_dec(req, OTX2_CPT_AEAD_ENC_DEC_NULL_REQ, false);
136262306a36Sopenharmony_ci}
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_cistatic struct skcipher_alg otx2_cpt_skciphers[] = { {
136562306a36Sopenharmony_ci	.base.cra_name = "xts(aes)",
136662306a36Sopenharmony_ci	.base.cra_driver_name = "cpt_xts_aes",
136762306a36Sopenharmony_ci	.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
136862306a36Sopenharmony_ci	.base.cra_blocksize = AES_BLOCK_SIZE,
136962306a36Sopenharmony_ci	.base.cra_ctxsize = sizeof(struct otx2_cpt_enc_ctx),
137062306a36Sopenharmony_ci	.base.cra_alignmask = 7,
137162306a36Sopenharmony_ci	.base.cra_priority = 4001,
137262306a36Sopenharmony_ci	.base.cra_module = THIS_MODULE,
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_ci	.init = otx2_cpt_enc_dec_init,
137562306a36Sopenharmony_ci	.exit = otx2_cpt_skcipher_exit,
137662306a36Sopenharmony_ci	.ivsize = AES_BLOCK_SIZE,
137762306a36Sopenharmony_ci	.min_keysize = 2 * AES_MIN_KEY_SIZE,
137862306a36Sopenharmony_ci	.max_keysize = 2 * AES_MAX_KEY_SIZE,
137962306a36Sopenharmony_ci	.setkey = otx2_cpt_skcipher_xts_setkey,
138062306a36Sopenharmony_ci	.encrypt = otx2_cpt_skcipher_encrypt,
138162306a36Sopenharmony_ci	.decrypt = otx2_cpt_skcipher_decrypt,
138262306a36Sopenharmony_ci}, {
138362306a36Sopenharmony_ci	.base.cra_name = "cbc(aes)",
138462306a36Sopenharmony_ci	.base.cra_driver_name = "cpt_cbc_aes",
138562306a36Sopenharmony_ci	.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
138662306a36Sopenharmony_ci	.base.cra_blocksize = AES_BLOCK_SIZE,
138762306a36Sopenharmony_ci	.base.cra_ctxsize = sizeof(struct otx2_cpt_enc_ctx),
138862306a36Sopenharmony_ci	.base.cra_alignmask = 7,
138962306a36Sopenharmony_ci	.base.cra_priority = 4001,
139062306a36Sopenharmony_ci	.base.cra_module = THIS_MODULE,
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_ci	.init = otx2_cpt_enc_dec_init,
139362306a36Sopenharmony_ci	.exit = otx2_cpt_skcipher_exit,
139462306a36Sopenharmony_ci	.ivsize = AES_BLOCK_SIZE,
139562306a36Sopenharmony_ci	.min_keysize = AES_MIN_KEY_SIZE,
139662306a36Sopenharmony_ci	.max_keysize = AES_MAX_KEY_SIZE,
139762306a36Sopenharmony_ci	.setkey = otx2_cpt_skcipher_cbc_aes_setkey,
139862306a36Sopenharmony_ci	.encrypt = otx2_cpt_skcipher_encrypt,
139962306a36Sopenharmony_ci	.decrypt = otx2_cpt_skcipher_decrypt,
140062306a36Sopenharmony_ci}, {
140162306a36Sopenharmony_ci	.base.cra_name = "ecb(aes)",
140262306a36Sopenharmony_ci	.base.cra_driver_name = "cpt_ecb_aes",
140362306a36Sopenharmony_ci	.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
140462306a36Sopenharmony_ci	.base.cra_blocksize = AES_BLOCK_SIZE,
140562306a36Sopenharmony_ci	.base.cra_ctxsize = sizeof(struct otx2_cpt_enc_ctx),
140662306a36Sopenharmony_ci	.base.cra_alignmask = 7,
140762306a36Sopenharmony_ci	.base.cra_priority = 4001,
140862306a36Sopenharmony_ci	.base.cra_module = THIS_MODULE,
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_ci	.init = otx2_cpt_enc_dec_init,
141162306a36Sopenharmony_ci	.exit = otx2_cpt_skcipher_exit,
141262306a36Sopenharmony_ci	.ivsize = 0,
141362306a36Sopenharmony_ci	.min_keysize = AES_MIN_KEY_SIZE,
141462306a36Sopenharmony_ci	.max_keysize = AES_MAX_KEY_SIZE,
141562306a36Sopenharmony_ci	.setkey = otx2_cpt_skcipher_ecb_aes_setkey,
141662306a36Sopenharmony_ci	.encrypt = otx2_cpt_skcipher_encrypt,
141762306a36Sopenharmony_ci	.decrypt = otx2_cpt_skcipher_decrypt,
141862306a36Sopenharmony_ci}, {
141962306a36Sopenharmony_ci	.base.cra_name = "cbc(des3_ede)",
142062306a36Sopenharmony_ci	.base.cra_driver_name = "cpt_cbc_des3_ede",
142162306a36Sopenharmony_ci	.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
142262306a36Sopenharmony_ci	.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
142362306a36Sopenharmony_ci	.base.cra_ctxsize = sizeof(struct otx2_cpt_enc_ctx),
142462306a36Sopenharmony_ci	.base.cra_alignmask = 7,
142562306a36Sopenharmony_ci	.base.cra_priority = 4001,
142662306a36Sopenharmony_ci	.base.cra_module = THIS_MODULE,
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_ci	.init = otx2_cpt_enc_dec_init,
142962306a36Sopenharmony_ci	.exit = otx2_cpt_skcipher_exit,
143062306a36Sopenharmony_ci	.min_keysize = DES3_EDE_KEY_SIZE,
143162306a36Sopenharmony_ci	.max_keysize = DES3_EDE_KEY_SIZE,
143262306a36Sopenharmony_ci	.ivsize = DES_BLOCK_SIZE,
143362306a36Sopenharmony_ci	.setkey = otx2_cpt_skcipher_cbc_des3_setkey,
143462306a36Sopenharmony_ci	.encrypt = otx2_cpt_skcipher_encrypt,
143562306a36Sopenharmony_ci	.decrypt = otx2_cpt_skcipher_decrypt,
143662306a36Sopenharmony_ci}, {
143762306a36Sopenharmony_ci	.base.cra_name = "ecb(des3_ede)",
143862306a36Sopenharmony_ci	.base.cra_driver_name = "cpt_ecb_des3_ede",
143962306a36Sopenharmony_ci	.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
144062306a36Sopenharmony_ci	.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
144162306a36Sopenharmony_ci	.base.cra_ctxsize = sizeof(struct otx2_cpt_enc_ctx),
144262306a36Sopenharmony_ci	.base.cra_alignmask = 7,
144362306a36Sopenharmony_ci	.base.cra_priority = 4001,
144462306a36Sopenharmony_ci	.base.cra_module = THIS_MODULE,
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_ci	.init = otx2_cpt_enc_dec_init,
144762306a36Sopenharmony_ci	.exit = otx2_cpt_skcipher_exit,
144862306a36Sopenharmony_ci	.min_keysize = DES3_EDE_KEY_SIZE,
144962306a36Sopenharmony_ci	.max_keysize = DES3_EDE_KEY_SIZE,
145062306a36Sopenharmony_ci	.ivsize = 0,
145162306a36Sopenharmony_ci	.setkey = otx2_cpt_skcipher_ecb_des3_setkey,
145262306a36Sopenharmony_ci	.encrypt = otx2_cpt_skcipher_encrypt,
145362306a36Sopenharmony_ci	.decrypt = otx2_cpt_skcipher_decrypt,
145462306a36Sopenharmony_ci} };
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_cistatic struct aead_alg otx2_cpt_aeads[] = { {
145762306a36Sopenharmony_ci	.base = {
145862306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha1),cbc(aes))",
145962306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha1_cbc_aes",
146062306a36Sopenharmony_ci		.cra_blocksize = AES_BLOCK_SIZE,
146162306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
146262306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx2_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
146362306a36Sopenharmony_ci		.cra_priority = 4001,
146462306a36Sopenharmony_ci		.cra_alignmask = 0,
146562306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
146662306a36Sopenharmony_ci	},
146762306a36Sopenharmony_ci	.init = otx2_cpt_aead_cbc_aes_sha1_init,
146862306a36Sopenharmony_ci	.exit = otx2_cpt_aead_exit,
146962306a36Sopenharmony_ci	.setkey = otx2_cpt_aead_cbc_aes_sha_setkey,
147062306a36Sopenharmony_ci	.setauthsize = otx2_cpt_aead_set_authsize,
147162306a36Sopenharmony_ci	.encrypt = otx2_cpt_aead_encrypt,
147262306a36Sopenharmony_ci	.decrypt = otx2_cpt_aead_decrypt,
147362306a36Sopenharmony_ci	.ivsize = AES_BLOCK_SIZE,
147462306a36Sopenharmony_ci	.maxauthsize = SHA1_DIGEST_SIZE,
147562306a36Sopenharmony_ci}, {
147662306a36Sopenharmony_ci	.base = {
147762306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha256),cbc(aes))",
147862306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha256_cbc_aes",
147962306a36Sopenharmony_ci		.cra_blocksize = AES_BLOCK_SIZE,
148062306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
148162306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx2_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
148262306a36Sopenharmony_ci		.cra_priority = 4001,
148362306a36Sopenharmony_ci		.cra_alignmask = 0,
148462306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
148562306a36Sopenharmony_ci	},
148662306a36Sopenharmony_ci	.init = otx2_cpt_aead_cbc_aes_sha256_init,
148762306a36Sopenharmony_ci	.exit = otx2_cpt_aead_exit,
148862306a36Sopenharmony_ci	.setkey = otx2_cpt_aead_cbc_aes_sha_setkey,
148962306a36Sopenharmony_ci	.setauthsize = otx2_cpt_aead_set_authsize,
149062306a36Sopenharmony_ci	.encrypt = otx2_cpt_aead_encrypt,
149162306a36Sopenharmony_ci	.decrypt = otx2_cpt_aead_decrypt,
149262306a36Sopenharmony_ci	.ivsize = AES_BLOCK_SIZE,
149362306a36Sopenharmony_ci	.maxauthsize = SHA256_DIGEST_SIZE,
149462306a36Sopenharmony_ci}, {
149562306a36Sopenharmony_ci	.base = {
149662306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha384),cbc(aes))",
149762306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha384_cbc_aes",
149862306a36Sopenharmony_ci		.cra_blocksize = AES_BLOCK_SIZE,
149962306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
150062306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx2_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
150162306a36Sopenharmony_ci		.cra_priority = 4001,
150262306a36Sopenharmony_ci		.cra_alignmask = 0,
150362306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
150462306a36Sopenharmony_ci	},
150562306a36Sopenharmony_ci	.init = otx2_cpt_aead_cbc_aes_sha384_init,
150662306a36Sopenharmony_ci	.exit = otx2_cpt_aead_exit,
150762306a36Sopenharmony_ci	.setkey = otx2_cpt_aead_cbc_aes_sha_setkey,
150862306a36Sopenharmony_ci	.setauthsize = otx2_cpt_aead_set_authsize,
150962306a36Sopenharmony_ci	.encrypt = otx2_cpt_aead_encrypt,
151062306a36Sopenharmony_ci	.decrypt = otx2_cpt_aead_decrypt,
151162306a36Sopenharmony_ci	.ivsize = AES_BLOCK_SIZE,
151262306a36Sopenharmony_ci	.maxauthsize = SHA384_DIGEST_SIZE,
151362306a36Sopenharmony_ci}, {
151462306a36Sopenharmony_ci	.base = {
151562306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha512),cbc(aes))",
151662306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha512_cbc_aes",
151762306a36Sopenharmony_ci		.cra_blocksize = AES_BLOCK_SIZE,
151862306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
151962306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx2_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
152062306a36Sopenharmony_ci		.cra_priority = 4001,
152162306a36Sopenharmony_ci		.cra_alignmask = 0,
152262306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
152362306a36Sopenharmony_ci	},
152462306a36Sopenharmony_ci	.init = otx2_cpt_aead_cbc_aes_sha512_init,
152562306a36Sopenharmony_ci	.exit = otx2_cpt_aead_exit,
152662306a36Sopenharmony_ci	.setkey = otx2_cpt_aead_cbc_aes_sha_setkey,
152762306a36Sopenharmony_ci	.setauthsize = otx2_cpt_aead_set_authsize,
152862306a36Sopenharmony_ci	.encrypt = otx2_cpt_aead_encrypt,
152962306a36Sopenharmony_ci	.decrypt = otx2_cpt_aead_decrypt,
153062306a36Sopenharmony_ci	.ivsize = AES_BLOCK_SIZE,
153162306a36Sopenharmony_ci	.maxauthsize = SHA512_DIGEST_SIZE,
153262306a36Sopenharmony_ci}, {
153362306a36Sopenharmony_ci	.base = {
153462306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha1),ecb(cipher_null))",
153562306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha1_ecb_null",
153662306a36Sopenharmony_ci		.cra_blocksize = 1,
153762306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC,
153862306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx2_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
153962306a36Sopenharmony_ci		.cra_priority = 4001,
154062306a36Sopenharmony_ci		.cra_alignmask = 0,
154162306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
154262306a36Sopenharmony_ci	},
154362306a36Sopenharmony_ci	.init = otx2_cpt_aead_ecb_null_sha1_init,
154462306a36Sopenharmony_ci	.exit = otx2_cpt_aead_exit,
154562306a36Sopenharmony_ci	.setkey = otx2_cpt_aead_ecb_null_sha_setkey,
154662306a36Sopenharmony_ci	.setauthsize = otx2_cpt_aead_null_set_authsize,
154762306a36Sopenharmony_ci	.encrypt = otx2_cpt_aead_null_encrypt,
154862306a36Sopenharmony_ci	.decrypt = otx2_cpt_aead_null_decrypt,
154962306a36Sopenharmony_ci	.ivsize = 0,
155062306a36Sopenharmony_ci	.maxauthsize = SHA1_DIGEST_SIZE,
155162306a36Sopenharmony_ci}, {
155262306a36Sopenharmony_ci	.base = {
155362306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha256),ecb(cipher_null))",
155462306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha256_ecb_null",
155562306a36Sopenharmony_ci		.cra_blocksize = 1,
155662306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC,
155762306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx2_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
155862306a36Sopenharmony_ci		.cra_priority = 4001,
155962306a36Sopenharmony_ci		.cra_alignmask = 0,
156062306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
156162306a36Sopenharmony_ci	},
156262306a36Sopenharmony_ci	.init = otx2_cpt_aead_ecb_null_sha256_init,
156362306a36Sopenharmony_ci	.exit = otx2_cpt_aead_exit,
156462306a36Sopenharmony_ci	.setkey = otx2_cpt_aead_ecb_null_sha_setkey,
156562306a36Sopenharmony_ci	.setauthsize = otx2_cpt_aead_null_set_authsize,
156662306a36Sopenharmony_ci	.encrypt = otx2_cpt_aead_null_encrypt,
156762306a36Sopenharmony_ci	.decrypt = otx2_cpt_aead_null_decrypt,
156862306a36Sopenharmony_ci	.ivsize = 0,
156962306a36Sopenharmony_ci	.maxauthsize = SHA256_DIGEST_SIZE,
157062306a36Sopenharmony_ci}, {
157162306a36Sopenharmony_ci	.base = {
157262306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha384),ecb(cipher_null))",
157362306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha384_ecb_null",
157462306a36Sopenharmony_ci		.cra_blocksize = 1,
157562306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC,
157662306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx2_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
157762306a36Sopenharmony_ci		.cra_priority = 4001,
157862306a36Sopenharmony_ci		.cra_alignmask = 0,
157962306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
158062306a36Sopenharmony_ci	},
158162306a36Sopenharmony_ci	.init = otx2_cpt_aead_ecb_null_sha384_init,
158262306a36Sopenharmony_ci	.exit = otx2_cpt_aead_exit,
158362306a36Sopenharmony_ci	.setkey = otx2_cpt_aead_ecb_null_sha_setkey,
158462306a36Sopenharmony_ci	.setauthsize = otx2_cpt_aead_null_set_authsize,
158562306a36Sopenharmony_ci	.encrypt = otx2_cpt_aead_null_encrypt,
158662306a36Sopenharmony_ci	.decrypt = otx2_cpt_aead_null_decrypt,
158762306a36Sopenharmony_ci	.ivsize = 0,
158862306a36Sopenharmony_ci	.maxauthsize = SHA384_DIGEST_SIZE,
158962306a36Sopenharmony_ci}, {
159062306a36Sopenharmony_ci	.base = {
159162306a36Sopenharmony_ci		.cra_name = "authenc(hmac(sha512),ecb(cipher_null))",
159262306a36Sopenharmony_ci		.cra_driver_name = "cpt_hmac_sha512_ecb_null",
159362306a36Sopenharmony_ci		.cra_blocksize = 1,
159462306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC,
159562306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx2_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
159662306a36Sopenharmony_ci		.cra_priority = 4001,
159762306a36Sopenharmony_ci		.cra_alignmask = 0,
159862306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
159962306a36Sopenharmony_ci	},
160062306a36Sopenharmony_ci	.init = otx2_cpt_aead_ecb_null_sha512_init,
160162306a36Sopenharmony_ci	.exit = otx2_cpt_aead_exit,
160262306a36Sopenharmony_ci	.setkey = otx2_cpt_aead_ecb_null_sha_setkey,
160362306a36Sopenharmony_ci	.setauthsize = otx2_cpt_aead_null_set_authsize,
160462306a36Sopenharmony_ci	.encrypt = otx2_cpt_aead_null_encrypt,
160562306a36Sopenharmony_ci	.decrypt = otx2_cpt_aead_null_decrypt,
160662306a36Sopenharmony_ci	.ivsize = 0,
160762306a36Sopenharmony_ci	.maxauthsize = SHA512_DIGEST_SIZE,
160862306a36Sopenharmony_ci}, {
160962306a36Sopenharmony_ci	.base = {
161062306a36Sopenharmony_ci		.cra_name = "rfc4106(gcm(aes))",
161162306a36Sopenharmony_ci		.cra_driver_name = "cpt_rfc4106_gcm_aes",
161262306a36Sopenharmony_ci		.cra_blocksize = 1,
161362306a36Sopenharmony_ci		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
161462306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct otx2_cpt_aead_ctx) + CRYPTO_DMA_PADDING,
161562306a36Sopenharmony_ci		.cra_priority = 4001,
161662306a36Sopenharmony_ci		.cra_alignmask = 0,
161762306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
161862306a36Sopenharmony_ci	},
161962306a36Sopenharmony_ci	.init = otx2_cpt_aead_gcm_aes_init,
162062306a36Sopenharmony_ci	.exit = otx2_cpt_aead_exit,
162162306a36Sopenharmony_ci	.setkey = otx2_cpt_aead_gcm_aes_setkey,
162262306a36Sopenharmony_ci	.setauthsize = otx2_cpt_aead_gcm_set_authsize,
162362306a36Sopenharmony_ci	.encrypt = otx2_cpt_aead_encrypt,
162462306a36Sopenharmony_ci	.decrypt = otx2_cpt_aead_decrypt,
162562306a36Sopenharmony_ci	.ivsize = AES_GCM_IV_SIZE,
162662306a36Sopenharmony_ci	.maxauthsize = AES_GCM_ICV_SIZE,
162762306a36Sopenharmony_ci} };
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_cistatic inline int cpt_register_algs(void)
163062306a36Sopenharmony_ci{
163162306a36Sopenharmony_ci	int i, err = 0;
163262306a36Sopenharmony_ci
163362306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(otx2_cpt_skciphers); i++)
163462306a36Sopenharmony_ci		otx2_cpt_skciphers[i].base.cra_flags &= ~CRYPTO_ALG_DEAD;
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci	err = crypto_register_skciphers(otx2_cpt_skciphers,
163762306a36Sopenharmony_ci					ARRAY_SIZE(otx2_cpt_skciphers));
163862306a36Sopenharmony_ci	if (err)
163962306a36Sopenharmony_ci		return err;
164062306a36Sopenharmony_ci
164162306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(otx2_cpt_aeads); i++)
164262306a36Sopenharmony_ci		otx2_cpt_aeads[i].base.cra_flags &= ~CRYPTO_ALG_DEAD;
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci	err = crypto_register_aeads(otx2_cpt_aeads,
164562306a36Sopenharmony_ci				    ARRAY_SIZE(otx2_cpt_aeads));
164662306a36Sopenharmony_ci	if (err) {
164762306a36Sopenharmony_ci		crypto_unregister_skciphers(otx2_cpt_skciphers,
164862306a36Sopenharmony_ci					    ARRAY_SIZE(otx2_cpt_skciphers));
164962306a36Sopenharmony_ci		return err;
165062306a36Sopenharmony_ci	}
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_ci	return 0;
165362306a36Sopenharmony_ci}
165462306a36Sopenharmony_ci
165562306a36Sopenharmony_cistatic inline void cpt_unregister_algs(void)
165662306a36Sopenharmony_ci{
165762306a36Sopenharmony_ci	crypto_unregister_skciphers(otx2_cpt_skciphers,
165862306a36Sopenharmony_ci				    ARRAY_SIZE(otx2_cpt_skciphers));
165962306a36Sopenharmony_ci	crypto_unregister_aeads(otx2_cpt_aeads, ARRAY_SIZE(otx2_cpt_aeads));
166062306a36Sopenharmony_ci}
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_cistatic int compare_func(const void *lptr, const void *rptr)
166362306a36Sopenharmony_ci{
166462306a36Sopenharmony_ci	const struct cpt_device_desc *ldesc = (struct cpt_device_desc *) lptr;
166562306a36Sopenharmony_ci	const struct cpt_device_desc *rdesc = (struct cpt_device_desc *) rptr;
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci	if (ldesc->dev->devfn < rdesc->dev->devfn)
166862306a36Sopenharmony_ci		return -1;
166962306a36Sopenharmony_ci	if (ldesc->dev->devfn > rdesc->dev->devfn)
167062306a36Sopenharmony_ci		return 1;
167162306a36Sopenharmony_ci	return 0;
167262306a36Sopenharmony_ci}
167362306a36Sopenharmony_ci
167462306a36Sopenharmony_cistatic void swap_func(void *lptr, void *rptr, int size)
167562306a36Sopenharmony_ci{
167662306a36Sopenharmony_ci	struct cpt_device_desc *ldesc = lptr;
167762306a36Sopenharmony_ci	struct cpt_device_desc *rdesc = rptr;
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_ci	swap(*ldesc, *rdesc);
168062306a36Sopenharmony_ci}
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ciint otx2_cpt_crypto_init(struct pci_dev *pdev, struct module *mod,
168362306a36Sopenharmony_ci			 int num_queues, int num_devices)
168462306a36Sopenharmony_ci{
168562306a36Sopenharmony_ci	int ret = 0;
168662306a36Sopenharmony_ci	int count;
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci	mutex_lock(&mutex);
168962306a36Sopenharmony_ci	count = atomic_read(&se_devices.count);
169062306a36Sopenharmony_ci	if (count >= OTX2_CPT_MAX_LFS_NUM) {
169162306a36Sopenharmony_ci		dev_err(&pdev->dev, "No space to add a new device\n");
169262306a36Sopenharmony_ci		ret = -ENOSPC;
169362306a36Sopenharmony_ci		goto unlock;
169462306a36Sopenharmony_ci	}
169562306a36Sopenharmony_ci	se_devices.desc[count].num_queues = num_queues;
169662306a36Sopenharmony_ci	se_devices.desc[count++].dev = pdev;
169762306a36Sopenharmony_ci	atomic_inc(&se_devices.count);
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_ci	if (atomic_read(&se_devices.count) == num_devices &&
170062306a36Sopenharmony_ci	    is_crypto_registered == false) {
170162306a36Sopenharmony_ci		if (cpt_register_algs()) {
170262306a36Sopenharmony_ci			dev_err(&pdev->dev,
170362306a36Sopenharmony_ci				"Error in registering crypto algorithms\n");
170462306a36Sopenharmony_ci			ret =  -EINVAL;
170562306a36Sopenharmony_ci			goto unlock;
170662306a36Sopenharmony_ci		}
170762306a36Sopenharmony_ci		try_module_get(mod);
170862306a36Sopenharmony_ci		is_crypto_registered = true;
170962306a36Sopenharmony_ci	}
171062306a36Sopenharmony_ci	sort(se_devices.desc, count, sizeof(struct cpt_device_desc),
171162306a36Sopenharmony_ci	     compare_func, swap_func);
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ciunlock:
171462306a36Sopenharmony_ci	mutex_unlock(&mutex);
171562306a36Sopenharmony_ci	return ret;
171662306a36Sopenharmony_ci}
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_civoid otx2_cpt_crypto_exit(struct pci_dev *pdev, struct module *mod)
171962306a36Sopenharmony_ci{
172062306a36Sopenharmony_ci	struct cpt_device_table *dev_tbl;
172162306a36Sopenharmony_ci	bool dev_found = false;
172262306a36Sopenharmony_ci	int i, j, count;
172362306a36Sopenharmony_ci
172462306a36Sopenharmony_ci	mutex_lock(&mutex);
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci	dev_tbl = &se_devices;
172762306a36Sopenharmony_ci	count = atomic_read(&dev_tbl->count);
172862306a36Sopenharmony_ci	for (i = 0; i < count; i++) {
172962306a36Sopenharmony_ci		if (pdev == dev_tbl->desc[i].dev) {
173062306a36Sopenharmony_ci			for (j = i; j < count-1; j++)
173162306a36Sopenharmony_ci				dev_tbl->desc[j] = dev_tbl->desc[j+1];
173262306a36Sopenharmony_ci			dev_found = true;
173362306a36Sopenharmony_ci			break;
173462306a36Sopenharmony_ci		}
173562306a36Sopenharmony_ci	}
173662306a36Sopenharmony_ci
173762306a36Sopenharmony_ci	if (!dev_found) {
173862306a36Sopenharmony_ci		dev_err(&pdev->dev, "%s device not found\n", __func__);
173962306a36Sopenharmony_ci		goto unlock;
174062306a36Sopenharmony_ci	}
174162306a36Sopenharmony_ci	if (atomic_dec_and_test(&se_devices.count)) {
174262306a36Sopenharmony_ci		cpt_unregister_algs();
174362306a36Sopenharmony_ci		module_put(mod);
174462306a36Sopenharmony_ci		is_crypto_registered = false;
174562306a36Sopenharmony_ci	}
174662306a36Sopenharmony_ci
174762306a36Sopenharmony_ciunlock:
174862306a36Sopenharmony_ci	mutex_unlock(&mutex);
174962306a36Sopenharmony_ci}
1750