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