162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * sl3516-ce-cipher.c - hardware cryptographic offloader for Storlink SL3516 SoC 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2021 Corentin LABBE <clabbe@baylibre.com> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This file adds support for AES cipher with 128,192,256 bits keysize in 862306a36Sopenharmony_ci * ECB mode. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <crypto/engine.h> 1262306a36Sopenharmony_ci#include <crypto/internal/skcipher.h> 1362306a36Sopenharmony_ci#include <crypto/scatterwalk.h> 1462306a36Sopenharmony_ci#include <linux/dma-mapping.h> 1562306a36Sopenharmony_ci#include <linux/delay.h> 1662306a36Sopenharmony_ci#include <linux/err.h> 1762306a36Sopenharmony_ci#include <linux/io.h> 1862306a36Sopenharmony_ci#include <linux/kernel.h> 1962306a36Sopenharmony_ci#include <linux/pm_runtime.h> 2062306a36Sopenharmony_ci#include <linux/slab.h> 2162306a36Sopenharmony_ci#include <linux/string.h> 2262306a36Sopenharmony_ci#include "sl3516-ce.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* sl3516_ce_need_fallback - check if a request can be handled by the CE */ 2562306a36Sopenharmony_cistatic bool sl3516_ce_need_fallback(struct skcipher_request *areq) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 2862306a36Sopenharmony_ci struct sl3516_ce_cipher_tfm_ctx *op = crypto_skcipher_ctx(tfm); 2962306a36Sopenharmony_ci struct sl3516_ce_dev *ce = op->ce; 3062306a36Sopenharmony_ci struct scatterlist *in_sg; 3162306a36Sopenharmony_ci struct scatterlist *out_sg; 3262306a36Sopenharmony_ci struct scatterlist *sg; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci if (areq->cryptlen == 0 || areq->cryptlen % 16) { 3562306a36Sopenharmony_ci ce->fallback_mod16++; 3662306a36Sopenharmony_ci return true; 3762306a36Sopenharmony_ci } 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci /* 4062306a36Sopenharmony_ci * check if we have enough descriptors for TX 4162306a36Sopenharmony_ci * Note: TX need one control desc for each SG 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci if (sg_nents(areq->src) > MAXDESC / 2) { 4462306a36Sopenharmony_ci ce->fallback_sg_count_tx++; 4562306a36Sopenharmony_ci return true; 4662306a36Sopenharmony_ci } 4762306a36Sopenharmony_ci /* check if we have enough descriptors for RX */ 4862306a36Sopenharmony_ci if (sg_nents(areq->dst) > MAXDESC) { 4962306a36Sopenharmony_ci ce->fallback_sg_count_rx++; 5062306a36Sopenharmony_ci return true; 5162306a36Sopenharmony_ci } 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci sg = areq->src; 5462306a36Sopenharmony_ci while (sg) { 5562306a36Sopenharmony_ci if ((sg->length % 16) != 0) { 5662306a36Sopenharmony_ci ce->fallback_mod16++; 5762306a36Sopenharmony_ci return true; 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci if ((sg_dma_len(sg) % 16) != 0) { 6062306a36Sopenharmony_ci ce->fallback_mod16++; 6162306a36Sopenharmony_ci return true; 6262306a36Sopenharmony_ci } 6362306a36Sopenharmony_ci if (!IS_ALIGNED(sg->offset, 16)) { 6462306a36Sopenharmony_ci ce->fallback_align16++; 6562306a36Sopenharmony_ci return true; 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci sg = sg_next(sg); 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci sg = areq->dst; 7062306a36Sopenharmony_ci while (sg) { 7162306a36Sopenharmony_ci if ((sg->length % 16) != 0) { 7262306a36Sopenharmony_ci ce->fallback_mod16++; 7362306a36Sopenharmony_ci return true; 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci if ((sg_dma_len(sg) % 16) != 0) { 7662306a36Sopenharmony_ci ce->fallback_mod16++; 7762306a36Sopenharmony_ci return true; 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci if (!IS_ALIGNED(sg->offset, 16)) { 8062306a36Sopenharmony_ci ce->fallback_align16++; 8162306a36Sopenharmony_ci return true; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci sg = sg_next(sg); 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci /* need same numbers of SG (with same length) for source and destination */ 8762306a36Sopenharmony_ci in_sg = areq->src; 8862306a36Sopenharmony_ci out_sg = areq->dst; 8962306a36Sopenharmony_ci while (in_sg && out_sg) { 9062306a36Sopenharmony_ci if (in_sg->length != out_sg->length) { 9162306a36Sopenharmony_ci ce->fallback_not_same_len++; 9262306a36Sopenharmony_ci return true; 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci in_sg = sg_next(in_sg); 9562306a36Sopenharmony_ci out_sg = sg_next(out_sg); 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci if (in_sg || out_sg) 9862306a36Sopenharmony_ci return true; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci return false; 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic int sl3516_ce_cipher_fallback(struct skcipher_request *areq) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 10662306a36Sopenharmony_ci struct sl3516_ce_cipher_tfm_ctx *op = crypto_skcipher_ctx(tfm); 10762306a36Sopenharmony_ci struct sl3516_ce_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 10862306a36Sopenharmony_ci struct skcipher_alg *alg = crypto_skcipher_alg(tfm); 10962306a36Sopenharmony_ci struct sl3516_ce_alg_template *algt; 11062306a36Sopenharmony_ci int err; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci algt = container_of(alg, struct sl3516_ce_alg_template, alg.skcipher.base); 11362306a36Sopenharmony_ci algt->stat_fb++; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci skcipher_request_set_tfm(&rctx->fallback_req, op->fallback_tfm); 11662306a36Sopenharmony_ci skcipher_request_set_callback(&rctx->fallback_req, areq->base.flags, 11762306a36Sopenharmony_ci areq->base.complete, areq->base.data); 11862306a36Sopenharmony_ci skcipher_request_set_crypt(&rctx->fallback_req, areq->src, areq->dst, 11962306a36Sopenharmony_ci areq->cryptlen, areq->iv); 12062306a36Sopenharmony_ci if (rctx->op_dir == CE_DECRYPTION) 12162306a36Sopenharmony_ci err = crypto_skcipher_decrypt(&rctx->fallback_req); 12262306a36Sopenharmony_ci else 12362306a36Sopenharmony_ci err = crypto_skcipher_encrypt(&rctx->fallback_req); 12462306a36Sopenharmony_ci return err; 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic int sl3516_ce_cipher(struct skcipher_request *areq) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 13062306a36Sopenharmony_ci struct sl3516_ce_cipher_tfm_ctx *op = crypto_skcipher_ctx(tfm); 13162306a36Sopenharmony_ci struct sl3516_ce_dev *ce = op->ce; 13262306a36Sopenharmony_ci struct sl3516_ce_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 13362306a36Sopenharmony_ci struct skcipher_alg *alg = crypto_skcipher_alg(tfm); 13462306a36Sopenharmony_ci struct sl3516_ce_alg_template *algt; 13562306a36Sopenharmony_ci struct scatterlist *sg; 13662306a36Sopenharmony_ci unsigned int todo, len; 13762306a36Sopenharmony_ci struct pkt_control_ecb *ecb; 13862306a36Sopenharmony_ci int nr_sgs = 0; 13962306a36Sopenharmony_ci int nr_sgd = 0; 14062306a36Sopenharmony_ci int err = 0; 14162306a36Sopenharmony_ci int i; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci algt = container_of(alg, struct sl3516_ce_alg_template, alg.skcipher.base); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci dev_dbg(ce->dev, "%s %s %u %x IV(%p %u) key=%u\n", __func__, 14662306a36Sopenharmony_ci crypto_tfm_alg_name(areq->base.tfm), 14762306a36Sopenharmony_ci areq->cryptlen, 14862306a36Sopenharmony_ci rctx->op_dir, areq->iv, crypto_skcipher_ivsize(tfm), 14962306a36Sopenharmony_ci op->keylen); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci algt->stat_req++; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (areq->src == areq->dst) { 15462306a36Sopenharmony_ci nr_sgs = dma_map_sg(ce->dev, areq->src, sg_nents(areq->src), 15562306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 15662306a36Sopenharmony_ci if (nr_sgs <= 0 || nr_sgs > MAXDESC / 2) { 15762306a36Sopenharmony_ci dev_err(ce->dev, "Invalid sg number %d\n", nr_sgs); 15862306a36Sopenharmony_ci err = -EINVAL; 15962306a36Sopenharmony_ci goto theend; 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci nr_sgd = nr_sgs; 16262306a36Sopenharmony_ci } else { 16362306a36Sopenharmony_ci nr_sgs = dma_map_sg(ce->dev, areq->src, sg_nents(areq->src), 16462306a36Sopenharmony_ci DMA_TO_DEVICE); 16562306a36Sopenharmony_ci if (nr_sgs <= 0 || nr_sgs > MAXDESC / 2) { 16662306a36Sopenharmony_ci dev_err(ce->dev, "Invalid sg number %d\n", nr_sgs); 16762306a36Sopenharmony_ci err = -EINVAL; 16862306a36Sopenharmony_ci goto theend; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci nr_sgd = dma_map_sg(ce->dev, areq->dst, sg_nents(areq->dst), 17162306a36Sopenharmony_ci DMA_FROM_DEVICE); 17262306a36Sopenharmony_ci if (nr_sgd <= 0 || nr_sgd > MAXDESC) { 17362306a36Sopenharmony_ci dev_err(ce->dev, "Invalid sg number %d\n", nr_sgd); 17462306a36Sopenharmony_ci err = -EINVAL; 17562306a36Sopenharmony_ci goto theend_sgs; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci len = areq->cryptlen; 18062306a36Sopenharmony_ci i = 0; 18162306a36Sopenharmony_ci sg = areq->src; 18262306a36Sopenharmony_ci while (i < nr_sgs && sg && len) { 18362306a36Sopenharmony_ci if (sg_dma_len(sg) == 0) 18462306a36Sopenharmony_ci goto sgs_next; 18562306a36Sopenharmony_ci rctx->t_src[i].addr = sg_dma_address(sg); 18662306a36Sopenharmony_ci todo = min(len, sg_dma_len(sg)); 18762306a36Sopenharmony_ci rctx->t_src[i].len = todo; 18862306a36Sopenharmony_ci dev_dbg(ce->dev, "%s total=%u SGS(%d %u off=%d) todo=%u\n", __func__, 18962306a36Sopenharmony_ci areq->cryptlen, i, rctx->t_src[i].len, sg->offset, todo); 19062306a36Sopenharmony_ci len -= todo; 19162306a36Sopenharmony_ci i++; 19262306a36Sopenharmony_cisgs_next: 19362306a36Sopenharmony_ci sg = sg_next(sg); 19462306a36Sopenharmony_ci } 19562306a36Sopenharmony_ci if (len > 0) { 19662306a36Sopenharmony_ci dev_err(ce->dev, "remaining len %d/%u nr_sgs=%d\n", len, areq->cryptlen, nr_sgs); 19762306a36Sopenharmony_ci err = -EINVAL; 19862306a36Sopenharmony_ci goto theend_sgs; 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci len = areq->cryptlen; 20262306a36Sopenharmony_ci i = 0; 20362306a36Sopenharmony_ci sg = areq->dst; 20462306a36Sopenharmony_ci while (i < nr_sgd && sg && len) { 20562306a36Sopenharmony_ci if (sg_dma_len(sg) == 0) 20662306a36Sopenharmony_ci goto sgd_next; 20762306a36Sopenharmony_ci rctx->t_dst[i].addr = sg_dma_address(sg); 20862306a36Sopenharmony_ci todo = min(len, sg_dma_len(sg)); 20962306a36Sopenharmony_ci rctx->t_dst[i].len = todo; 21062306a36Sopenharmony_ci dev_dbg(ce->dev, "%s total=%u SGD(%d %u off=%d) todo=%u\n", __func__, 21162306a36Sopenharmony_ci areq->cryptlen, i, rctx->t_dst[i].len, sg->offset, todo); 21262306a36Sopenharmony_ci len -= todo; 21362306a36Sopenharmony_ci i++; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cisgd_next: 21662306a36Sopenharmony_ci sg = sg_next(sg); 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci if (len > 0) { 21962306a36Sopenharmony_ci dev_err(ce->dev, "remaining len %d\n", len); 22062306a36Sopenharmony_ci err = -EINVAL; 22162306a36Sopenharmony_ci goto theend_sgs; 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci switch (algt->mode) { 22562306a36Sopenharmony_ci case ECB_AES: 22662306a36Sopenharmony_ci rctx->pctrllen = sizeof(struct pkt_control_ecb); 22762306a36Sopenharmony_ci ecb = (struct pkt_control_ecb *)ce->pctrl; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci rctx->tqflag = TQ0_TYPE_CTRL; 23062306a36Sopenharmony_ci rctx->tqflag |= TQ1_CIPHER; 23162306a36Sopenharmony_ci ecb->control.op_mode = rctx->op_dir; 23262306a36Sopenharmony_ci ecb->control.cipher_algorithm = ECB_AES; 23362306a36Sopenharmony_ci ecb->cipher.header_len = 0; 23462306a36Sopenharmony_ci ecb->cipher.algorithm_len = areq->cryptlen; 23562306a36Sopenharmony_ci cpu_to_be32_array((__be32 *)ecb->key, (u32 *)op->key, op->keylen / 4); 23662306a36Sopenharmony_ci rctx->h = &ecb->cipher; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci rctx->tqflag |= TQ4_KEY0; 23962306a36Sopenharmony_ci rctx->tqflag |= TQ5_KEY4; 24062306a36Sopenharmony_ci rctx->tqflag |= TQ6_KEY6; 24162306a36Sopenharmony_ci ecb->control.aesnk = op->keylen / 4; 24262306a36Sopenharmony_ci break; 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci rctx->nr_sgs = nr_sgs; 24662306a36Sopenharmony_ci rctx->nr_sgd = nr_sgd; 24762306a36Sopenharmony_ci err = sl3516_ce_run_task(ce, rctx, crypto_tfm_alg_name(areq->base.tfm)); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_citheend_sgs: 25062306a36Sopenharmony_ci if (areq->src == areq->dst) { 25162306a36Sopenharmony_ci dma_unmap_sg(ce->dev, areq->src, sg_nents(areq->src), 25262306a36Sopenharmony_ci DMA_BIDIRECTIONAL); 25362306a36Sopenharmony_ci } else { 25462306a36Sopenharmony_ci dma_unmap_sg(ce->dev, areq->src, sg_nents(areq->src), 25562306a36Sopenharmony_ci DMA_TO_DEVICE); 25662306a36Sopenharmony_ci dma_unmap_sg(ce->dev, areq->dst, sg_nents(areq->dst), 25762306a36Sopenharmony_ci DMA_FROM_DEVICE); 25862306a36Sopenharmony_ci } 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_citheend: 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci return err; 26362306a36Sopenharmony_ci} 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ciint sl3516_ce_handle_cipher_request(struct crypto_engine *engine, void *areq) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci int err; 26862306a36Sopenharmony_ci struct skcipher_request *breq = container_of(areq, struct skcipher_request, base); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci err = sl3516_ce_cipher(breq); 27162306a36Sopenharmony_ci local_bh_disable(); 27262306a36Sopenharmony_ci crypto_finalize_skcipher_request(engine, breq, err); 27362306a36Sopenharmony_ci local_bh_enable(); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci return 0; 27662306a36Sopenharmony_ci} 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ciint sl3516_ce_skdecrypt(struct skcipher_request *areq) 27962306a36Sopenharmony_ci{ 28062306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 28162306a36Sopenharmony_ci struct sl3516_ce_cipher_tfm_ctx *op = crypto_skcipher_ctx(tfm); 28262306a36Sopenharmony_ci struct sl3516_ce_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 28362306a36Sopenharmony_ci struct crypto_engine *engine; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci memset(rctx, 0, sizeof(struct sl3516_ce_cipher_req_ctx)); 28662306a36Sopenharmony_ci rctx->op_dir = CE_DECRYPTION; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci if (sl3516_ce_need_fallback(areq)) 28962306a36Sopenharmony_ci return sl3516_ce_cipher_fallback(areq); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci engine = op->ce->engine; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci return crypto_transfer_skcipher_request_to_engine(engine, areq); 29462306a36Sopenharmony_ci} 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ciint sl3516_ce_skencrypt(struct skcipher_request *areq) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); 29962306a36Sopenharmony_ci struct sl3516_ce_cipher_tfm_ctx *op = crypto_skcipher_ctx(tfm); 30062306a36Sopenharmony_ci struct sl3516_ce_cipher_req_ctx *rctx = skcipher_request_ctx(areq); 30162306a36Sopenharmony_ci struct crypto_engine *engine; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci memset(rctx, 0, sizeof(struct sl3516_ce_cipher_req_ctx)); 30462306a36Sopenharmony_ci rctx->op_dir = CE_ENCRYPTION; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci if (sl3516_ce_need_fallback(areq)) 30762306a36Sopenharmony_ci return sl3516_ce_cipher_fallback(areq); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci engine = op->ce->engine; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci return crypto_transfer_skcipher_request_to_engine(engine, areq); 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ciint sl3516_ce_cipher_init(struct crypto_tfm *tfm) 31562306a36Sopenharmony_ci{ 31662306a36Sopenharmony_ci struct sl3516_ce_cipher_tfm_ctx *op = crypto_tfm_ctx(tfm); 31762306a36Sopenharmony_ci struct sl3516_ce_alg_template *algt; 31862306a36Sopenharmony_ci const char *name = crypto_tfm_alg_name(tfm); 31962306a36Sopenharmony_ci struct crypto_skcipher *sktfm = __crypto_skcipher_cast(tfm); 32062306a36Sopenharmony_ci struct skcipher_alg *alg = crypto_skcipher_alg(sktfm); 32162306a36Sopenharmony_ci int err; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci memset(op, 0, sizeof(struct sl3516_ce_cipher_tfm_ctx)); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci algt = container_of(alg, struct sl3516_ce_alg_template, alg.skcipher.base); 32662306a36Sopenharmony_ci op->ce = algt->ce; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci op->fallback_tfm = crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); 32962306a36Sopenharmony_ci if (IS_ERR(op->fallback_tfm)) { 33062306a36Sopenharmony_ci dev_err(op->ce->dev, "ERROR: Cannot allocate fallback for %s %ld\n", 33162306a36Sopenharmony_ci name, PTR_ERR(op->fallback_tfm)); 33262306a36Sopenharmony_ci return PTR_ERR(op->fallback_tfm); 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci sktfm->reqsize = sizeof(struct sl3516_ce_cipher_req_ctx) + 33662306a36Sopenharmony_ci crypto_skcipher_reqsize(op->fallback_tfm); 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci dev_info(op->ce->dev, "Fallback for %s is %s\n", 33962306a36Sopenharmony_ci crypto_tfm_alg_driver_name(&sktfm->base), 34062306a36Sopenharmony_ci crypto_tfm_alg_driver_name(crypto_skcipher_tfm(op->fallback_tfm))); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci err = pm_runtime_get_sync(op->ce->dev); 34362306a36Sopenharmony_ci if (err < 0) 34462306a36Sopenharmony_ci goto error_pm; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci return 0; 34762306a36Sopenharmony_cierror_pm: 34862306a36Sopenharmony_ci pm_runtime_put_noidle(op->ce->dev); 34962306a36Sopenharmony_ci crypto_free_skcipher(op->fallback_tfm); 35062306a36Sopenharmony_ci return err; 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_civoid sl3516_ce_cipher_exit(struct crypto_tfm *tfm) 35462306a36Sopenharmony_ci{ 35562306a36Sopenharmony_ci struct sl3516_ce_cipher_tfm_ctx *op = crypto_tfm_ctx(tfm); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci kfree_sensitive(op->key); 35862306a36Sopenharmony_ci crypto_free_skcipher(op->fallback_tfm); 35962306a36Sopenharmony_ci pm_runtime_put_sync_suspend(op->ce->dev); 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ciint sl3516_ce_aes_setkey(struct crypto_skcipher *tfm, const u8 *key, 36362306a36Sopenharmony_ci unsigned int keylen) 36462306a36Sopenharmony_ci{ 36562306a36Sopenharmony_ci struct sl3516_ce_cipher_tfm_ctx *op = crypto_skcipher_ctx(tfm); 36662306a36Sopenharmony_ci struct sl3516_ce_dev *ce = op->ce; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci switch (keylen) { 36962306a36Sopenharmony_ci case 128 / 8: 37062306a36Sopenharmony_ci break; 37162306a36Sopenharmony_ci case 192 / 8: 37262306a36Sopenharmony_ci break; 37362306a36Sopenharmony_ci case 256 / 8: 37462306a36Sopenharmony_ci break; 37562306a36Sopenharmony_ci default: 37662306a36Sopenharmony_ci dev_dbg(ce->dev, "ERROR: Invalid keylen %u\n", keylen); 37762306a36Sopenharmony_ci return -EINVAL; 37862306a36Sopenharmony_ci } 37962306a36Sopenharmony_ci kfree_sensitive(op->key); 38062306a36Sopenharmony_ci op->keylen = keylen; 38162306a36Sopenharmony_ci op->key = kmemdup(key, keylen, GFP_KERNEL | GFP_DMA); 38262306a36Sopenharmony_ci if (!op->key) 38362306a36Sopenharmony_ci return -ENOMEM; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci crypto_skcipher_clear_flags(op->fallback_tfm, CRYPTO_TFM_REQ_MASK); 38662306a36Sopenharmony_ci crypto_skcipher_set_flags(op->fallback_tfm, tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK); 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci return crypto_skcipher_setkey(op->fallback_tfm, key, keylen); 38962306a36Sopenharmony_ci} 390