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