18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci/*
48c2ecf20Sopenharmony_ci * Copyright (C) 2016 Cavium, Inc.
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <crypto/aes.h>
88c2ecf20Sopenharmony_ci#include <crypto/algapi.h>
98c2ecf20Sopenharmony_ci#include <crypto/authenc.h>
108c2ecf20Sopenharmony_ci#include <crypto/internal/des.h>
118c2ecf20Sopenharmony_ci#include <crypto/xts.h>
128c2ecf20Sopenharmony_ci#include <linux/crypto.h>
138c2ecf20Sopenharmony_ci#include <linux/err.h>
148c2ecf20Sopenharmony_ci#include <linux/list.h>
158c2ecf20Sopenharmony_ci#include <linux/scatterlist.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include "cptvf.h"
188c2ecf20Sopenharmony_ci#include "cptvf_algs.h"
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistruct cpt_device_handle {
218c2ecf20Sopenharmony_ci	void *cdev[MAX_DEVICES];
228c2ecf20Sopenharmony_ci	u32 dev_count;
238c2ecf20Sopenharmony_ci};
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistatic struct cpt_device_handle dev_handle;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic void cvm_callback(u32 status, void *arg)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	struct crypto_async_request *req = (struct crypto_async_request *)arg;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	req->complete(req, !status);
328c2ecf20Sopenharmony_ci}
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic inline void update_input_iv(struct cpt_request_info *req_info,
358c2ecf20Sopenharmony_ci				   u8 *iv, u32 enc_iv_len,
368c2ecf20Sopenharmony_ci				   u32 *argcnt)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	/* Setting the iv information */
398c2ecf20Sopenharmony_ci	req_info->in[*argcnt].vptr = (void *)iv;
408c2ecf20Sopenharmony_ci	req_info->in[*argcnt].size = enc_iv_len;
418c2ecf20Sopenharmony_ci	req_info->req.dlen += enc_iv_len;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	++(*argcnt);
448c2ecf20Sopenharmony_ci}
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistatic inline void update_output_iv(struct cpt_request_info *req_info,
478c2ecf20Sopenharmony_ci				    u8 *iv, u32 enc_iv_len,
488c2ecf20Sopenharmony_ci				    u32 *argcnt)
498c2ecf20Sopenharmony_ci{
508c2ecf20Sopenharmony_ci	/* Setting the iv information */
518c2ecf20Sopenharmony_ci	req_info->out[*argcnt].vptr = (void *)iv;
528c2ecf20Sopenharmony_ci	req_info->out[*argcnt].size = enc_iv_len;
538c2ecf20Sopenharmony_ci	req_info->rlen += enc_iv_len;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	++(*argcnt);
568c2ecf20Sopenharmony_ci}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistatic inline void update_input_data(struct cpt_request_info *req_info,
598c2ecf20Sopenharmony_ci				     struct scatterlist *inp_sg,
608c2ecf20Sopenharmony_ci				     u32 nbytes, u32 *argcnt)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	req_info->req.dlen += nbytes;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	while (nbytes) {
658c2ecf20Sopenharmony_ci		u32 len = min(nbytes, inp_sg->length);
668c2ecf20Sopenharmony_ci		u8 *ptr = sg_virt(inp_sg);
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci		req_info->in[*argcnt].vptr = (void *)ptr;
698c2ecf20Sopenharmony_ci		req_info->in[*argcnt].size = len;
708c2ecf20Sopenharmony_ci		nbytes -= len;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci		++(*argcnt);
738c2ecf20Sopenharmony_ci		++inp_sg;
748c2ecf20Sopenharmony_ci	}
758c2ecf20Sopenharmony_ci}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cistatic inline void update_output_data(struct cpt_request_info *req_info,
788c2ecf20Sopenharmony_ci				      struct scatterlist *outp_sg,
798c2ecf20Sopenharmony_ci				      u32 nbytes, u32 *argcnt)
808c2ecf20Sopenharmony_ci{
818c2ecf20Sopenharmony_ci	req_info->rlen += nbytes;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	while (nbytes) {
848c2ecf20Sopenharmony_ci		u32 len = min(nbytes, outp_sg->length);
858c2ecf20Sopenharmony_ci		u8 *ptr = sg_virt(outp_sg);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci		req_info->out[*argcnt].vptr = (void *)ptr;
888c2ecf20Sopenharmony_ci		req_info->out[*argcnt].size = len;
898c2ecf20Sopenharmony_ci		nbytes -= len;
908c2ecf20Sopenharmony_ci		++(*argcnt);
918c2ecf20Sopenharmony_ci		++outp_sg;
928c2ecf20Sopenharmony_ci	}
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic inline u32 create_ctx_hdr(struct skcipher_request *req, u32 enc,
968c2ecf20Sopenharmony_ci				 u32 *argcnt)
978c2ecf20Sopenharmony_ci{
988c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
998c2ecf20Sopenharmony_ci	struct cvm_enc_ctx *ctx = crypto_skcipher_ctx(tfm);
1008c2ecf20Sopenharmony_ci	struct cvm_req_ctx *rctx = skcipher_request_ctx(req);
1018c2ecf20Sopenharmony_ci	struct fc_context *fctx = &rctx->fctx;
1028c2ecf20Sopenharmony_ci	u32 enc_iv_len = crypto_skcipher_ivsize(tfm);
1038c2ecf20Sopenharmony_ci	struct cpt_request_info *req_info = &rctx->cpt_req;
1048c2ecf20Sopenharmony_ci	__be64 *ctrl_flags = NULL;
1058c2ecf20Sopenharmony_ci	__be64 *offset_control;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	req_info->ctrl.s.grp = 0;
1088c2ecf20Sopenharmony_ci	req_info->ctrl.s.dma_mode = DMA_GATHER_SCATTER;
1098c2ecf20Sopenharmony_ci	req_info->ctrl.s.se_req = SE_CORE_REQ;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	req_info->req.opcode.s.major = MAJOR_OP_FC |
1128c2ecf20Sopenharmony_ci					DMA_MODE_FLAG(DMA_GATHER_SCATTER);
1138c2ecf20Sopenharmony_ci	if (enc)
1148c2ecf20Sopenharmony_ci		req_info->req.opcode.s.minor = 2;
1158c2ecf20Sopenharmony_ci	else
1168c2ecf20Sopenharmony_ci		req_info->req.opcode.s.minor = 3;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	req_info->req.param1 = req->cryptlen; /* Encryption Data length */
1198c2ecf20Sopenharmony_ci	req_info->req.param2 = 0; /*Auth data length */
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	fctx->enc.enc_ctrl.e.enc_cipher = ctx->cipher_type;
1228c2ecf20Sopenharmony_ci	fctx->enc.enc_ctrl.e.aes_key = ctx->key_type;
1238c2ecf20Sopenharmony_ci	fctx->enc.enc_ctrl.e.iv_source = FROM_DPTR;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	if (ctx->cipher_type == AES_XTS)
1268c2ecf20Sopenharmony_ci		memcpy(fctx->enc.encr_key, ctx->enc_key, ctx->key_len * 2);
1278c2ecf20Sopenharmony_ci	else
1288c2ecf20Sopenharmony_ci		memcpy(fctx->enc.encr_key, ctx->enc_key, ctx->key_len);
1298c2ecf20Sopenharmony_ci	ctrl_flags = (__be64 *)&fctx->enc.enc_ctrl.flags;
1308c2ecf20Sopenharmony_ci	*ctrl_flags = cpu_to_be64(fctx->enc.enc_ctrl.flags);
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	offset_control = (__be64 *)&rctx->control_word;
1338c2ecf20Sopenharmony_ci	*offset_control = cpu_to_be64(((u64)(enc_iv_len) << 16));
1348c2ecf20Sopenharmony_ci	/* Storing  Packet Data Information in offset
1358c2ecf20Sopenharmony_ci	 * Control Word First 8 bytes
1368c2ecf20Sopenharmony_ci	 */
1378c2ecf20Sopenharmony_ci	req_info->in[*argcnt].vptr = (u8 *)offset_control;
1388c2ecf20Sopenharmony_ci	req_info->in[*argcnt].size = CONTROL_WORD_LEN;
1398c2ecf20Sopenharmony_ci	req_info->req.dlen += CONTROL_WORD_LEN;
1408c2ecf20Sopenharmony_ci	++(*argcnt);
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	req_info->in[*argcnt].vptr = (u8 *)fctx;
1438c2ecf20Sopenharmony_ci	req_info->in[*argcnt].size = sizeof(struct fc_context);
1448c2ecf20Sopenharmony_ci	req_info->req.dlen += sizeof(struct fc_context);
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	++(*argcnt);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	return 0;
1498c2ecf20Sopenharmony_ci}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_cistatic inline u32 create_input_list(struct skcipher_request  *req, u32 enc,
1528c2ecf20Sopenharmony_ci				    u32 enc_iv_len)
1538c2ecf20Sopenharmony_ci{
1548c2ecf20Sopenharmony_ci	struct cvm_req_ctx *rctx = skcipher_request_ctx(req);
1558c2ecf20Sopenharmony_ci	struct cpt_request_info *req_info = &rctx->cpt_req;
1568c2ecf20Sopenharmony_ci	u32 argcnt =  0;
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	create_ctx_hdr(req, enc, &argcnt);
1598c2ecf20Sopenharmony_ci	update_input_iv(req_info, req->iv, enc_iv_len, &argcnt);
1608c2ecf20Sopenharmony_ci	update_input_data(req_info, req->src, req->cryptlen, &argcnt);
1618c2ecf20Sopenharmony_ci	req_info->incnt = argcnt;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	return 0;
1648c2ecf20Sopenharmony_ci}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistatic inline void store_cb_info(struct skcipher_request *req,
1678c2ecf20Sopenharmony_ci				 struct cpt_request_info *req_info)
1688c2ecf20Sopenharmony_ci{
1698c2ecf20Sopenharmony_ci	req_info->callback = (void *)cvm_callback;
1708c2ecf20Sopenharmony_ci	req_info->callback_arg = (void *)&req->base;
1718c2ecf20Sopenharmony_ci}
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_cistatic inline void create_output_list(struct skcipher_request *req,
1748c2ecf20Sopenharmony_ci				      u32 enc_iv_len)
1758c2ecf20Sopenharmony_ci{
1768c2ecf20Sopenharmony_ci	struct cvm_req_ctx *rctx = skcipher_request_ctx(req);
1778c2ecf20Sopenharmony_ci	struct cpt_request_info *req_info = &rctx->cpt_req;
1788c2ecf20Sopenharmony_ci	u32 argcnt = 0;
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	/* OUTPUT Buffer Processing
1818c2ecf20Sopenharmony_ci	 * AES encryption/decryption output would be
1828c2ecf20Sopenharmony_ci	 * received in the following format
1838c2ecf20Sopenharmony_ci	 *
1848c2ecf20Sopenharmony_ci	 * ------IV--------|------ENCRYPTED/DECRYPTED DATA-----|
1858c2ecf20Sopenharmony_ci	 * [ 16 Bytes/     [   Request Enc/Dec/ DATA Len AES CBC ]
1868c2ecf20Sopenharmony_ci	 */
1878c2ecf20Sopenharmony_ci	/* Reading IV information */
1888c2ecf20Sopenharmony_ci	update_output_iv(req_info, req->iv, enc_iv_len, &argcnt);
1898c2ecf20Sopenharmony_ci	update_output_data(req_info, req->dst, req->cryptlen, &argcnt);
1908c2ecf20Sopenharmony_ci	req_info->outcnt = argcnt;
1918c2ecf20Sopenharmony_ci}
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_cistatic inline int cvm_enc_dec(struct skcipher_request *req, u32 enc)
1948c2ecf20Sopenharmony_ci{
1958c2ecf20Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
1968c2ecf20Sopenharmony_ci	struct cvm_req_ctx *rctx = skcipher_request_ctx(req);
1978c2ecf20Sopenharmony_ci	u32 enc_iv_len = crypto_skcipher_ivsize(tfm);
1988c2ecf20Sopenharmony_ci	struct fc_context *fctx = &rctx->fctx;
1998c2ecf20Sopenharmony_ci	struct cpt_request_info *req_info = &rctx->cpt_req;
2008c2ecf20Sopenharmony_ci	void *cdev = NULL;
2018c2ecf20Sopenharmony_ci	int status;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	memset(req_info, 0, sizeof(struct cpt_request_info));
2048c2ecf20Sopenharmony_ci	req_info->may_sleep = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) != 0;
2058c2ecf20Sopenharmony_ci	memset(fctx, 0, sizeof(struct fc_context));
2068c2ecf20Sopenharmony_ci	create_input_list(req, enc, enc_iv_len);
2078c2ecf20Sopenharmony_ci	create_output_list(req, enc_iv_len);
2088c2ecf20Sopenharmony_ci	store_cb_info(req, req_info);
2098c2ecf20Sopenharmony_ci	cdev = dev_handle.cdev[smp_processor_id()];
2108c2ecf20Sopenharmony_ci	status = cptvf_do_request(cdev, req_info);
2118c2ecf20Sopenharmony_ci	/* We perform an asynchronous send and once
2128c2ecf20Sopenharmony_ci	 * the request is completed the driver would
2138c2ecf20Sopenharmony_ci	 * intimate through  registered call back functions
2148c2ecf20Sopenharmony_ci	 */
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	if (status)
2178c2ecf20Sopenharmony_ci		return status;
2188c2ecf20Sopenharmony_ci	else
2198c2ecf20Sopenharmony_ci		return -EINPROGRESS;
2208c2ecf20Sopenharmony_ci}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_cistatic int cvm_encrypt(struct skcipher_request *req)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	return cvm_enc_dec(req, true);
2258c2ecf20Sopenharmony_ci}
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_cistatic int cvm_decrypt(struct skcipher_request *req)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	return cvm_enc_dec(req, false);
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic int cvm_xts_setkey(struct crypto_skcipher *cipher, const u8 *key,
2338c2ecf20Sopenharmony_ci		   u32 keylen)
2348c2ecf20Sopenharmony_ci{
2358c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher);
2368c2ecf20Sopenharmony_ci	struct cvm_enc_ctx *ctx = crypto_tfm_ctx(tfm);
2378c2ecf20Sopenharmony_ci	int err;
2388c2ecf20Sopenharmony_ci	const u8 *key1 = key;
2398c2ecf20Sopenharmony_ci	const u8 *key2 = key + (keylen / 2);
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	err = xts_check_key(tfm, key, keylen);
2428c2ecf20Sopenharmony_ci	if (err)
2438c2ecf20Sopenharmony_ci		return err;
2448c2ecf20Sopenharmony_ci	ctx->key_len = keylen;
2458c2ecf20Sopenharmony_ci	memcpy(ctx->enc_key, key1, keylen / 2);
2468c2ecf20Sopenharmony_ci	memcpy(ctx->enc_key + KEY2_OFFSET, key2, keylen / 2);
2478c2ecf20Sopenharmony_ci	ctx->cipher_type = AES_XTS;
2488c2ecf20Sopenharmony_ci	switch (ctx->key_len) {
2498c2ecf20Sopenharmony_ci	case 32:
2508c2ecf20Sopenharmony_ci		ctx->key_type = AES_128_BIT;
2518c2ecf20Sopenharmony_ci		break;
2528c2ecf20Sopenharmony_ci	case 64:
2538c2ecf20Sopenharmony_ci		ctx->key_type = AES_256_BIT;
2548c2ecf20Sopenharmony_ci		break;
2558c2ecf20Sopenharmony_ci	default:
2568c2ecf20Sopenharmony_ci		return -EINVAL;
2578c2ecf20Sopenharmony_ci	}
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	return 0;
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_cistatic int cvm_validate_keylen(struct cvm_enc_ctx *ctx, u32 keylen)
2638c2ecf20Sopenharmony_ci{
2648c2ecf20Sopenharmony_ci	if ((keylen == 16) || (keylen == 24) || (keylen == 32)) {
2658c2ecf20Sopenharmony_ci		ctx->key_len = keylen;
2668c2ecf20Sopenharmony_ci		switch (ctx->key_len) {
2678c2ecf20Sopenharmony_ci		case 16:
2688c2ecf20Sopenharmony_ci			ctx->key_type = AES_128_BIT;
2698c2ecf20Sopenharmony_ci			break;
2708c2ecf20Sopenharmony_ci		case 24:
2718c2ecf20Sopenharmony_ci			ctx->key_type = AES_192_BIT;
2728c2ecf20Sopenharmony_ci			break;
2738c2ecf20Sopenharmony_ci		case 32:
2748c2ecf20Sopenharmony_ci			ctx->key_type = AES_256_BIT;
2758c2ecf20Sopenharmony_ci			break;
2768c2ecf20Sopenharmony_ci		default:
2778c2ecf20Sopenharmony_ci			return -EINVAL;
2788c2ecf20Sopenharmony_ci		}
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci		if (ctx->cipher_type == DES3_CBC)
2818c2ecf20Sopenharmony_ci			ctx->key_type = 0;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci		return 0;
2848c2ecf20Sopenharmony_ci	}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	return -EINVAL;
2878c2ecf20Sopenharmony_ci}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_cistatic int cvm_setkey(struct crypto_skcipher *cipher, const u8 *key,
2908c2ecf20Sopenharmony_ci		      u32 keylen, u8 cipher_type)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci	struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher);
2938c2ecf20Sopenharmony_ci	struct cvm_enc_ctx *ctx = crypto_tfm_ctx(tfm);
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	ctx->cipher_type = cipher_type;
2968c2ecf20Sopenharmony_ci	if (!cvm_validate_keylen(ctx, keylen)) {
2978c2ecf20Sopenharmony_ci		memcpy(ctx->enc_key, key, keylen);
2988c2ecf20Sopenharmony_ci		return 0;
2998c2ecf20Sopenharmony_ci	} else {
3008c2ecf20Sopenharmony_ci		return -EINVAL;
3018c2ecf20Sopenharmony_ci	}
3028c2ecf20Sopenharmony_ci}
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_cistatic int cvm_cbc_aes_setkey(struct crypto_skcipher *cipher, const u8 *key,
3058c2ecf20Sopenharmony_ci			      u32 keylen)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci	return cvm_setkey(cipher, key, keylen, AES_CBC);
3088c2ecf20Sopenharmony_ci}
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_cistatic int cvm_ecb_aes_setkey(struct crypto_skcipher *cipher, const u8 *key,
3118c2ecf20Sopenharmony_ci			      u32 keylen)
3128c2ecf20Sopenharmony_ci{
3138c2ecf20Sopenharmony_ci	return cvm_setkey(cipher, key, keylen, AES_ECB);
3148c2ecf20Sopenharmony_ci}
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_cistatic int cvm_cfb_aes_setkey(struct crypto_skcipher *cipher, const u8 *key,
3178c2ecf20Sopenharmony_ci			      u32 keylen)
3188c2ecf20Sopenharmony_ci{
3198c2ecf20Sopenharmony_ci	return cvm_setkey(cipher, key, keylen, AES_CFB);
3208c2ecf20Sopenharmony_ci}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic int cvm_cbc_des3_setkey(struct crypto_skcipher *cipher, const u8 *key,
3238c2ecf20Sopenharmony_ci			       u32 keylen)
3248c2ecf20Sopenharmony_ci{
3258c2ecf20Sopenharmony_ci	return verify_skcipher_des3_key(cipher, key) ?:
3268c2ecf20Sopenharmony_ci	       cvm_setkey(cipher, key, keylen, DES3_CBC);
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_cistatic int cvm_ecb_des3_setkey(struct crypto_skcipher *cipher, const u8 *key,
3308c2ecf20Sopenharmony_ci			       u32 keylen)
3318c2ecf20Sopenharmony_ci{
3328c2ecf20Sopenharmony_ci	return verify_skcipher_des3_key(cipher, key) ?:
3338c2ecf20Sopenharmony_ci	       cvm_setkey(cipher, key, keylen, DES3_ECB);
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_cistatic int cvm_enc_dec_init(struct crypto_skcipher *tfm)
3378c2ecf20Sopenharmony_ci{
3388c2ecf20Sopenharmony_ci	crypto_skcipher_set_reqsize(tfm, sizeof(struct cvm_req_ctx));
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	return 0;
3418c2ecf20Sopenharmony_ci}
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_cistatic struct skcipher_alg algs[] = { {
3448c2ecf20Sopenharmony_ci	.base.cra_flags		= CRYPTO_ALG_ASYNC |
3458c2ecf20Sopenharmony_ci				  CRYPTO_ALG_ALLOCATES_MEMORY,
3468c2ecf20Sopenharmony_ci	.base.cra_blocksize	= AES_BLOCK_SIZE,
3478c2ecf20Sopenharmony_ci	.base.cra_ctxsize	= sizeof(struct cvm_enc_ctx),
3488c2ecf20Sopenharmony_ci	.base.cra_alignmask	= 7,
3498c2ecf20Sopenharmony_ci	.base.cra_priority	= 4001,
3508c2ecf20Sopenharmony_ci	.base.cra_name		= "xts(aes)",
3518c2ecf20Sopenharmony_ci	.base.cra_driver_name	= "cavium-xts-aes",
3528c2ecf20Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	.ivsize			= AES_BLOCK_SIZE,
3558c2ecf20Sopenharmony_ci	.min_keysize		= 2 * AES_MIN_KEY_SIZE,
3568c2ecf20Sopenharmony_ci	.max_keysize		= 2 * AES_MAX_KEY_SIZE,
3578c2ecf20Sopenharmony_ci	.setkey			= cvm_xts_setkey,
3588c2ecf20Sopenharmony_ci	.encrypt		= cvm_encrypt,
3598c2ecf20Sopenharmony_ci	.decrypt		= cvm_decrypt,
3608c2ecf20Sopenharmony_ci	.init			= cvm_enc_dec_init,
3618c2ecf20Sopenharmony_ci}, {
3628c2ecf20Sopenharmony_ci	.base.cra_flags		= CRYPTO_ALG_ASYNC |
3638c2ecf20Sopenharmony_ci				  CRYPTO_ALG_ALLOCATES_MEMORY,
3648c2ecf20Sopenharmony_ci	.base.cra_blocksize	= AES_BLOCK_SIZE,
3658c2ecf20Sopenharmony_ci	.base.cra_ctxsize	= sizeof(struct cvm_enc_ctx),
3668c2ecf20Sopenharmony_ci	.base.cra_alignmask	= 7,
3678c2ecf20Sopenharmony_ci	.base.cra_priority	= 4001,
3688c2ecf20Sopenharmony_ci	.base.cra_name		= "cbc(aes)",
3698c2ecf20Sopenharmony_ci	.base.cra_driver_name	= "cavium-cbc-aes",
3708c2ecf20Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	.ivsize			= AES_BLOCK_SIZE,
3738c2ecf20Sopenharmony_ci	.min_keysize		= AES_MIN_KEY_SIZE,
3748c2ecf20Sopenharmony_ci	.max_keysize		= AES_MAX_KEY_SIZE,
3758c2ecf20Sopenharmony_ci	.setkey			= cvm_cbc_aes_setkey,
3768c2ecf20Sopenharmony_ci	.encrypt		= cvm_encrypt,
3778c2ecf20Sopenharmony_ci	.decrypt		= cvm_decrypt,
3788c2ecf20Sopenharmony_ci	.init			= cvm_enc_dec_init,
3798c2ecf20Sopenharmony_ci}, {
3808c2ecf20Sopenharmony_ci	.base.cra_flags		= CRYPTO_ALG_ASYNC |
3818c2ecf20Sopenharmony_ci				  CRYPTO_ALG_ALLOCATES_MEMORY,
3828c2ecf20Sopenharmony_ci	.base.cra_blocksize	= AES_BLOCK_SIZE,
3838c2ecf20Sopenharmony_ci	.base.cra_ctxsize	= sizeof(struct cvm_enc_ctx),
3848c2ecf20Sopenharmony_ci	.base.cra_alignmask	= 7,
3858c2ecf20Sopenharmony_ci	.base.cra_priority	= 4001,
3868c2ecf20Sopenharmony_ci	.base.cra_name		= "ecb(aes)",
3878c2ecf20Sopenharmony_ci	.base.cra_driver_name	= "cavium-ecb-aes",
3888c2ecf20Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	.min_keysize		= AES_MIN_KEY_SIZE,
3918c2ecf20Sopenharmony_ci	.max_keysize		= AES_MAX_KEY_SIZE,
3928c2ecf20Sopenharmony_ci	.setkey			= cvm_ecb_aes_setkey,
3938c2ecf20Sopenharmony_ci	.encrypt		= cvm_encrypt,
3948c2ecf20Sopenharmony_ci	.decrypt		= cvm_decrypt,
3958c2ecf20Sopenharmony_ci	.init			= cvm_enc_dec_init,
3968c2ecf20Sopenharmony_ci}, {
3978c2ecf20Sopenharmony_ci	.base.cra_flags		= CRYPTO_ALG_ASYNC |
3988c2ecf20Sopenharmony_ci				  CRYPTO_ALG_ALLOCATES_MEMORY,
3998c2ecf20Sopenharmony_ci	.base.cra_blocksize	= AES_BLOCK_SIZE,
4008c2ecf20Sopenharmony_ci	.base.cra_ctxsize	= sizeof(struct cvm_enc_ctx),
4018c2ecf20Sopenharmony_ci	.base.cra_alignmask	= 7,
4028c2ecf20Sopenharmony_ci	.base.cra_priority	= 4001,
4038c2ecf20Sopenharmony_ci	.base.cra_name		= "cfb(aes)",
4048c2ecf20Sopenharmony_ci	.base.cra_driver_name	= "cavium-cfb-aes",
4058c2ecf20Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	.ivsize			= AES_BLOCK_SIZE,
4088c2ecf20Sopenharmony_ci	.min_keysize		= AES_MIN_KEY_SIZE,
4098c2ecf20Sopenharmony_ci	.max_keysize		= AES_MAX_KEY_SIZE,
4108c2ecf20Sopenharmony_ci	.setkey			= cvm_cfb_aes_setkey,
4118c2ecf20Sopenharmony_ci	.encrypt		= cvm_encrypt,
4128c2ecf20Sopenharmony_ci	.decrypt		= cvm_decrypt,
4138c2ecf20Sopenharmony_ci	.init			= cvm_enc_dec_init,
4148c2ecf20Sopenharmony_ci}, {
4158c2ecf20Sopenharmony_ci	.base.cra_flags		= CRYPTO_ALG_ASYNC |
4168c2ecf20Sopenharmony_ci				  CRYPTO_ALG_ALLOCATES_MEMORY,
4178c2ecf20Sopenharmony_ci	.base.cra_blocksize	= DES3_EDE_BLOCK_SIZE,
4188c2ecf20Sopenharmony_ci	.base.cra_ctxsize	= sizeof(struct cvm_des3_ctx),
4198c2ecf20Sopenharmony_ci	.base.cra_alignmask	= 7,
4208c2ecf20Sopenharmony_ci	.base.cra_priority	= 4001,
4218c2ecf20Sopenharmony_ci	.base.cra_name		= "cbc(des3_ede)",
4228c2ecf20Sopenharmony_ci	.base.cra_driver_name	= "cavium-cbc-des3_ede",
4238c2ecf20Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	.min_keysize		= DES3_EDE_KEY_SIZE,
4268c2ecf20Sopenharmony_ci	.max_keysize		= DES3_EDE_KEY_SIZE,
4278c2ecf20Sopenharmony_ci	.ivsize			= DES_BLOCK_SIZE,
4288c2ecf20Sopenharmony_ci	.setkey			= cvm_cbc_des3_setkey,
4298c2ecf20Sopenharmony_ci	.encrypt		= cvm_encrypt,
4308c2ecf20Sopenharmony_ci	.decrypt		= cvm_decrypt,
4318c2ecf20Sopenharmony_ci	.init			= cvm_enc_dec_init,
4328c2ecf20Sopenharmony_ci}, {
4338c2ecf20Sopenharmony_ci	.base.cra_flags		= CRYPTO_ALG_ASYNC |
4348c2ecf20Sopenharmony_ci				  CRYPTO_ALG_ALLOCATES_MEMORY,
4358c2ecf20Sopenharmony_ci	.base.cra_blocksize	= DES3_EDE_BLOCK_SIZE,
4368c2ecf20Sopenharmony_ci	.base.cra_ctxsize	= sizeof(struct cvm_des3_ctx),
4378c2ecf20Sopenharmony_ci	.base.cra_alignmask	= 7,
4388c2ecf20Sopenharmony_ci	.base.cra_priority	= 4001,
4398c2ecf20Sopenharmony_ci	.base.cra_name		= "ecb(des3_ede)",
4408c2ecf20Sopenharmony_ci	.base.cra_driver_name	= "cavium-ecb-des3_ede",
4418c2ecf20Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	.min_keysize		= DES3_EDE_KEY_SIZE,
4448c2ecf20Sopenharmony_ci	.max_keysize		= DES3_EDE_KEY_SIZE,
4458c2ecf20Sopenharmony_ci	.ivsize			= DES_BLOCK_SIZE,
4468c2ecf20Sopenharmony_ci	.setkey			= cvm_ecb_des3_setkey,
4478c2ecf20Sopenharmony_ci	.encrypt		= cvm_encrypt,
4488c2ecf20Sopenharmony_ci	.decrypt		= cvm_decrypt,
4498c2ecf20Sopenharmony_ci	.init			= cvm_enc_dec_init,
4508c2ecf20Sopenharmony_ci} };
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_cistatic inline int cav_register_algs(void)
4538c2ecf20Sopenharmony_ci{
4548c2ecf20Sopenharmony_ci	return crypto_register_skciphers(algs, ARRAY_SIZE(algs));
4558c2ecf20Sopenharmony_ci}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_cistatic inline void cav_unregister_algs(void)
4588c2ecf20Sopenharmony_ci{
4598c2ecf20Sopenharmony_ci	crypto_unregister_skciphers(algs, ARRAY_SIZE(algs));
4608c2ecf20Sopenharmony_ci}
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ciint cvm_crypto_init(struct cpt_vf *cptvf)
4638c2ecf20Sopenharmony_ci{
4648c2ecf20Sopenharmony_ci	struct pci_dev *pdev = cptvf->pdev;
4658c2ecf20Sopenharmony_ci	u32 dev_count;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	dev_count = dev_handle.dev_count;
4688c2ecf20Sopenharmony_ci	dev_handle.cdev[dev_count] = cptvf;
4698c2ecf20Sopenharmony_ci	dev_handle.dev_count++;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	if (dev_count == 3) {
4728c2ecf20Sopenharmony_ci		if (cav_register_algs()) {
4738c2ecf20Sopenharmony_ci			dev_err(&pdev->dev, "Error in registering crypto algorithms\n");
4748c2ecf20Sopenharmony_ci			return -EINVAL;
4758c2ecf20Sopenharmony_ci		}
4768c2ecf20Sopenharmony_ci	}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	return 0;
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_civoid cvm_crypto_exit(void)
4828c2ecf20Sopenharmony_ci{
4838c2ecf20Sopenharmony_ci	u32 dev_count;
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	dev_count = --dev_handle.dev_count;
4868c2ecf20Sopenharmony_ci	if (!dev_count)
4878c2ecf20Sopenharmony_ci		cav_unregister_algs();
4888c2ecf20Sopenharmony_ci}
489