162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci/*
462306a36Sopenharmony_ci * Copyright (C) 2016 Cavium, Inc.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <crypto/aes.h>
862306a36Sopenharmony_ci#include <crypto/algapi.h>
962306a36Sopenharmony_ci#include <crypto/authenc.h>
1062306a36Sopenharmony_ci#include <crypto/internal/des.h>
1162306a36Sopenharmony_ci#include <crypto/xts.h>
1262306a36Sopenharmony_ci#include <linux/crypto.h>
1362306a36Sopenharmony_ci#include <linux/err.h>
1462306a36Sopenharmony_ci#include <linux/list.h>
1562306a36Sopenharmony_ci#include <linux/scatterlist.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include "cptvf.h"
1862306a36Sopenharmony_ci#include "cptvf_algs.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistruct cpt_device_handle {
2162306a36Sopenharmony_ci	void *cdev[MAX_DEVICES];
2262306a36Sopenharmony_ci	u32 dev_count;
2362306a36Sopenharmony_ci};
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic struct cpt_device_handle dev_handle;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistatic void cvm_callback(u32 status, void *arg)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	struct crypto_async_request *req = (struct crypto_async_request *)arg;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	crypto_request_complete(req, !status);
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic inline void update_input_iv(struct cpt_request_info *req_info,
3562306a36Sopenharmony_ci				   u8 *iv, u32 enc_iv_len,
3662306a36Sopenharmony_ci				   u32 *argcnt)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	/* Setting the iv information */
3962306a36Sopenharmony_ci	req_info->in[*argcnt].vptr = (void *)iv;
4062306a36Sopenharmony_ci	req_info->in[*argcnt].size = enc_iv_len;
4162306a36Sopenharmony_ci	req_info->req.dlen += enc_iv_len;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	++(*argcnt);
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistatic inline void update_output_iv(struct cpt_request_info *req_info,
4762306a36Sopenharmony_ci				    u8 *iv, u32 enc_iv_len,
4862306a36Sopenharmony_ci				    u32 *argcnt)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	/* Setting the iv information */
5162306a36Sopenharmony_ci	req_info->out[*argcnt].vptr = (void *)iv;
5262306a36Sopenharmony_ci	req_info->out[*argcnt].size = enc_iv_len;
5362306a36Sopenharmony_ci	req_info->rlen += enc_iv_len;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	++(*argcnt);
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic inline void update_input_data(struct cpt_request_info *req_info,
5962306a36Sopenharmony_ci				     struct scatterlist *inp_sg,
6062306a36Sopenharmony_ci				     u32 nbytes, u32 *argcnt)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	req_info->req.dlen += nbytes;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	while (nbytes) {
6562306a36Sopenharmony_ci		u32 len = min(nbytes, inp_sg->length);
6662306a36Sopenharmony_ci		u8 *ptr = sg_virt(inp_sg);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci		req_info->in[*argcnt].vptr = (void *)ptr;
6962306a36Sopenharmony_ci		req_info->in[*argcnt].size = len;
7062306a36Sopenharmony_ci		nbytes -= len;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci		++(*argcnt);
7362306a36Sopenharmony_ci		++inp_sg;
7462306a36Sopenharmony_ci	}
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic inline void update_output_data(struct cpt_request_info *req_info,
7862306a36Sopenharmony_ci				      struct scatterlist *outp_sg,
7962306a36Sopenharmony_ci				      u32 nbytes, u32 *argcnt)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	req_info->rlen += nbytes;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	while (nbytes) {
8462306a36Sopenharmony_ci		u32 len = min(nbytes, outp_sg->length);
8562306a36Sopenharmony_ci		u8 *ptr = sg_virt(outp_sg);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci		req_info->out[*argcnt].vptr = (void *)ptr;
8862306a36Sopenharmony_ci		req_info->out[*argcnt].size = len;
8962306a36Sopenharmony_ci		nbytes -= len;
9062306a36Sopenharmony_ci		++(*argcnt);
9162306a36Sopenharmony_ci		++outp_sg;
9262306a36Sopenharmony_ci	}
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic inline u32 create_ctx_hdr(struct skcipher_request *req, u32 enc,
9662306a36Sopenharmony_ci				 u32 *argcnt)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
9962306a36Sopenharmony_ci	struct cvm_enc_ctx *ctx = crypto_skcipher_ctx(tfm);
10062306a36Sopenharmony_ci	struct cvm_req_ctx *rctx = skcipher_request_ctx_dma(req);
10162306a36Sopenharmony_ci	struct fc_context *fctx = &rctx->fctx;
10262306a36Sopenharmony_ci	u32 enc_iv_len = crypto_skcipher_ivsize(tfm);
10362306a36Sopenharmony_ci	struct cpt_request_info *req_info = &rctx->cpt_req;
10462306a36Sopenharmony_ci	__be64 *ctrl_flags = NULL;
10562306a36Sopenharmony_ci	__be64 *offset_control;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	req_info->ctrl.s.grp = 0;
10862306a36Sopenharmony_ci	req_info->ctrl.s.dma_mode = DMA_GATHER_SCATTER;
10962306a36Sopenharmony_ci	req_info->ctrl.s.se_req = SE_CORE_REQ;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	req_info->req.opcode.s.major = MAJOR_OP_FC |
11262306a36Sopenharmony_ci					DMA_MODE_FLAG(DMA_GATHER_SCATTER);
11362306a36Sopenharmony_ci	if (enc)
11462306a36Sopenharmony_ci		req_info->req.opcode.s.minor = 2;
11562306a36Sopenharmony_ci	else
11662306a36Sopenharmony_ci		req_info->req.opcode.s.minor = 3;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	req_info->req.param1 = req->cryptlen; /* Encryption Data length */
11962306a36Sopenharmony_ci	req_info->req.param2 = 0; /*Auth data length */
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.enc_cipher = ctx->cipher_type;
12262306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.aes_key = ctx->key_type;
12362306a36Sopenharmony_ci	fctx->enc.enc_ctrl.e.iv_source = FROM_DPTR;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	if (ctx->cipher_type == AES_XTS)
12662306a36Sopenharmony_ci		memcpy(fctx->enc.encr_key, ctx->enc_key, ctx->key_len * 2);
12762306a36Sopenharmony_ci	else
12862306a36Sopenharmony_ci		memcpy(fctx->enc.encr_key, ctx->enc_key, ctx->key_len);
12962306a36Sopenharmony_ci	ctrl_flags = (__be64 *)&fctx->enc.enc_ctrl.flags;
13062306a36Sopenharmony_ci	*ctrl_flags = cpu_to_be64(fctx->enc.enc_ctrl.flags);
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	offset_control = (__be64 *)&rctx->control_word;
13362306a36Sopenharmony_ci	*offset_control = cpu_to_be64(((u64)(enc_iv_len) << 16));
13462306a36Sopenharmony_ci	/* Storing  Packet Data Information in offset
13562306a36Sopenharmony_ci	 * Control Word First 8 bytes
13662306a36Sopenharmony_ci	 */
13762306a36Sopenharmony_ci	req_info->in[*argcnt].vptr = (u8 *)offset_control;
13862306a36Sopenharmony_ci	req_info->in[*argcnt].size = CONTROL_WORD_LEN;
13962306a36Sopenharmony_ci	req_info->req.dlen += CONTROL_WORD_LEN;
14062306a36Sopenharmony_ci	++(*argcnt);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	req_info->in[*argcnt].vptr = (u8 *)fctx;
14362306a36Sopenharmony_ci	req_info->in[*argcnt].size = sizeof(struct fc_context);
14462306a36Sopenharmony_ci	req_info->req.dlen += sizeof(struct fc_context);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	++(*argcnt);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	return 0;
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic inline u32 create_input_list(struct skcipher_request  *req, u32 enc,
15262306a36Sopenharmony_ci				    u32 enc_iv_len)
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	struct cvm_req_ctx *rctx = skcipher_request_ctx_dma(req);
15562306a36Sopenharmony_ci	struct cpt_request_info *req_info = &rctx->cpt_req;
15662306a36Sopenharmony_ci	u32 argcnt =  0;
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	create_ctx_hdr(req, enc, &argcnt);
15962306a36Sopenharmony_ci	update_input_iv(req_info, req->iv, enc_iv_len, &argcnt);
16062306a36Sopenharmony_ci	update_input_data(req_info, req->src, req->cryptlen, &argcnt);
16162306a36Sopenharmony_ci	req_info->incnt = argcnt;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	return 0;
16462306a36Sopenharmony_ci}
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_cistatic inline void store_cb_info(struct skcipher_request *req,
16762306a36Sopenharmony_ci				 struct cpt_request_info *req_info)
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	req_info->callback = (void *)cvm_callback;
17062306a36Sopenharmony_ci	req_info->callback_arg = (void *)&req->base;
17162306a36Sopenharmony_ci}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_cistatic inline void create_output_list(struct skcipher_request *req,
17462306a36Sopenharmony_ci				      u32 enc_iv_len)
17562306a36Sopenharmony_ci{
17662306a36Sopenharmony_ci	struct cvm_req_ctx *rctx = skcipher_request_ctx_dma(req);
17762306a36Sopenharmony_ci	struct cpt_request_info *req_info = &rctx->cpt_req;
17862306a36Sopenharmony_ci	u32 argcnt = 0;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	/* OUTPUT Buffer Processing
18162306a36Sopenharmony_ci	 * AES encryption/decryption output would be
18262306a36Sopenharmony_ci	 * received in the following format
18362306a36Sopenharmony_ci	 *
18462306a36Sopenharmony_ci	 * ------IV--------|------ENCRYPTED/DECRYPTED DATA-----|
18562306a36Sopenharmony_ci	 * [ 16 Bytes/     [   Request Enc/Dec/ DATA Len AES CBC ]
18662306a36Sopenharmony_ci	 */
18762306a36Sopenharmony_ci	/* Reading IV information */
18862306a36Sopenharmony_ci	update_output_iv(req_info, req->iv, enc_iv_len, &argcnt);
18962306a36Sopenharmony_ci	update_output_data(req_info, req->dst, req->cryptlen, &argcnt);
19062306a36Sopenharmony_ci	req_info->outcnt = argcnt;
19162306a36Sopenharmony_ci}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_cistatic inline int cvm_enc_dec(struct skcipher_request *req, u32 enc)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
19662306a36Sopenharmony_ci	struct cvm_req_ctx *rctx = skcipher_request_ctx_dma(req);
19762306a36Sopenharmony_ci	u32 enc_iv_len = crypto_skcipher_ivsize(tfm);
19862306a36Sopenharmony_ci	struct fc_context *fctx = &rctx->fctx;
19962306a36Sopenharmony_ci	struct cpt_request_info *req_info = &rctx->cpt_req;
20062306a36Sopenharmony_ci	void *cdev = NULL;
20162306a36Sopenharmony_ci	int status;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	memset(req_info, 0, sizeof(struct cpt_request_info));
20462306a36Sopenharmony_ci	req_info->may_sleep = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) != 0;
20562306a36Sopenharmony_ci	memset(fctx, 0, sizeof(struct fc_context));
20662306a36Sopenharmony_ci	create_input_list(req, enc, enc_iv_len);
20762306a36Sopenharmony_ci	create_output_list(req, enc_iv_len);
20862306a36Sopenharmony_ci	store_cb_info(req, req_info);
20962306a36Sopenharmony_ci	cdev = dev_handle.cdev[smp_processor_id()];
21062306a36Sopenharmony_ci	status = cptvf_do_request(cdev, req_info);
21162306a36Sopenharmony_ci	/* We perform an asynchronous send and once
21262306a36Sopenharmony_ci	 * the request is completed the driver would
21362306a36Sopenharmony_ci	 * intimate through  registered call back functions
21462306a36Sopenharmony_ci	 */
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	if (status)
21762306a36Sopenharmony_ci		return status;
21862306a36Sopenharmony_ci	else
21962306a36Sopenharmony_ci		return -EINPROGRESS;
22062306a36Sopenharmony_ci}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_cistatic int cvm_encrypt(struct skcipher_request *req)
22362306a36Sopenharmony_ci{
22462306a36Sopenharmony_ci	return cvm_enc_dec(req, true);
22562306a36Sopenharmony_ci}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_cistatic int cvm_decrypt(struct skcipher_request *req)
22862306a36Sopenharmony_ci{
22962306a36Sopenharmony_ci	return cvm_enc_dec(req, false);
23062306a36Sopenharmony_ci}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_cistatic int cvm_xts_setkey(struct crypto_skcipher *cipher, const u8 *key,
23362306a36Sopenharmony_ci		   u32 keylen)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	struct cvm_enc_ctx *ctx = crypto_skcipher_ctx(cipher);
23662306a36Sopenharmony_ci	int err;
23762306a36Sopenharmony_ci	const u8 *key1 = key;
23862306a36Sopenharmony_ci	const u8 *key2 = key + (keylen / 2);
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	err = xts_verify_key(cipher, key, keylen);
24162306a36Sopenharmony_ci	if (err)
24262306a36Sopenharmony_ci		return err;
24362306a36Sopenharmony_ci	ctx->key_len = keylen;
24462306a36Sopenharmony_ci	memcpy(ctx->enc_key, key1, keylen / 2);
24562306a36Sopenharmony_ci	memcpy(ctx->enc_key + KEY2_OFFSET, key2, keylen / 2);
24662306a36Sopenharmony_ci	ctx->cipher_type = AES_XTS;
24762306a36Sopenharmony_ci	switch (ctx->key_len) {
24862306a36Sopenharmony_ci	case 32:
24962306a36Sopenharmony_ci		ctx->key_type = AES_128_BIT;
25062306a36Sopenharmony_ci		break;
25162306a36Sopenharmony_ci	case 64:
25262306a36Sopenharmony_ci		ctx->key_type = AES_256_BIT;
25362306a36Sopenharmony_ci		break;
25462306a36Sopenharmony_ci	default:
25562306a36Sopenharmony_ci		return -EINVAL;
25662306a36Sopenharmony_ci	}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	return 0;
25962306a36Sopenharmony_ci}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_cistatic int cvm_validate_keylen(struct cvm_enc_ctx *ctx, u32 keylen)
26262306a36Sopenharmony_ci{
26362306a36Sopenharmony_ci	if ((keylen == 16) || (keylen == 24) || (keylen == 32)) {
26462306a36Sopenharmony_ci		ctx->key_len = keylen;
26562306a36Sopenharmony_ci		switch (ctx->key_len) {
26662306a36Sopenharmony_ci		case 16:
26762306a36Sopenharmony_ci			ctx->key_type = AES_128_BIT;
26862306a36Sopenharmony_ci			break;
26962306a36Sopenharmony_ci		case 24:
27062306a36Sopenharmony_ci			ctx->key_type = AES_192_BIT;
27162306a36Sopenharmony_ci			break;
27262306a36Sopenharmony_ci		case 32:
27362306a36Sopenharmony_ci			ctx->key_type = AES_256_BIT;
27462306a36Sopenharmony_ci			break;
27562306a36Sopenharmony_ci		default:
27662306a36Sopenharmony_ci			return -EINVAL;
27762306a36Sopenharmony_ci		}
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci		if (ctx->cipher_type == DES3_CBC)
28062306a36Sopenharmony_ci			ctx->key_type = 0;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci		return 0;
28362306a36Sopenharmony_ci	}
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	return -EINVAL;
28662306a36Sopenharmony_ci}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_cistatic int cvm_setkey(struct crypto_skcipher *cipher, const u8 *key,
28962306a36Sopenharmony_ci		      u32 keylen, u8 cipher_type)
29062306a36Sopenharmony_ci{
29162306a36Sopenharmony_ci	struct cvm_enc_ctx *ctx = crypto_skcipher_ctx(cipher);
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	ctx->cipher_type = cipher_type;
29462306a36Sopenharmony_ci	if (!cvm_validate_keylen(ctx, keylen)) {
29562306a36Sopenharmony_ci		memcpy(ctx->enc_key, key, keylen);
29662306a36Sopenharmony_ci		return 0;
29762306a36Sopenharmony_ci	} else {
29862306a36Sopenharmony_ci		return -EINVAL;
29962306a36Sopenharmony_ci	}
30062306a36Sopenharmony_ci}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_cistatic int cvm_cbc_aes_setkey(struct crypto_skcipher *cipher, const u8 *key,
30362306a36Sopenharmony_ci			      u32 keylen)
30462306a36Sopenharmony_ci{
30562306a36Sopenharmony_ci	return cvm_setkey(cipher, key, keylen, AES_CBC);
30662306a36Sopenharmony_ci}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_cistatic int cvm_ecb_aes_setkey(struct crypto_skcipher *cipher, const u8 *key,
30962306a36Sopenharmony_ci			      u32 keylen)
31062306a36Sopenharmony_ci{
31162306a36Sopenharmony_ci	return cvm_setkey(cipher, key, keylen, AES_ECB);
31262306a36Sopenharmony_ci}
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_cistatic int cvm_cfb_aes_setkey(struct crypto_skcipher *cipher, const u8 *key,
31562306a36Sopenharmony_ci			      u32 keylen)
31662306a36Sopenharmony_ci{
31762306a36Sopenharmony_ci	return cvm_setkey(cipher, key, keylen, AES_CFB);
31862306a36Sopenharmony_ci}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_cistatic int cvm_cbc_des3_setkey(struct crypto_skcipher *cipher, const u8 *key,
32162306a36Sopenharmony_ci			       u32 keylen)
32262306a36Sopenharmony_ci{
32362306a36Sopenharmony_ci	return verify_skcipher_des3_key(cipher, key) ?:
32462306a36Sopenharmony_ci	       cvm_setkey(cipher, key, keylen, DES3_CBC);
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_cistatic int cvm_ecb_des3_setkey(struct crypto_skcipher *cipher, const u8 *key,
32862306a36Sopenharmony_ci			       u32 keylen)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	return verify_skcipher_des3_key(cipher, key) ?:
33162306a36Sopenharmony_ci	       cvm_setkey(cipher, key, keylen, DES3_ECB);
33262306a36Sopenharmony_ci}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_cistatic int cvm_enc_dec_init(struct crypto_skcipher *tfm)
33562306a36Sopenharmony_ci{
33662306a36Sopenharmony_ci	crypto_skcipher_set_reqsize_dma(tfm, sizeof(struct cvm_req_ctx));
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	return 0;
33962306a36Sopenharmony_ci}
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_cistatic struct skcipher_alg algs[] = { {
34262306a36Sopenharmony_ci	.base.cra_flags		= CRYPTO_ALG_ASYNC |
34362306a36Sopenharmony_ci				  CRYPTO_ALG_ALLOCATES_MEMORY,
34462306a36Sopenharmony_ci	.base.cra_blocksize	= AES_BLOCK_SIZE,
34562306a36Sopenharmony_ci	.base.cra_ctxsize	= sizeof(struct cvm_enc_ctx),
34662306a36Sopenharmony_ci	.base.cra_alignmask	= 7,
34762306a36Sopenharmony_ci	.base.cra_priority	= 4001,
34862306a36Sopenharmony_ci	.base.cra_name		= "xts(aes)",
34962306a36Sopenharmony_ci	.base.cra_driver_name	= "cavium-xts-aes",
35062306a36Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	.ivsize			= AES_BLOCK_SIZE,
35362306a36Sopenharmony_ci	.min_keysize		= 2 * AES_MIN_KEY_SIZE,
35462306a36Sopenharmony_ci	.max_keysize		= 2 * AES_MAX_KEY_SIZE,
35562306a36Sopenharmony_ci	.setkey			= cvm_xts_setkey,
35662306a36Sopenharmony_ci	.encrypt		= cvm_encrypt,
35762306a36Sopenharmony_ci	.decrypt		= cvm_decrypt,
35862306a36Sopenharmony_ci	.init			= cvm_enc_dec_init,
35962306a36Sopenharmony_ci}, {
36062306a36Sopenharmony_ci	.base.cra_flags		= CRYPTO_ALG_ASYNC |
36162306a36Sopenharmony_ci				  CRYPTO_ALG_ALLOCATES_MEMORY,
36262306a36Sopenharmony_ci	.base.cra_blocksize	= AES_BLOCK_SIZE,
36362306a36Sopenharmony_ci	.base.cra_ctxsize	= sizeof(struct cvm_enc_ctx),
36462306a36Sopenharmony_ci	.base.cra_alignmask	= 7,
36562306a36Sopenharmony_ci	.base.cra_priority	= 4001,
36662306a36Sopenharmony_ci	.base.cra_name		= "cbc(aes)",
36762306a36Sopenharmony_ci	.base.cra_driver_name	= "cavium-cbc-aes",
36862306a36Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	.ivsize			= AES_BLOCK_SIZE,
37162306a36Sopenharmony_ci	.min_keysize		= AES_MIN_KEY_SIZE,
37262306a36Sopenharmony_ci	.max_keysize		= AES_MAX_KEY_SIZE,
37362306a36Sopenharmony_ci	.setkey			= cvm_cbc_aes_setkey,
37462306a36Sopenharmony_ci	.encrypt		= cvm_encrypt,
37562306a36Sopenharmony_ci	.decrypt		= cvm_decrypt,
37662306a36Sopenharmony_ci	.init			= cvm_enc_dec_init,
37762306a36Sopenharmony_ci}, {
37862306a36Sopenharmony_ci	.base.cra_flags		= CRYPTO_ALG_ASYNC |
37962306a36Sopenharmony_ci				  CRYPTO_ALG_ALLOCATES_MEMORY,
38062306a36Sopenharmony_ci	.base.cra_blocksize	= AES_BLOCK_SIZE,
38162306a36Sopenharmony_ci	.base.cra_ctxsize	= sizeof(struct cvm_enc_ctx),
38262306a36Sopenharmony_ci	.base.cra_alignmask	= 7,
38362306a36Sopenharmony_ci	.base.cra_priority	= 4001,
38462306a36Sopenharmony_ci	.base.cra_name		= "ecb(aes)",
38562306a36Sopenharmony_ci	.base.cra_driver_name	= "cavium-ecb-aes",
38662306a36Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	.min_keysize		= AES_MIN_KEY_SIZE,
38962306a36Sopenharmony_ci	.max_keysize		= AES_MAX_KEY_SIZE,
39062306a36Sopenharmony_ci	.setkey			= cvm_ecb_aes_setkey,
39162306a36Sopenharmony_ci	.encrypt		= cvm_encrypt,
39262306a36Sopenharmony_ci	.decrypt		= cvm_decrypt,
39362306a36Sopenharmony_ci	.init			= cvm_enc_dec_init,
39462306a36Sopenharmony_ci}, {
39562306a36Sopenharmony_ci	.base.cra_flags		= CRYPTO_ALG_ASYNC |
39662306a36Sopenharmony_ci				  CRYPTO_ALG_ALLOCATES_MEMORY,
39762306a36Sopenharmony_ci	.base.cra_blocksize	= AES_BLOCK_SIZE,
39862306a36Sopenharmony_ci	.base.cra_ctxsize	= sizeof(struct cvm_enc_ctx),
39962306a36Sopenharmony_ci	.base.cra_alignmask	= 7,
40062306a36Sopenharmony_ci	.base.cra_priority	= 4001,
40162306a36Sopenharmony_ci	.base.cra_name		= "cfb(aes)",
40262306a36Sopenharmony_ci	.base.cra_driver_name	= "cavium-cfb-aes",
40362306a36Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	.ivsize			= AES_BLOCK_SIZE,
40662306a36Sopenharmony_ci	.min_keysize		= AES_MIN_KEY_SIZE,
40762306a36Sopenharmony_ci	.max_keysize		= AES_MAX_KEY_SIZE,
40862306a36Sopenharmony_ci	.setkey			= cvm_cfb_aes_setkey,
40962306a36Sopenharmony_ci	.encrypt		= cvm_encrypt,
41062306a36Sopenharmony_ci	.decrypt		= cvm_decrypt,
41162306a36Sopenharmony_ci	.init			= cvm_enc_dec_init,
41262306a36Sopenharmony_ci}, {
41362306a36Sopenharmony_ci	.base.cra_flags		= CRYPTO_ALG_ASYNC |
41462306a36Sopenharmony_ci				  CRYPTO_ALG_ALLOCATES_MEMORY,
41562306a36Sopenharmony_ci	.base.cra_blocksize	= DES3_EDE_BLOCK_SIZE,
41662306a36Sopenharmony_ci	.base.cra_ctxsize	= sizeof(struct cvm_des3_ctx),
41762306a36Sopenharmony_ci	.base.cra_alignmask	= 7,
41862306a36Sopenharmony_ci	.base.cra_priority	= 4001,
41962306a36Sopenharmony_ci	.base.cra_name		= "cbc(des3_ede)",
42062306a36Sopenharmony_ci	.base.cra_driver_name	= "cavium-cbc-des3_ede",
42162306a36Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	.min_keysize		= DES3_EDE_KEY_SIZE,
42462306a36Sopenharmony_ci	.max_keysize		= DES3_EDE_KEY_SIZE,
42562306a36Sopenharmony_ci	.ivsize			= DES_BLOCK_SIZE,
42662306a36Sopenharmony_ci	.setkey			= cvm_cbc_des3_setkey,
42762306a36Sopenharmony_ci	.encrypt		= cvm_encrypt,
42862306a36Sopenharmony_ci	.decrypt		= cvm_decrypt,
42962306a36Sopenharmony_ci	.init			= cvm_enc_dec_init,
43062306a36Sopenharmony_ci}, {
43162306a36Sopenharmony_ci	.base.cra_flags		= CRYPTO_ALG_ASYNC |
43262306a36Sopenharmony_ci				  CRYPTO_ALG_ALLOCATES_MEMORY,
43362306a36Sopenharmony_ci	.base.cra_blocksize	= DES3_EDE_BLOCK_SIZE,
43462306a36Sopenharmony_ci	.base.cra_ctxsize	= sizeof(struct cvm_des3_ctx),
43562306a36Sopenharmony_ci	.base.cra_alignmask	= 7,
43662306a36Sopenharmony_ci	.base.cra_priority	= 4001,
43762306a36Sopenharmony_ci	.base.cra_name		= "ecb(des3_ede)",
43862306a36Sopenharmony_ci	.base.cra_driver_name	= "cavium-ecb-des3_ede",
43962306a36Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	.min_keysize		= DES3_EDE_KEY_SIZE,
44262306a36Sopenharmony_ci	.max_keysize		= DES3_EDE_KEY_SIZE,
44362306a36Sopenharmony_ci	.ivsize			= DES_BLOCK_SIZE,
44462306a36Sopenharmony_ci	.setkey			= cvm_ecb_des3_setkey,
44562306a36Sopenharmony_ci	.encrypt		= cvm_encrypt,
44662306a36Sopenharmony_ci	.decrypt		= cvm_decrypt,
44762306a36Sopenharmony_ci	.init			= cvm_enc_dec_init,
44862306a36Sopenharmony_ci} };
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_cistatic inline int cav_register_algs(void)
45162306a36Sopenharmony_ci{
45262306a36Sopenharmony_ci	return crypto_register_skciphers(algs, ARRAY_SIZE(algs));
45362306a36Sopenharmony_ci}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_cistatic inline void cav_unregister_algs(void)
45662306a36Sopenharmony_ci{
45762306a36Sopenharmony_ci	crypto_unregister_skciphers(algs, ARRAY_SIZE(algs));
45862306a36Sopenharmony_ci}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ciint cvm_crypto_init(struct cpt_vf *cptvf)
46162306a36Sopenharmony_ci{
46262306a36Sopenharmony_ci	struct pci_dev *pdev = cptvf->pdev;
46362306a36Sopenharmony_ci	u32 dev_count;
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	dev_count = dev_handle.dev_count;
46662306a36Sopenharmony_ci	dev_handle.cdev[dev_count] = cptvf;
46762306a36Sopenharmony_ci	dev_handle.dev_count++;
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	if (dev_count == 3) {
47062306a36Sopenharmony_ci		if (cav_register_algs()) {
47162306a36Sopenharmony_ci			dev_err(&pdev->dev, "Error in registering crypto algorithms\n");
47262306a36Sopenharmony_ci			return -EINVAL;
47362306a36Sopenharmony_ci		}
47462306a36Sopenharmony_ci	}
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	return 0;
47762306a36Sopenharmony_ci}
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_civoid cvm_crypto_exit(void)
48062306a36Sopenharmony_ci{
48162306a36Sopenharmony_ci	u32 dev_count;
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	dev_count = --dev_handle.dev_count;
48462306a36Sopenharmony_ci	if (!dev_count)
48562306a36Sopenharmony_ci		cav_unregister_algs();
48662306a36Sopenharmony_ci}
487